【问题标题】:Interfaces not matching in Fortran 90Fortran 90 中的接口不匹配
【发布时间】:2018-03-20 12:33:10
【问题描述】:

我很难理解 Fortran 接口。粘贴在问题末尾的测试代码在 ifort

In file test.f90:79

 call rk4(y, dydx, x, h, yout1, der, pars,*10)
                                1
Error: Interface of actual procedure does not match interface of dummy procedure at (1)
In file test.f90:81

 call rk4(y, dydx, x, h/2.d0, yout2, der, pars,*10)
                                     1
Error: Interface of actual procedure does not match interface of dummy procedure at (1)
In file test.f90:85

 call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10)
                                                 1
Error: Interface of actual procedure does not match interface of dummy procedure at (1)

但我不确定我做错了什么......

module RK

implicit none

contains

SUBROUTINE rk4(y, dydx, x, h, yout, der, pars, *)
IMPLICIT NONE
integer, parameter :: dp=kind(1.d0)
REAL(dp), DIMENSION(:), INTENT(IN) :: y,dydx,pars
REAL(dp), INTENT(IN) :: x,h
REAL(dp), DIMENSION(:), INTENT(OUT) :: yout
REAL(dp) :: h6,hh,xh
REAL(dp), DIMENSION(size(y)) :: dym,dyt,yt

INTERFACE
SUBROUTINE der(x,y,dydx,pars,*)
IMPLICIT NONE
integer, parameter :: dp=kind(1.d0)
REAL(dp), INTENT(IN) :: x
REAL(dp), DIMENSION(:), INTENT(IN) ::  pars
REAL(dp), DIMENSION(:), INTENT(IN) :: y
REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx
END SUBROUTINE der
END INTERFACE


hh = h*0.5d0
h6 = h/6.d0
xh = x + hh

yt(:)=y(:)+hh*dydx(:)

call der(xh, yt, dyt, pars,*10)

yt(:)=y(:)+hh*dyt(:)

call der(xh, yt, dym, pars,*10)

yt(:)=y(:)+h*dym(:)

dym(:)=dyt(:)+dym(:)

call der(x+h, yt, dyt, pars,*10)

yout(:)=y(:)+h6*(dydx(:)+dyt(:)+2.d0*dym(:))  

return
10 return 1


end subroutine


subroutine adaptive_RK4(y,dydx,x,h,yout2,yerr,der,pars,*)
implicit none
integer, parameter :: dp=kind(1.d0)
REAL (dp) :: h, x
REAL (dp), DIMENSION (:) ::  y, dydx, yout2, yerr, pars
REAL (dp), DIMENSION (size(y)) :: dydx2, yout1
intent(in) :: y, dydx, x, h, pars
intent(out) :: yout2, yerr
INTERFACE
SUBROUTINE der(x,y,dydx,pars,*)
IMPLICIT NONE
integer, parameter :: dp=kind(1.d0)
REAL(dp), INTENT(IN) :: x
REAL(dp), DIMENSION(:), INTENT(IN) :: pars
REAL(dp), DIMENSION(:), INTENT(IN) :: y
REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx
END SUBROUTINE der
END INTERFACE


call rk4(y, dydx, x, h, yout1, der, pars,*10)

call rk4(y, dydx, x, h/2.d0, yout2, der, pars,*10)

call der(x+h/2.d0, yout2, dydx2, pars,*10)  

call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10)

yerr(:)=yout2(:)-yout1(:)

yout2(:)=(16.d0*yout2(:)-yout1(:))/15.d0

return

10 return 1

end subroutine

end module

module derivative
implicit none
contains
    SUBROUTINE derr(x,y,dydx,pars,*)
    IMPLICIT NONE
integer, parameter :: dp=kind(1.d0)
    REAL(dp), INTENT(IN) :: x
    REAL(dp), DIMENSION(:), INTENT(IN) :: pars
    REAL(dp), DIMENSION(:), INTENT(IN) :: y
    REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx


dydx=(pars+y)*x
return 

END SUBROUTINE derr

end module

program test
use rk
use derivative
implicit none
integer, parameter :: dp=kind(1.d0)
real(dp), dimension(2) :: y,pars,dydx, yout, yerr
real(dp) :: x

y=(/0.1d0,2.d0/)
pars=(/0.7d0,3.d0/)
x=2.1d0

call derr(x,y,dydx,pars,*10)

write(*,*) dydx
call adaptive_RK4(y,dydx,x,0.0001d0,yout,yerr,derr,pars,*10)

stop
10 write(*,*) "some error"

end program

【问题讨论】:

  • 欢迎。请务必接受欢迎tour。对所有 Fortran 问题使用标签 fortran。您可以为特定版本的问题添加特定的版本标签,但请注意 Fortran 90 是一个旧的和过时的版本,通常您不希望受到限制。
  • 请使用一些缩进(每行开头的空格)。您的代码很难阅读。我们看不到结构。
  • 而且 OMG 现在停止使用备用返回功能 (stackoverflow.com/questions/7835270/…),相信我们,这是一条通往地狱的道路。
  • 请注意子程序derderr 甚至不使用备用返回。我认为没有理由仅仅因为参数存在就需要实际使用备用返回,但它可能会弄乱编译器。

标签: fortran


【解决方案1】:

代码在 gfortran 版本 6 和 7 中运行良好。

Gfortran 4.8 版崩溃,但这是编译器的问题。即使代码很糟糕,编译器也不应该崩溃。

英特尔 Fortran 也是如此。如果它在编译期间崩溃,那是编译器的错。

现在,代码确实不是很好,并且使用了编译器可能难以使用的功能。当涉及违反标准的事情时,gfortran 6 抱怨:

interface2.f90:81:9:

 call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10)
         1
Warning: Same actual argument associated with INTENT(IN) argument ‘y’ and INTENT(OUT) argument ‘yout’ at (1)

Fortran 不允许以这种方式将相同的变量传递给参数。编译器将假定intent(in) 参数永远不会改变,但是当您修改yout 时它确实会改变。这可能会导致严重的问题。

对于G95编译时错误,我认为是编译器错误,错误信息是假的。 rk4adaptive_rk4中的接口块完全一样。

我强烈建议您清理代码,摆脱备用退出功能,编译器编译代码会容易得多。我想这是由于您过度使用了未经过太多测试的备用返回功能。


对于您的下一个问题,请务必仔细阅读 [mcve]。有必要使您的代码短得多,以应对您未来的问题。这是您应该询问的实际 MCVE,可以用作错误报告的基础:

module m

  implicit none

contains

  subroutine a(d)
    interface
      subroutine d(*)
      end subroutine d
    end interface

    10 return 1
  end subroutine


  subroutine b(d)
    interface
      subroutine d(*)
      end subroutine d
    end interface

    call a(d)
  end subroutine
end module

将其与您提供给我们的很长的代码进行比较。如果没有编译器崩溃消失(ifort 17 和 gcc 4.8),这将无法真正减少。问题显然出在虚拟过程中(即使它实际上并没有在任何地方调用),它使用了备用返回功能,编译器无法正确处理它。

【讨论】:

  • 谢谢!我没有注意到 intent(out) 属性的问题,事后看来,这确实解释了代码编译时在该行发生的其他一些奇怪的事情。对过时的功能/长代码感到抱歉,我以后会记住的
【解决方案2】:

我替换了来自DERR / DER实例的备用返回,然后编译在英特尔Fortran(XE 2017)中工作。 我也同意建议 (1) 清理代码和 (2) 避免使用备用返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    相关资源
    最近更新 更多