F2PY:将单元素数组传递给 Fortran

发布于 2024-08-20 01:21:10 字数 376 浏览 1 评论 0原文

以下 Fortran 代码用值 v 填充 2D 数组 x

      subroutine fill(x,v,m,n)
      real*8 x(m,n),v
      integer m,n,i
cf2py intent(in) :: x,v,m,n
      forall(i=1:m,j=1:n) x(i,j) = v
      end

当从 Python 调用此函数时:

x = numpy.array([[[0.0]]],order='F')
fill(x[:,:,0],2.0)
assert(x[0,0,0]==2.0) # Assertion failed

为什么此断言失败?

The following Fortran code fills a 2D array x with value v

      subroutine fill(x,v,m,n)
      real*8 x(m,n),v
      integer m,n,i
cf2py intent(in) :: x,v,m,n
      forall(i=1:m,j=1:n) x(i,j) = v
      end

When calling this function from Python:

x = numpy.array([[[0.0]]],order='F')
fill(x[:,:,0],2.0)
assert(x[0,0,0]==2.0) # Assertion failed

Why is this assertion failing ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

影子的影子 2024-08-27 01:21:10

如果您希望 x 将值传递回调用者,则应将 x 声明为 intent(inout)

然而,这会导致另一个问题,因为传递数组切片不适用于 intent(inout) 数组。 来绕过它

在这个简单的示例中,您可以通过从 python 调用: fill(x, 2.0)

。如果你真的想传递一个切片,那么你需要将 x 声明为 Intent(in,out),并从 python 调用:
x[:,:,0] = fill(x[:,:,0],2.0)

不同属性的描述可以在以下位置找到:

http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#attributes

x should be declared as intent(inout) if you want it to pass values back to the caller.

However this causes an additional problem because passing array slices doesn't work for intent(inout) arrays. In this simple example you can get around it by calling from python:

fill(x, 2.0).

If you really wanted to pass a slice then you need to declare x as intent(in,out), and call from python:
x[:,:,0] = fill(x[:,:,0],2.0)

The description of the different attributes can be found at:

http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#attributes

难如初 2024-08-27 01:21:10

我刚刚遇到这个问题。 intent(inout)intent(inplace) 都没有修复它。问题显然出在 fortranobject.c 中的数组检查例程 array_from_pyobj() 中,该例程随 f2py 一起提供,并与构建的每个模块链接。 array_from_pyobj() 尽一切努力将任何输入转换为形状正确的连续数组,并进行许多检查。其中之一无法正确处理单元素数组,因此会生成副本而不是处理原始数组。

人们可以解决这个问题,但是……好吧……无论如何,我不想在性能库的接口中出现任何这种多态性的东西……我有一个Python类包装了库调用,它已经保证了所有参数被正确地传递。

所以我的解决办法是制作我自己的 fortranobject.c 副本,并简单地将 array_from_pyobj() 替换为以下虚拟版本:

extern PyArrayObject * 
array_from_pyobj(const int type_num, npy_intp *dims,
                 const int rank, const int intent, PyObject *obj) {

    int i;
    PyArrayObject *arr = (PyArrayObject *)obj;

    for (i=0; i<arr->nd; ++i)
        dims[i] = arr->dimensions[i];
    return arr;
}

我的计划是使用原始的 fortranobject .c 在我的 Python 包装类的开发过程中,无可否认,每次调用库函数时出错时,获得温和的错误消息而不是严重崩溃是一个优势。一旦我确定所有库调用都有效,我将使用自定义的 fortranobject.c,它也适用于单元素数组。

I just had this issue. Neither intent(inout) nor intent(inplace) fixed it. The problem is obviously in the array checking routine array_from_pyobj() in fortranobject.c, which ships with f2py and is linked with every module one builds. array_from_pyobj() makes every effort that any input is converted to a properly shaped contiguous array, doing many many checks. One of them does not work properly with single-element arrays, such that a copy is made instead of working on the original array.

One could fix that, but ...well... I don't want any of this polymorphism stuff in an interface to a performance library anyway... I have a Python class wrapping the library calls that already guarantees that all the arguments are passed on correctly.

So my fix was to make my own copy of fortranobject.c and simply replace array_from_pyobj() by the following dummy version:

extern PyArrayObject * 
array_from_pyobj(const int type_num, npy_intp *dims,
                 const int rank, const int intent, PyObject *obj) {

    int i;
    PyArrayObject *arr = (PyArrayObject *)obj;

    for (i=0; i<arr->nd; ++i)
        dims[i] = arr->dimensions[i];
    return arr;
}

My plan is to use the original fortranobject.c during development of my Python wrapper class, where admittedly it is an advantage to get gentle error messages instead of hard crashes every time one makes a mistake calling a library function. Once I'm sure that all the library calls work, I'll use my custom fortranobject.c, which also works with single-element arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文