2012-09-21 9 views
7

私はf2pyで遊んでいます。私は、ナンキンな内在型対fortran 90型について少し混乱しています。 Fortran 90では、Pythonとやり取りするときにのみ単精度実数を使うことができるようです。私は例で説明しましょう:f2py:pythonとインターフェースするときにfortranで本当の精度を指定する?

module test 
implicit none 

integer, parameter :: sp = selected_real_kind(6,37) ! single precision 
integer, parameter :: dp = selected_real_kind(15,307) ! double precision 

real(sp) :: r_sp = 1.0 
real(dp) :: r_dp = 1.0_dp 
end module 

と、私は次のようにコンパイルします:

は、私はpythonでf2pyしてコンパイルしてインポートするには、このFORTRAN 90モジュール、test.f90を、持っていると言う

f2py -c -mテストtest.f90

その後、Pythonで:

>>> import test 
>>> test.test.r_sp 
array(1.0, dtype=float32) 
>>> test.test.r_dp 
array(1.0) 

IOW、 f2pyは倍精度を受け入れないようです。これは、pythonからfortran 90サブルーチンに入力を渡すときに、さらに問題になります。私は私のモジュールを拡張言う:だから-1.15948430791165406E + 155

>>> import test 
>>> test.test.input_sp(array(1.0,dtype=float32)) 
1.0000000  
>>> test.test.input_sp(array(1.0,dtype=float64)) 
1.0000000  
>>> test.test.input_dp(array(1.0,dtype=float32)) 
-1.15948430791165406E+155 
>>> test.test.input_dp(array(1.0,dtype=float64)) 

module test 

implicit none 
integer, parameter :: sp = selected_real_kind(6,37) ! single precision 
integer, parameter :: dp = selected_real_kind(15,307) ! double precision 

real(sp) :: r_sp = 1.0 
real(dp) :: r_dp = 1.0_dp 

contains 

subroutine input_sp(val) 
    real(sp), intent(in) :: val 
    real(sp) :: x 
    x = val 
    write(*,*) x 
end subroutine 

subroutine input_dp(val) 
    real(dp), intent(in) :: val 
    real(dp) :: x 
    x = val 
    write(*,*) x 
end subroutine 
end module 

f2py -c -mテストtest.f90

のpython、それがどのように思えますPythonから送信される入力変数は、単精度で宣言する必要があります。これはf2pyの既知の問題ですか?

また、フォローアップの質問のように、次の意味で、作品をDPするSPからの変換:

subroutine input_sp_to_dp(val) 
    real(sp), intent(in) :: val(2) 
    real(dp) :: x(2) 
    x = val 
    write(*,*) x 
end subroutine 

しかし、これがすべてでは特定のコンパイラでありますかしら?上記のサブルーチンは、任意のアーキテクチャ上の任意のコンパイラで適切な処理を行うことができますか?テストの際には、上記の例をすべて使用しました。

答えて

12

最初の例では、test.test.r_dp倍精度の場合、f2pyが倍精度を受け入れないように思われる理由はわかりません。小数点と明示的なdtypeを持たない値を示す数値配列は、倍精度配列です。

第2の例では、F2PYのタイプ定義の処理には、kind=<kind>という制限があります。 FAQをご覧ください: http://cens.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

何が起きているのかを確認するには、f2py test.f90 -m testを実行してください。それがマッピングの両方単精度であるC「フロート」は、「本物の(種類= SP)」と「現実の(種類= DP)」されていることを

Reading fortran codes... 
    Reading file 'test.f90' (format:free) 
Post-processing... 
    Block: test 
      Block: test 
       Block: input_sp 
       Block: input_dp 
Post-processing (stage 2)... 
    Block: test 
     Block: unknown_interface 
      Block: test 
       Block: input_sp 
       Block: input_dp 
Building modules... 
    Building module "test"... 
     Constructing F90 module support for "test"... 
      Variables: r_dp sp r_sp dp 
      Constructing wrapper function "test.input_sp"... 
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
       input_sp(val) 
      Constructing wrapper function "test.input_dp"... 
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). 
       input_dp(val) 
    Wrote C/API module "test" to file "./testmodule.c" 
    Fortran 90 wrappers are saved to "./test-f2pywrappers2.f90" 

注:私はこれを取得します。

これを解決するにはいくつかの方法があります。

方法1つの

変化型宣言 "実(種類= 4)" と "実際の(種類= 8)"(又は "実* 4" と "実* 8")、 にそれぞれ、

もちろん、これはselected_real_kindを使用する目的に反し、一部のコンパイラでは 4と8は単精度と倍精度の正しいKIND値ではありません。 この場合、gfortranではspが4で、dpは8なので、動作します。

方法2

それらの宣言を処理する方法をf2py伝えます。これはf2pyのFAQで説明されており、上記のf2pyの出力にある "getctype:..."メッセージで提案されているアプローチです。

この場合は、ファイルを作成しますが(あなたがf2pyを実行しているディレクトリ内).f2py_f2cmapと呼ばその後f2pyは、それらのreal(sp)real(dp)宣言して、正しいことを行いますライン

dict(real=dict(sp='float', dp='double')) 

が含まれています。

方法3

は、それはまた、あなたのコードビットを並べ替えるために動作します:

module types 

implicit none 
integer, parameter :: sp = selected_real_kind(6,37) ! single precision 
integer, parameter :: dp = selected_real_kind(15,307) ! double precision 

real(sp) :: r_sp = 1.0 
real(dp) :: r_dp = 1.0_dp 

end module 


module input 

contains 

subroutine input_sp(val) 
    use types 
    real(sp), intent(in) :: val 
    real(sp) :: x 
    x = val 
    write(*,*) x 
end subroutine 

subroutine input_dp(val) 
    use types 
    real(dp), intent(in) :: val 
    real(dp) :: x 
    x = val 
    write(*,*) dp, val, x 
end subroutine 

end module 

は、同様の提案のためのSubroutine argument not passed correctly from Python to Fortranを参照してください。

+0

あなたの答えをありがとう。私はまず方法2を行い、それはうまくいった。しかし、私はこれを実際のプログラムに適用しようとしました。これは、distutilsを使ってsetup.pyファイルなどを使ってコンパイルを行います。私はその後、.f2py_cmapファイルを持っているだけでは、ビルド中に.f2py_cmapからの変更をうまく適用しても、十分ではないことがわかりました。実際には、私はすでに精度変数の定義に別のモジュールを使用していましたが、個々のサブルーチン内ではなく、モジュールを使用したモジュールのトップの 'use types'ステートメントがありました。 – arne

関連する問題