f2py - 防止数组重新排序

时间:2012-06-28 15:28:33

标签: python interface fortran f2py

我有一个数组,它通过f2py从fortran子程序读取为1D数组。然后在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之前一直试图转置一个。 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应该在解决方案中有一些部分,我似乎无法弄清楚它是什么部分(或者可能是ravel后跟一个reshape(shape,order='F')

修改

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

2 个答案:

答案 0 :(得分:5)

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会为您解决这个问题。

答案 1 :(得分:2)

看起来答案相当简单:

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

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

b=a.T

因为转置会返回一个视图,快速查看b.flagsa.flags相比,这表明这就是我想要的。 (b.flags是F_CONTIGUOUS)。