I have been trying to pass a function into my rk4 subroutine with no progress. The code I have is:
! 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
subroutine rk4(df, y, ti, tf, n, data)
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 module mod_math
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
use mod_math, only : rk4, f2d
use mod_func, only : func
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!
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.