如何将子例程的输出之一用作函数?
How to use one of the outputs of a subroutine as a function?
我在 Fortran 中工作,我试图将子例程的输出之一用作函数并对其进行操作,但我不知道如何正确地进行操作。这是我正在尝试做的测试程序
module funciones
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none
type ptr_wrapper
procedure(f), nopass, pointer :: func
end type ptr_wrapper
abstract interface
function f(x1,x2)
import
real(dp), intent(in) :: x1,x2
real(dp) :: f
end function f
end interface
abstract interface
subroutine g(x,y,f1,f2)
import
real(dp), intent(in) :: x,y
real(dp), intent(out) :: f1,f2
end subroutine g
end interface
contains
subroutine test_func(x,y,f1,f2)
real(dp), intent(in) :: x,y
real(dp), intent(out) :: f1,f2
f1 = x*y
f2 = 2d0*x+5d0*y
end subroutine test_func
function Derivate (x,y,fx) result (d)
implicit none
real(dp), intent(in) :: x,y
procedure(f), pointer :: fx
real(dp) :: d
real(dp) :: h = 1.0E-6
d = (1.0*fx(x-2*h,y) - 8.0*fx(x-h,y) + 8.0*fx(x+h,y) - 1.0*fx(x+2*h,y))/(12.0*h)
end function Derivate
function separation1(x,y,F_in) result(DF_out1)
implicit none
real(dp), intent(in) :: x,y
procedure(g) :: F_in
real(dp) :: F_out1, F_out2
real(dp) :: DF_out1
procedure (f), pointer:: F1_ptr
Call F_in (x,y,F_out1,F_out2)
F1_ptr => F_out1
DF_out1 = Derivate(x,y,F1_ptr)
end function separation1
function separation2(x,y,F_in) result(F_out2)
implicit none
real(dp), intent(in) :: x,y
procedure(g) :: F_in
real(dp) :: F_out1, F_out2
Call F_in (x,y,F_out1,F_out2)
end function separation2
end module funciones
program testsubroutines
use, intrinsic :: iso_fortran_env, only: dp => real64
use funciones
implicit none
print*, separation1(1d0,3d0,test_func)
print*, separation2(1d0,3d0,test_func)
end program testsubroutines
所以基本上这个程序创建测试功能(使用子例程)然后分离出来。函数 separate2 工作正常,所以我决定向前迈出一步,在 separate1 中实现派生它的函数。但是我不知道如何将指针分配给 out 并且我总是在该行中遇到错误。
我也试过创建两个指针
F1_ptr,F2_ptr
并将它们分配为
(F1_ptr,F2_ptr)=>Call F_in(x,y,F_out1,F_out2)
但我明白了
Error : Unclassifiable assignment at (1).
如果我赋值为
F1_ptr => F_out1
我收到错误消息
Error: Invalid procedure pointer assignment at (1)
或者如果我这样做
F1_ptr %func => Call F_in (x,y,F_out1,F_out2)
1
Error: Invalid character in name at (1)
和
DF_out1 = Derivate(x,y,F1_ptr)
1
Error: Type mismatch in argument ‘fx’ at (1); passed TYPE(ptr_wrapper) to REAL(8)
我也尝试了这两个变化
...
abstract interface
subroutine g(x,y,f1,f2)
import
real(dp), intent(in) :: x,y
procedure(f),pointer :: f1,f2
end subroutine g
end interface
contains
subroutine test_func(x,y,f1,f2)
real(dp), intent(in) :: x,y
type (ptr_wrapper) :: f1,f2
f1%func => x*y
f2%func => 2d0*x+5d0*y
...
但我得到
f1%func => x*y
1
Error: Invalid procedure pointer assignment at (1)
和 f2
的相同错误消息
那么,我该怎么做呢?
子例程 test_func
有两个伪参数,让子例程报告两个 值,这些值是子例程内部某些计算的结果。
在 Fortran 中,值不是函数。
(这种区别在某些其他语言中是模糊的或消除的,但在 Fortran 中不是。)
在 Fortran 中,值是调用函数时可能产生的结果,但调用函数与函数本身之间存在差异。
我不清楚这个问题背后的意图,但是如果你想公开子程序 test_func
中的计算(顺便说一句 - 将 "func" 放在一个名称中子例程相当混乱)作为一个函数,那么您需要编写一个调用 test_func
的函数,将感兴趣的输出参数作为函数结果传回。这样的函数很简单,可以是这样的:
function get_f1_from_test_func(x, y) result(f1)
real(dp), intent(in) :: x
real(dp), intent(in) :: y
real(dp) :: f1
real(dp) :: ignored
call test_func(x, y, f1, ignored)
end function get_f1_from_test_func
该函数 returns test_func
中 f1
虚拟参数的值。如果您想要 f2
参数,请编写另一个函数。
function get_f2_from_test_func(x, y) result(f2)
real(dp), intent(in) :: x
real(dp), intent(in) :: y
real(dp) :: f2
real(dp) :: ignored
call test_func(x, y, ignored, f2)
end function get_f2_from_test_func
以上两个函数与Derivate的fx
伪参数要求的函数接口一致
如上述包装函数中局部变量的名称所示,当调用包装函数时,test_func
的输出伪参数之一的结果将被丢弃。这在计算上不太可能有效,但这种情况是在 test_func
.
中将两个计算捆绑在一起的结果
我在 Fortran 中工作,我试图将子例程的输出之一用作函数并对其进行操作,但我不知道如何正确地进行操作。这是我正在尝试做的测试程序
module funciones
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none
type ptr_wrapper
procedure(f), nopass, pointer :: func
end type ptr_wrapper
abstract interface
function f(x1,x2)
import
real(dp), intent(in) :: x1,x2
real(dp) :: f
end function f
end interface
abstract interface
subroutine g(x,y,f1,f2)
import
real(dp), intent(in) :: x,y
real(dp), intent(out) :: f1,f2
end subroutine g
end interface
contains
subroutine test_func(x,y,f1,f2)
real(dp), intent(in) :: x,y
real(dp), intent(out) :: f1,f2
f1 = x*y
f2 = 2d0*x+5d0*y
end subroutine test_func
function Derivate (x,y,fx) result (d)
implicit none
real(dp), intent(in) :: x,y
procedure(f), pointer :: fx
real(dp) :: d
real(dp) :: h = 1.0E-6
d = (1.0*fx(x-2*h,y) - 8.0*fx(x-h,y) + 8.0*fx(x+h,y) - 1.0*fx(x+2*h,y))/(12.0*h)
end function Derivate
function separation1(x,y,F_in) result(DF_out1)
implicit none
real(dp), intent(in) :: x,y
procedure(g) :: F_in
real(dp) :: F_out1, F_out2
real(dp) :: DF_out1
procedure (f), pointer:: F1_ptr
Call F_in (x,y,F_out1,F_out2)
F1_ptr => F_out1
DF_out1 = Derivate(x,y,F1_ptr)
end function separation1
function separation2(x,y,F_in) result(F_out2)
implicit none
real(dp), intent(in) :: x,y
procedure(g) :: F_in
real(dp) :: F_out1, F_out2
Call F_in (x,y,F_out1,F_out2)
end function separation2
end module funciones
program testsubroutines
use, intrinsic :: iso_fortran_env, only: dp => real64
use funciones
implicit none
print*, separation1(1d0,3d0,test_func)
print*, separation2(1d0,3d0,test_func)
end program testsubroutines
所以基本上这个程序创建测试功能(使用子例程)然后分离出来。函数 separate2 工作正常,所以我决定向前迈出一步,在 separate1 中实现派生它的函数。但是我不知道如何将指针分配给 out 并且我总是在该行中遇到错误。
我也试过创建两个指针
F1_ptr,F2_ptr
并将它们分配为
(F1_ptr,F2_ptr)=>Call F_in(x,y,F_out1,F_out2)
但我明白了
Error : Unclassifiable assignment at (1).
如果我赋值为
F1_ptr => F_out1
我收到错误消息
Error: Invalid procedure pointer assignment at (1)
或者如果我这样做
F1_ptr %func => Call F_in (x,y,F_out1,F_out2)
1
Error: Invalid character in name at (1)
和
DF_out1 = Derivate(x,y,F1_ptr)
1
Error: Type mismatch in argument ‘fx’ at (1); passed TYPE(ptr_wrapper) to REAL(8)
我也尝试了这两个变化
...
abstract interface
subroutine g(x,y,f1,f2)
import
real(dp), intent(in) :: x,y
procedure(f),pointer :: f1,f2
end subroutine g
end interface
contains
subroutine test_func(x,y,f1,f2)
real(dp), intent(in) :: x,y
type (ptr_wrapper) :: f1,f2
f1%func => x*y
f2%func => 2d0*x+5d0*y
...
但我得到
f1%func => x*y
1
Error: Invalid procedure pointer assignment at (1)
和 f2
的相同错误消息那么,我该怎么做呢?
子例程 test_func
有两个伪参数,让子例程报告两个 值,这些值是子例程内部某些计算的结果。
在 Fortran 中,值不是函数。
(这种区别在某些其他语言中是模糊的或消除的,但在 Fortran 中不是。)
在 Fortran 中,值是调用函数时可能产生的结果,但调用函数与函数本身之间存在差异。
我不清楚这个问题背后的意图,但是如果你想公开子程序 test_func
中的计算(顺便说一句 - 将 "func" 放在一个名称中子例程相当混乱)作为一个函数,那么您需要编写一个调用 test_func
的函数,将感兴趣的输出参数作为函数结果传回。这样的函数很简单,可以是这样的:
function get_f1_from_test_func(x, y) result(f1)
real(dp), intent(in) :: x
real(dp), intent(in) :: y
real(dp) :: f1
real(dp) :: ignored
call test_func(x, y, f1, ignored)
end function get_f1_from_test_func
该函数 returns test_func
中 f1
虚拟参数的值。如果您想要 f2
参数,请编写另一个函数。
function get_f2_from_test_func(x, y) result(f2)
real(dp), intent(in) :: x
real(dp), intent(in) :: y
real(dp) :: f2
real(dp) :: ignored
call test_func(x, y, ignored, f2)
end function get_f2_from_test_func
以上两个函数与Derivate的fx
伪参数要求的函数接口一致
如上述包装函数中局部变量的名称所示,当调用包装函数时,test_func
的输出伪参数之一的结果将被丢弃。这在计算上不太可能有效,但这种情况是在 test_func
.