Reputation: 218
Here is a minimalized snippet from a Fortran subroutine that i want to call in python. The task is very simple. The first time the code is called a value is assigned to the first entry of the array iwk. The subroutine is then called a second time, the expected behaviour would be that the assigned entry is unchanged.
subroutine testf2py (md,iwk,ndp,nip)
implicit none
integer ndp
!f2py intent(in) :: ndp
integer nip
!f2py intent(in) :: nip
integer iwk(31*ndp + nip)
!f2py intent(in) :: iwk
integer md
!f2py intent(in) :: md
if ( md == 1 ) then
iwk(1) = ndp
end if
print*, iwk(1)
end
(first call: md=1, subsequent calls: md>1). The array iwk should be allocated in python and the values in the array should be untouched in between calls. Calling this function in Fortran this works without problem:
program main
implicit none
integer :: i, ndp, nip
integer, allocatable :: iwk(:)
ndp = 10
nip = 10
allocate(iwk(31*ndp+nip))
call test (1, iwk, ndp, nip)
call test (2, iwk, ndp, nip)
end program main
Output of the 2 calls:
10
10
In python, after compiling the subroutine with f2py, it does not work. The values in iwk change:
import testf2py
import numpy as np
ndp = 10
nip = 10
iwk = np.empty([31*ndp+nip,], dtype=int, order='F')
testf2py.test(1, iwk, ndp, nip)
testf2py.test(2, iwk, ndp, nip)
Output of the 2 calls:
10
1686728152
The second number is random.
I tried allocating in python in different ways, np.empty_like, np.zeros. Did not help. I assumed that the problem lies with how to allocate the iwk array (hence the question title), but not sure. What do i have to change to make it work? Preferably, i want to change only the python script and leave the Fortran code as it is.
Upvotes: 3
Views: 1603
Reputation: 59998
You tell python that the array is intent(in)
:
integer iwk(31*ndp + nip)
!f2py intent(in) :: iwk
You are not allowed to change it and expect the change will be retained. Probably you want intent(inout)
.
Even better, forget !f2py intent
and use directly:
integer, intent(inout) :: iwk(31*ndp + nip)
and the compiler will tell you you are wrong if you try to modify an intent(in)
variable.
Be careful to use the correct dtype
in Python, it must correspond to the Fortran type. Most often Fortran integer
is equivalent to int32
, but it might be int64
sometimes. You can control that in Fortran too (integer*4
, integer(int32)
,...).
Upvotes: 3