Как отладить ошибку f2py "не удалось создать намерение (кеш | скрыть) | необязательный массив - должны быть определены измерения, но получено (-1,)" - PullRequest
0 голосов
/ 31 января 2019

Есть ли общий способ отладки ошибки

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

для функции fortran, обернутой в f2py?

Вот простой пример.Это мой модуль 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

Тогда все работает как положено и без ошибок.

Старая версия:

У меня есть старый, довольно сложный код на фортране, который я сейчас пытаюсь обернуть с помощью f2py.Я уже создал заголовочный файл f2py и адаптировал множество функций.Тем не менее, теперь я застрял с этой ошибкой и не знаю, что делать дальше, поскольку существует довольно много возможных массивов, ответственных за эту ошибку.К сожалению, сообщение об ошибке не намекает мне на определенный массив.

Проблемная часть, я думаю, состоит в том, что модуль foo зависит от трех внешних подмодулей edif, adif и fdif и они оба имеют несколько массивов rpar и ipar.Я действительно не хочу использовать их, так как они предназначены только для дополнительной связи между подпрограммами.

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