0

我想编写一个 Fortran 子程序,它接受另一个子程序的名称作为参数——假设第一个子程序是 PDE 求解器,而第二个子程序提供 PDE 的右侧。请注意,第二个子程序可能由其他人实现,因此我们可能对它一无所知,除了它的签名。

这可以使用抽象接口和过程语句来实现。例如,参见 https://github.com/jacobwilliams/PowellOpt/blob/master/src/newuoa.f90

当然也可以使用外部函数: http: //malayamaarutham.blogspot.com/2006/02/passing-function-names-as-arguments-in.html

但是,抽象接口和过程语句仅在 Fortran 2003 之后可用,而外部函数则不可取。这是我的第一个问题

是否可以在不使用抽象接口和过程语句或外部函数的情况下在 Fortran 90/95 中将子例程名称作为参数传递?

一开始我的答案似乎是否定的,因为我看到了这个讨论: http ://computer-programming-forum.com/49-fortran/dba58f497a8dc996.htm

幸运的是,经过更多研究,根据 Fortran |等来源,我发现可以通过普通接口(不是抽象接口)实现。在其他函数中将函数作为参数传递如何在 Fortran 中将子例程名称作为参数传递?, https://www.tek-tips.com/viewthread.cfm?qid=1572869

我实现了以下代码作为最小的工作示例。我的第二个问题是:

以下代码符合 Fortran 90/95 标准吗?

我尝试使用 gfortran、ifort 和 g95 编译代码。前两个编译器很高兴,但是 g95 提出了一个警告:

use fun_mod, only : fun
                    1
Warning (102): MODULE PROCEDURE 'fun' USEd at (1) is not referenced

当我执行

g95 -Wall -Wextra -std=f95 -pedantic main.f90

生成的可执行文件没有任何问题,但为什么会出现这个警告?这是g95的bug吗?如果没有,如何摆脱这个警告?对代码的任何其他评论/批评也将受到高度赞赏。

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

请注意,在这段代码中,我们需要在每个接收 FUN 作为参数的子程序中为 FUN 编写一个接口块。如果我有很多这样的子例程,那将是乏味的。这激发了我的第三个问题

是否可以将 FUN 的接口封装在一个模块中,并使用该模块分配接口块?(我试过但没有成功。)

非常感谢!

编辑:正如@Ian Bush 和@francescalus 所指出的,也许我应该接受使用抽象接口和过程语句,检查用户的编译器是否实现了F2003 的这种功能。那么第四个问题来了:

实现抽象接口和过程语句的常用 Fortran 编译器(gfortran、ifort、nagfor、pgfortran ...)的最早版本是什么?

我知道我应该自己检查文档——我会的。我把这个问题放在这里,以防有人知道答案。稍后我将编辑问题以包含答案,以防其他人正在寻找相同的东西。谢谢。

回答第四个问题:

4

0 回答 0