5

Assume we need to call fortran function, which returns some values, in python program. I found out that rewriting fortran code in such way:

subroutine pow2(in_x, out_x)
      implicit none
      real, intent(in)      :: in_x
!f2py real, intent(in, out) :: out_x
      real, intent(out)     :: out_x
      out_x = in_x ** 2
      return
end

and calling it in python in such way:

import modulename
a = 2.0
b = 0.0
b = modulename.pow2(a, b)

gives us working result. Can I call fortran function in other way, cause I think the first way is a bit clumsy?

user983302
  • 1,377
  • 3
  • 14
  • 23
  • How it can help me? As far as I know it's sort of upgraded interactive mode. – user983302 Nov 19 '12 at 21:12
  • 1
    It also allows you to interface with other programs such as R, MATLAB, and FORTRAN. Check out [this video](http://pyvideo.org/video/1605/science-and-python-retrospective-of-a-mostly-s) – inspectorG4dget Nov 19 '12 at 21:26
  • what's the problem with what you have? How do you want to call it? – mgilson Nov 19 '12 at 21:29
  • @mgilson I suppose there will be situations where I'll need to update lots of fortran code in mentioned way, but I don't want to do it cause I'm not crazy and don't have time to do it. – user983302 Nov 19 '12 at 21:32

3 Answers3

10

I think you just need to change your f2py function signature slightly (so that out_x is only intent(out) and in_x is only intent(in)):

subroutine pow2(in_x, out_x)
  implicit none
  real, intent(in)   :: in_x
  !f2py real, intent(in) :: in_x
  real, intent(out)     :: out_x
  !f2py real, intent(out) :: out_x
  out_x = in_x ** 2
  return
end subroutine pow2

Now compile:

f2py -m test -c test.f90

Now run:

>>> import test
>>> test.pow2(3)   #only need to pass intent(in) parameters :-)
9.0
>>>

Note that in this case, f2py is able to correctly scan the signature of the function without the special !f2py comments:

!test2.f90
subroutine pow2(in_x, out_x)
  implicit none
  real, intent(in)   :: in_x
  real, intent(out)     :: out_x
  out_x = in_x ** 2
  return
end subroutine pow2

Compile:

f2py -m test2 -c test2.f90

run:

>>> import test2
>>> test2.pow2(3)   #only need to pass intent(in) parameters :-)
9.0
>>>
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Wow, that's awesome! This way even can return multiple variables in tuple! Just because of my curiosity if there are some other tricks I won't tick this answer right now. – user983302 Nov 19 '12 at 21:43
  • I'm frequently impressed by how easy it is to wrap fortran code with `f2py`. Because of that, I've never bothered to learn any of the python C API or even `Cython` although at some point I'd like to pick up those skills. – mgilson Nov 19 '12 at 21:45
0

Another benefit to avoiding intent(inout) arguments is (with a few other restrictions) the resulting function can be considered PURE. This is related to the no-side-effects approach taken by functional languages and pays off with better optimization and error detection by the Fortran compiler and is especially important for auto-parallelization.

Community
  • 1
  • 1
arclight
  • 1,608
  • 1
  • 15
  • 19
0

If you're using IPython, try magic command, which makes it able to write

%%fortran
subroutine pow2(in_x, out_x)
  implicit none
  real, intent(in)   :: in_x
  real, intent(out)     :: out_x
  out_x = in_x ** 2
  return
end subroutine pow2

and then simply use this function in your code (without additional imports).

Alleo
  • 7,891
  • 2
  • 40
  • 30