我有一个数组,它通过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.asfortranarray
或np.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)
。我想保留内存布局。
答案 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.flags
与a.flags
相比,这表明这就是我想要的。 (b.flags
是F_CONTIGUOUS)。