4

私の問題は、f2py でコンパイルすると、一部のモジュール変数がモジュール内で定義された関数によって認識されないことです。エラーは、関数に渡される引数の変数型が宣言されている場所で発生します ( の型を記述する変数real、または次元要素など)。gfortran でコンパイルすると、このエラーは発生しません。f2py でコンパイルした場合の違いと、これらのエラーを修正するにはどうすればよいですか?

サンプル ファイル にmoddata.f90は、次のコードが含まれています。

module mod

  implicit none

  integer, parameter :: dp = selected_real_kind(15)
  integer, parameter :: nelem = 3
  real(kind=dp), dimension(nelem) :: b

  parameter (b=(/3,1,2/))

contains
  function foo(x,y) result(z)
!  dp, nelem are defined in module above
    real(kind=dp), intent(in) :: x !scalar
    integer, dimension(nelem), intent(in) :: y
!  local variable
    real(kind=dp) :: z

    z = sum(b*y*x)

  end function foo
end module mod

そして私はコンパイルします

f2py -c -m moddata moddata.f90

そして、私はこれらのエラーを受け取ります:

  y_Dims[0]=(nelem);
             ^
1 warning and 1 error generated.reduce to a constant expression

integer, parameter :: nelem=3前に再定義しinteger, dimension(nelem), intent(in) :: yて再コンパイルすると、

      real(kind=dp) foof2pywrap
                1
Error: Parameter 'dp' at (1) has not been declared or is a variable, which does not reduce to a constant expression

real(kind=dp)各宣言で同じエラーが発生し、

      foof2pywrap = foo(x, y)
                    1
Warning: Possible change of value in conversion from REAL(8) to REAL(4) at (1)

dpそのため、関数内でbyを再定義する必要integer, parameter :: dp = selected_real_kind(15)があります。そして、それは機能します。

このモジュールを fortran ラッパーでコンパイルすると、これらのエラーは発生しません。なぜnelemand dpin the function が f2py で適切にスコープされていないのだろうか?

4

1 に答える 1

4

おそらく私は間違っていますが、f2py がFortran 90のmodule+機能を処理できるとは思いません。contains

function foo(x,y) result(z)
   integer, parameter :: dp = selected_real_kind(15)
   real(kind=dp), intent(in) :: x
   integer, parameter :: nelem = 3
   integer, dimension(3), parameter :  = (/3, 1, 2/)
   integer, dimension(nelem), intent(in) :: y
   real(kind=dp) :: z

   z = sum(b*y*x)
end function

以前のようにコンパイルすると、動作します:

 >>> x = 1.0000000000
 >>> y = [2, 3, 4]
 >>> moddata.foo(x,y)
 17.0

編集

SO に関するこの質問への回答は、f2pyが Fortran 関数を Python 関数に変換する方法を理解していないことを示しています。だから私はに変更function foosubroutine foo2、次にコンパイルしf2py moddata.f90 -m moddataて出力として取得しました

Reading fortran codes...
        Reading file 'moddata.f90' (format:free)
Post-processing...
        Block: moddata
                        Block: moddata
In: :moddata:moddata.f90:moddata
get_parameters: got "invalid syntax (<string>, line 1)" on '(/3, 1, 2/)'
                                Block: foo2
Post-processing (stage 2)...
        Block: moddata
                Block: unknown_interface
                    Block: moddata
                            Block: foo2
Building modules...
        Building module "moddata"...
                Constructing F90 module support for "moddata"...
                    Variables: nelem b dp
                    Constructing wrapper function "moddata.foo2"...
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
                          z = foo2(x,y)
Wrote C/API module "moddata" to file "./moddatamodule.c"
Fortran 90 wrappers are saved to "./moddata-f2pywrappers2.f90"

そのため、倍精度が失われているように見えるため、 というファイルを編集するという提案に従って.f2py_f2cmap、私はそうしましたが、 に関してはエラーは発生しませんでしたdp。ただし、それでもエラーが発生するためnelem、これに対する2つの解決策を考えることができます。

  1. 3代わりに使用することに固執するnelem
  2. nelemandbを変数としてサブルーチンに渡します

また、この行を使用するとparameter(b = (/3.d0, 1.d0, 2.d0/) )、次のような警告が表示されることもわかりました

analyzeline: Failed to evaluate '/3.e0+1j*( 1.e0+1j*( 2.e0/)'. Ignoring: invalid syntax (<string>, line 1)

これについてどうすればよいかわかりません。x=1.0ただし、and を使用するとy=(/ 3, 6, 2/)(Python を使用する場合と Fortran プログラムでモジュールを使用する場合の両方)、答えとして 18 が得られます。

つまり、f2py を使用している場合は、関数を完全に使用しないでください。

于 2013-09-09T13:22:25.840 に答える