2012-06-28 92 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