使用函数作为参数——如何调用?
Using functions as arguments - how to call?
我有以下代码,我从一个子例程调用一个函数,它们都在同一个模块中:
module mymodule
implicit none
contains
subroutine mycode
real :: y0(3), a = 0.0, b = 1.0
integer :: i, N = 10
real, allocatable :: y(:,:)
y0(:) = [1.0, 1.0, 1.0]
y = AB2(od, a, b, N, y0)
do i = 1, N
print *, y(:,i)
end do
end subroutine mycode
function AB2(f, a, b, N, y0)
real, allocatable :: AB2(:,:)
interface
function f(x, y)
real, allocatable :: f(:)
real, intent(in) :: x, y(:)
end function
end interface
real, intent(in) :: a, b
integer, intent(in) :: N
real, intent(in) :: y0(:)
real :: xn0, xn1, step
real, allocatable :: yn0(:), yn1(:)
integer :: i
allocate(AB2(size(y0),N))
step = (b-a)/(N-1)
AB2(:,1) = y0
AB2(:,2) = y0 + step*f(a, y0)
do i = 3, N
xn0 = a+(i-2)*step
xn1 = a+(i-1)*step
yn0 = AB2(:,i-2)
yn1 = AB2(:,i-1)
AB2(:,i) = AB2(:,i-1) + step*(3.0/2.0*f(xn1,yn1)
& -0.5*f(xn0,yn0))
end do
end function
function od(x, y)
real, allocatable :: od(:)
real, intent(in) :: x, y(:)
allocate(od(3))
od(1) = x + y(1)
od(2) = -y(3) - y(2) - x
od(3) = x - y(1) + y(3)
end function
end module mymodule
如果我想给函数 od 另一个参数,比如说 c,我必须把它包含在这一行
real, intent(in) :: x, c, y(:)
还有
function od(x,c,y)
但是,我应该在哪里提供这个参数的值呢?调用中没有选项
y = AB2(od, a, b, N, y0)
此答案不会尝试重复 Fortran minimization of a function with additional arguments Passing external function of multiple variables as a function of one variable in Fortran or 的答案,而是在非常基本的层面上介绍问题。
假设您有一个函数 AB2
和另一个小函数 od
。
它们的使用方式是 AB2
接受 od
作为参数,因此您调用
y = AB2(od)
函数看起来像
real function AB2(f)
interface
real function f(x)
real x
end function
end interface
... call f(x) here ...
end function
real function od(x)
real x
end function
您需要将额外的数据 c
传递给 od
。怎么做?
您不能仅通过为 c
添加参数来更改 od
而保持 AB2
不变。 AB2
包含参数 f
和 od(x,c)
与 f(x)
不兼容的接口的描述。
此外,您将无法将数据传递给 AB2
。你肯定做不到
y = AB2(od(c))
通过执行 od(c)
您正在通过调用 od(x)
计算一个数字,然后您将尝试将此数字传递给 AB2
而不是应该传递的函数。
有几种方法可以缓解这种情况。它们在上面链接的答案中进行了描述。我将展示一种简单的可能性。
假设我们有函数 od(b,x)
,我们需要将 c
传递给 b
,但我们不知道如何使用我们的 AB2
.
real function od(b,x)
real b, x
end function
在我们的调用代码中,我们创建了一个包装函数,它为我们调用 od
和 c
。它可以是内部函数或模块函数。然后我们将 wrapper
传递给 AB2
.
subroutine caller(c)
y = AB2(wrapper)
contains
real function wrapper(x)
real x
!we must be able to see c from here, by host association or by using a module
wrapper = od(c,x)
end function
end subroutine
我有以下代码,我从一个子例程调用一个函数,它们都在同一个模块中:
module mymodule
implicit none
contains
subroutine mycode
real :: y0(3), a = 0.0, b = 1.0
integer :: i, N = 10
real, allocatable :: y(:,:)
y0(:) = [1.0, 1.0, 1.0]
y = AB2(od, a, b, N, y0)
do i = 1, N
print *, y(:,i)
end do
end subroutine mycode
function AB2(f, a, b, N, y0)
real, allocatable :: AB2(:,:)
interface
function f(x, y)
real, allocatable :: f(:)
real, intent(in) :: x, y(:)
end function
end interface
real, intent(in) :: a, b
integer, intent(in) :: N
real, intent(in) :: y0(:)
real :: xn0, xn1, step
real, allocatable :: yn0(:), yn1(:)
integer :: i
allocate(AB2(size(y0),N))
step = (b-a)/(N-1)
AB2(:,1) = y0
AB2(:,2) = y0 + step*f(a, y0)
do i = 3, N
xn0 = a+(i-2)*step
xn1 = a+(i-1)*step
yn0 = AB2(:,i-2)
yn1 = AB2(:,i-1)
AB2(:,i) = AB2(:,i-1) + step*(3.0/2.0*f(xn1,yn1)
& -0.5*f(xn0,yn0))
end do
end function
function od(x, y)
real, allocatable :: od(:)
real, intent(in) :: x, y(:)
allocate(od(3))
od(1) = x + y(1)
od(2) = -y(3) - y(2) - x
od(3) = x - y(1) + y(3)
end function
end module mymodule
如果我想给函数 od 另一个参数,比如说 c,我必须把它包含在这一行
real, intent(in) :: x, c, y(:)
还有
function od(x,c,y)
但是,我应该在哪里提供这个参数的值呢?调用中没有选项
y = AB2(od, a, b, N, y0)
此答案不会尝试重复 Fortran minimization of a function with additional arguments Passing external function of multiple variables as a function of one variable in Fortran or
假设您有一个函数 AB2
和另一个小函数 od
。
它们的使用方式是 AB2
接受 od
作为参数,因此您调用
y = AB2(od)
函数看起来像
real function AB2(f)
interface
real function f(x)
real x
end function
end interface
... call f(x) here ...
end function
real function od(x)
real x
end function
您需要将额外的数据 c
传递给 od
。怎么做?
您不能仅通过为 c
添加参数来更改 od
而保持 AB2
不变。 AB2
包含参数 f
和 od(x,c)
与 f(x)
不兼容的接口的描述。
此外,您将无法将数据传递给 AB2
。你肯定做不到
y = AB2(od(c))
通过执行 od(c)
您正在通过调用 od(x)
计算一个数字,然后您将尝试将此数字传递给 AB2
而不是应该传递的函数。
有几种方法可以缓解这种情况。它们在上面链接的答案中进行了描述。我将展示一种简单的可能性。
假设我们有函数 od(b,x)
,我们需要将 c
传递给 b
,但我们不知道如何使用我们的 AB2
.
real function od(b,x)
real b, x
end function
在我们的调用代码中,我们创建了一个包装函数,它为我们调用 od
和 c
。它可以是内部函数或模块函数。然后我们将 wrapper
传递给 AB2
.
subroutine caller(c)
y = AB2(wrapper)
contains
real function wrapper(x)
real x
!we must be able to see c from here, by host association or by using a module
wrapper = od(c,x)
end function
end subroutine