简体   繁体   English

将回调函数与 f2py 一起使用时出错

[英]Error when using callback function with f2py

I'm trying to pass a python function to a f2py generated function.我正在尝试将 python 函数传递给 f2py 生成的函数。 I can not figure out how to do this when the python function's input and output is an array.当 python 函数的输入和输出是一个数组时,我无法弄清楚如何做到这一点。 (I'm new to f2py!) (我是 f2py 的新手!)

Here is my fortran code (num_Dg.f):这是我的 Fortran 代码(num_Dg.f):

     subroutine num_Dg(func,U,jacob,n)
        double precision, intent(in) :: U(n)
        double precision, intent(out) :: jacob(n,n)
        double precision Up(n), Um(n)
        double precision g_valp(n),g_valm(n)
        double precision :: rel_eps = 2.e-5
        double precision eps
        integer i, j
        external func

        eps = minval(U)*rel_eps

        do j=1,n
          do i=1,n
            if (i .eq. j) then
            Up(i) = U(i)+(eps)
            Um(i) = U(i)-(eps)
            else
            Up(i) = 0
            Um(i) = 0
            endif
          enddo
          call func(Up,g_valp,n)
          call func(Um,g_valm,n)
          do i=1,n
            jacob(i,j) = 0.0
            jacob(i,j) = (g_valp(i)-g_valm(i))/(2*eps)
          enddo
        enddo
      end subroutine

I use f2py to compile: f2py -c num_Dg.f -m num_Dg .我使用 f2py 编译: f2py -c num_Dg.f -m num_Dg It compiles without errors.它编译没有错误。 But when import the function into python I get this:但是当将函数导入 python 时,我得到了这个:

>>> from num_Dg import num_dg
>>> print(num_dg.__doc__)
jacob = num_dg(func,u,[n,func_extra_args])

Wrapper for ``num_dg``.

Parameters
----------
func : call-back function
u : input rank-1 array('d') with bounds (n)

Other Parameters
----------------
func_extra_args : input tuple, optional
    Default: ()
n : input int, optional
    Default: len(u)

Returns
-------
jacob : rank-2 array('d') with bounds (n,n)

Notes
-----
Call-back functions::

  def func(up,gvalp,[n]): return 
  Required arguments:
    up : input rank-1 array('d') with bounds (n)
    gvalp : input rank-1 array('d') with bounds (n)
  Optional arguments:
    n : input int, optional
    Default: len(up)

There is a problem with the callback function func .回调函数func有问题。 The input should be array U , and the output should be gval .输入应该是数组U ,输出应该是gval Instead, both U and gval are inputs, with no output.相反, Ugval都是输入,没有输出。

I'm assuming this is why the following python script returns garbage:我假设这就是以下 python 脚本返回垃圾的原因:

import num_Dg

def func(x):
    return [x[0]**2,x[1],x[2]]

val = [0.2,0.1,0.1]

num_Dg.num_dg(func,val)

How should I change my fortran subroutine so that the callback function works properly?我应该如何更改我的 fortran 子例程,以便回调函数正常工作? Any advice is appreciated!任何建议表示赞赏! Thanks!谢谢!

I ended up figuring it out.我终于弄清楚了。 I think the reason why it wasn't working was because I was missing the line cf2py intent(out), depend(n) :: g_valp .我认为它不起作用的原因是因为我错过了cf2py intent(out), depend(n) :: g_valp The script can be compiled in the normal way with f2py: f2py -c num_Dg.f -m num_Dg可以使用 f2py 以正常方式编译脚本: f2py -c num_Dg.f -m num_Dg

      subroutine num_Dg(U,jacob,n)
cf2py   intent(callback) func
        external func
        integer n
        double precision :: U(n)
        double precision :: jacob(n,n)
        double precision Up(n), Um(n)
        double precision g_valp(n),g_valm(n)
        double precision :: rel_eps = 2.e-5
        double precision eps
        integer i, j

cf2py   intent(in,copy), depend(n) :: U
cf2py   intent(hide) :: n
cf2py   intent(out), depend(n) :: jacob
cf2py   intent(out), depend(n) :: g_valp

        eps = minval(U)*rel_eps
        do j=1,n
          do i=1,n
            if (i .eq. j) then
            Up(i) = U(i)+(eps)
            Um(i) = U(i)-(eps)
            else
            Up(i) = 0
            Um(i) = 0
            endif
          enddo

          call func(n,Up,g_valp)
          call func(n,Um,g_valm)

          do i=1,n
            jacob(i,j) = (g_valp(i)-g_valm(i))/(2*eps)

          enddo

        enddo
      end subroutine

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM