我在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
所以基本上这个程序创建测试函数(使用子程序)然后分离出来。函数separates2工作正常,所以我决定向前迈出一步,并在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相同的错误消息
那么,我该怎么做呢?
答案 0 :(得分:0)
子程序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
该函数返回f1
中test_func
伪参数的值。如果您想要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
中捆绑在一起的结果。