我如何分配输入数组与f2py? [英] How do I allocate input arrays with f2py?
问题描述
警告.....我是一个相对的python noob,并且完全使用f2py。
我尝试尽职调查并搜索答案在我的问题在这里和其他地方interweb,但我有运气。这很可能是由于我对这个主题的无知。
我的问题:我有一个遗留fortran(f77)子程序以及子程序使用的几个函数从数据文件中读取各种数组。这个数据文件本身是几个f77原子物理学代码之一的结果。
我想用f2py封装fortran子程序/函数,并以numpy数组的形式访问存储在文件中的数据。我被困在如何正确地分配在Python中的数组。我在Ubuntu 14.04(64位)上使用了Anaconda python distibrution(Python 3.4-64位)和gfortran编译器。
我成功(我希望)管理使用py2f创建一个python签名文件,使用 py2f -h< filename.py2f> <输入文件>
。这是签名文件的内容。我为它的长度道歉。这是一个相当长的子程序,并且有很多变量。
! - * - f90 - * -
!注意:此文件的上下文区分大小写。
子程序xxdata_04(iunit,ndlev,ndtrn,ndmet,ndqdn,nvmax,titled,iz,iz0,iz1,bwno,npl,bwnoa,lbseta,prtwta,cprta,il,qdorb,lqdorb,qdn ,IORB,IA,cstrga,ISA,ILA,XJA,WA,CPLA,NPLA,IPLA,zpla,NV,SCEF,itran,maxlev,t码,I1A,I2A,AVAL,SCOM,贝斯,iadftyp,lprn,LCPL,lorb ,lbeth,letyp,lptyp,lrtyp,lhtyp,lityp,lstyp,lltyp,itieactn,ltied)!在xxdata04_string.for
integer :: iunit
整数,可选,check(len(ia)> = ndlev),depends(ia):: ndlev = len(ia)
整数,可选,check(形状(tcode,0)== ndtrn),依赖(tcode):: ndtrn = shape(tcode,0)
整数,可选,检查(len(bwnoa)> = ndmet) (bwnoa):: ndmet = len(bwnoa)
整数,可选,check(len(qdn)> = ndqdn),depends(qdn):: ndqdn = len(qdn)
整数,可选,检查(len(scef)> = nvmax),依赖(scef):: nvmax = len(scef)
字符* 3 ::标题
integer :: iz
integer :: iz0
整数:: iz1
real * 8 :: bwno
整数:: npl
real * 8维(ndmet):: bwnoa
逻辑维(ndmet) ,依赖(ndmet):: lbseta
real * 8维(ndmet),依赖(ndmet):: prtwta
字符维(ndmet,9),依赖(ndmet):: cprta
整数:: il
real * 8维((ndqdn *(ndqdn + 1))/ 2),depends(ndqdn):: qdorb
逻辑维((ndqdn *(ndqdn + 1))/ 2),取决于(NDQ dn):: lqdorb
real * 8维(ndqdn):: qdn
整数:: iorb
整数维(ndlev):: ia
字符维(ndlev,(* )),depend(ndlev):: cstrga
整数维(ndlev),依赖(ndlev):: isa
整数维(ndlev),依赖(ndlev):: ila
real * 8维(ndlev),depends(ndlev):: xja
real * 8维(ndlev),depends(ndlev):: wa
字符维(ndlev,1),depend(ndlev):: cpla
整数维(ndlev),depends(ndlev):: npla
整数维(ndmet,ndlev),依赖(ndmet,ndlev):: ipla
real * 8维(ndmet, ndlev),depend(ndmet,ndlev):: zpla
integer :: nv
real * 8维(nvmax):: scef
整数:: itran
整数:: maxlev
字符维(ndtrn,1):: tcode
整数维(ndtrn),依赖(ndtrn):: i1a
整数维(ndtrn),依赖(ndtrn):: i2a
real * 8维(ndtrn),depends(ndtrn):: aval
real * 8角钱nsion(nvmax,ndtrn),depend(nvmax,ndtrn):: scom
real * 8维(ndtrn),depends(ndtrn):: beth
整数:: iadftyp
logical :: lprn
logical :: lcpl
logical :: lorb
logical :: lbeth
logical :: letyp
logical :: lptyp
logical :: lrtyp
logical :: lhtyp
logical :: lityp
logical :: lstyp
logical :: lltyp
integer :: itieactn
逻辑维(ndlev),depend (ndlev):: ltied
结束子程序xxdata_04
函数i4unit(iunit)!在i4unit.for
integer :: iunit
integer :: i4unit
结束函数i4unit
子程序xxword(ctext,cdelim,nfirst,iwords,ifirst,ilast,nwords)!在xxword.for
字符*(*):: ctext
字符*(*):: cdelim
integer :: nfirst
整数,可选,check(len(ifirst) > = iwords),依赖(ifirst):: iwords = len(ifirst)
整数维(iwords):: ifirst
整数维(iwords),depends(iwords):: ilast
整数:: nwords
结束子程序xxword
子程序xxslen(cstrng,ifirst,ilast)!在xxslen.for
字符*(*):: cstrng
整数:: ifirst
整数:: ilast
结束子程序xxslen
子程序xxprs1(ndmet,string_bn, wno,cpl,npt,ipla,zpla,ifail)! in xxprs1.for
integer * 4,可选,check(len(ipla)> = ndmet),depend(ipla):: ndmet = len(ipla)
字符*(*):: string_bn
real * 8 :: wno
字符* 1 :: cpl
整数* 4 :: npt
整数* 4维(ndmet):: ipla
real * 8维(ndmet),依赖(ndmet):: zpla
整数* 4 :: ifail
结束子程序xxprs1
函数r8fctn(str,iabt)!在r8fctn.for
字符*(*):: str
integer :: iabt
real * 8 :: r8fctn
结束函数r8fctn
函数i4fctn(str, iabt)!在i4fctn.for
字符*(*):: str
整数:: iabt
整数:: i4fctn
结束函数i4fctn
函数i4idfl(n,l) ! in i4idfl.for
integer :: n
integer :: l
integer :: i4idfl
end function i4idfl
子程序xxpars(ndmet,strng1,npt,bwnoa, lseta,prtwta,cprta,ifail,itype)! (bwnoa):: ndmet = len(bwnoa)
字符*(*):: strng1
integer * 4 :: npt
real * 8维(ndmet):: bwnoa
逻辑维(ndmet),depends(ndmet):: lseta
real * 8维( ndmet),depend(ndmet):: prtwta
字符维(ndmet,(*)),depends(ndmet):: cprta
整数* 4 :: ifail
整数* 4 :: itype
结束子程序xxpars
子程序xxrmve(cstrg1,cstrg2,crmve)!在xxrmve.for
字符*(*):: cstrg1
字符*(*):: cstrg2
字符* 1 :: crmve
结束子程序xxrmve
子程序xxcase(输入,输出,type_bn)!在xxcase.for
字符*(*)::输入
字符*(*)::输出
字符* 2 :: type_bn
结束子程序xxcase
!这个文件是用f2py(版本:2)自动生成的。
!见http://cens.ioc.ee/projects/f2py2e/
然后我用 f2py -c -m
。编译完成时只有几个警告但没有错误。生成的python共享对象是 adf04_2py.cpython-35m-x86_64-linux-gnu.so
我已经开始构建一个我想用来导入共享对象并调用'xxdata_04'子例程的python脚本。到目前为止,我的过程一直是这样的......
- 调用子程序。它失败了,并找出我需要传递给它的变量。
- 在我的python脚本中初始化并分配该变量。
- 重复。
我确信有更好的方法可以做到这一点,但fortran代码很多,并且有点冗长,而不是我自己的,所以这看起来是最直接的方法。
到目前为止,我的脚本如下所示:
import adf04_2py as adf
进口numpy为np
itieactn = 1
iunit = 19;标题='---'; iz = 18; iz0 = 0; iz1 = 0; il = 0
bwno = 0.0; npl = 0; bwnoa = 1.0; prtwta = 0.0
qdorb = 0.0; qdn = 0.0; iorb = 0; ia = 0; cstrga =' - '
isa = 0; ila = 0; xja = 0.0; wa = 0.0; cpla =' - '; npla = 0; ipla = 0
zpla = 0; nv = 0; scef = 0.0; itran = 0; maxlev = 0; tcode =' - '
ila = 0; i2a = 0; aval = 0.0; scom = 0.0; beth = 0; iadftyp = 0
cprta = np.asarray([['---------'],['---------'],[' - -------']],dtype ='c')
lbseta = False; lqdorb = False; lprn = False; lcpl = False; lorb = False
lbeth = False; letyp = False; lptyp = False; lrtyp = False; lhtyp = False
lityp = False; lstyp = False; lltyp = False; ltied = False
adf04_dat = adf.xxdata_04(iunit,标题为iz,iz0,iz1,bwno,npl,bwnoa,
lbseta,prtwta,cprta,il,qdorb ,lqdorb,
qdn,iorb,ia,cstrga,isa,ila,xja,wa,
cpla,npla,ipla,zpla,nv,scef,itran,
maxlev,tcode,ila ,i2a,aval,scom,beth,
iadftyp,lprn,lcpl,lorb,lbeth,letyp,lptyp,
lrtyp,lhtyp,lityp,lstyp,lltyp,itieactn,
目前,它失败:
runfile('/ home / ivan / GoogleDrive / AUAMO / codes / read_adf04_2py / xxdata_04 / read_adf2py.py',wdir ='/ home / ivan / GoogleDrive / AUAMO / codes / read_adf04_2py / xxdata_04')
文件/home/ivan/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py,行699,在运行文件
execfile(f ilename,namespace)
执行文件$ b $中的文件/home/ivan/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py,第88行b exec(compile(open(filename,'rb').read(),filename,'exec'),namespace)
文件/ home / ivan / GoogleDrive / AUAMO / codes / read_adf04_2py / xxdata_04 / read_adf2py.py,第32行,位于< module>
ltied)
错误:未能将adf04_2py.xxdata_04的第11个参数`cprta'转换为C / Fortran数组
根据签名文件,cprta应该是形状的字符数组((ndmet),(#字符数)),其中ndmet是亚稳状态的数量和#字符数是9.我试图通过使用np.asarray分配这个。我还是得到了将adf04_2py.xxdata_04的第11个参数`cprta'转换为C / Fortran数组失败。
任何帮助?我完全意识到我不知道我在做什么。
感谢CT Zhu为此问题提供的解决方案。
0维度必须固定为1,但得到3(
Traceback(最近一次调用的最后一个):
在< module>文件中,第33行的文件read_adf2py.py
ltied)
adf04_2py.error:未能将adf04_2py.xxdata_04的第11个参数`cprta'转换为C / Fortran数组
我重新分配了字符串数组,使其维度为1 x 9,并且该错误消失。
cprta = np.asarray(['---------'],dtype ='c')
现在我收到了段错误,但我认为这是一个单独的问题。
感谢CT Zhu!
Warning..... I am a relative python noob, and completely new to using f2py.
I have tried to exercise due diligence and search for the answer to my questions here and elsewhere on the interweb, but I've had little luck. This is very likely due to my own ignorance on this subject.
My problem: I have a legacy fortran (f77) subroutine along with several functions that are used by the subroutine to read in various arrays from a data file. This data file is itself the result of one of several f77 atomic physics codes.
I would like to wrap the fortran subroutines/functions using f2py, and have access to the data stored in the file in the form of numpy arrays. I'm stuck at how to properly allocate the arrays in python. I am using the Anaconda python distibrution (Python 3.4 - 64 bit) and the gfortran compiler on Ubuntu 14.04 (64 bit).
I've successfully (I hope) managed to create a python signature file using py2f, using py2f -h <filename.py2f> <input files>
. Here's the contents of the signature file. I apologize for its length. This is a fairly lengthy subroutine and has a lot of variables.
! -*- f90 -*-
! Note: the context of this file is case sensitive.
subroutine xxdata_04(iunit,ndlev,ndtrn,ndmet,ndqdn,nvmax,titled,iz,iz0,iz1,bwno,npl,bwnoa,lbseta,prtwta,cprta,il,qdorb,lqdorb,qdn,iorb,ia,cstrga,isa,ila,xja,wa,cpla,npla,ipla,zpla,nv,scef,itran,maxlev,tcode,i1a,i2a,aval,scom,beth,iadftyp,lprn,lcpl,lorb,lbeth,letyp,lptyp,lrtyp,lhtyp,lityp,lstyp,lltyp,itieactn,ltied) ! in xxdata04_string.for
integer :: iunit
integer, optional,check(len(ia)>=ndlev),depend(ia) :: ndlev=len(ia)
integer, optional,check(shape(tcode,0)==ndtrn),depend(tcode) :: ndtrn=shape(tcode,0)
integer, optional,check(len(bwnoa)>=ndmet),depend(bwnoa) :: ndmet=len(bwnoa)
integer, optional,check(len(qdn)>=ndqdn),depend(qdn) :: ndqdn=len(qdn)
integer, optional,check(len(scef)>=nvmax),depend(scef) :: nvmax=len(scef)
character*3 :: titled
integer :: iz
integer :: iz0
integer :: iz1
real*8 :: bwno
integer :: npl
real*8 dimension(ndmet) :: bwnoa
logical dimension(ndmet),depend(ndmet) :: lbseta
real*8 dimension(ndmet),depend(ndmet) :: prtwta
character dimension(ndmet,9),depend(ndmet) :: cprta
integer :: il
real*8 dimension((ndqdn*(ndqdn+1))/2),depend(ndqdn) :: qdorb
logical dimension((ndqdn*(ndqdn+1))/2),depend(ndqdn) :: lqdorb
real*8 dimension(ndqdn) :: qdn
integer :: iorb
integer dimension(ndlev) :: ia
character dimension(ndlev,(*)),depend(ndlev) :: cstrga
integer dimension(ndlev),depend(ndlev) :: isa
integer dimension(ndlev),depend(ndlev) :: ila
real*8 dimension(ndlev),depend(ndlev) :: xja
real*8 dimension(ndlev),depend(ndlev) :: wa
character dimension(ndlev,1),depend(ndlev) :: cpla
integer dimension(ndlev),depend(ndlev) :: npla
integer dimension(ndmet,ndlev),depend(ndmet,ndlev) :: ipla
real*8 dimension(ndmet,ndlev),depend(ndmet,ndlev) :: zpla
integer :: nv
real*8 dimension(nvmax) :: scef
integer :: itran
integer :: maxlev
character dimension(ndtrn,1) :: tcode
integer dimension(ndtrn),depend(ndtrn) :: i1a
integer dimension(ndtrn),depend(ndtrn) :: i2a
real*8 dimension(ndtrn),depend(ndtrn) :: aval
real*8 dimension(nvmax,ndtrn),depend(nvmax,ndtrn) :: scom
real*8 dimension(ndtrn),depend(ndtrn) :: beth
integer :: iadftyp
logical :: lprn
logical :: lcpl
logical :: lorb
logical :: lbeth
logical :: letyp
logical :: lptyp
logical :: lrtyp
logical :: lhtyp
logical :: lityp
logical :: lstyp
logical :: lltyp
integer :: itieactn
logical dimension(ndlev),depend(ndlev) :: ltied
end subroutine xxdata_04
function i4unit(iunit) ! in i4unit.for
integer :: iunit
integer :: i4unit
end function i4unit
subroutine xxword(ctext,cdelim,nfirst,iwords,ifirst,ilast,nwords) ! in xxword.for
character*(*) :: ctext
character*(*) :: cdelim
integer :: nfirst
integer, optional,check(len(ifirst)>=iwords),depend(ifirst) :: iwords=len(ifirst)
integer dimension(iwords) :: ifirst
integer dimension(iwords),depend(iwords) :: ilast
integer :: nwords
end subroutine xxword
subroutine xxslen(cstrng,ifirst,ilast) ! in xxslen.for
character*(*) :: cstrng
integer :: ifirst
integer :: ilast
end subroutine xxslen
subroutine xxprs1(ndmet,string_bn,wno,cpl,npt,ipla,zpla,ifail) ! in xxprs1.for
integer*4, optional,check(len(ipla)>=ndmet),depend(ipla) :: ndmet=len(ipla)
character*(*) :: string_bn
real*8 :: wno
character*1 :: cpl
integer*4 :: npt
integer*4 dimension(ndmet) :: ipla
real*8 dimension(ndmet),depend(ndmet) :: zpla
integer*4 :: ifail
end subroutine xxprs1
function r8fctn(str,iabt) ! in r8fctn.for
character*(*) :: str
integer :: iabt
real*8 :: r8fctn
end function r8fctn
function i4fctn(str,iabt) ! in i4fctn.for
character*(*) :: str
integer :: iabt
integer :: i4fctn
end function i4fctn
function i4idfl(n,l) ! in i4idfl.for
integer :: n
integer :: l
integer :: i4idfl
end function i4idfl
subroutine xxpars(ndmet,strng1,npt,bwnoa,lseta,prtwta,cprta,ifail,itype) ! in xxpars.for
integer*4, optional,check(len(bwnoa)>=ndmet),depend(bwnoa) :: ndmet=len(bwnoa)
character*(*) :: strng1
integer*4 :: npt
real*8 dimension(ndmet) :: bwnoa
logical dimension(ndmet),depend(ndmet) :: lseta
real*8 dimension(ndmet),depend(ndmet) :: prtwta
character dimension(ndmet,(*)),depend(ndmet) :: cprta
integer*4 :: ifail
integer*4 :: itype
end subroutine xxpars
subroutine xxrmve(cstrg1,cstrg2,crmve) ! in xxrmve.for
character*(*) :: cstrg1
character*(*) :: cstrg2
character*1 :: crmve
end subroutine xxrmve
subroutine xxcase(input,output,type_bn) ! in xxcase.for
character*(*) :: input
character*(*) :: output
character*2 :: type_bn
end subroutine xxcase
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/
I then compiled with f2py -c -m <filename> <input files>
. Compilation completed with a few warnings but no errors. The resulting python shared object is adf04_2py.cpython-35m-x86_64-linux-gnu.so
I have started building a python script that I would like to use to import the shared object and call the 'xxdata_04' subroutine. My process so far has been this.....
- Call the subroutine.
- Let it fail, and figure out what variable I need to pass to it.
- Initialize and allocate that variable in my python script.
- repeat.
I'm sure there's a better way to do this, but the fortran code(s) are many and somewhat lengthy, and not my own, so this seemed like the most direct method.
So far my script looks like this:
import adf04_2py as adf
import numpy as np
itieactn = 1
iunit = 19 ; titled = '---' ; iz = 18 ; iz0 = 0 ; iz1 = 0 ; il = 0
bwno = 0.0 ; npl = 0 ; bwnoa = 1.0 ; prtwta = 0.0
qdorb = 0.0 ; qdn =0.0 ; iorb = 0 ; ia = 0 ; cstrga = '-'
isa = 0 ; ila = 0 ; xja = 0.0 ; wa = 0.0 ; cpla = '-' ; npla = 0 ; ipla = 0
zpla = 0 ; nv = 0 ; scef = 0.0 ; itran = 0 ; maxlev = 0 ; tcode = '-'
ila = 0 ; i2a = 0 ; aval = 0.0 ; scom = 0.0 ; beth = 0 ; iadftyp = 0
cprta = np.asarray([['---------'],['---------'],['---------']],dtype='c')
lbseta = False ; lqdorb = False ; lprn = False ; lcpl= False ; lorb = False
lbeth = False ; letyp = False ; lptyp = False ; lrtyp = False ; lhtyp = False
lityp = False ; lstyp = False ; lltyp = False ; ltied = False
adf04_dat = adf.xxdata_04(iunit, titled, iz, iz0, iz1 , bwno, npl, bwnoa ,
lbseta , prtwta , cprta , il , qdorb , lqdorb ,
qdn , iorb , ia , cstrga , isa , ila , xja , wa ,
cpla , npla, ipla , zpla , nv , scef , itran ,
maxlev , tcode , ila , i2a , aval , scom , beth ,
iadftyp , lprn, lcpl , lorb , lbeth , letyp, lptyp ,
lrtyp , lhtyp , lityp , lstyp , lltyp , itieactn ,
Currently, it fails with:
runfile('/home/ivan/GoogleDrive/AUAMO/codes/read_adf04_2py/xxdata_04/read_adf2py.py', wdir='/home/ivan/GoogleDrive/AUAMO/codes/read_adf04_2py/xxdata_04')
File "/home/ivan/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 699, in runfile
execfile(filename, namespace)
File "/home/ivan/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 88, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "/home/ivan/GoogleDrive/AUAMO/codes/read_adf04_2py/xxdata_04/read_adf2py.py", line 32, in <module>
ltied )
error: failed in converting 11st argument `cprta' of adf04_2py.xxdata_04 to C/Fortran array
according to the signature file, cprta should be a character array of shape((ndmet),(# of characters)), where ndmet is the number of metastable states and # of characters is 9. I've tried to allocate this by using np.asarray. I still get the "failed in converting 11st argument `cprta' of adf04_2py.xxdata_04 to C/Fortran array" error.
Any help? I am fully aware that I have no clue what I'm doing.
Thanks to CT Zhu for the solution to this problem. Running the script from a terminal gave a more informative error message.
0-th dimension must be fixed to 1 but got 3 (real index=0)
Traceback (most recent call last):
File "read_adf2py.py", line 33, in <module>
ltied )
adf04_2py.error: failed in converting 11st argument `cprta' of adf04_2py.xxdata_04 to C/Fortran array
I reallocated the string array to have dimension 1 x 9 and that error vanished.
cprta = np.asarray(['---------'],dtype='c')
Now I'm getting a segfault, but I think that's a separate issue.
Thanks CT Zhu!
这篇关于我如何分配输入数组与f2py?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!