Reputation: 11
I am trying to have a function be the argument to another function however I keep getting the error:
Error: Internal procedure 'polytrope' is not allowed as an actual argument at (1)
Bellow is a barebones version of the program making the call to the function and which contains the actual callback:
PROGRAM testbutcher
USE butcher
IMPLICIT NONE
REAL :: t = 0, dt = 0.01
REAL, DIMENSION(2) :: v0 = (/ 1.0, 0.0 /), fargs = (/ 1.0, 1.0 /)
v0 = step(polytrope, v0, 2, t, dt, fargs)
CONTAINS
FUNCTION polytrope(v0, t, fargs) result(v1)
REAL, DIMENSION(:) :: fargs
REAL, DIMENSION(2) :: v0, v1
REAL :: t
v1 = t * v0
RETURN
END FUNCTION
END PROGRAM
and then the module which the function taking the functional argument is:
MODULE butcher
IMPLICIT NONE
CONTAINS
FUNCTION step(fxn, v0, n, t, dt, fargs) RESULT(v1)
REAL, DIMENSION(n) :: v0, v1
REAL, DIMENSION(:) :: fargs
REAL, DIMENSION(tn,tm) :: tab
REAL :: t, dt
INTEGER :: n, tn, tm
INTERFACE
FUNCTION fxn(v, t, fargs)
REAL, DIMENSION(:), INTENT(in) :: v
REAL, DIMENSION(:), INTENT(in) :: fargs
REAL, INTENT(in) :: t
END FUNCTION
END INTERFACE
v1 = fxn( v0, &
t + dt, &
fargs &
)
RETURN
END FUNCTION
END MODULE
So basically, testbutcher contains a function to be evaluated in a special way, so it sends it off to the module butcher (specifically the function step in butcher) to be evaluated. I can't figure out how to actually do this! If I were working in C i would simply make a pointer to polytrope and throw it to fxn.
Upvotes: 1
Views: 2579
Reputation: 9224
This is what has worked for me in the past with all of MS Fortran, Digital Fortran, Intel Fortran, and gfortran:
It's what I use to declare a library-invoked 'usage' subroutine in every program. It is likely that the compiler won't check that the function's signature is correct unless you also use an INTERFACE
statement (which is not a bad idea).
PROGRAM testbutcher
USE butcher
IMPLICIT NONE
EXTERNAL polytrope !!!!!
REAL :: t = 0, dt = 0.01
REAL, DIMENSION(2) :: v0 = (/ 1.0, 0.0 /), fargs = (/ 1.0, 1.0 /)
v0 = step(polytrope, v0, 2, t, dt, fargs)
CONTAINS
END PROGRAM
!!!!!
FUNCTION polytrope(v0, t, fargs) result(v1)
REAL, DIMENSION(:) :: fargs
REAL, DIMENSION(2) :: v0, v1
REAL :: t
v1 = t * v0
RETURN
END FUNCTION
Upvotes: 0
Reputation: 7102
In the function step, you define the inputs to fxn as being of INTENT(IN), but you don't declare any intent in your function polytrope. Also, the return type of fxn is not specified so it is being implicitly defined and won't be compatible with "REAL, DIMENSION(2)". I think you need a few more "IMPLICIT NONE" declarations in your code to catch this error.
Upvotes: 2