【问题标题】:How do I allocate input arrays with f2py?如何使用 f2py 分配输入数组?
【发布时间】:2016-05-19 20:03:36
【问题描述】:

警告.....我是一个相对的 python 菜鸟,对使用 f2py 完全陌生。

我曾尝试尽职尽责并在互联网上的其他地方寻找我的问题的答案,但我运气不佳。这很可能是由于我自己对这个问题的无知。

我的问题:我有一个旧的 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> <input files>。这是签名文件的内容。我为它的长度道歉。这是一个相当长的子程序,并且有很多变量。

!    -*- 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/

然后我用 f2py -c -m <filename> <input files> 编译。编译完成,有一些警告但没有错误。生成的python共享对象是adf04_2py.cpython-35m-x86_64-linux-gnu.so

我已经开始构建一个 python 脚本,我想用它来导入共享对象并调用“xxdata_04”子例程。到目前为止我的过程是这样的......

  1. 调用子程序。
  2. 让它失败,然后找出我需要传递给它的变量。
  3. 在我的 python 脚本中初始化并分配该变量。
  4. 重复。

我确信有更好的方法可以做到这一点,但是 fortran 代码很多而且有些冗长,而且不是我自己的,所以这似乎是最直接的方法。

到目前为止,我的脚本如下所示:

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 ,

目前,它失败了:

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

根据签名文件,cprta应该是shape((ndmet),(# of characters))的字符数组,其中ndmet是亚稳态数,# of characters是9。我试过分配这通过使用 np.asarray。我仍然收到“将 adf04_2py.xxdata_04 的第 11 个参数 `cprta' 转换为 C/Fortran 数组失败”错误。

有什么帮助吗?我完全清楚我不知道自己在做什么。

【问题讨论】:

  • 听起来像是尺寸不匹配的问题。你能看一下终端窗口,看看有没有像1-th dimension must be fixed to _M_ but got _N_这样的行吗?
  • 感谢您的回复。看起来这至少是问题的一部分,尽管我现在可能有更多问题。从终端运行脚本产生 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 &lt;module&gt; ltied ) adf04_2py.error: failed in converting 11st argument cprta' of adf04_2py.xxdata_04 to C/Fortran array`
  • 当然,现在我遇到了段错误,所以也许是时候提出一个新问题了?
  • 段错误可能表示其他维度不匹配。维度为(1,9)cprta 可能是子例程的某些部分所期望的,可能有些地方实际上需要(3,9)。我只是在猜测,因为 cprta 似乎被设计为具有 (ndmet, 9) 的维度,如签名文件所示。因此,一些额外的未匹配是真正的可能性......
  • 看来你是对的。我肯定有持续的尺寸问题。我在这里发布了一个新问题:link。任何进一步的将不胜感激。再次感谢您迄今为止的帮助。 -伊万

标签: python numpy fortran f2py


【解决方案1】:

感谢 CT Zhu 解决这个问题。从终端运行脚本会给出更多信息的错误消息。

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

我将字符串数组重新分配为维度为 1 x 9 并且该错误消失了。

cprta = np.asarray(['---------'],dtype='c')

现在我遇到了段错误,但我认为这是一个单独的问题。

感谢朱总!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 2022-12-05
    • 2017-05-17
    • 2022-11-27
    相关资源
    最近更新 更多