Procedure with assumed-shape dummy argument must have an explicit interface [duplicate] - function

This question already has an answer here:
Module calling an external procedure with implicit interface
(1 answer)
Closed 5 years ago.
I am completely new to Fortran 90 and I am trying to understand how to pass an array to a function. I looked on the web and I could not find any clear and simple enough example, so I decided to post here.
I would like the function be able to work on an array of any length (the length of the array should not be one of the parameters of the functions).
I tried to write a simple example of a function that returns the sum of the elements of an array:
function mysum(arr)
implicit none
real, dimension(:), intent(in) :: arr
real :: mysum
integer :: i,arrsize
arrsize = size(arr)
mysum=0.0
do i=1,arrsize
mysum=mysum+arr(i)
enddo
end function mysum
program test
implicit none
real, dimension(4) :: a
real :: mysum,a_sum
call random_number(a)
print *,a
a_sum=mysum(a)
print *,a_sum
end program
When I try to compile, I get the following error:
array_test.f90:17.14:
real mysum,a_sum
1
Error: Procedure 'mysum' at (1) with assumed-shape dummy argument 'arr' must have an explicit interface
What is the problem with my program?

Assumed shape dummy arguments (those with (:)) require explicit interface to the procedure to be available at the call site. That means the calling code must know how exactly the subroutine header looks like. See also Module calling an external procedure with implicit interface
That explicit interface can be provided in several ways
1.
preferred - a module procedure
module procedures
implicit none
contains
function mysum(arr)
real, dimension(:), intent(in) :: arr
real :: mysum
integer :: i,arrsize
arrsize = size(arr)
mysum=0.0
do i=1,arrsize
mysum=mysum+arr(i)
enddo
end function mysum
end module
program test
use procedures
implicit none
!no mysum declared here, it comes from the module
...
end program
2.
internal procedure - only for short simple procedures or if the procedure needs access to the host's variables. Because of the access to the host variables it is error-prone.
program test
implicit none
!no a_sum declared here, it is visible below contains
...
contains
function mysum(arr)
!implicit none inherited from the program
real, dimension(:), intent(in) :: arr
real :: mysum
integer :: i,arrsize
arrsize = size(arr)
mysum=0.0
do i=1,arrsize
mysum=mysum+arr(i)
enddo
end function mysum
end program
3.
interface block - not recommended at all, you should have some particular reason to use it
function mysum(arr)
! removed to save space
end function mysum
program test
implicit none
interface
function mysum(arr)
real, dimension(:), intent(in) :: arr
real :: mysum
end function
end interface
!no mysum declared there
!it is declared in the interface block
...
end program

Related

Fortran function returning unallocated array causes segmentation fault

I'm struggling with some Modern Fortran wrappers to some MPI scatter/gather routines. I am trying to have a wrapper interface that only has an array on input and returns the MPI-operated result on output, for several derived types, doing something like this:
type(mytype), allocatable :: chunk(:),whole(:)
! [...] chunk descends from previous parts of the code
! Get global array
whole = gatherv(array=chunk,receiver_node=cpuid)
I'm doing this using functions that return allocatable arrays. However, I'm getting segmentation fault on both gcc 6.2.0 and gcc 7.1.0 whenever I return a non-allocated result.
The reason I need a non-allocated result is that sometimes I need to gather the whole array only on a specified CPU, so I don't want to waste memory on all other nodes: the receiver node returns an allocated array with the data, and all other nodes receive an empty and deallocated array.
This is sample code that reproduces the issue:
program test_allocatable_fun
implicit none
integer, allocatable :: my_array(:)
integer :: n
n = 3; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n =-3; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 5; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 0; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
return
contains
function unallocated_array(n) result(array)
integer, intent(in) :: n
integer, allocatable :: array(:)
integer :: j
if (n>0) then
allocate(array(n))
array(:) = [(j,j=1,n)]
else
if (allocated(array)) deallocate(array)
end if
end function unallocated_array
end program test_allocatable_fun
The segmentation fault happens at the assignment line, i.e.:
my_array = unallocated_array(n)
Has any of you had the same issue before? Or, am I violating anything in the standard? I can't see why a function returning an allocatable array should be forced to have the return value allocated. Isn't it the same as having an intent(out) dummy variable in a subroutine?
A function result is not the same as a dummy argument with the intent(out) attribute. It differs in a significant way here in that a non-pointer function result must always be defined when execution of the function terminates. This is covered by Fortran 2008 12.6.2.2 p4.
It is necessary, but not sufficient, for an allocatable function result (any object) to be allocated to be defined.
To some extent you can consider this in the way that a function result is always referenced (otherwise the function wouldn't be executed). An actual argument not defined may also not be referenced, but such referencing wouldn't be "automatic".
As mentioned in comments, the function result may be allocated to be an array of size zero. Zero-sized arrays are always of defined value.
You can see some comparison of zero-sized arrays and not-allocated arrays in this other question.
I suspect any allocatable array in a main program contains data of a global nature. I usually put such variables in a module. This way this variable does not need to be passed around and can be allocated and deallocated in the main program, subroutines, and/or functions.
Since the array is the only return value, I changed it to a subroutine. How does this work for you? P.S. 'implicit none' should be in every module, program, function, and subroutine.
module fun
implicit none
integer, allocatable :: my_array(:)
end module fun
program test_allocatable_fun
use fun
implicit none
integer :: n
n = 3; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n =-3; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 5; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 0; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
return
contains
subroutine unallocated_array(n)
use fun
implicit none
integer, intent(in) :: n
integer :: j
if (n>0) then
allocate(my_array(n))
my_array(:) = [(j,j=1,n)]
else
if (allocated(my_array)) deallocate(my_array)
end if
end subroutine unallocated_array
end program test_allocatable_fun

User defined constructor for Fortran derived type instance

This is my second question related to Fortran (I use C++, so forgive me my way of thinking).
I want to use OOP, to say, derived type in Fortran whenever appropriate.
In C++, you can use user defined constructor such as https://msdn.microsoft.com/en-us/library/s16xw1a8.aspx
Here in Fortran, things are different.
The first thing I tried is from here:
https://www.ibm.com/developerworks/community/blogs/b10932b4-0edd-4e61-89f2-6e478ccba9aa/entry/object_oriented_fortran_user_defined_constructors2?lang=en
Link is broken, so I pasted it here:
module m
!...
interface base
module procedure new_base
end interface
contains
!...
function new_base(I)
integer, intent(in) :: I
type(base) new_base
allocate(new_base%data(I))
new_base%data = I
end function
!...
end module
The interface above defines a user-defined constructor for type base. It is used in a similar way to a structure constructor. It can even take argument keywords.
Then I found some other ways to do it.
Here I listed a few approaches seemly to work but I only tested the first and second:
generic interface with the same name as the derived type they're supposed to construct, see link above;
use type-bound procedure (This is not even a "traditional" constructor)
MODULE mymod
TYPE mytype
Private
INTEGER :: x
CONTAINS
PROCEDURE, PASS :: init
END TYPE
CONTAINS
SUBROUTINE init(this, i)
CLASS(mytype), INTENT(OUT) :: this
INTEGER, INTENT(IN) :: i
write(*,*) this%x
IF(i > 0) THEN
this%x = 1
ELSE
this%x = 2
END IF
write(*,*) this%x
END SUBROUTINE init
END
PROGRAM test
USE mymod
TYPE(mytype) :: y
CALL y%init(1)
END PROGRAM
use Static Constructors or Structure Constructors (http://www.lahey.com/docs/lfenthelp/NLMOvUsInvConst.htm)
But it appears that this is NOT for general Fortran http://www.lahey.com/docs/lfenthelp/NLMGSWhatIs.htm
So I haven't understood well enough what is most preferred and flexible approach to initialize/construct a derived type in practice, especially when I use nested derived type in development. I hope I can organize this topic with some help.
OK, so I will assume you read well the answers at How to override a structure constructor in fortran and I will answer your problem raised in the comment. There is not enough place in the comment to answer that.
You can also make constructors in Fortran which accept variable number of arguments.
It is even possible with the default structure constructors which every derived type has by default. If you default-initialize a component, it is optional in the constructor. The same holds for allocatable and pointer components.
For type
type t1
integer :: i = 1
integer, pointer :: ip => null()
integer, allocatable :: ap
end type
you can call the default constructor just as
instance = t1()
and it is perfectly legal, i will be 1, ip will point to null and ap will not be allocated.
Or you can call it as
instance = t1(ap=5)
and the ap component will be allocated and set to 5 and the other components will be left default.
You can achieve similar stuff with user defined constructors just by making the arguments optional.
function t1_user(ap, i) result(res)
type(t1) :: res
integer, allocatable :: ap !this argument MUST be passed,
! it does not have to be allocated
integer, optional :: i ! this argument is optional
if (present(i)) then
...
end if
end function
any type-bound procedure can of-course also have optional arguments.
As for the nested types, that is really best done with constructors as functions, no matter if they are default or user defined:
type inner
real :: x, y
end type
type outer
type(inner), allocatable :: in
real :: z
end type
instance1 = outer(inner(1., 2.), 3.)
instance2 = outer(z=4.)

Constant's value given by a non-intrinsic function

In Fortran, is there a way to initialize my named constant at compilation time using a function of other constants, other than the intrinsic functions?
I want to calculate a value using my own function and then use this value to declare the size of an array, such as in my attempt below.
integer function factorial(n)
implicit none
integer, intent(in) :: n
integer :: i, ans
ans=1
do i=1,n
ans=ans*i
end do
factorial = ans
end function Factorial
integer function binomial(n,k)
implicit none
integer, intent(in) :: n, k
integer :: factorial
binomial = Factorial(n)/factorial(n-k)/factorial(k)
end function binomial
program main
implicit none
integer, parameter :: m=10, n=3
integer :: binomial
integer, parameter :: sz=binomial(m,n)
complex, dimension(sz) :: hamiltonian
...
end program main
Or do I have have to calculate this value myself and write it explicitly in the code ?
As you seem to know, the Fortran standard prohibits calculations, at compile time, beyond what intrinsic routines are capable of. If you really must make those calculations at compile time then a hack like this might appeal to you:
INTEGER, DIMENSION(20), PARAMETER :: ints = [1,2,3,4,5,6,7,8,9,10, &
11,12,13,14,15,16,17,18,19,20]
INTEGER, PARAMETER :: m=10, n=3
INTEGER, PARAMETER :: sz = PRODUCT(ints(1:m))/PRODUCT(ints(1:m-n))/&
PRODUCT(ints(1:n))
COMPLEX, DIMENSION(sz) :: hamiltonian
This compiles, and executes, correctly. If you confine yourself to 64-bit integers the array ints doesn't need to go larger than 20.
Oh, in passing, don't use size as the name of a parameter, it's already the name of a useful intrinsic function.
Then again, you could just compute the factorials yourself and write:
INTEGER, DIMENSION(20), PARAMETER :: factorial = [1,2,6,24,...]
INTEGER, PARAMETER :: m=10, n=3
INTEGER, PARAMETER :: sz = factorial(m)/factorial(m-n)/factorial(n)
COMPLEX, DIMENSION(sz) :: hamiltonian
and be done with it.

Fortran and interface blocks in functions or subroutines

I would like to write a module which will perform some action based on function type provided by "user" in different file. This function will be passed as an argument of "execute(...)" subroutine of that module. This is basically what I want to obtain, but I don't know if this is possible and how should I do it correctly.
module mod1
contains
subroutine execute(func)
interface func
real function func1(a,b)
real a,b
end function
real function func2(a,b,c)
real a,b,c
end function
! more similar functions here
end interface func
! -------------------
! here some how choose between func1 or func2
! and do the calculations
if(func1) then ...
else if(func2) ...
! -------------------
endsubroutine execute
endmodule mod1
------------------------------------------
program
use mod1
call execute(test)
contains
real function test(a,b)
real a,b
test = a + b
end function
end program
I know that this code wont compile, but this is just a sketch how it would look like. For now, the only ugly solution for that problem for me is to write many alternatives for execute subroutine i.e execute_1, execute_2 and depending on the test function user will have to choose proper execute_X function.
Is there any better solution for that problem?
Thanks in advance. KK
You can also put the interfaces in the module header, and use the procedure attribute for func1 and func2 like so. This is useful if you want to use them elsewhere, since you are only defining them in one place.
module mod1
abstract interface
real function f1(a,b)
real,intent(in) :: a,b
end function f1
real function f2(a,b,c)
real,intent(in) :: a,b,c
end function f2
end interface
contains
subroutine execute(func1, func2)
procedure(f1),optional :: func1
procedure(f2),optional :: func2
!...
if (present(func1)) x = func1(a, b)
if (present(func2)) x = func2(a, b, c)
end subroutine execute
end module mod1
Guessing a little at your intent based on the example source, your problem is that you want a dummy procedure that may vary in its characteristics - for example the number of arguments.
I don't recommend this, but Fortran permits a dummy procedure to have an implicit interface - you could just give the func dummy procedure the external attribute, and then it is on the programmer's head to make sure that the nature of the reference through the dummy procedure is consistent with the interface of the actual procedure. Language facilities that require an explicit interface may not be used with this approach.
subroutine execute(func)
real, external :: func
!...
if (some_condition) then
x = func(a, b)
else
x = func(a, b, c)
end if
If you want the dummy procedure to have an explicit interface, then you might be able to use optional arguments.
module mod1
contains
subroutine execute(func1, func2)
interface
real function func1(a,b)
real a,b
end function func1
real function func2(a,b,c)
real a,b,c
end function func2
end interface
optional :: func1, func2
!...
if (present(func1)) x = func1(a, b)
if (present(func2)) x = func2(a, b, c)
end subroutine execute
end module mod1
program p
use mod1
call execute(func1=test)
contains
real function test(a,b)
real a,b
test = a + b
end function
end program p
More general solutions to this problem may invoke the procedure through a a binding of a derived type - the invocation of the procedure always uses the same interface, but additional information can then be passed through to the procedure using components of the derived type.

Dynamic function creation from another function

I have a Fortran 90 subroutine which takes a function as an argument, and I would like to pass a modified version of that function into another subroutine. I want the program to look something like this:
subroutine foo(f, ...)
real :: pt(2), dir(2)
interface
function f(x) result(y)
real, intent(in) :: x(2)
real :: y
end function f
end interface
pt = ...
dir = ...
!! Somehow create g(x) = f(pt + x*dir)
call bar(g)
end subroutine foo
subroutine bar(g)
interface
function g(x) result(y)
real, intent(in) :: x
real :: y
end function g
end interface
!! Do stuff with g
end subroutine bar
I've managed to do something similar when 'g' only needs to use normal variables, not a function. In that case I made it a global function, using global variables, and assigned to those global variables in 'foo'. However, I can't find a way to turn 'f' global, or assign it to a global function.
Anybody have any ideas how to do this? The solution can be as hacky as you want.
This is not so easy. In some languages you can pass pointers to nested functions in a so called closure. This is not possible in Fortran (or C and similar languages), because the data are destroyed with the stack of the higher function. I would suggest you to try function objects, i.e. a class with a function pointer (or more) and data needed for the function. In this way you can even do function composition and similar functional stuff.
More on the concept http://en.wikipedia.org/wiki/Function_object
Below is a sample for a function object for composition of two single argument functions:
module ComposeObj
use Parameters, only: rp
use AritmFunctions, only: fce
implicit none
private
public Compose
type Compose
private
procedure(fce),pointer,nopass :: f1 => null(),f2=>null()
contains
procedure,public :: call => helper
end type Compose
interface Compose
procedure NewCompose
end interface
contains
function NewCompose(f,g)
procedure(fce) :: f,g
type(Compose) :: NewCompose
NewCompose%f1 => f
NewCompose%f2 => g
end function NewCompose
pure real(rp) function helper(this,x)
class(Compose),intent(in) :: this
real(rp),intent(in) :: x
helper = this%f1(this%f2(x))
end function helper
end module ComposeObj
You could do a lot with procedure pointers, constructing a function that is a combination of other functions. See Function pointer arrays in Fortran for a code example.