- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@da-james wrote:
.. Any help would be appreciated!
You nearly had it. The procedure pointer assignment instruction does not need parenthesis on the target. You also had a mismatch in your interface relative to your function implementation in terms of missing POINTER attribute on dummy argument 'd' and the INTENT with argument 'y' - I presume you wanted them in the interface.
Taking a bit of an editorial liberty with the use of abstract interface to signal the intent of declaring a signature of an expected argument and with the use of a helpful "I" prefix with such signatures and of course with defined kinds, here's revised code you can try.
module kinds_m
! Choose suitable kind for integer objects with their expected range
integer, parameter :: I4 = selected_int_kind( r=9 ) !<-- Expected is a '4-byte' integer
! Choose minimum desired precision for floating-point objects
integer, parameter :: R8 = selected_real_kind( p=12 ) !<-- Expected is a '8-byte' real
end module
module mod_math
use kinds_m, only : I4, R8
implicit none
abstract interface
function Ifunc_2d(t, y, d) &
result(dy)
import :: I4, R8
implicit none
real(R8), intent(in) :: t
real(R8), intent(in) :: y(2)
real(R8), intent(in), pointer :: d(:,:)
real(R8) :: dy(2)
end function Ifunc_2d
end interface
contains
subroutine rk4(df, y, ti, tf, n, data)
! arguments
procedure(Ifunc_2d), pointer :: df
real(R8), pointer, intent(inout) :: y(:)
real(R8), intent(in) :: ti, tf
integer(I4), intent(in) :: n
real(R8), pointer, intent(in) :: data(:,:)
! ...
end subroutine
end module mod_math
module mod_func
use kinds_m, only : I4, R8
implicit none
contains
function func(t, u, d) &
result(du)
! calling variables
real(R8), intent(in) :: t
real(R8), intent(in) :: u(2)
real(R8), pointer, intent(in) :: d(:,:)
real(R8) :: du(2)
! ...
end function func
end module mod_func
program main
use mod_math, only : rk4, Ifunc_2d
use mod_func, only : func
implicit none
procedure(Ifunc_2d), 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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@da-james wrote:
.. Any help would be appreciated!
You nearly had it. The procedure pointer assignment instruction does not need parenthesis on the target. You also had a mismatch in your interface relative to your function implementation in terms of missing POINTER attribute on dummy argument 'd' and the INTENT with argument 'y' - I presume you wanted them in the interface.
Taking a bit of an editorial liberty with the use of abstract interface to signal the intent of declaring a signature of an expected argument and with the use of a helpful "I" prefix with such signatures and of course with defined kinds, here's revised code you can try.
module kinds_m
! Choose suitable kind for integer objects with their expected range
integer, parameter :: I4 = selected_int_kind( r=9 ) !<-- Expected is a '4-byte' integer
! Choose minimum desired precision for floating-point objects
integer, parameter :: R8 = selected_real_kind( p=12 ) !<-- Expected is a '8-byte' real
end module
module mod_math
use kinds_m, only : I4, R8
implicit none
abstract interface
function Ifunc_2d(t, y, d) &
result(dy)
import :: I4, R8
implicit none
real(R8), intent(in) :: t
real(R8), intent(in) :: y(2)
real(R8), intent(in), pointer :: d(:,:)
real(R8) :: dy(2)
end function Ifunc_2d
end interface
contains
subroutine rk4(df, y, ti, tf, n, data)
! arguments
procedure(Ifunc_2d), pointer :: df
real(R8), pointer, intent(inout) :: y(:)
real(R8), intent(in) :: ti, tf
integer(I4), intent(in) :: n
real(R8), pointer, intent(in) :: data(:,:)
! ...
end subroutine
end module mod_math
module mod_func
use kinds_m, only : I4, R8
implicit none
contains
function func(t, u, d) &
result(du)
! calling variables
real(R8), intent(in) :: t
real(R8), intent(in) :: u(2)
real(R8), pointer, intent(in) :: d(:,:)
real(R8) :: du(2)
! ...
end function func
end module mod_func
program main
use mod_math, only : rk4, Ifunc_2d
use mod_func, only : func
implicit none
procedure(Ifunc_2d), 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
By the way, your inquiry is general Fortran that is applicable in the context of more than one Fortran processor e.g., with gfortran as you alluded to as well as any other Fortran compiler in addition to Intel Fortran.
Under the circumstances, you may want to consider posting your inquiries at this Fortran DIscourse site for wider feedback on any and all Fortran-related topics of interest to you:
https://fortran-lang.discourse.group/
You may also ask there regarding any questions with code modernization and Fortran 2018. You can also inquire there about how to write better general interfaces while keeping in mind the Fortran language standard is decidedly deficient in this aspect and which is a topic for further enhancement in a future revision of the language.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Oh, that is my mistake including that parentheses at
df => func()
I actually did write it as
df => func
And after I tried some of your alterations such as using abstract, I'm still getting the same error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually re-going through the interface, I found a small difference between it and my function.
Thank you for the input!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Setting checking options is always a good thing. The original code you posted has some errors as you have found.
ifort mod_func.f90 mod_math.f90 main.f90 /stand /check:all
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.1.1.216 Build 20200306
Copyright (C) 1985-2020 Intel Corporation. All rights reserved.
mod_func.f90(8): warning #6178: The return value of this FUNCTION has not been defined. [DU]
result(du)
-------^
main.f90(11): error #6631: A non-optional actual argument must be present when invoking a procedure with an explicit interface. [T]
df => func()
------^
main.f90(11): error #6631: A non-optional actual argument must be present when invoking a procedure with an explicit interface. [U]
df => func()
------^
main.f90(11): error #6631: A non-optional actual argument must be present when invoking a procedure with an explicit interface. [D]
df => func()
------^
main.f90(11): error #6678: When the target is an expression it must deliver a pointer result.
df => func()
------^
compilation aborted for main.f90 (code 1)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FF,
RE:
module mod_math
use kinds_m, only : I4, R8
implicit none
abstract interface
function Ifunc_2d(t, y, d) &
result(dy)
import :: I4, R8
...
Could you explain the reason for using "import :: ..." verses "use kinds_m, only : ..." in the abstract interface?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'll tell you why I prefer IMPORT here - it helps down the road if the source of the definitions changes. It also makes clear that these are the same entities as are visible in the host scope.
I wrote about IMPORT in Domestic or Imported?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@jimdempseyatthecove wrote:
FF,
..
Could you explain the reason for using "import :: ..." verses "use kinds_m, only : ..." in the abstract interface? ..
Jim,
You can see Steve's comment upthread and his blogpost for the technical reasons to prefer the IMPORT statement, particularly the important one that conveys to the processor and to the reader of the code the same entities as in the host scope apply to those in the interface block.
Coders may find these good reasons help them a bit with reduced verbosity as well e.g., entities in the host scope which may be associated across USE multiple statements and separate declarations can all be listed in a simple IMPORT statement in an interface if the coder so wishes i.e., this can also become a stylistic preference.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page