2012-09-21 12 views
7

F2py ile oynuyorum. Ben numran intrinsic türleri vs fortran 90 türleri hakkında biraz kafam karıştı. Python ile etkileşime girdiğinde, yalnızca 90'lı yıllardaki tekli hassas işleri kullanabiliyorum gibi görünüyor. f2py: Python ile arabirim oluştururken Fortran'da gerçek kesinlik belirtiliyor mu?

Ben f2py ile derlenmiş ve piton ithal edilecek, bu Fortran 90 modülü, test.f90 olduğunu varsayalım:

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 

ve böyle derlemek: Bir örnekle açıklayalım

f2py c -m Test test.f90

Sonra python:

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

IOW, f2py çift duyarlığı kabul etmiyor gibi görünüyor. Bu, girdiyi pitondan bir fortran 90 alt programına geçirirken daha da sorunlu hale gelir. Ben benim modülü uzatmak ki:

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 Yani

>>> 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)) 

-1.15948430791165406E + 155

piton test.f90

testi -m -c, herhangi gibi görünüyor python'dan gönderilecek giriş değişkeni tek bir hassasiyet olarak bildirilmelidir. Bu f2py ile bilinen bir sorun mu? Ayrıca

, bir takip sorusu olarak: Aşağıdaki anlamda çalışmalarını dp için sp dönüştürme:

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

Ama bu özel derleyici hiç olduğunu acaba? Yukarıdaki altprogramın herhangi bir mimaride herhangi bir derleyiciyle doğru şeyi yapmasını bekleyebilir miyim? Test ederken, yukarıdaki tüm örnekler için gfortran kullandım.

cevap

12

İlk örneğinizde, neden bir çift duyarlık, test.test.r_dp çift kesinlik, çift duyarlık kabul etmiyor gibi görünüyorsun bilmiyorum. Ondalık noktaya sahip bir değer ve açık bir dtype gösteren bir sayı dizisi, çift duyarlıklı bir dizidir.

İkinci örnek, F2PY'nin kind=<kind> ile tür tanımlarını ele almasında bir sınırlama gösterir. SSS: http://cens.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

Neler olduğunu görmek için, f2py test.f90 -m test numaralı telefonu çalıştırın. o haritalama hem tek duyarlıklı C "şamandıra", "gerçek (tür = sp)" ve "gerçek (tür = dp)" olduğunu

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" 

Not: Ben bu olsun.

Bunu düzeltmenin çeşitli yolları vardır.

Yöntem 1

değiştirme türü bildirimleri "gerçek (tür = 4)" ve "gerçek (tür = 8)" (veya "gerçek * 4" ve "gerçek * 8"), için sırasıyla.

Elbette, bu, selected_real_kind kullanmanın amacını ortadan kaldırır ve bazı derleyiciler için 4 ve 8, tek ve çift duyarlık için doğru KIND değerleri değildir. Bu durumda, gfortran ile, sp 4 ve dp 8, bu yüzden çalışır.

Yöntem 2

bu bildirimleri nasıl işleneceğini f2py söyle. Bu, f2py SSS'de açıklanmıştır ve yukarıda gösterilen f2py çıkışındaki "getctype: ..." mesajlarında önerilen yaklaşımdır. Bu durumda

, bunu Sonra f2py bu real(sp) ve real(dp) bildirimleri ile doğru olanı yapacaktır hattını oluşturmak

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

içeriyor (eğer f2py çalıştıran dizinde) .f2py_f2cmap adlı bir dosya oluşturur.

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 

benzer öneri için Subroutine argument not passed correctly from Python to Fortran bakınız:

Yöntem 3

Aynı zamanda kod biraz yeniden düzenlemek için çalışır.

+0

Cevabınız için teşekkürler. İlk olarak yöntem 2'yi yaptım ve bu iyi çalıştı. Ama sonra bunu yazdığım gerçek bir programa uygulamayı denedim, bu da derlemeyi bir setup.py dosyası aracılığıyla yapmak ve benzerleri yapmak için gerekenleri kullanır. Daha sonra, bir .f2py_cmap dosyasının sahip olmasının, yapı sırasında .f2py_cmap uygulamasından başarıyla uygulanan değişiklikleri uygulamasına rağmen, yeterli olmadığını buldum. Bu nedenle, 3. yöntemi kullanmam gerekti. Aslında, hassas değişkenlerin tanımları için ayrı bir modül kullanıyordum, fakat modülün üst kısmının, kullanılan tek alt yordamlar içinde değil, kullanılan 'kullanım türleri' ifadesi vardı. – arne

İlgili konular