8

我有一个数组,它通过 f2py 从 fortran 子例程中读取为一维数组。然后在 python 中,该数组被重塑:

a=np.zeros(nx*ny*nz)
read_fortran_array(a)
a=a.reshape(nz,ny,nx)  #in fortran, the order is a(nx,ny,nz), C/Python it is reversed

现在我想将该数组作为 3D 数组传回 fortran。

some_data=fortran_routine(a)

问题是 f2py 在传递给 fortran_routine 之前一直试图转置 a。fortran 例程如下所示:

subroutine fortran_routine(nx,ny,nz,a,b)
real a
real b
integer nx,ny,nz
!f2py intent(hidden) nx,ny,nz
!f2py intent(in) a
!f2py intent(out) b
...
end subroutine

如何防止所有来回转调?(我很高兴在两种语言中使用不同的数组索引约定)。

编辑

似乎np.asfortranarraynp.flags.f_contiguous应该在解决方案中包含某些部分,我似乎无法弄清楚那是什么部分(或者可能是 aravel后跟 a reshape(shape,order='F')

编辑

看来这篇文章引起了一些混乱。这里的问题是f2py试图保留索引方案而不是内存布局。因此,如果我有一个带有 shape 的 numpy 数组(按 C 顺序)(nz, ny, nx),那么 f2py 会尝试使该数组也具有(nz, ny, nx)fortran 中的形状。如果 f2py 保留内存布局,则数组将(nz, ny, nx)在 python 和(nx, ny ,nz)fortran 中具有形状。我想保留内存布局。

4

2 回答 2

4

Fortran 不会反转轴顺序,它只是将数据存储在内存中,与 C/Python 不同。您可以告诉 numpy 以 Fortran 顺序存储数据,这与反转轴不同。

我会这样重写你的代码

a=np.zeros(nx*ny*nz)
read_fortran_array(a)
a=a.reshape(nx,ny,nz, order='F') # It is now in Fortran order

现在, f2py 在传递时不会尝试重新排序数组。

作为旁注,这也将起作用

a=a.reshape(nx,ny,nz) # Store in C order

因为在幕后,当您将 C 顺序数组传递给 Fortran 例程时,f2py 会执行这些操作:

a=a.flatten() # Flatten array (Make 1-D)
a=a.reshape(nx,ny,nz, order='F')  # Place into Fortran order

当然,从一开始就以 Fortran 顺序存储更有效。

一般来说,除非您有性能关键部分,否则您不必担心数组排序,因为 f2py 会为您处理这个问题。

于 2012-06-28T15:55:02.473 回答
3

看起来答案相当简单:

b=np.ravel(a).reshape(tuple(reversed(a.shape)),order='F')

有效,但显然,这与以下内容相同:

b=a.T

因为转置返回一个视图并且快速查看b.flags比较a.flags表明这就是我想要的。(b.flags是 F_CONTIGUOUS)。

于 2012-07-02T12:31:06.617 回答