Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
For the latest information on Intel’s response to the Log4j/Log4Shell vulnerability, please see Intel-SA-00646

Passing function as an argument


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


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

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


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


module mod_func

implicit none


function func(t, u, d) &
! 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


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
Valued Contributor III

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.


Black Belt

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