在模块中使用外部函数

Ast*_*ist 2 fortran gfortran

我正在用 Fortran 编写一个 n 维数值求解器。我为此创建了一个从主程序调用的模块。我external在为一阶 ode 编写时用于调用未知函数。但是,在使用多维复制结果时,external出现以下错误

Error: EXTERNAL attribute conflicts with DIMENSION attribute in 'f_x' 
Run Code Online (Sandbox Code Playgroud)

这意味着我的编译器无法处理带有数组输出的外部函数。

我尝试使用接口块来预定义具有固定维度的函数参数,但最终出现此错误

Error: PROCEDURE attribute conflicts with INTENT attribute in 'f_x' 
Run Code Online (Sandbox Code Playgroud)

Fortran 中是否有任何方法可以让外部函数返回使用子例程中的虚拟函数初始化的数组。

这是我使用的代码。

module int_adaptive
implicit none
contains

subroutine RK4nd(f_x, norder, nvar, x_0, t_0, t_f, x_out, t_out)
    INTERFACE
        FUNCTION f_x (x_0, t_0)
            integer, parameter  :: dp=kind(0.d0)
            REAL(dp), INTENT(IN)    :: x_0(2, 3), t_0
            REAL, intent(out)   :: f_x(2,3)
        END FUNCTION f_x
    END INTERFACE


    integer, parameter  :: dp=kind(0.d0)
    integer             :: norder, i, nvar
    external            :: f_x
    real(dp), intent(in):: x_0(norder, nvar), t_0, t_f
    real(dp)            :: x_out(norder, nvar), t_out, k1(norder, nvar), y1(norder, nvar), y(norder, nvar)
    real(dp)            :: k2(norder, nvar), k3(norder, nvar), k4(norder, nvar),&
                           y2(norder, nvar), y3(norder, nvar), y4(norder, nvar)!, f_x(norder, nvar)
    real(dp)            :: h_min, h_0, h_max, tol, err_est, h, t

    if (h_0<h) then
        h = h_0
    end if
    if ((t_f - t_0) < 0.0) then
        h = -h
    end if
    t = t_0
    y = x_0

    do while (t .NE. t_f)
        k1 = f_x(y, t)
        y1 = y + k1*h/2.0

        k2 = f_x(y1, t+h/2.0)
        y2 = y + k2*h/2.0

        k3 = f_x(y2, t+h/2.0)
        y3 = y + k3*h

        k4 = f_x(y3, t+h)
        y4 = y + (k1+ 2*k2 + 2*k3 +k4)*h/6.0

        t = t + h
        y = y4

    end do

    x_out = y
    t_out = t

end subroutine
end module
Run Code Online (Sandbox Code Playgroud)

我可以在模块内定义一个具有固定功能输入的标准积分器并直接按名称调用它,但是由于我处理各种订单的 ODE,因此每次更改订单时都会很复杂,我也需要更新此模块.

fra*_*lus 5

你在这里有两个不同的问题。

第一个是,你该函数的显式接口的规格f_x不正确:函数的结果f_x不得有intent(out)属性。这涵盖了第二条错误消息。

第一条错误信息与后面的使用有关

external f_x
Run Code Online (Sandbox Code Playgroud)

这个external语句给出f_xexternal属性。这很好,因为虚拟过程是一个外部函数。但是,您还为该过程提供了带有(现已更正)接口块的显式接口。此接口块还声明该过程具有该external属性。

这样做,你违反了一个约束,即一个实体不能在一个作用域块中被明确赋予两次相同的属性。要解决此问题,您应该删除其中一项规范。因为函数返回一个数组结果,它的接口在它被引用的子程序中必须是显式的,所以必须保留接口块。也就是说,删除external语句。

为清楚起见,您还应该删除注释掉的real(dp) f_x(norder, nvar)声明。这样的声明对于函数来说是错误的。