How do I allocate input arrays with f2py?

╄→гoц情女王★ 提交于 2019-12-21 23:03:27

问题


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.....

  1. Call the subroutine.
  2. Let it fail, and figure out what variable I need to pass to it.
  3. Initialize and allocate that variable in my python script.
  4. 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.


回答1:


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!



来源:https://stackoverflow.com/questions/35298786/how-do-i-allocate-input-arrays-with-f2py

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!