Python 运行f2py时,主.f90模块调用特定的.f文件时出现问题?(未知的_子程序?)
我正在尝试使用f2py将fortran函数与我的主python代码集成。但是,当我尝试包含一个特定的“.f”文件时,f2py会引发一个错误(但可以与其他“.f”文件一起使用)。我已经为我的主“.f90”文件创建了以下最小工作示例:Python 运行f2py时,主.f90模块调用特定的.f文件时出现问题?(未知的_子程序?),python,fortran,gfortran,f2py,Python,Fortran,Gfortran,F2py,我正在尝试使用f2py将fortran函数与我的主python代码集成。但是,当我尝试包含一个特定的“.f”文件时,f2py会引发一个错误(但可以与其他“.f”文件一起使用)。我已经为我的主“.f90”文件创建了以下最小工作示例: module min_example implicit none public :: calc_min contains subroutine calc_min print*, 'test' return end subroutine
module min_example
implicit none
public :: calc_min
contains
subroutine calc_min
print*, 'test'
return
end subroutine calc_min
end module min_example
而导致我出现问题的“.f”文件是“qromb.f”,如下所示:
我使用以下方法编译它:
gfortran -c min_example.f90
gfortran -c qromb.f
f2py -c qromb.f min_example.f90 -m min_example
任何帮助都将不胜感激!谢谢大家!
更新:我一直在四处搜索,发现的线索很少。有人建议f2py对内联注释有问题,但删除它们并没有帮助。我读到的另一个答案建议将“.f”文件转换为“.f90”文件,但老实说,我不知道两者之间的区别(我对fortran非常陌生)。所以我不知道该怎么做(我不太清楚.f文件的结构),也不知道它是否会减慢速度
另一个更新:使用“f2py-m min_example min_example.f90 qromb.f”编译时,会得到以下输出:
Reading fortran codes...
Reading file 'min_example.f90' (format:free)
Reading file 'qromb.f' (format:fix,strict)
Post-processing...
Block: min_example
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: func
Block: polint
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: polint
Building modules...
Constructing call-back function "cb_func_in_trapzd__user__routines"
def func(x,q): return sum
Building module "min_example"...
Constructing wrapper function "qromb"...
routsign2map: Confused: function qromb has externals ['func'] but no "use" statement.
sign2map: Confused: external func is not in lcb_map[].
append_needs: unknown need 'func'
append_needs: unknown need 'func'
qromb(func,a,b,ss,q,[func_extra_args])
Constructing wrapper function "trapzd"...
trapzd(func,a,b,s,n,q,[func_extra_args])
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "./min_examplemodule.c"
Fortran 90 wrappers are saved to "./min_example-f2pywrappers2.f90"
<auto-generated documentation strings>
f2py: 2
scipy: 2
并生成以下文件:
min_example-f2pywrappers2.f90
min_example.mod
min_example.o
qromb.o
min_examplemodule.c
这看起来很有希望,但当我进入python时,我无法导入该函数 为了让F2PY为Fortran过程创建包装,它需要完全识别Fortran过程参数的类型和意图,即参数是整数/实数、标量/向量、输入/输出/两者,等等。在F2PY中,此Fortran接口称为过程的签名。如果函数作为参数传递(例如
trapzd
中的func
和链接文件qromb.f
中的qromb
),F2PY还需要为传递的函数参数标识此信息。与Fortran 90及更高版本不同,Fortran 77(似乎是用qromb.f
编写的方言)没有提供任何语言直接在Fortran代码中明确定义此信息
因此,在您的案例中发生的情况是,F2PY无法使用手头的信息自动识别过程签名(因此是未知的_子例程输出)
但是,F2PY可以通过多种方式成功包装代码:
qromb.f
的过程签名文件qromb
min_示例
模块,并将Fortran 77代码作为
预编译对象到F2PY。例如,见本报告第一部分
. 李>
qromb.f
,
显式定义所有接口(您的代码似乎已被修改
来自Fortran 77中的数值公式,其中Fortran 90
版本存在,这可能会有所帮助)f2py -m min_example -h min_example.pyf min_example.f90 qromb.f
f2py -c min_example.pyf min_example.f90 qromb.f
这将创建一个名为min_example.pyf
的签名文件,打开该文件,您将注意到trapzd
和qromb
的Fortran接口(F2PY签名)仅显示为未知的子例程
。此外,polint
的接口需要修改
然后,第二步是修改min_example.pyf
,使其仅由以下文本组成(另请参阅):
第三步也是最后一步是通过执行以下命令,使用F2PY和手动更正的签名文件编译源代码:
f2py -m min_example -h min_example.pyf min_example.f90 qromb.f
f2py -c min_example.pyf min_example.f90 qromb.f
您的示例没有显示您打算如何在Python中使用Fortran代码,但下面是一个示例Python脚本,显示了刚刚编译的模块的使用:
import numpy as np
from scipy.integrate import romberg
import min_example
print(min_example.__doc__)
print(min_example.qromb.__doc__)
def func(x, q):
return q*np.sin(x)
a = 0.0
b = np.pi
q = 1.0
f_f2py = min_example.qromb(func, a, b, q)
f_scipy = romberg(func, a, b, args=(q,))
print("f2py: {:0.7g}".format(f_f2py))
print("scipy: {:0.7g}".format(f_scipy))
这给了我以下输出:
Reading fortran codes...
Reading file 'min_example.f90' (format:free)
Reading file 'qromb.f' (format:fix,strict)
Post-processing...
Block: min_example
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: func
Block: polint
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: polint
Building modules...
Constructing call-back function "cb_func_in_trapzd__user__routines"
def func(x,q): return sum
Building module "min_example"...
Constructing wrapper function "qromb"...
routsign2map: Confused: function qromb has externals ['func'] but no "use" statement.
sign2map: Confused: external func is not in lcb_map[].
append_needs: unknown need 'func'
append_needs: unknown need 'func'
qromb(func,a,b,ss,q,[func_extra_args])
Constructing wrapper function "trapzd"...
trapzd(func,a,b,s,n,q,[func_extra_args])
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "./min_examplemodule.c"
Fortran 90 wrappers are saved to "./min_example-f2pywrappers2.f90"
<auto-generated documentation strings>
f2py: 2
scipy: 2
f2py:2
科学:2
如果没有工作示例,我看不出您是否正在提交f77固定格式文件,以在f90自由格式选项下编译。如果您有Fortran或cpp意义上的include文件,则需要遵循以下规则:如果没有工作示例,我看不出您是否正在提交f77固定格式文件以在f90自由格式选项下编译。如果您有Fortran或cpp意义上的include文件,则需要遵循以下规则:注释必须以开头!不能超出第72列或跨行继续。必须避免使用语句标签(以数字开头的行)。续行必须在第6列中使用&并在第72列之后重复(第一行和后面的&,后面的行和在每一端)。延续不能跨行传输标识符。使用f2py编译模块通常是完全正确的,前提是f2py只交给源代码中的模块,其余的预编译。你能试试f2py-m min_example min_example.f90 qromb.f吗
?嗨,@tim18,谢谢你的评论!我想我已经提交了一个工作示例(链接中显示了文件'qromb.f')。你还需要什么?嗨@Pierredebyl,我已经在我的问题中添加了一个编辑来显示当我尝试时会发生什么(太长了,无法在这里发布)。这看起来确实是一个进步,但我真的不明白,也不知道下一步该怎么做?非常感谢!我可以证实这是完美的。谢谢你把逻辑解释得这么清楚。我从中学到了很多!:)