Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 在模块中使用外部函数_Fortran_Gfortran - Fatal编程技术网

Fortran 在模块中使用外部函数

Fortran 在模块中使用外部函数,fortran,gfortran,Fortran,Gfortran,我正在用Fortran编写一个n维数值解算器。我创建了一个模块,从主程序调用。当我为一阶ode编写代码时,我使用external调用未知函数。但是,在使用external复制多个维度的结果时,我得到以下错误 Error: EXTERNAL attribute conflicts with DIMENSION attribute in 'f_x' 这意味着我的编译器无法处理具有数组输出的外部函数 我尝试使用一个接口块来预定义具有固定维度的函数参数,结果出现了这个错误 Error: PROCED

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

Error: EXTERNAL attribute conflicts with DIMENSION attribute in 'f_x' 
这意味着我的编译器无法处理具有数组输出的外部函数

我尝试使用一个接口块来预定义具有固定维度的函数参数,结果出现了这个错误

Error: PROCEDURE attribute conflicts with INTENT attribute in 'f_x' 
在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
模块内部自适应
隐式无
包含
子程序RK4nd(f_x,norder,nvar,x_0,t_0,t_f,x_out,t_out)
接口
函数f_x(x_0,t_0)
整数,参数::dp=kind(0.d0)
真实(dp),意图(IN)::x_0(2,3),t_0
真实,意图(外)::f_x(2,3)
端函数f_x
端接口
整数,参数::dp=kind(0.d0)
整数::norder,i,nvar
外部::f_x
真实(dp),意图(in)::x_0(诺德,内华达州),t_0,t_f
真实(dp):x_out(诺德,nvar),t_out,k1(诺德,nvar),y1(诺德,nvar),y(诺德,nvar)
真实(dp):k2(诺德,nvar),k3(诺德,nvar),k4(诺德,nvar)&
y2(诺德,nvar),y3(诺德,nvar),y4(诺德,nvar)!,f_x(诺德,内华达州)
真实值(dp)::最小值,0,最大值,tol,误差,最大值,h,t

如果(h_0这里有两个明显的问题

首先,您对函数
f_x
的显式接口的规范是:函数结果
f_x
不得具有
intent(out)
属性。这包括第二条错误消息

第一条错误消息与以后使用

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

执行此操作时,您违反了一个约束,即一个实体在一个作用域块中不能两次显式赋予同一属性。若要解决此问题,您应该删除其中一个规范。由于函数返回数组结果,因此其接口必须在引用它的子例程中显式,因此必须删除接口块保留。即,删除
外部
语句


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

正如francescalus已经指出的那样,函数要么显式接口,要么声明为外部函数,而不是两者都声明。使用外部函数是老式的Fortran,因为函数接口是在Fortran 90中引入的,以取代外部函数的需要,而外部函数的需要是一个相当复杂的过程olete特性,对于向后兼容性仍然有效

此外,函数结果不能有INTENT属性。函数应该通过“自己的名称”返回结果,如
y=f_x(…)
。因此,您应该将
f_x
本身声明为REAL(无任何INTENT属性),或者,更好的做法是在函数声明及其接口中使用RESULT属性。在递归函数中,使用RESULT属性实际上是必要的,但即使函数不是递归的,也最好这样做。因此,函数的接口应编写为

INTERFACE
    FUNCTION f_x (x_0, t_0) RESULT(res)
        INTEGER, PARAMETER :: dp=kind(0.d0)
        REAL(kind=dp), DIMENSION(2,3), INTENT(IN) :: x_0
        REAL(kind=dp), INTENT(IN) :: t_0
        REAL, DIMENSION(2,3) :: res
    END FUNCTION f_x
END INTERFACE
在实际的
f_x
实现中,应使用
res
(或任何您想要调用结果的内容)作为保存此函数应返回的结果的变量


请注意,我还做了一些修改,这些修改不是严格必要的,但强烈推荐:声明
x0
,正如您所做的那样,
REAL(dp),INTENT(IN)::x0(2,3)
也是老式Fortran(引入维度属性是为了让事情更清楚)。此外,一些Fortran实现,特别是F标准,不接受
REAL(dp)
,需要
REAL(kind=dp)
取而代之。

我得到了删除外部块的要点,但正是意图部分起到了作用。没有编译器错误。需要对其进行测试。多谢洛蒂不会对首选
结果
的风格点发表评论,但有话要说。使用
结果
(不是属性)对于递归函数,接口块中不需要。函数结果的名称不是(函数结果或函数的)特征,由于没有引用函数而不是函数结果的可执行语句,因此不需要有不同的名称。实现需要有一种方法来区分它们,但实现中函数结果的名称和接口不需要匹配,@francescalus:根据F标准,即使对于非递归函数,使用
result
(对我来说,这似乎是一个函数属性,不管它是如何被正式调用的)也是必须的。在这种特殊情况下,可能需要使用
result
还有另一个原因:函数的实际结果是一个数组,一些编译器不接受
实维(2,3):f_x
。当然,接口中函数结果的名称与实际实现不需要匹配,因此可以在接口中使用
result(res)
result(foo)
在函数实现中。@Pap感谢您提供的信息,我们将详细了解结果,但我认为明确说明维度是您在