如何使用子程序的一个输出作为函数?

时间:2016-11-27 21:49:12

标签: function pointers fortran assign subroutine

我在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相同的错误消息

那么,我该怎么做呢?

1 个答案:

答案 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

该函数返回f1test_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中捆绑在一起的结果。