2012-06-28 74 views
6

我有一个数组,它通过f2py从fortran子程序读取为一维数组。然后在蟒蛇,该数组被重塑:f2py - 防止数组重新排序

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 

现在我想传递数组回到FORTRAN作为3D阵列。

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)。我想保留内存布局。

+0

喜mgilson,对此问题非常快速的问题。我写了一个fortran代码,它需要一个3d数组作为输入: – toylas

回答

2

它看起来像答案相当简单:

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

作品,但显然,这是同样的事情:

b=a.T 

因为转返回一个视图和快速浏览一下b.flagsa.flags相比,表明这是我想要的。 (b.flags是F_CONTIGUOUS)。

+0

非常简单的解决方案,似乎是一个非常复杂的问题。很好的答案。 – Chiel

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会为你处理这个问题。

+0

更简单的是将order ='F'参数传递给numpy.zeros的初始调用。那么不需要重塑或重新排序。 – DaveP

+0

对此感到抱歉,(我出城了)。我真的不明白你的解决方案。 'a = a.reshape(nx,ny,nz)'不是我想要的*因为'nx'应该是快速索引(这里是慢速索引)。我不能使用第一个解决方案,因为我已经写了更多的代码,假设在python端使用C/Python索引。我尝试了'b = a.flatten()。reshape(tuple(reversed(a.shape)),order ='F')',但那不起作用(Error:'0-dimension必须固定为0但得到了448')。 – mgilson

+1

对不起。 ID10T错误。 PEBKAC,不管。 'b = a.flatten()。reshape(tuple(reversed(a.shape)),order ='F')'does not work(Thanks for the idea)。这里的效率不应该是一个问题,因为numpy没有制作阵列数据的副本,只是对元数据进行了更改。由于我在C/Python部分使用了C/Python索引,而在Fortran的代码部分使用了Fortran索引,因此“反向”确实需要在那里。这对我来说是最有意义的。 (如果你更新你的帖子来包含这个,我会很乐意接受你的回答)。 – mgilson