Проблемы с запуском f2py с основным модулем .f90, вызывающим определенный файл .f?(Unknown_subroutine?) - PullRequest
0 голосов
/ 22 декабря 2018

Я пытаюсь использовать 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», как показано здесь: https://github.com/david-deboer/cosmo/blob/master/Komatsu/mf_jenkins/qromb.f

The error looks like this (sorry for the huge block - I'm new to this and not sure what is relevant):

running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "min_example" sources
f2py options: []
f2py:> /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
creating /tmp/tmpQULhjN/src.linux-x86_64-2.7
Reading fortran codes...
    Reading file 'qromb.f' (format:fix,strict)
Line #1 in qromb.f:"      SUBROUTINE qromb(func,a,b,ss,q) ! one parameter"
    analyzeline: No name/args pattern found for line.
Line #22 in qromb.f:"      SUBROUTINE trapzd(func,a,b,s,n,q) ! one paramete"
    analyzeline: No name/args pattern found for line.
    Reading file 'min_example.f90' (format:free)
Post-processing...
    Block: min_example
            Block: unknown_subroutine
            Block: unknown_subroutine
            Block: polint
            Block: min_example
                Block: calc_min
Post-processing (stage 2)...
    Block: min_example
        Block: unknown_interface
            Block: unknown_subroutine
            Block: unknown_subroutine
            Block: polint
            Block: min_example
                Block: calc_min
Building modules...
    Building module "min_example"...
        Constructing wrapper function "unknown_subroutine"...
          unknown_subroutine()
        Constructing wrapper function "unknown_subroutine"...
          unknown_subroutine()
        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 "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c"
    Fortran 90 wrappers are saved to "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90"
  adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.c' to sources.
  adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7' to include_dirs.
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
  adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90' to sources.
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler
customize Gnu95FCompiler using build_ext
building 'min_example' extension
compiling C sources
C compiler: gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC

creating /tmp/tmpQULhjN/tmp
creating /tmp/tmpQULhjN/tmp/tmpQULhjN
creating /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7
compile options: '-I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c'
gcc: /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
                 from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
                 from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
                 from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
                 from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
 #warning "Using deprecated NumPy API, disable it by " \
  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
 static int f2py_size(PyArrayObject* var, ...)
            ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
                 from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
                 from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
                 from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
                 from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
 #warning "Using deprecated NumPy API, disable it by " \
  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
 static int f2py_size(PyArrayObject* var, ...)
            ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
 static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
             ^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
 static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
                  ^
error: Command "gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c -o /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o -MMD -MF /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o.d" failed with exit status 1

И я компилирую его, используя:

gfortran -c min_example.f90
gfortran -c qromb.f
f2py -c qromb.f min_example.f90 -m min_example

Любая помощь будет очень цениться!Спасибо!

Обновление: я продолжил поиск и нашел очень мало потенциальных клиентов.Кто-то предположил, что у f2py есть проблема со встроенными комментариями, но удаление их не помогло.В другом ответе, который я прочитал, предлагалось преобразовать файл «.f» в файл «.f90», но, если честно, я не знаю разницы между ними (я очень новичок в Фортране).Поэтому я не знаю, как это сделать (структура файла .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"

и генерирует следующие файлы:

min_example-f2pywrappers2.f90
min_example.mod
min_example.o
qromb.o
min_examplemodule.c 

Это выглядит многообещающе, но когда я вхожу в pythonЯ не могу импортировать функцию.

1 Ответ

0 голосов
/ 30 декабря 2018

Чтобы F2PY мог создавать оболочки для процедуры на Фортране, он должен полностью определить тип и намерение аргументов процедуры на Фортране, то есть является ли аргумент целочисленным / вещественным, скалярным / векторным, входным / выходным / обоими, и т. Д.Этот интерфейс Fortran упоминается как сигнатура процедуры в F2PY.Если в качестве аргумента передается функция (например, func в trapzd и qromb в связанном файле qromb.f), F2PY также необходимо идентифицировать эту информацию для аргументов этой переданной функции.В отличие, например, от Fortran 90 и более поздних версий, Fortran 77 (диалект, на котором, кажется, написано qromb.f) не предоставляет никакого языка для явного определения этой информации непосредственно в коде Fortran.

Таким образом, то, что произошло в вашем случае, это то, что F2PY не удалось автоматически идентифицировать сигнатуры процедур с помощью имеющейся информации (отсюда вывод unknown_subroutine ).

Однако существует несколько способов, которыми F2PY может успешно обернуть ваш код:

  1. Помочь F2PY в идентификации подписей процедур, создав и вручную изменив файл сигнатур процедур для qromb.f.
  2. Определите интерфейс и используйте, например, qromb в вашем модуле min_example, и передайте код Fortran 77 как предварительно скомпилированный объект в F2PY.Смотрите, например, первую часть этого ответа .
  3. Переписать qromb.f на более современном диалекте Фортрана, явно определяя все интерфейсы (ваш код, кажется, изменен с Числовые рецепты на Фортране 77 , для которых существует версия на Фортране 90, которая можетбыть полезным).

Вы упоминаете, что вы новичок в Фортране и, следовательно, можете не хотеть напрямую изменять свой исходный код.Имея это в виду, я опишу первое из перечисленных выше решений более подробно применительно к вашему примеру:

Первый шаг - создать файл подписи (см. Умный способ в документации F2PY ), выполнив следующую команду:

f2py -m min_example -h min_example.pyf min_example.f90 qromb.f

Это создаст файл подписи с именем min_example.pyf, открыв этот файл, вы заметите, что интерфейс Fortran (F2PY * 1046)* подписи ) до trapzd и qromb отображаются только как unknown_subroutine.Кроме того, интерфейс к polint требует модификации.

Затем вы должны изменить min_example.pyf, чтобы он состоял только из следующего текста (см. Также документацию F2Py по функциям обратного вызова ):

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

python module __user__routines 
    interface
        function fun(x,q) result(res) ! in :min_example:qromb.f
            real*8 intent(in)   :: x, q
            real*8              :: res
        end function fun
    end interface
end python module __user__routines

python module min_example ! in 
    interface  ! in :min_example
        module min_example ! in :min_example:min_example.f90
            subroutine calc_min ! in :min_example:min_example.f90:min_example
            end subroutine calc_min
        end module min_example
        subroutine qromb(func,a,b,ss,q) ! in :min_example:qromb.f
            use __user__routines, func=>fun
            external func
            real*8 intent(in)    :: a, b, q
            real*8 intent(out)   :: ss
        end subroutine qromb
        subroutine trapzd(func,a,b,s,n,q) ! in :min_example:qromb.f
            use __user__routines, func=>fun
            external func
            real*8 intent(in)       :: a, b, q
            integer intent(in)      :: n
            real*8 intent(inout)    :: s
        end subroutine trapzd
        subroutine polint(xa,ya,n,x,y,dy) ! in :min_example:qromb.f
            real*8 dimension(n),intent(in)                              :: xa
            real*8 dimension(n),intent(in),depend(n)                    :: ya
            integer, optional,intent(in),check(len(xa)>=n),depend(xa)   :: n=len(xa)
            real*8 intent(in)                                           :: x
            real*8 intent(out)                                          :: y, dy
        end subroutine polint
    end interface 
end python module min_example

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

Третий и последний шаг - скомпилировать ваш исходный код, используя F2PY и исправленный вручную файл подписи, выполнив следующую команду:

f2py -c min_example.pyf min_example.f90 qromb.f

В вашем примере не показано, как вы собираетесь использовать код Фортрана в Python, но вот пример скрипта 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))

, который дает мне следующий вывод:

<auto-generated documentation strings>

f2py:  2
scipy: 2
...