【问题标题】:Function in fortran, passing array in, receiving array outfortran中的函数,传入数组,接收数组
【发布时间】:2014-08-01 22:18:50
【问题描述】:

我有这个功能,如下图所示。它传入两个向量,每个向量具有三个值,并且应该传递一个具有三个值的向量。我这样调用函数:

Fr       = Flux(W(:,i),W(:,i+1))

我通过弄乱代码、尝试纯函数和模块以及研究错误语句(我将在底部包含)意识到的是,fortran 正在读取我的函数 Flux,并认为输入向量是尝试从数组中调用一个条目。这是我对正在发生的事情的最佳猜测。我在实验室里四处询问,大多数人建议使用子程序,但这似乎很笨拙,我想应该有更优雅的方法,但我还没有找到。我试图通过以下方式定义结果:

 DOUBLE PRECISION FUNCTION Flux(W1,W2) Result(FluxArray(3))

然后返回fluxarray,但这不起作用,因为fortran无法理解语法

实际功能是这样的:

DOUBLE PRECISION FUNCTION Flux(W1,W2)
USE parameters
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(3), INTENT(IN)::W1, W2
DOUBLE PRECISION, DIMENSION(3), INTENT(OUT):: Flux
DOUBLE PRECISION, DIMENSION(3):: F1, F2
DOUBLE PRECISION::U1,U2,Rh1,Rh2,P1,P2,E1,E2,Rh,P,u,c,Lambda
INTEGER:: k
U1=W1(2)/W1(1)
U2=W2(2)/W2(1)

Rh1=W1(1)
Rh2=W2(1)

P1=(gamma_constant-1.d0)*(W1(3)-.5d0*Rh1*U1**2)
P2=(gamma_constant-1.d0)*(W2(3)-.5d0*Rh2*U2**2)

E1=W1(3)
E2=W2(3)

F1=[Rh1*U1,Rh1*U1**2+P1,(E1+P1)*U1]
F2=[Rh2*U2,Rh2*U2**2+P2,(E2+P2)*U2]

Rh=.5d0*(Rh1+Rh2)
P=.5d0*(P1+P2)
u=.5d0*(U1+U2)
c=sqrt(gamma_constant*P/Rh)

Lambda=max(u, u+c, u-c)
do k=1,3,1
    Flux(k)=.5d0*(F1(k)+F2(k))-.5d0*eps*Lambda*(W2(k)-W1(k))
end do
RETURN
END FUNCTION Flux

这是错误声明:

Quasi1DEuler.f90:191.51:

DOUBLE PRECISION, DIMENSION(3), INTENT(OUT):: Flux
                                               1
Error: Symbol 'flux' at (1) already has basic type of REAL
Quasi1DEuler.f90:217.58:

Flux(k)=.5d0*(F1(k)+F2(k))-.5d0*eps*Lambda*(W2(k)-W1(k))
                                                      1
Error: Unexpected STATEMENT FUNCTION statement at (1)
Quasi1DEuler.f90:76.18:

Fr      = Flux(W(:,i),W(:,i+1))

最后一个错误发生在 Fr 和 Fl 上。感谢您的宝贵时间以及您可以提供的任何帮助或考虑!

编辑/跟进:: 感谢您的帮助,我不知道有更好的方式来呈现这个,所以我将编辑最初的问题。

我按照你的建议做了,它解决了这个问题,现在它说:

Fr      = Flux(W(:,i),W(:,i+1))
         1
Error: The reference to function 'flux' at (1) either needs an explicit INTERFACE or the rank is incorrect  

我在这个链接上看到了类似的问题:

Computing the cross product of two vectors in Fortran 90

他们建议他将所有功能放入模块中。有没有更好/更简单的方法来修复这个错误?

【问题讨论】:

  • 这是我在回复该帖子时尝试的第一件事,但没有成功。如果我没有在上面说清楚,我很抱歉,但是我尝试使用 FluxArray 作为结果,同时分别声明类型和特征,但仍然收到错误

标签: fortran fortran90


【解决方案1】:

对于RESULT(FluxArray)fluxArray结果变量名称。因此,您在结果子句中声明特征的尝试是错误的。

相反,结果变量应该在函数体中指定:

function Flux(W1,W2) result(fluxArray)
  double precision, dimension(3), intent(in)::W1, W2
  double precision, dimension(3) :: fluxArray  ! Note, no intent for result.
end function Flux

是的,可以在function 语句中声明结果变量的类型,但不能在那里声明数组属性。我不建议在结果变量的函数体中使用不同的 dimension 语句。

请注意,当引用返回数组的函数时,调用者需要有一个显式接口。一种方法是将函数放在used 的模块中。有关更多详细信息,请参阅 SO 或语言教程的其他地方。

在没有result 的情况下解决您的问题中的错误。

DOUBLE PRECISION FUNCTION Flux(W1,W2)
  DOUBLE PRECISION, DIMENSION(3), INTENT(OUT):: Flux

这里Flux 的类型被声明了两次。此外,它不是函数的虚拟参数,因此与上面一样,它不需要具有intent 属性。

可以写

FUNCTION Flux(W1,W2)
  DOUBLE PRECISION, DIMENSION(3) :: Flux  ! Deleting intent

或(颤抖)

DOUBLE PRECISION FUNCTION Flux(W1,W2)
  DIMENSION :: Flux(3)

关于声明函数的抱怨在这里并不重要,继错误声明之后。

【讨论】:

  • 谢谢!我按照你的建议做了,它解决了这个问题,现在它说: Fr = Flux(W(:,i),W(:,i+1)) 1 Error: The reference to function 'flux' at (1) 要么需要明确的 INTERFACE 或排名不正确 我在此链接上看到了类似的问题:stackoverflow.com/questions/6511711/… 他们建议他将所有功能放入模块中。有没有更好的方法来解决这个错误?
  • 确实如此。返回一个数组意味着需要一个显式接口,而模块是解决这个问题的好方法。查看我的更新。
猜你喜欢
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 2013-12-16
  • 2015-02-28
相关资源
最近更新 更多