0

I have a subroutine that calculates a large array and writes it to a file. I'm trying to transform that into a function that returns that array. However, I'm getting a very weird error which seems to be connected to the fact that I am returning an array. When I try to return a float (as a test) it works perfectly fine.

Here's the MWE, which I call from python with mwe('dir', 'postpfile', 150, 90.):

FUNCTION mwe(dir, postpfile, nz, z_scale)
IMPLICIT NONE

INTEGER         :: nz
REAL(KIND=8)    :: z_scale
CHARACTER(len=100)      :: postpfile
CHARACTER(len=100)         :: dir
REAL(kind=8)  :: mwe

print*,'dir ', dir
print*,'postpfile ', postpfile
print*,'nz ', nz
print*,'Lz ', z_scale

mwe = 4.5d0
END FUNCTION mwe

This works well and prints, as expected:

 dir dir                                                                                                 
 postpfile postpfile                                                                                           
 nz          150
 Lz    90.000000000000000     

However, if I define the function as an array:

FUNCTION mwe(dir, postpfile, nz, z_scale)
IMPLICIT NONE

INTEGER         :: nz
REAL(KIND=8)    :: z_scale
CHARACTER(len=100)      :: postpfile
CHARACTER(len=100)         :: dir
REAL(KIND=8),DIMENSION (2,23)   :: mwe

print*,'dir ', dir
print*,'postpfile ', postpfile
print*,'nz ', nz
print*,'Lz ', z_scale

mwe = 4.5d0
END FUNCTION mwe

Then it prints this:

 dir postpfile                                                                                           
 postpfile ��:����������k�� 2����V@(����H���;�!��v
 nz            0
Segmentation fault (core dumped)

I am running f2py version 2, NumPy 1.11.1 and Python 3.5.1.

EDIT

I'm compiling with f2py -c -m fmwe fmwe.f90, and calling the function with mwe('dir', 'postpfile', 150, 90.).

TomCho
  • 3,204
  • 6
  • 32
  • 83
  • @JonatanÖström Here's the new question. This way you can test my MWE. – TomCho Oct 16 '16 at 22:02
  • 1
    those code snippets are the same. – Łukasz Rogalski Oct 16 '16 at 22:17
  • @ŁukaszRogalski my bad. Just fixed it. – TomCho Oct 16 '16 at 22:29
  • How did you fix it? What did you fix? – Holmz Oct 17 '16 at 13:41
  • It may be helpful if you provide the `f2py` command that you use as well as the minimal python to show how you import and use. – d_1999 Oct 17 '16 at 14:54
  • @d_1999 Just added the info. Thanks – TomCho Oct 17 '16 at 19:51
  • Sorry for coming back late. In fact f2py is not maintained (afaik) and is not (officially) compatible with python 3.X so try using python2.7 to get higher chance of success. Then we will see if there are still any problems. I got the same results as you in python 3.5, but in python 2 something else was a problem, but that seemed to be related to some software on my machine, so you can try it. EDIT. Actually, using `apt-file find f2py` i see there is f2py for the python 3 system but it is called f2py3. – Jonatan Öström Oct 22 '16 at 18:58
  • I did some tests and made it into a subroutine, which worked fine in python3. So the second part of @trblnc's answer below is what I would do, and is also the only way I have experience with. – Jonatan Öström Oct 22 '16 at 19:59

1 Answers1

1

I think the problem is coming from somewhere from lack of the explicit interface. (not sure may be someone else can point out what is the problem more precisely.)

Even though, I am not sure about my explanation, I have 2 working cases. Changing your function into a subroutine or putting your function inside a module (which generates the explicit interface by itself) solves the issue you mentioned.

Below script still can be called like my_sub('dir', 'postpfile', 150, 90.) from python.

subroutine my_sub(mwe, dir, postpfile, nz, z_scale)
implicit none

integer,intent(in)             :: nz
real(KIND=8),intent(in)        :: z_scale
chracter(len=100),intent(in)   :: postpfile
character(len=100), intent(in) :: dir
real(KIND=8), intent(out)      :: mwe(2,23)

print*,'dir ', dir
print*,'postpfile ', postpfile
print*,'nz ', nz
print*,'Lz ', z_scale

mwe = 4.5d0
end subroutine my_sub

If you use the function within a module, you need to make the call from python a little differently; test('dir', 'postpfile', 150, 90.).

module test

contains 
function mwe(dir, postpfile, nz, z_scale)
implicit none

integer            :: nz
real(KIND=8)       :: z_scale
chracter           :: postpfile
character(len=100) :: dir
real(KIND=8)       :: mwe(2,23)

print*,'dir ', dir
print*,'postpfile ', postpfile
print*,'nz ', nz
print*,'Lz ', z_scale

mwe = 4.5d0
end function mwe

end module test

I did not try, but it will probably work with proper Fortran interface including your function.(assuming existence of the explicit interface is the key)

I hope that someone will complete/correct my answer.

trblnc
  • 222
  • 5
  • 14