1

我正在尝试使用 FortranFile 来获取可以在用 F95 编写的模拟代码中使用的输出。我无法让 fortranfile 正常工作。也许是因为我不明白它是如何工作的。这是我的问题:

如果我想使用 FortranFile 编写一维数组,它可以正常工作:

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()

上面的 1D 版本就像一个魅力。一旦我尝试为二维数组做这件事,我就会遇到问题

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

任何想法可能会发生什么?

谢谢!

4

2 回答 2

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 等)具有更广泛的兼容性。这样我们就不必担心奇怪的前导尾随标记、字节序等。

我希望这也能帮助我遇到这种情况的其他人。

于 2013-04-05T01:46:03.867 回答
0

我从来不需要同时使用 Fortran 和 Python 做任何事情,并且对 fortranfile.py 一无所知,但我最好的猜测是 fortranfile 不支持 numpy。

当您使用 1D numpy 数组或 Python 数组、列表等时,堆栈跟踪的最后一部分中的迭代表明它需要一个可迭代的数字(“for r in reals”),而当您尝试序列化 2D numpy 数组,我不确定它会得到什么(即“r”最终是什么),可能是迭代器的可迭代,或者一维数组的可迭代。简而言之,'r' 不仅仅是预期的数字(“必需的参数不是浮点数”),而是其他的东西(如一维数组、列表等)。

我会尝试看一下,看看 fortranfile 中是否有 writeReals() 的替代方法,如果没有,可以使用一些 copypasta 来破解一个可以处理 2D 数组的方法。

我将首先在“self.write()”行 (217) 之前放置一个诊断打印,该行告诉您“r”实际上是什么,因为它不是预期的浮点数。

于 2013-04-04T22:53:21.997 回答