mgi*_*son 8 python fortran interface 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
Run Code Online (Sandbox Code Playgroud)
现在我想将该数组作为3D数组传递回fortran.
some_data=fortran_routine(a)
Run Code Online (Sandbox Code Playgroud)
问题是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
Run Code Online (Sandbox Code Playgroud)
如何防止所有来回移调?(我很高兴在两种语言中使用不同的数组索引约定).
编辑
似乎np.asfortranarray或者np.flags.f_contiguous应该在解决方案中有一些部分,我似乎无法弄清楚它是什么部分(或者可能是ravel后面的一个reshape(shape,order='F')?
编辑
看来这篇文章引起了一些混乱.这里的问题是f2py尝试保留索引方案而不是内存布局.所以,如果我有一个带有形状的numpy数组(按C顺序)(nz, ny, nx),那么f2py也会尝试使该数组(nz, ny, nx)在fortran中具有形状.如果f2py保留了内存布局,那么数组将(nz, ny, nx)在python和(nx, ny ,nz)fortran中具有形状.我想保留内存布局.
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
Run Code Online (Sandbox Code Playgroud)
现在,f2py在传递时不会尝试重新排序数组.
作为旁注,这也将起作用
a=a.reshape(nx,ny,nz) # Store in C order
Run Code Online (Sandbox Code Playgroud)
因为在幕后,当您将C顺序数组传递给Fortran例程时,f2py会执行这些操作:
a=a.flatten() # Flatten array (Make 1-D)
a=a.reshape(nx,ny,nz, order='F') # Place into Fortran order
Run Code Online (Sandbox Code Playgroud)
但是,从一开始就以Fortran顺序存储更有效.
一般情况下,您不必担心数组排序,除非您有一个性能关键部分,因为f2py会为您解决这个问题.
看起来答案相当简单:
b=np.ravel(a).reshape(tuple(reversed(a.shape)),order='F')
Run Code Online (Sandbox Code Playgroud)
有效,但显然,这与:
b=a.T
Run Code Online (Sandbox Code Playgroud)
因为转置返回一个视图并快速查看b.flags比较a.flags表明这就是我想要的。(b.flags是 F_CONTIGUOUS)。