I would like to write a Fortran subroutine that accepts the name of another subroutine as an argument --- imagine that the first subroutine is a PDE solver while the second provides the right-hand side of the PDE. Note that the second subroutine may be implemented by others, and hence we may not know anything about it except for its signature.
This is possible using abstract interfaces and a procedure statements. See, for example, https://github.com/jacobwilliams/PowellOpt/blob/master/src/newuoa.f90
It is of course also doable using external functions: http://malayamaarutham.blogspot.com/2006/02/passing-function-names-as-arguments-in.html
However, abstract interfaces and procedure statements are available only after Fortran 2003, while external functions are not desirable. Here comes my first question:
Is it possible to pass a subroutine name as an argument in Fortran 90/95 without using abstract interfaces and procedure statements or external functions?
The answer seemed negative to me at the beginning, because I saw this discussion: http://computer-programming-forum.com/49-fortran/dba58f497a8dc996.htm
Fortunately, after more study, I found it possible via the normal interface (not the abstract one) according to sources like Fortran | Passing functions as arguments in other functions , How to pass subroutine names as arguments in Fortran? , https://www.tek-tips.com/viewthread.cfm?qid=1572869 .
I implemented the following piece of code as a minimal working example. My second question is:
Is the following piece of code Fortran 90/95 compliant?
I tried compiling the code using gfortran, ifort, and g95. The first two compilers were happy, but g95 raised a warning that
use fun_mod, only : fun
1
Warning (102): MODULE PROCEDURE 'fun' USEd at (1) is not referenced
when I executed
g95 -Wall -Wextra -std=f95 -pedantic main.f90
The resultant executable worked without any problem, but why this warning? Is this a bug of g95? If not, how to get rid of this warning? Any other comments/criticism on the code will also be highly appreciated.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module proc_mod
! PROC_MOD provides a subroutine PROC(X, Y, F) that invokes a subroutine
! F at (X, Y) and then increment Y by 1.
implicit none
private
public :: proc
contains
subroutine proc(x, y, f)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: y
interface
subroutine f(x, y)
real, intent(in) :: x(:)
real, intent(out) :: y
end subroutine f
end interface
call f(x, y)
y = y + 1.0
end subroutine proc
end module proc_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module fun_mod
! FUN_MOD provides a subroutine FUN(X, Y) that sets Y = SUM(X**2).
! In practice, this module is provided by OTHERS, and we do not
! know how it is implemented except for the signature of FUN.
implicit none
private
public :: fun
contains
subroutine fun(x, y)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: y
y = sum(x**2)
end subroutine fun
end module fun_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program main
! MAIN tests PROC(X, Y, FUN) with PROC from PROC_MOD and FUN from FUN_MOD.
use proc_mod, only : proc
use fun_mod, only : fun
implicit none
real :: x(3), y
call random_number(x)
print *, x
call proc(x, y, fun)
print *, y
print *, sum(x**2) + 1.0
end program main
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Note that, in this code, we need to write an interface block for FUN in every subroutine that receives FUN as an argument. It would be tedious if I had many such subroutines. This motivates my third question:
Is it possible to wrap the interface of FUN in a module and dispense the interface block by using the module? (I tried but did not succeed.)
Thank you very much!
Edit: As pointed out by @Ian Bush and @francescalus, maybe I should accept using abstract interfaces and procedure statements, checking whether the users' compilers implement such a feature of F2003. So here comes the 4th question:
What is the earliest version of commonly used Fortran compilers (gfortran, ifort, nagfor, pgfortran ...) that implements the abstract interface and the procedure statement?
I know that I should check the documentation myself --- I will. I put this question here just in case someone knows the answer. Later I will edit the question to include the answer in case someone else is looking for the same thing. Thanks.
Answer to the fourth question:
- gfortran: 4.3 (according to https://gcc.gnu.org/wiki/GFortran/News#GCC4.3), released in 2008
- nagfor: 5.1 (according to http://geco.mines.edu/software/nagfor/nag_f2003.html#AUTOTOC_9_1), released in 2008
- IBM XL Fortran for Linux or AIX: no later than 12.1 (according to http://publibfp.dhe.ibm.com/epubs/pdf/c2385550.pdf and https://www.ibm.com/support/pages/sites/default/files/support/swg/swgdocs.nsf/0/5f70ca824c75701b852574720069a576/%24FILE/compiler.pdf), released in 2008
- ifort: 11.0 (according to https://jp.xlsoft.com/documents/intel/compiler/11/Release_Notes_f_osx.pdf), released in 2009
- pgfortran: 10.8 (according to https://www.pgroup.com/support/new_rel_2010.htm#new), released in 2010
- absoft Fortran: 14.0 (according to https://www.absoft.com/wp-content/uploads/2015/08/ProFortran2014WindowsReleaseNotes.pdf and http://www.gmsl.it/wp-content/uploads/2014/09/Fortran_Reference.pdf), released in 2014