{"id":39,"date":"2022-02-18T15:25:30","date_gmt":"2022-02-18T15:25:30","guid":{"rendered":"http:\/\/www.pulsars.info\/wordpress\/?p=39"},"modified":"2022-02-18T15:25:32","modified_gmt":"2022-02-18T15:25:32","slug":"combining-fortran-and-python","status":"publish","type":"post","link":"http:\/\/www.pulsars.info\/wordpress\/uncategorized\/combining-fortran-and-python\/","title":{"rendered":"Combining Fortran and Python"},"content":{"rendered":"\n<p>It is possible to compile a dynamic library from a Fortran source code. The procedure differs slightly from one used to combine C++\/C and Python. In fact, the numpy module provides an instrument f2py to create a library from fortran source code. <a href=\"https:\/\/numpy.org\/devdocs\/f2py\/getting-started.html\">This<\/a> is one of the most useful resources about this subject.<\/p>\n\n\n\n<p>Below I show an example. First, I write a function in fortran which performs a simple numerical integration using the Euler method.<\/p>\n\n\n\n<pre style=\"color:#000000;background:#ffffff;\"><span style=\"color:#800000; font-weight:bold; \">function<\/span> <span style=\"color:#800000; font-weight:bold; \">value<\/span> <span style=\"color:#808030; \">(<\/span>step<span style=\"color:#808030; \">)<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">real<\/span><span style=\"color:#808030; \">*<\/span><span style=\"color:#008c00; \">8<\/span> step\n      <span style=\"color:#800000; font-weight:bold; \">real<\/span><span style=\"color:#808030; \">*<\/span><span style=\"color:#008c00; \">8<\/span> res<span style=\"color:#808030; \">,<\/span> <span style=\"color:#800000; font-weight:bold; \">value<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">integer<\/span> intpart\n      <span style=\"color:#800000; font-weight:bold; \">integer<\/span> n<span style=\"color:#808030; \">,<\/span> i\n      <span style=\"color:#800000; font-weight:bold; \">REAL<\/span><span style=\"color:#808030; \">*<\/span><span style=\"color:#008c00; \">8<\/span><span style=\"color:#808030; \">,<\/span> <span style=\"color:#800000; font-weight:bold; \">PARAMETER<\/span> <span style=\"color:#808030; \">::<\/span> Pi <span style=\"color:#808030; \">=<\/span> <span style=\"color:#008c00; \">3.1415927<\/span>\n      remainder <span style=\"color:#808030; \">=<\/span> mod <span style=\"color:#808030; \">(<\/span>Pi <span style=\"color:#808030; \">\/<\/span> <span style=\"color:#008c00; \">2.0<\/span><span style=\"color:#808030; \">,<\/span>  step<span style=\"color:#808030; \">)<\/span>\n      n <span style=\"color:#808030; \">=<\/span> FLOOR<span style=\"color:#808030; \">(<\/span>Pi <span style=\"color:#808030; \">\/<\/span> <span style=\"color:#008c00; \">2.0<\/span> <span style=\"color:#808030; \">\/<\/span> step<span style=\"color:#808030; \">)<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">do<\/span> i <span style=\"color:#808030; \">=<\/span> <span style=\"color:#008c00; \">0<\/span><span style=\"color:#808030; \">,<\/span> n<span style=\"color:#808030; \">,<\/span> <span style=\"color:#008c00; \">1<\/span>\n         pos <span style=\"color:#808030; \">=<\/span> i <span style=\"color:#808030; \">*<\/span> step\n         res <span style=\"color:#808030; \">=<\/span> res <span style=\"color:#808030; \">+<\/span> step <span style=\"color:#808030; \">*<\/span> cos<span style=\"color:#808030; \">(<\/span>pos<span style=\"color:#808030; \">)<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">enddo<\/span>\n      res <span style=\"color:#808030; \">=<\/span> res <span style=\"color:#808030; \">+<\/span> remainder <span style=\"color:#808030; \">*<\/span> cos<span style=\"color:#808030; \">(<\/span>Pi <span style=\"color:#808030; \">\/<\/span> <span style=\"color:#008c00; \">2.0<\/span><span style=\"color:#808030; \">)<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">value<\/span> <span style=\"color:#808030; \">=<\/span> res\n      <span style=\"color:#800000; font-weight:bold; \">return<\/span>\n      <span style=\"color:#800000; font-weight:bold; \">end<\/span>\n<\/pre>\n\n\n\n<p>This function can be compiled using following instruction:<\/p>\n\n\n\n<pre style=\"color:#000000;background:#ffffff;\">f2py-<span style=\"color:#008c00; \">2<\/span><span style=\"color:#800000; font-weight:bold; \">.<\/span><span style=\"color:#008c00; \">7<\/span> <span style=\"color:#44aadd; \">-c<\/span> --<span style=\"color:#797997; \">fcompiler<\/span><span style=\"color:#808030; \">=<\/span>gnu95 -m fun fun<span style=\"color:#800000; font-weight:bold; \">.<\/span>f95<\/pre>\n\n\n\n<p>Further I call the library fun.so inside a Python script:<\/p>\n\n\n\n<pre style=\"color:#000000;background:#ffffff;\"><span style=\"color:#800000; font-weight:bold; \">import<\/span> numpy <span style=\"color:#800000; font-weight:bold; \">as<\/span> np\n<span style=\"color:#800000; font-weight:bold; \">import<\/span> matplotlib<span style=\"color:#808030; \">.<\/span>pyplot <span style=\"color:#800000; font-weight:bold; \">as<\/span> plt\n\n<span style=\"color:#800000; font-weight:bold; \">import<\/span> fun\n\ngrid <span style=\"color:#808030; \">=<\/span> np<span style=\"color:#808030; \">.<\/span>linspace <span style=\"color:#808030; \">(<\/span><span style=\"color:#008000; \">0.01<\/span><span style=\"color:#808030; \">,<\/span> <span style=\"color:#008000; \">1.0<\/span><span style=\"color:#808030; \">,<\/span> <span style=\"color:#008c00; \">50<\/span><span style=\"color:#808030; \">)<\/span>\n\nres_list <span style=\"color:#808030; \">=<\/span> <span style=\"color:#808030; \">[<\/span><span style=\"color:#808030; \">]<\/span>\n\n<span style=\"color:#800000; font-weight:bold; \">for<\/span> i <span style=\"color:#800000; font-weight:bold; \">in<\/span> <span style=\"color:#400000; \">range<\/span> <span style=\"color:#808030; \">(<\/span><span style=\"color:#008c00; \">0<\/span><span style=\"color:#808030; \">,<\/span> <span style=\"color:#400000; \">len<\/span><span style=\"color:#808030; \">(<\/span>grid<span style=\"color:#808030; \">)<\/span><span style=\"color:#808030; \">)<\/span><span style=\"color:#808030; \">:<\/span>\n        res <span style=\"color:#808030; \">=<\/span> fun<span style=\"color:#808030; \">.<\/span>value<span style=\"color:#808030; \">(<\/span>grid<span style=\"color:#808030; \">[<\/span>i<span style=\"color:#808030; \">]<\/span><span style=\"color:#808030; \">)<\/span>\n        res_list<span style=\"color:#808030; \">.<\/span>append<span style=\"color:#808030; \">(<\/span>res<span style=\"color:#808030; \">)<\/span>\n\nplt<span style=\"color:#808030; \">.<\/span>plot<span style=\"color:#808030; \">(<\/span>grid<span style=\"color:#808030; \">,<\/span> res_list<span style=\"color:#808030; \">)<\/span>\nplt<span style=\"color:#808030; \">.<\/span>xlabel<span style=\"color:#808030; \">(<\/span><span style=\"color:#0000e6; \">'Numerical integration step size'<\/span><span style=\"color:#808030; \">)<\/span>\nplt<span style=\"color:#808030; \">.<\/span>ylabel<span style=\"color:#808030; \">(<\/span><span style=\"color:#0000e6; \">'Result of integration'<\/span><span style=\"color:#808030; \">)<\/span>\nplt<span style=\"color:#808030; \">.<\/span>savefig<span style=\"color:#808030; \">(<\/span><span style=\"color:#0000e6; \">'plot.pdf'<\/span><span style=\"color:#808030; \">)<\/span>\nplt<span style=\"color:#808030; \">.<\/span>show<span style=\"color:#808030; \">(<\/span><span style=\"color:#808030; \">)\n<\/span>\n<\/pre>\n\n\n\n<p>Since the tool f2py is a part of the numpy package, it is not required to properly transform types as it was the case with ctypes package. <\/p>\n\n\n\n<p>The result of python script run is shown below.<\/p>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"http:\/\/pulsars.info\/ignotur\/wp-content\/uploads\/2019\/09\/7834_900.jpg\" alt=\"\" class=\"wp-image-269\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting\">Troubleshooting<\/h2>\n\n\n\n<p>Recently using one popular fortran code I have experienced an usual problem. I could have easily compiled the code either using ifort or fortran, but the f2py did not work returning error:<\/p>\n\n\n\n<p>redefinition of &#8216;f2py_rout_fun_unknown_subroutine&#8217; <\/p>\n\n\n\n<p>It was absolutely not clear why subroutine is unknown and where to start searching for the problem. In reality the problem is tiny and could be solved in minutes. The solution is to start from preparing a signature file:<\/p>\n\n\n\n<p>f2py -m sig_file -h sig_file.pyf my_fotran_code.f &#8211;overwrite-signature<\/p>\n\n\n\n<p>In this case the signature file sig_file.pyf contains a few&nbsp;function unknown_function() which looks extremely suspicious. Comparing successful definitions of functions with unsuccessful ones I figured out that unsuccessful definitions looked like this:<\/p>\n\n\n\n<p>function fun1(arg1,arg2,arg3) ! tstts<\/p>\n\n\n\n<p>While successful ones did not have any comments at the end of the line. Moving comments to the next line solved the problem completely. <\/p>\n\n\n\n<p>If you use subroutines in fortran instead of functions it is important to declare an intent for f2py:<\/p>\n\n\n\n<p>Cf2py intent(in) in_par<\/p>\n\n\n\n<p>Cf2py intent(inout) out_par<\/p>\n\n\n\n<p>The variable in_par only accept parameters from the python script while out_par also changes the variable declared in Python. More examples can be found <a href=\"https:\/\/numpy.org\/devdocs\/f2py\/python-usage.html\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is possible to compile a dynamic library from a Fortran source code. The procedure differs slightly from one used to combine C++\/C and Python.&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"http:\/\/www.pulsars.info\/wordpress\/uncategorized\/combining-fortran-and-python\/\">Continue Reading<span class=\"screen-reader-text\">Combining Fortran and Python<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/posts\/39"}],"collection":[{"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/comments?post=39"}],"version-history":[{"count":1,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/posts\/39\/revisions"}],"predecessor-version":[{"id":40,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/posts\/39\/revisions\/40"}],"wp:attachment":[{"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/media?parent=39"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/categories?post=39"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.pulsars.info\/wordpress\/wp-json\/wp\/v2\/tags?post=39"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}