首页 > 解决方案 > 如何调试 f2py 错误“无法创建意图(缓存|隐藏)|可选数组 - 必须已定义尺寸但得到 (-1,)”

问题描述

是否有调试错误的一般方法

ValueError: failed to create intent(cache|hide)|optional array--  must have defined dimensions but got (-1,)

对于用 f2py 包装的 fortran 函数?

这是一个简单的例子。这是我的模块routine.f

      Subroutine myscript(x,fun,o,n)
      external fun
      integer n
      double precision x(n,*)
      double precision o(*)
      write(*,*) n
      !write(*,*) x(1,:)
      call fun(n,x,o)
      write(*,*) "done with function call"
      write(*,*) o(1)
      end

这是相应的头文件routine.pyf

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

python module myscript__user__routines 
    interface myscript_user_interface 
        subroutine fun(n,x,o) ! in :routine:routine.f:myscript:unknown_interface
            integer,intent(in) :: n
            double precision dimension(n,0) :: x
            double precision dimension(0),intent(out) :: o
        end subroutine fun
    end interface myscript_user_interface
end python module myscript__user__routines
python module routine ! in 
    interface myscript ! in :routine
        subroutine myscript(x,fun,o,n) ! in :routine:routine.f
            use myscript__user__routines
            double precision dimension(n,*) :: x
        intent(callback) fun
            external fun
            double precision dimension(*),intent(out) :: o
            integer,intent(in) :: n
        end subroutine myscript
    end interface myscript
end python module routine

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

和对应的python文件

import numpy as np
import routine
import ipdb
def fun(n, X):
    print("In Callback function")
    ipdb.set_trace()
    print(X)
    O = X[1,:]
    print(O)
    return O
O = np.array([1.,0.])
X = np.identity(2)
n=2
routine.myscript(X, fun)

我编译f2py -c routine.pyf routine.f然后运行python脚本。

另一方面,如果我编译并运行 fortran 文件

      Subroutine fun(n,x,o)
      integer  n
      double precision x(n,*)
      double precision o(*)
      write(*,*) "in function"
      o(1) = 3. *x(1,1)
      end 
      program main
      external fun
      double precision x(2,2)
      double precision o(2)
      integer n
      n=2
      write(*,*) "bla"
      x(1,1) = 1.
      x(2,1) = 0.
      x(1,2) = 0.
      x(2,2) = 1.
      o(1) = 1.
      o(2) = 2.

      call myscript(x,fun,o,n)
      end

然后一切都按预期工作并且没有错误。

旧版:

我得到了一些旧的、相当复杂的 fortran 代码,我目前正在尝试用 f2py 包装这些代码。我已经创建了一个 f2py 头文件并调整了很多功能。但是,现在我被这个错误困住了,真的不知道如何继续,因为有很多可能的数组负责这个错误。不幸的是,错误消息没有提示我某个数组。

我猜有问题的部分是该模块foo依赖于三个外部子模块edif,adiffdif它们都共享一些数组rparipar. 我真的不在乎使用这些,因为它们仅用于例程之间的可选通信。

python module __user__routines 
    interface
    subroutine edif(n,t,idif,e,lde,ipar,rpar,ierr)
        integer,intent(in) :: n
        double precision,intent(in) :: t
        integer,intent(in) :: idif
        double precision dimension(lde,*) :: e
        integer, optional,check(shape(e,0)==lde),depend(e) :: lde=shape(e,0)
        integer dimension(1),intent(hide) :: ipar
        double precision dimension(1), intent(hide) :: rpar
        integer,intent(out) :: ierr
    end subroutine edif
    subroutine adif(n,t,idif,a,lda,ipar,rpar,ierr) 
        integer,intent(in) :: n
        double precision,intent(in) :: t
        integer,intent(in) :: idif
        double precision dimension(lda,*) :: a
        integer, optional,check(shape(a,0)==lda),depend(a) :: lda=shape(a,0)
        integer dimension(1),intent(hide) :: ipar
        double precision dimension(1), intent(hide) :: rpar
        integer,intent(out) :: ierr
    end subroutine adif
    subroutine fdif(n,t,idif,f,ipar,rpar,ierr) 
        integer,intent(in) :: n
        double precision,intent(in) :: t
        integer,intent(in) :: idif
        double precision dimension(*) :: f
        integer dimension(1),intent(hide) :: ipar
        double precision dimension(1), intent(hide) :: rpar
        integer,intent(out) :: ierr
    end subroutine fdif
    end interface 
end python module __user__routines
python module foo 
    interface 
    subroutine ffoo(edif,adif,fdif,neq,t,tout,x,xprime,cval,ipar,rpar,iwork,liw,rwork,lrw,rtol,atol,method,info,iwarn,ierr) ! in :test:SRC/dgelda.f
        use __user__routines, edif=>edif, adif=>adif, fdif=>fdif
        external edif
        external adif
        external fdif
        integer,intent(in) :: neq
        double precision,intent(inout) :: t
        double precision,intent(in) :: tout
        double precision dimension(*),intent(inout),optional :: x
        double precision dimension(*),intent(out) :: xprime
        integer dimension(4),intent(out) :: cval
        integer dimension(1),intent(hide) :: ipar = 0
        double precision dimension(1),intent(hide) :: rpar =0.
        integer dimension(liw),intent(cache),depend(liw) :: iwork
        integer,intent(hide),depend(iwork) :: liw=20+6*neq
        double precision dimension(lrw),intent(cache),depend(lrw) :: rwork
        integer,intent(hide),depend(rwork) ::: lrw = 1000*neq*neq
        double precision dimension(*),intent(in) :: rtol
        double precision dimension(*),intent(in) :: atol
        integer,intent(in),optional :: method=1
        integer dimension(20),intent(in),optional :: info
        integer,intent(out) :: iwarn
        integer,intent(out) :: ierr
    end subroutine dgelda
    end interface 
end python module foo

更新:我还是不明白。我从定义中删除了每个intent(hide|cache|optional)数组,它仍然抛出相同的错误。这是我的更新版本(我将某些数组大小设置为常量):

python module __user__routines 
interface
    subroutine edif(n,t,idif,e,lde,ipar,rpar,ierr)
    integer,intent(in) :: n
    double precision,intent(in) :: t
    integer,intent(in) :: idif
    double precision dimension(lde,*),intent(out) :: e
    integer, optional,check(shape(e,0)==lde),depend(e) :: lde=shape(e,0)
    integer dimension(8) :: ipar
    double precision dimension(8) :: rpar
    integer,intent(out) :: ierr
    end subroutine edif
    subroutine adif(n,t,idif,a,lda,ipar,rpar,ierr) 
    integer,intent(in) :: n
    double precision,intent(in) :: t
    integer,intent(in) :: idif
    double precision dimension(lda,*),intent(out) :: a
    integer, optional,check(shape(a,0)==lda),depend(a) :: lda=shape(a,0)
    integer dimension(8) :: ipar
    double precision dimension(8) :: rpar
    integer,intent(out) :: ierr
    end subroutine adif
    subroutine fdif(n,t,idif,f,ipar,rpar,ierr) 
    integer,intent(in) :: n
    double precision,intent(in) :: t
    integer,intent(in) :: idif
    double precision dimension(*),intent(out) :: f
    integer dimension(8) :: ipar
    double precision dimension(8) :: rpar
    integer,intent(out) :: ierr
    end subroutine fdif
end interface 
end python module __user__routines
python module foo 
interface 
    subroutine foo(edif,adif,fdif,neq,t,tout,x,xprime,cval,ipar,rpar,iwork,liw,rwork,lrw,rtol,atol,method,info,iwarn,ierr) ! in :test:SRC/dgelda.f
    use __user__routines, edif=>edif, adif=>adif, fdif=>fdif
    external edif
    external adif
    external fdif
    integer,intent(in) :: neq
    double precision,intent(inout) :: t
    double precision,intent(in) :: tout
    double precision dimension(*),intent(inout) :: x
    double precision dimension(*),intent(out) :: xprime
    integer dimension(4),intent(out) :: cval
    integer dimension(8) :: ipar
    double precision dimension(8) :: rpar
    integer dimension(liw),depend(liw) :: iwork
    integer,intent(hide) :: liw=20+6*neq
    double precision dimension(lrw),depend(lrw) :: rwork
    integer,intent(hide) :: lrw = 1000*neq*neq
    double precision dimension(*),intent(in) :: rtol
    double precision dimension(*),intent(in) :: atol
    integer,intent(in),optional :: method=1
    integer dimension(20),intent(in),optional :: info
    integer,intent(out) :: iwarn
    integer,intent(out) :: ierr
    end subroutine foo
end interface 
end python module foo

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

标签: pythonfortranf2py

解决方案


推荐阅读