【问题标题】:pass function as argument to subroutine using interface doesn't work in Plato Fortran 90使用接口将函数作为参数传递给子程序在 Plato Fortran 90 中不起作用
【发布时间】:2014-09-21 05:39:31
【问题描述】:

我创建了一个 fortran 90 程序,在 linux 机器上使用并使用 gfortran 编译。它在带有 gfortran 的 linux 机器上运行良好,但提供了错误

error 327 - In the INTERFACE to SECANTMETHOD (from MODULE SECMETH), the ninth dummy argument (F) was of type REAL(KIND=2) FUNCTION, whereas the actual argument is of type REAL(KIND=2)

使用 Plato 编译器 (FTN95) 时。有谁知道我需要如何更改我的代码才能在柏拉图工作?我试图阅读这个错误,并且提到了一些指针,但从我尝试的结果来看,它不起作用。我已经想出了一些解决方法,但是它们使子例程不再接受任何函数作为参数-这几乎没用。任何帮助将不胜感激。我的代码如下。

!--! A module to define a real number precision.
module types
  integer, parameter :: dp=selected_real_kind(15)
end module types

module secFuncs
  contains

  function colebrookWhite(T)
    use types

    real(dp) :: colebrookWhite
    real(dp), intent(in) :: T

    colebrookwhite=25-T**2

    return
  end function colebrookWhite
end module secFuncs

module secMeth
  contains

  subroutine secantMethod(xolder,xold,xnew,epsi1,epsi2,maxit,exitFlag,numit,f)
    use types
    use secFuncs
    implicit none

    interface
      function f(T)
        use types
        real(dp) :: f
        real(dp), intent(in) :: T
      end function f
    end interface

    real(dp), intent(in) :: epsi1, epsi2
    real(dp), intent(inout) :: xolder, xold
    real(dp), intent(out) :: xnew
    integer, intent(in) :: maxit
    integer, intent(out) :: numit, exitFlag
    real(dp) :: fxold, fxolder, fxnew
    integer :: i

    fxolder = f(xolder)
    fxold = f(xold)

    i = 0

    do
      i = i + 1

      xnew = xold - fxold*(xold-xolder)/(fxold-fxolder)

      fxnew = f(xnew)

      if (i == maxit) then
        exitFlag = 1
        numit = i
        return
      else if (abs(fxnew) < epsi1) then
        exitFlag = 2
        numit = i
        return
      else if (abs(xnew - xold) < epsi2) then
        exitFlag = 3
        numit = i
        return
      end if

      xolder = xold
      xold = xnew
      fxolder = fxold
      fxold = fxnew
    end do
  end subroutine secantMethod

end module secMeth

program secantRoots
  use types
  use secMeth
  use secFuncs
  implicit none

  real(dp) :: x1, x2, xfinal, epsi1, epsi2
  integer :: ioerror, maxit, numit, exitFlag

  do
    write(*,'(A)',advance="no")"Please enter two initial root estimates, 2epsi's, and maxit: "
    read(*,*,iostat=ioerror) x1, x2, epsi1, epsi2, maxit

    if (ioerror /= 0) then
      write(*,*)"Invalid input."
    else
      exit
    end if
  end do

  call secantMethod(x1,x2,xfinal,epsi1,epsi2,maxit,exitFlag,numit,colebrookWhite)

  if (exitFlag == 1) then
    write(*,*)"The maximum number of iterations was reached."
  else if (exitFlag == 2) then
    write(*,'(a,f5.3,a,i3,a)')"The root is ", xfinal, ", which was reached in ", numit, " iterations."
  else if (exitFlag == 3) then
    write(*,'(a,i3,a)')"There is slow or no progress at ", numit, " iterations."
  end if

end program secantRoots

【问题讨论】:

    标签: function fortran fortran90 subroutine plato


    【解决方案1】:

    当前 gfortran 在调用 secantMethod 过程中检测到错误,在该过程中,colebrookWhite 函数名后面有括号,但没有参数列表。

    如果您想将函数作为参数传递(而不是评估函数的结果),这就是您想要在此处执行的操作,则不要在函数名称后面加上括号对。

    call secantMethod(x1,x2,xfinal,epsi1,epsi2,maxit,exitFlag,numit,colebrookWhite )
    !                                                                             ^
    

    【讨论】:

    • 哎呀,我不是故意要包括那个 - 我实际上是在我尝试调试时添加的(我现在从原始帖子中删除了它)。没有括号,程序运行并要求我输入;当我输入输入时,当我收到错误“在需要过程时尝试使用参数号 9 作为实数(种类 = 2)调用例程”时,错误的详细信息是“SECMETH!SECANTMETHOD - 在文件 secantnew .f90 在第 19 行 [+00a4] SECANTROOTS - 在文件 secantnew.f90 的第 100 行 [+0274]”。任何想法为什么会发生此错误以及如何修复它以在柏拉图中工作?感谢您的帮助!
    【解决方案2】:

    我最终只是从 Plato 切换到 Geany IDE(实际上我更喜欢 Geany 方式,因为我已经使用了几个小时),使用 Geany 设置 gfortran,并且代码适用于该设置。我猜我得到 Plato 错误的原因是它的编译器实际上是一个 fortran95 编译器,而 gfortran 是一个 fortran90 编译器。让一切正常工作需要一段时间,但是一旦我为 gfortran 下载了 mingw-w64 并将路径用户(而不是系统)环境变量设置为正确的位置,一切都很好。我仍然有兴趣看看是否有办法让代码与 FTN95 编译器一起工作,但最后我仍然坚持使用 gfortran 和 Geany。

    【讨论】:

    • 请注意,gfortran 不仅仅是一个“Fortran 90”编译器,尽管它支持 Fortran 90。它还支持 Fortran 95、2003 和 2008 的部分版本。它还支持固定格式的 FORTRAN 77。
    猜你喜欢
    • 1970-01-01
    • 2015-12-09
    • 2015-06-03
    • 1970-01-01
    • 2015-03-22
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多