Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Passing function as an argument

tuvi2021
Beginner
528 Views

I have been trying to pass a function into my rk4 subroutine with no progress. The code I have is:

mod_math.f90:

module mod_math

implicit none

! I initially tried to have my interface more general for different system sizes

! but got frustrated so fixed it for a 2d system since that's my use case atm

interface
function f2d(t, y, d) &
result(dy)
real(8), intent(in) :: t
real(8), intent(in) :: d(:,:)
real(8) :: y(2)
real(8) :: dy(2)
end function f2d
end interface

contains

subroutine rk4(df, y, ti, tf, n, data)
! arguments
procedure(f2d), pointer :: df
real(8), pointer, intent(inout) :: y(:)
real(8), intent(in) :: ti, tf
integer(4), intent(in) :: n
real(8), pointer, intent(in) :: data(:,:)

! ...

end subroutine

end module mod_math

mod_func.f90:

module mod_func

implicit none

contains

function func(t, u, d) &
result(du)
! calling variables
real(8), intent(in) :: t
real(8), intent(in) :: u(2)
real(8), pointer, intent(in) :: d(:,:)
real(8) :: du(2)

! ...

end function func

end module mod_func

main.f90:

program main

use mod_math, only : rk4, f2d
use mod_func, only : func

implicit none

procedure(f2d), pointer :: df => null()

! this causes the error
df => func()

! I've omitted the other variables, because it seems the error

! happens on the line above before I even go to the rk4 part.

! rk4(df, y0, ti, tf, n, data)

end program main

The error I get is: error #8178: The procedure pointer and the procedure target must have matching arguments.

My old rk4 was from the "Numerical Recipes", but I believe that since it's F77 it seems to get errors since it passes functions by using

external :: func

Now the newer 2018 standard seems to use procedure pointers. Since I've been trying to learn the newer standards I've been re-writing some of my code and can't seem to get the procedure to point correctly. I think another difference is that before I ran my old rk4 on the gfortran compiler which seemed to be more lax about interfaces and using the ifort is also newer for me. 

I have looked at several resources online, and I'm not sure how much more I can fix my code.

Any help would be appreciated!

0 Kudos
2 Replies
Arjen_Markus
Honored Contributor I
517 Views

I used gfortran, version 10.2, on this source code and got:

   65 | df => func()
      |      1
Error: Invalid character in name at (1)

(func() is actually a call to the function without arguments - func is the name and that is what you want here)

After correcting that, I got:

   65 | df => func
      |      1
Error: Interface mismatch in procedure pointer assignment at (1): INTENT mismatch in argument 'y'

Indeed, the second agument of the interface has no intent, whereas your actual function does have intent(in) for this one.

I have not checked the messages from Intel Fortran, but they will probably be very similar. Although, error messages can be enigmatic and then I often use a second compiler to see whether its messages provide me a better clue ;).

That said, a few remarks:

  • If you post code, use the "Insert/Edit code example" button. It is a trifle hidden, "</>" under the "...", but it is easier on the eye :).
  • Is there a specific reason that you have argument "d" of the actual function to be a pointer (that is also missing in the interface by the way)?
  • I see other pointer arguments as well, probably not needed, especially as they are all intent(in) arguments.
  • You could pass func as an actual argument, no need to use a procedure pointer.

 

mecej4
Honored Contributor III
498 Views

Tuvi2021, you should probably use an ABSTRACT  interface in such a situation. For details, please read this article.

0 Kudos
Reply