2012-09-21 13 views
7

मैं f2py के साथ खेल रहा हूं। मैं numpy आंतरिक प्रकार बनाम fortran 90 प्रकार के बारे में थोड़ा उलझन में हूँ। ऐसा लगता है जैसे मैं अजगर के साथ बातचीत करते समय, फोर्टन 90 में केवल एक परिशुद्धता वास्तविकता का उपयोग कर सकता हूं।f2py: अजगर के साथ इंटरफेसिंग करते समय फोर्टन में वास्तविक परिशुद्धता निर्दिष्ट करना?

मैं इस fortran 90 मॉड्यूल, test.f90 है, f2py साथ संकलित और अजगर में आयात करने के लिए कहते हैं::

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 

और मैं इस तरह संकलन: मुझे एक उदाहरण के साथ वर्णन करते

f2py -c -m परीक्षण test.f90

फिर, अजगर में:

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

IOW, ऐसा लगता है कि f2py डबल परिशुद्धता स्वीकार नहीं करता है। पाइथन से एक फॉरेन 90 सबराउटिन में इनपुट पास करते समय यह और भी समस्याग्रस्त हो जाता है। मैं अपने मॉड्यूल का विस्तार कहते हैं:

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 -m -c परीक्षण test.f90

अजगर

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

इसलिए, यह किसी भी तरह लगता है पाइथन से भेजे जाने वाले इनपुट चर को एकल परिशुद्धता घोषित किया जाना चाहिए। क्या यह f2py के साथ एक ज्ञात मुद्दा है?

इसके अलावा, एक अनुवर्ती प्रश्न के रूप में: एसपी से परिवर्तित काम करता है डीपी को निम्नलिखित अर्थ में,:

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

लेकिन मुझे आश्चर्य है कि अगर यह संकलक विशिष्ट बिल्कुल है? क्या मैं उपर्युक्त उपरोक्त किसी भी वास्तुकला पर किसी भी कंपाइलर के साथ सही काम करने की उम्मीद कर सकता हूं? परीक्षण करते समय, मैंने उपर्युक्त उदाहरणों के लिए gfortran का उपयोग किया।

उत्तर

12

आपके पहले उदाहरण में, मुझे नहीं पता कि ऐसा क्यों लगता है कि ऐसा लगता है कि ऐसा लगता है कि यह f2py डबल परिशुद्धता स्वीकार नहीं करता है, जब test.test.r_dp डबल परिशुद्धता है। एक numpy सरणी जो एक दशमलव बिंदु के साथ एक मूल्य दिखाता है और कोई स्पष्ट dtype एक डबल परिशुद्धता सरणी है।

दूसरा उदाहरण kind=<kind> के साथ प्रकार की परिभाषाओं के F2PY के हैंडलिंग में एक सीमा दिखाता है। एफएक्यू देखें: http://cens.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

यह देखने के लिए कि क्या हो रहा है, f2py test.f90 -m test चलाएं।

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 एकल और डबल परिशुद्धता के लिए सही किंड मान नहीं हैं। इस मामले में, gfortran के साथ, sp 4 और dp 8 है, इसलिए यह काम करता है।

विधि 2

बताएँ f2py कैसे उन घोषणाओं को संभालने के लिए। यह f2py FAQ में समझाया गया है, और यह ऊपर दिखाए गए f2py के आउटपुट में "getctype: ..." संदेशों में सुझाया गया दृष्टिकोण है।

इस मामले में, आप एक फ़ाइल (निर्देशिका है जहाँ आप f2py चल रहे हैं में) .f2py_f2cmap बनाएं जिसका नाम होता है कि लाइन

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

शामिल तब f2py उन real(sp) और real(dp) घोषणाओं के साथ सही काम करेंगे।

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 देखें:

विधि 3

यह भी अपने कोड थोड़ा पुनर्व्यवस्थित करने के लिए काम करता है।

+0

आपके उत्तर के लिए धन्यवाद। मैंने पहली बार विधि 2 की, और यह ठीक काम किया। लेकिन फिर मैंने इसे लिखने वाले वास्तविक कार्यक्रम में इसे लागू करने का प्रयास किया, जो setup.py फ़ाइल के माध्यम से संकलन करने के लिए distutils का उपयोग करता है और इसी तरह। मैंने तब पाया कि सिर्फ एक .f2py_cmap फ़ाइल होने के लिए पर्याप्त नहीं था, भले ही यह पता चला कि निर्माण के दौरान .f2py_cmap से सफलतापूर्वक परिवर्तन लागू किए गए हैं। इसलिए मुझे विधि 3 का उपयोग करना पड़ा। दरअसल, मैं पहले से ही सटीक चर की परिभाषाओं के लिए एक अलग मॉड्यूल का उपयोग कर रहा था, लेकिन मेरे पास मॉड्यूल के शीर्ष का 'उपयोग प्रकार' कथन था जो व्यक्तिगत उपरोक्त के अंदर नहीं था। – arne

संबंधित मुद्दे