Есть ли общий способ отладки ошибки
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/