Fortran传递语句功能

时间:2014-10-31 19:10:43

标签: function fortran

我希望传递一个语句函数来在另一个函数中进行求值,这可能吗?我正在尝试一个可以在数字上集成一般功能的功能。我真正的问题中还有其他值,所以我不想拥有外部函数。

编辑2014/11/1 02:22 GMT

@IanH输入的代码中有一些错误。这是在我处理错误后可以运行的代码。


program trapezoidZ
  implicit none

  ! main program global variables and constants here.

  call main
contains
subroutine main
    real :: u, integral1
    integer :: i
    integer, parameter :: n = 5000
    ! delete declaration of trapezoid_integration and f.

    integral1 = trapezoid_integration(TrigSin, n, 0., 3.14159 / 2.0)

    write (*,*) "I - Trap = ",1 - integral1
end subroutine main

function my_f(u)
    real :: my_f
    real, intent(in) :: u

    my_f = (u**4)*EXP(u)/((EXP(u)-1.0)**2)
end function my_f

function TrigSin(u) result(my_f)
    real :: my_f
    real, intent(in) :: u

    my_f = sin(u)
end function TrigSin

function trapezoid_integration (f, n, start_val, end_val) result (integral)
    ! delete declaration of integrand (assuming you have it).
    procedure(my_f) :: f

    integer :: n
    real :: start_val, end_val
    real :: integral,u,h
    integer :: i

    integral = 0.0

    do i=0,n
        u = start_val + ((end_val - start_val)*i)/n

        ! implement Eqn G.4
        if ((i.eq.0).or.(i.eq.n)) then
            integral = integral+integrand(f, u)
        else
            integral = integral+(2.0*integrand(f, u))
        end if

    end do

    h=(end_val - start_val)/n
    integral = (h/2.0)*integral

end function trapezoid_integration

function integrand(f, x) result (value)
    implicit none
    real :: x
    real :: value
    real :: f

    if (x .lt. 0.00001) then
        x = 0.00001
    end if

    value = f(x)
end function integrand

end program trapezoidZ

下面是原始代码。不要使用


<击>

<击>
program trapezoidZ
  implicit none
  integer, parameter :: n = 10
  real :: u, integral
  integer :: i
  real :: f, trapezoid_integration

  f(u) = (u**4)*EXP(u)/((EXP(u)-1.0)**2)

  integral = trapezoid_integration(f, n, 0.2, 3.0)
  write (*,*) '#trapezoidal integration = ',integral

end program trapezoidZ

function trapezoid_integration(f, n, start_val, end_val)
  implicit none
  integer :: n
  real :: start_val, end_val
  real :: f
  real :: integral,u,h
  integer :: i

  integral = 0.0

  do i=0,n
     u = start_val + ((end_val - start_val)*i)/n

     ! implement Eqn G.4
     if ((i.eq.0).or.(i.eq.n)) then
        integral = integral+integrand(f, u)
     else
        integral = integral+(2.0*integrand(f, u))
     end if

  end do

  h=(end_val - start_val)/n
  integral = (h/2.0)*integral

end subroutine trapezoid_integration

function integrand(f, x) result (value)
  implicit none
  real :: x
  real :: value
  real :: f

  if (x .lt. 0.00001) then
     x = 0.00001
  end if

  value = f(x)
end function integrand

<击>

2 个答案:

答案 0 :(得分:4)

标准Fortran中不允许 - 声明函数不在Fortran 2008中约束C1235的允许过程类型列表中。

但是,正如该约束所示,您不仅限于外部功能。从Fortran 90开始,实际参数可以是模块过程。从Fortran 2008开始,它可以是一个内部程序。

这提供了紧凑且更强大的来源的可能性:

program trapezoidZ
  implicit none

  ! main program global variables and constants here.

  call main
contains
  subroutine main
    real :: u, integral
    integer :: i
    integer, parameter :: n = 10
    ! delete declaration of trapezoid_integration and f.

    integral = trapezoid_integration(my_f, 0.2, 3.0)
    write (*,*) '#trapezoidal integration = ',integral
  end subroutine main

  function my_f(u)
    real :: my_f
    real, intent(in) :: u

    my_f = (u**4)*EXP(u)/((EXP(u)-1.0)**2)
  end function my_f

  function trapezoid_integration(f, n, start_val, end_val)
    ! delete declaration of integrand (assuming you have it).
    procedure(my_f) :: f
    ...
  end function trapezoid_integration

  function integrand(f, x) result (value)
    ...
  end function integrand
end program trapezoidZ

答案 1 :(得分:1)

我必须提交的2008标准草案第12.6.4.4段:

  

声明函数不应作为实际参数提供。

所以我认为你不能按照你想要的方式做你想做的事。我想知道当你试图编译上面的代码时你的编译器告诉你了什么。当我更正了您的帖子中function trapezoid_integrationend subroutine trapezoid_integration之间的不匹配时,我的编译器(最新版本的gfortran)抱怨,指出在调用f时使用了trapezoid_integration

  

错误:(1)中的语句功能'f'不允许作为实际   参数

它还抱怨其他几件事。它可能已经指出,但没有,自1990年标准以来,该陈述功能已经过时。

有多种方法可以修复程序,其中一种方法是将函数内部集成,即在程序中的contains部分内声明它。实际上,我将包含您在程序中的这一部分中显示的所有函数。在编写代码时,两个过程trapezoid_integrationintegrand都是外部的,编译器在调用它们时无法检查它们的接口。将f重写为函数,并在contains处插入end program并将end program移至源文件的末尾,然后整理剩余的错误。