In Bezug auf die Eingabe und Ausgabe von Python <-> fortran ist es schwierig, eine zusammenhängende Beschreibung im Internet zu finden, daher habe ich beschlossen, sie meines Wissens zusammenzufassen.
Abgesehen davon werden "np.savez" und "np.load" für die Dateneingabe / -ausgabe zwischen Pythons empfohlen.
Daten wie folgt ausgeben
astype
in binär konvertierentofile
Beispiel für Python-Code, der reelle 3D-Zahlen mit doppelter Genauigkeit und Little Endian ausgibt
import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx))
a.reshape([ix*jx*kx],order='F').astype(endian+'d').tofile('test.dat')
Um dies mit fortran zu lesen, gehen Sie wie folgt vor. Angenommen, der von Ihnen verwendete Computer ist ein kleines Endian. Open
in fortran erfordert access = 'stream'
program test
implicit none
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
read(idf) a
close(idf)
stop
end program test
Wenn Sie Big-Endian-Daten austauschen möchten, verwenden Sie Python-Code
endian='>'
Sie können es in ändern. Diese "endian" -Variable steuert, wie mit "astype" in eine Binärdatei konvertiert wird
Im fortran Code
open(newunit=idf, file='test.dat',form='unformatted',access='stream',convert='big_endian')
Und. Wenn Sie mit einfacher Genauigkeit ausgeben / eingeben möchten, schreiben Sie den Python-Code wie folgt neu
import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx),dtype=np.float32)
a.reshape([ix*jx*kx],order='F').astype(endian+'f').tofile('test.dat')
Die Teile von "np.ones" und "astype" wurden geändert, um eine einfache Genauigkeit zu erzielen.
Der entsprechende fortran-Code sieht folgendermaßen aus:
program test
implicit none
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.e0)), dimension(ix,jx,kx) :: a
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
read(idf) a
close(idf)
stop
end program test
Nur der Teil von "real (KIND (0.e0))" wurde geändert.
Wenn Sie mehrere Arrays in eine Datei ausgeben möchten, führen Sie die folgenden Schritte aus.
np.array
T
aus.import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx),dtype=np.float32)
b = np.ones((ix,jx,kx),dtype=np.float32)*2
c = np.ones((ix,jx,kx),dtype=np.float32)*3
np.array([a,b,c]).T.reshape([3*ix*jx*kx],order='F').astype(endian+'f').tofile('test.dat')
Der zu lesende fortran-Code lautet
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.e0)), dimension(ix,jx,kx) :: a,b,c
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
read(idf) a,b,c
close(idf)
stop
end program test
Sollte sein
Zum anderen bei der Ausgabe von Arrays unterschiedlicher Größe
np.concatenate
, um das Array zu organisieren
Sie müssen nur die Prozedur befolgenDer Python-Code sieht so aus
import numpy as np
ix, jx, kx = 3, 4, 5
lx, mx = 2, 4
endian='<'
a = np.ones((ix,jx,kx))
b = np.ones((lx,mx))*2
a1 = a.reshape([ix*jx*kx],order='F')
b1 = b.reshape([lx*mx],order='F')
np.concatenate([a1,b1]).astype(endian+'d').tofile('test.dat')
Beim Lesen aus fortran ist es dasselbe wie zuvor, aber gehen Sie wie folgt vor.
program test
implicit none
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
integer, parameter :: lx = 2, mx = 4
real(KIND(0.d0)), dimension(ix,jx,kx) :: a
real(KIND(0.d0)), dimension(lx,mx) :: b
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
read(idf) a,b
close(idf)
stop
end program test
Die obige Methode ist für Python-Code einfacher, aber wenn Sie in fortran nicht "access =" stream "" verwenden, müssen Sie den Datenheader selbst bearbeiten.
Es ist scipy.io.FortranFile
, das diesen Teil gut anpasst.
Python-Code sieht so aus
import numpy as np
from scipy.io import FortranFile
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx))
f = FortranFile('test.dat','w')
f.write_record(a)
f.close()
Der Fortran-Code zum Lesen lautet
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a
open(newunit=idf, file='test.dat',form='unformatted')
read(idf) a
close(idf)
stop
end program test
Es sollte getan werden.
Die Ausgabe mehrerer Arrays ist einfacher als die Verwendung von Numpy
a = np.ones((ix,jx,kx))
b = np.ones((ix,jx,kx))*2
f = FortranFile('test.dat','w')
f.write_record(a,b)
f.close()
Und fügen Sie es einfach dem Argument "write_record" hinzu. Fortran liest Code
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a,b
open(newunit=idf, file='test.dat',form='unformatted')
read(idf) a,b
close(idf)
stop
end program test
Sie müssen lediglich die Arrays so anordnen, dass sie nebeneinander gelesen werden.
Wenn Sie sich jedoch die [scipy-Website] ansehen (https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.FortranFile.html)
Since this is a non-standard file format, whose contents depend on the compiler and the endianness of the machine, caution is advised. Files from gfortran 4.8.0 and gfortran 4.1.2 on x86_64 are known to work.
Consider using Fortran direct-access files or files from the newer Stream I/O, which can be easily read by numpy.fromfile.
es ist so geschrieben. Das fortran-Format scheint stark vom Compiler abhängig zu sein, und die Methode mit numpy scheint empfohlen zu werden.
Um fortran-Daten mit numpy zu lesen, wird empfohlen, mit access = 'stream'
auszugeben (dies ist nicht unbedingt erforderlich, da Sie den Header usw. selbst anpassen können).
Definieren Sie ein Array mit fortran und output
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a
a = 1.d0
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
write(idf) a
close(idf)
stop
end program test
Der einfachste Weg, es mit Python zu laden, ist die Verwendung von "np.fromfile".
import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
f = open('test.dat','rb')
a = np.fromfile(f,endian+'d',ix*jx*kx)
a = a.reshape((ix,jx,kx),order='F')
f.close()
Selbst wenn Sie "np.fromfile" verwenden, können Sie "np.dtype" für ein vielseitigeres Lesen verwenden. Gehen Sie beispielsweise wie folgt vor
import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
f = open('test.dat','rb')
dtype = np.dtype([('a',endian+str(ix*jx*kx)+'d')])
a = np.fromfile(f,dtype=dtype)['a']
a = a.reshape((ix,jx,kx),order='F')
f.close()
Es ist bequemer, "np.dtype" zu verwenden, wenn Sie mit mehreren Arrays arbeiten. Zunächst gibt fortran mehrere Arrays in eine Datei aus, wie unten gezeigt.
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a,b
a = 1.d0
b = 2.d0
open(newunit=idf, file='test.dat',form='unformatted',access='stream')
write(idf) a,b
close(idf)
stop
end program test
So laden Sie dies mit Python:
import numpy as np
ix, jx, kx = 3, 4, 5
endian='<'
f = open('test.dat','rb')
dtype = np.dtype([('a',endian+str(ix*jx*kx)+'d'),('b',endian+str(ix*jx*kx)+'d')])
data = np.fromfile(f,dtype=dtype)
a = data['a'].reshape((ix,jx,kx),order='F')
b = data['b'].reshape((ix,jx,kx),order='F')
f.close()
Es ist einfach, "scipy.io.FortranFile" zu verwenden, um fortran-Daten zu lesen, die "access =" stream "" nicht verwenden.
Die Ausgabe von fortran ist wie folgt
program test
implicit none
integer :: i,j,k
integer :: idf
integer, parameter :: ix = 3, jx = 4, kx = 5
real(KIND(0.d0)), dimension(ix,jx,kx) :: a
a = 1.d0
open(newunit=idf, file='test.dat',form='unformatted')
write(idf) a
close(idf)
stop
end program test
Der Python-Code zum Lesen sieht folgendermaßen aus
import numpy as np
from scipy.io import FortranFile
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx))
b = np.ones((ix,jx,kx))*2
f = FortranFile('test.dat','r')
a = f.read_record(endian+'('+str(ix)+','+str(jx)+','+str(kx)+')d')
f.close()
Es kann auch mit np.dtype
wie folgt gelesen werden:
import numpy as np
from scipy.io import FortranFile
ix, jx, kx = 3, 4, 5
endian='<'
a = np.ones((ix,jx,kx))
b = np.ones((ix,jx,kx))*2
f = FortranFile('test.dat','r')
dtype = np.dtype([('a',endian+str(ix*jx*kx)+'d')])
a = f.read_record(dtype=dtype)
a = a['a'].reshape(ix,jx,kx,order='F')
f.close()
Recommended Posts