Fortran Define Parameter from variable - fortran

I wish to define a parameter that will not change in my module from a input variable.
Example
module foo
contains
subroutine function1(external_var)
integer, parameter x = external_var(1)
write(*,*) x
end subroutine function1
end module foo
However, this gives an error.
PGF90-S-0087-Non-constant expression where constant expression required

Related

Overloading functions with optional arguments

I would like to write a procedure which takes an optional argument, which may be of type FooType or of type BarType, such that this program is valid:
module m
implicit none
type :: FooType
end type
type :: BarType
end type
end module
program mwe
use m
implicit none
type(FooType), allocatable :: foo(:)
type(BarType), allocatable :: bar(:)
call func()
call func([FooType()])
call func([BarType()])
call func(foo)
call func(bar)
end program
My current attempt is:
module m
implicit none
type :: FooType
end type
type :: BarType
end type
interface func
module procedure func_FooType
module procedure func_BarType
end interface
contains
subroutine func_FooType(input)
type(FooType), intent(in), optional :: input(:)
write(*,*) 'foo'
end subroutine
subroutine func_BarType(input)
type(BarType), intent(in) :: input(:)
write(*,*) 'bar'
end subroutine
end module
But this does not work. Compiling with either gfortran 10.1.0 or ifort 2021.1 gives the output
foo
foo
bar
foo
bar
The problem is the final call, to func(bar). bar is not allocated, and so if it were passed to an optional argument it would not be present. However, the procedure which gets called is func_BarType, which believes its input is not optional, and so has no way of checking if input is present. Indeed, if I change the input to be a scalar not an array, the call to func(bar) crashes at runtime under gfortran.
I think the only way to do this is with a single function which takes an optional polymorphic argument, so:
subroutine func(input)
class(*), intent(in), optional :: input(:)
if (present(input)) then
select type(input); type is(FooType)
! Code for FooType.
type is(BarType)
! Code for BarType.
class default
! Any other class. Probably throw an error.
end select
else
! Code for input not present.
endif
end subroutine
I'm surprised that there doesn't seem to be a way of doing this without using polymorphic types.

Passing functions, which have derived types as arguments, as arguments in Fortran

I have a subroutine which receives some data and another function as arguments. The function can take as argument this data. The subroutine is just there to call this function with the given data. Now let us assume the data can be of type foo. I would assume that I can also pass data of the from foo derived type bar. Apparently Fortran disagrees.
I have tried to compile the code below with gfortran 9. It fails with the error message:
47 | call funA(x, y, baz)
| 1
Error: Interface mismatch in dummy procedure ‘baz’ at (1): Type mismatch in argument 'y' (CLASS(foo)/CLASS(bar))
Various other attempts of replacing foo by bar yield similar resuts. Using pgfortran 19.4 yields the same error.
module A
implicit none
private
type, abstract, public :: foo
end type foo
public :: funA
contains
subroutine funA(x, y, baz)
integer, intent(in) :: x
class(foo), intent(in) :: y
interface
function baz(x, y) result(z)
import foo
integer, intent(in) :: x
class(foo), intent(in) :: y
integer :: z
end function baz
end interface
write(*,*) baz(x, y)
end subroutine funA
end module
module B
use A
implicit none
private
type, extends(foo), public :: bar
integer :: ii
end type bar
public :: fiz
contains
function baz(x, y) result(z)
integer, intent(in) :: x
class(bar), intent(in) :: y
integer :: z
z = x + y%ii
end function baz
subroutine fiz(x, y)
integer, intent(in) :: x
class(bar), intent(in) :: y
call funA(x, y, baz) ! <---- This causes errors.
end subroutine fiz
end module
program meh
use B
implicit none
integer :: x
type(bar) :: y
x = 1
y%ii = 2
call fiz(x, y)
end program meh
My expectation would have been that since y is of type bar, it is also of type foo and thus I can pass it to funA. The function baz must know that y is of type bar, otherwise it cannot access ii. However the rest of the code doesn't really need to know this, does it?
Where is the error in my reasoning? How can I get the above code to compile and run?
The error pointed to here is in the characteristics of the procedure argument. The procedure dummy argument baz of funA has characteristics which are not matched by the procedure actual argument baz of module B. The dummy argument has second argument (y) of declared type foo whereas the procedure baz passed to it has corresponding argument of declared type bar.
It is not allowed to have this mismatch in characteristics in dummy and actual procedure arguments.
To fix this problem it is necessary to make the dummy arguments y of the dummy baz and module procedure baz to be of the same declared type (probably foo). Of course, you'll then need to work around having y in baz (of module B) having declared type foo: such a y doesn't have a component ii. A quick hack would be to use a select type construct, but there may well be other approaches if a different flow can be designed.
As you can see, often discussions around code like this are helped if various arguments and the like have distinct names.

How to store a reference to a procedure in a Fortran derived type

Can I store a reference to a procedure inside a Fortran type?
My goal is to reduce repeated arguments into a Fortran subroutine by grouping them into a type. However Fortran doesn't let me do this for external procedures.
Here is a simplified example of what I try to do:
module my_functions
type mytype
external :: f
end type
contains
subroutine fa()
WRITE(*,*) "yiha"
end subroutine
subroutine fb(t)
type(mytype) t
call t%f()
end subroutine
end module
program test
use my_functions
type(mytype) :: m
m%f = fa
call fb(m)
end program
However gfortran gives me
external :: f
1
Error: Unexpected attribute declaration statement at (1)
A derived type may have procedure pointers as components:
implicit none
type mytype
procedure(), pointer, nopass :: f
end type
type(mytype) m
external fa
m%f => fa
call m%f()
end
This type has a procedure with an implicit interface which is referenced later as a subroutine. Because it has an implicit interface, the nopass attribute is required for the pointer.

fortran initializing a derived type inline or type casting

I want to know if there is a way to pass a derived type inline in a subroutine. Suppose that I have a module
module test_mod
type a
end type
type b
end type
contains
subroutine test(var)
type(a),intent(in) :: var
...
end subroutine
subroutine test(var)
type(b),intent(in) :: var
...
end subroutine
end module
Where I could implement this module with something like
program testTest
use test_mod
call test(type(a)::temp)
! call test(type(a)::temp) ! or
end program
I know this can be done in c++ using something like (double)(i), but this is a conversion. I'm interested in (I guess) initializing a derived type inline
The syntax you are using is alien to the language, but you can use structure constructors.
It is a function which returns the type and it has the same name as the type. Every derived type has a default one and you can define your own by overriding the type name in a generic interface. The arguments of the default constructor are the type components.
program testTest
use test_mod
call test(a())
end program
You can also use constructors in other situations, in compound expressions, or just on the right hand side of simple assignments
type :: t
real :: x
end type
type(t) :: o
o = t(1.0)
Example of a user-defined constructor:
type :: t
real :: x
end type
interface t
module procedure my_init
end interface
contains
function my_init(...) result(res)
type(t) :: res
...
end function

fortran extended types over different modules

With extended types in Fortran should a private component by visible to a type extension in a different module.
With both gcc4.7 and ifort the following code results in a error since bName is in both the initial type and the extension. But since it's private, it isn't accesible in the extension in a different module, i.e., if you comment out bName in the bar_type you will get an error that it's private.
module foo
type :: foo_type
character(256),private :: bName = "foo"
contains
procedure :: pName => pName
end type
contains
subroutine pName(this)
class(foo_type), intent(in) :: this
print*,trim(this%bName)
end subroutine
end module
module bar
use foo, only : foo_type
type,extends(foo_type) :: bar_type
character(256),private :: bName = "bar"
contains
procedure :: pName => pName
end type
contains
subroutine pName(this)
class(bar_type), intent(in) :: this
print*,this%bName
end subroutine
end module
program test
use foo, only : foo_type
use bar, only : bar_type
type(foo_type) :: foo_inst
type(bar_type) :: bar_inst
call foo_inst%pName()
call bar_inst%pName()
end program
If bar_type was contained in the same module as foo_type, then bName would be accessible from bar_type, i.e., the following code will compile
module foo
type :: foo_type
character(256),private :: bName = "foo"
contains
procedure :: pName => pName
end type
type, extends(foo_type) :: baz_type
contains
procedure :: pName => pName_baz
end type
contains
subroutine pName_baz(this)
class(baz_type), intent(in) :: this
print*,trim(this%bName)
end subroutine
subroutine pName(this)
class(foo_type), intent(in) :: this
print*,trim(this%bName)
end subroutine
end module
program test
use foo, only : foo_type,baz_type
type(foo_type) :: foo_inst
type(baz_type) :: baz_inst
call foo_inst%pName()
call baz_inst%pName()
end program
Been having a hard time parsing the standards to know what should happen in the first example.
I believe the first example is not standard-conforming.
Even though the private attribute makes the component bName inaccessible outside module foo, it is still inherited by bar_type (perhaps rather pointless, because nothing can be done with it, but that's not the issue) -- see Note 4.51 in f2003:
Inaccessible components and bindings of the parent type are also inherited, but they remain inaccessible
in the extended type. Inaccessible entities occur if the type being extended is accessed via
use association and has a private entity.
So bar_type has an inherited component with the name bName, which makes it an error to add another component by that name (see paragraph 16.2 for scope and name rules).