Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 运行f2py时,主.f90模块调用特定的.f文件时出现问题?(未知的_子程序?)_Python_Fortran_Gfortran_F2py - Fatal编程技术网

Python 运行f2py时,主.f90模块调用特定的.f文件时出现问题?(未知的_子程序?)

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

我正在尝试使用f2py将fortran函数与我的主python代码集成。但是,当我尝试包含一个特定的“.f”文件时,f2py会引发一个错误(但可以与其他“.f”文件一起使用)。我已经为我的主“.f90”文件创建了以下最小工作示例:

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可以通过多种方式成功包装代码:

  • 协助F2PY通过创建和 手动修改
    qromb.f
    的过程签名文件
  • 定义接口并在您的应用程序中使用例如
    qromb
    min_示例
    模块,并将Fortran 77代码作为 预编译对象到F2PY。例如,见本报告第一部分 .
  • 用更现代的Fortran方言重写
    qromb.f
    , 显式定义所有接口(您的代码似乎已被修改 来自Fortran 77中的数值公式,其中Fortran 90 版本存在,这可能会有所帮助)
  • 您提到您是Fortran新手,因此可能不想直接修改源代码。考虑到这一点,我将更详细地描述上面列出的第一个解决方案,并将其应用于您的示例:

    第一步是通过执行以下命令创建签名文件(请参见中的智能方式):

    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,我已经在我的问题中添加了一个编辑来显示当我尝试时会发生什么(太长了,无法在这里发布)。这看起来确实是一个进步,但我真的不明白,也不知道下一步该怎么做?非常感谢!我可以证实这是完美的。谢谢你把逻辑解释得这么清楚。我从中学到了很多!:)