我有一些旧的fortran代码,我想用f2py包装它们,并且不允许更改。
程序的核心是一些子例程,这些子例程取决于用户定义的子例程。这些子例程的全部共享公共参数数组,以在例程之间交换用户提供的数据。这些参数数组是一维的,因此不要期望主子例程头中有任何预定义的输入大小。
但是,似乎像python回调函数标头一样,需要有关数组实际大小的精确信息。
让我们看一个例子:
这是我的fortran代码:
Subroutine myscript(x,fun,o,n,rpar, ipar)
external fun
integer n
double precision x(n,*)
double precision o(n)
double precision rpar(*)
integer ipar(*)
write(*,*) n
!write(*,*) x(1,:)
call fun(n,x,o,rpar,ipar)
write(*,*) o
write(*,*) rpar(1)
end
这是我的python部分:
import numpy as np
import routine
import ipdb
def fun(X, rpar):
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)
rpar = np.array([1.,1.])
routine.myscript(X, fun, rpar)
我使用f2py -c routine.pyf routine.f
和以下标头文件
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module myscript__user__routines
interface myscript_user_interface
subroutine fun(n,x,o,rpar,ipar) ! in :routine:routine.f:myscript:unknown_interface
integer, optional,intent(hide),check(shape(x,0)==n),depend(x) :: n=shape(x,0)
double precision dimension(n,n),intent(in) :: x
double precision dimension(n),intent(out),depend(n) :: o
double precision dimension(100),intent(in) :: rpar
integer, optional, dimension(*) :: ipar
end subroutine fun
end interface myscript_user_interface
end python module myscript__user__routines
python module routine ! in
interface ! in :routine
subroutine myscript(x,fun,o,n,rpar,ipar) ! in :routine:routine.f
use myscript__user__routines
double precision dimension(n,*),intent(in,copy) :: x
external fun
double precision dimension(n),intent(out),depend(n) :: o
integer, optional,intent(hide),check(shape(x,0)==n),depend(x) :: n=shape(x,0)
double precision dimension(shape(rpar,0)) :: rpar
integer, optional, dimension(2) :: ipar
end subroutine myscript
end interface
end python module routine
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/
头文件中的重要行是
double precision dimension(100),intent(in) :: rpar
在python调试器中,rpar
现在是一个100维数组,其中最后98个值是垃圾(不足为奇)。
将维度更改为*
只会返回一个空数组
ipdb> rpar
array([], dtype=float64)
在主例程中将尺寸更改为shape(rpar,0)
会产生错误
ValueError: negative dimensions are not allowed
是否存在让python用户动态决定参数数组rpar
的尺寸的优雅方法?
示例中的期望值为2
,因为它是输入数组的维。
我想我可以更改接口并添加另一个整数变量来声明此数组的大小。但是,这意味着在每次代码中更改对该子例程的所有调用。我想避免的事情