2013-04-04 127 views
1

我正在嘗試使用FortranFile來獲取可在我的F95編寫的仿真代碼中使用的輸出。我遇到麻煩讓fortranfile正常工作。也許這是因爲我不明白它是如何工作的。這裏是我的問題:Fortran的未格式化輸入/輸出

如果我想寫使用FortranFile一維數組,它工作正常:

以上1D
nx = 128 
bxo = np.zeros(nx, dtype=float) 
bxo = something 
import fortranfile as fofi 
bxf=fofi.FortranFile('Fbx.dat',mode='w') 
bxf.writeReals(bxo,prec='d') 
bxf.close() 

版本的作品就像一個魅力。當我嘗試做了一個二維數組,我得到的問題

nx = 128; ny = 128 
bxo = np.zeros((nx,ny), dtype=float) 
bxo = something 
import fortranfile as fofi 
bxf=fofi.FortranFile('Fbx.dat',mode='w') 
bxf.writeReals(bxo,prec='d') 
bxf.close() 

當我嘗試這樣做,我得到以下錯誤:

--------------------------------------------------------------------------- 
error          Traceback (most recent call last) 
/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/site-packages/IPython/utils/py3compat.py in execfile(fname, *where) 
    173    else: 
    174     filename = fname 
--> 175    __builtin__.execfile(filename, *where) 

/Users/parashar/Dropbox/sandbox/test2d.py in <module>() 
    130 vyf=fofi.FortranFile('Fvy.dat',mode='w') 
    131 vzf=fofi.FortranFile('Fvz.dat',mode='w') 
--> 132 bxf.writeReals(bxo,prec='d') 
    133 byf.writeReals(byo,prec='d') 
    134 bzf.writeReals(bzo,prec='d') 

/Users/parashar/Dropbox/sandbox/fortranfile.py in writeReals(self, reals, prec) 
    215   _fmt = self.ENDIAN + prec 
    216   for r in reals: 
--> 217    self.write(struct.pack(_fmt,r)) 
    218   self._write_check(length_bytes) 
    219 

error: required argument is not a float 

任何想法可能是怎麼回事?

謝謝!

回答

1

我喜歡Emmet的建議,但考慮到我對Python的知識是非常基本的,對於一個簡短的目標來說,這將是一個很大的努力。我只是意識到我可以以一種稍微不同的方式處理這種情況。

Fortran中的直接訪問文件沒有通常未格式化的fortran文件所做的不必要的前導/後續信息。因此,處理Fortran和Python之間交換的無格式數據的最簡單方法是將文件視爲Fortran中的直接訪問。這裏是我們如何使用python/fortran數據的例子。

Python代碼:

import numpy as np 
nx=128; ny=128; 
bxo=np.zeros((nx,ny),dtype=float) 
bxo=something 
bxf=open('Fbx.dat',mode='wb') 
np.transpose(bxo).tofile(bxf) # We transpose the array to map indices 
           # from python to fortran properly 
bxo.close() 

Fortran代碼:

program test 
    implicit none 
    double precision, dimension(128,128) :: bx 
    integer :: NNN, i, j 
    inquire(iolength=NNN) bx 
    open(unit=23,file='Fbx.dat',form='unformatted',status='old',& 
     access='direct',recl=NNN) 
    read(23,rec=1) bx 
    close(23) 
    ! Write it out to a text file to test it 
    ! by plotting in gnuplot 
    do i=1,128; do j=1,128 
    write(23,*) i,j,bx(i,j) 
    enddo; enddo 
    end 

因爲我們使用標準二進制甲酸到讀/寫數據,此方法將不同於FortranFile任何大小的陣列工作方法。我已經意識到,通過堅持Fortran中的直接訪問文件,我們可以與其他語言Python,IDL等。這樣我們就不必擔心奇怪的前導標記,尾數等。

我希望這也能幫助其他人。

+1

直接訪問文件**可能**沒有記錄標記。那裏有一些處理器仍然會爲這些文件添加記錄標記,而Fortran標準明確允許這樣做。改爲使用Fortran 2003的未格式化流訪問。 – IanH 2013-04-05 02:52:11

+0

感謝您的信息@IanH!我在2004年至2005年至少有5-6臺不同的超級計算機上生成了直接訪問文件,並且能夠像IDL文件一樣在IDL中讀取它們。所以我沒有意識到這一點。你能否提供一些指導來閱讀這一點?謝謝! – toylas 2013-04-05 02:59:10

+0

這種處理器的一個例子是帶有-vms編譯標誌的英特爾Fortran。我見過的另一個放置/期望在文件的頭文件中匹配RECL以進行錯誤檢查。允許的標準擴展到第9條 - 尋找「依賴於處理器」/「處理器可能」,並且您很快就會意識到任何事情都會發生。這絕不是常見的情況,但它的可能性正是流式訪問被添加到語言中的原因。有關流訪問的描述,請參閱F2003或您最喜愛的當前編譯器手冊 - 大量的問題/答案也在本站上討論。 – IanH 2013-04-05 03:16:57

0

我從來不需要同時對Fortran和Python做任何事情,並且對fortranfile.py一無所知,但我最好的猜測是fortranfile不是numpy-aware。

當您使用1D numpy數組或Python數組,列表等時,堆棧跟蹤的最後一部分中的迭代表明它期望可迭代數字(「for r in reals」),而當您嘗試序列化二維numpy數組,我不知道它得到了什麼(即什麼「r」最終成爲),也許迭代器的iterable,或一維數組的迭代。簡而言之,'r'不僅僅是期望的數字(「所需的參數不是浮點數」),而是其他的東西(比如一維數組,列表等)。

我會試試看看是否有替代fortranfile中的writeReals(),如果不是,可以用一點copypasta來處理二維數組。

我會先在「self.write()」行(217)之前放入診斷打印,告訴你實際是什麼'r',因爲它不是預期的浮點數。

+0

感謝您的回答Emmet!考慮到我對python有一個相當基本的理解,對我來說這將是很多時間輸入。 我只是意識到我可以做的事情,而不訴諸於FortranFile包。 fortran中的直接訪問文件與通用未格式化的二進制文件幾乎相同。所以我可以用numpy的tofile工具寫出一個簡單的二進制文件,例如bxo.tofile('Fbx.dat'),然後在Fortran中讀取Fbx.dat作爲直接訪問文件。 – toylas 2013-04-05 01:17:43