0

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:

Nuno
  • 256
  • 1
  • 11
  • Why don't you want to use f2003? If it is because you want to use g95 be aware that it doesn't appear to have been developed in a long time - I would not recommend usig it for that reason. But also note what you quote above is a warning, not an error, you will still get a (hopefully working) executable – Ian Bush Aug 08 '20 at 08:04
  • Thank you for the comment, @Ian Bush. I would be very happy to use f2003, but my users may not. As for g95, I use it (and many other compilers) to check my code --- sometimes it raises very useful warnings that other compilers do not. Here I am curious why g95 gives me such a warning when it seems not the case. But I do not use g95 in practice --- as you said, it is not being developed. Thanks again. – Nuno Aug 08 '20 at 08:08
  • Why are your users not happy with f2003? All currently developed compilers that support f95 also support f2003 and it essentially completely backwards compatible. What do your users dislike? – Ian Bush Aug 08 '20 at 08:24
  • 1
    F2003 is fully supported by gfortran 5.0 (released in 2017) and ifort 16.0 (released in 2015). Today we are in 2020. 2017 and 2015 are not early enough to make sure that everyone has updated their compilers to gfortan 5.0 or ifort 16.0. I do not want my code to crash on a machine that uses a system deployed in 2014. I would feel more assured about this in 2025, but not now. However, I am not an expert on Fortran or its compilers, so I may be wrong. Thanks for correcting me or convincing me that using F2003 is 100% safe now. – Nuno Aug 08 '20 at 08:34
  • In fact, I will be more than happy to hear that "No problem, F2003 has been supported everywhere. Just use it." It will make life a lot easier. :) – Nuno Aug 08 '20 at 08:44
  • Worrying about whether Version x.y.z of compiler P is Fortran Q compliant is the wrong thing. (Even ifort 19.1.2 released last month is not Fortran 2003 compliant.) Instead, 'do the compilers I want to support correctly implement the features I want to use?'. – francescalus Aug 08 '20 at 09:06
  • 1
    Thanks. Good point. I agree. But then I will need to guess what compilers (gfortran, ifort, nagfor, ...) the users are using. The reason that I want F90/95 is that almost all currently used compilers support them. I do not worry too much about machines that were deployed more than ten years ago, but I do care about those deployed five years ago --- I myself am using such a machine with Ubuntu 16.04 and gfortran 4.x. – Nuno Aug 08 '20 at 09:15
  • 1
    Everything will be simple if one is coding for a small group of people that he/she knows (e.g., him/herself). It is not the case here. We are coding a general-purpose library of certain numerical algorithms. Its audience is as broad as you can imagine. We do not know who will use it (you may say engineers/scientists will use it, but not more than that). Thanks. – Nuno Aug 08 '20 at 09:35
  • What do you mean 'undesirable'? Functors have been working this way since 195x. (See also the `EXTERNAL` keyword.) – Lorinczy Zsigmond Aug 08 '20 at 15:01
  • 2
    This is purely subjective. I prefer that every subroutine is contained in a module, and then use that module to access the subroutine. Thanks. – Nuno Aug 08 '20 at 15:37
  • 1
    @LorinczyZsigmond This is not just subjective, there are many good reasons to avoid implicit interfaces. – Vladimir F Героям слава Aug 11 '20 at 09:23
  • Procedure pointers make passing subroutines as arguments very convenient. It's not F95 though. – Christoph90 Aug 14 '20 at 17:06

0 Answers0