f2py: Pre-allocating 数组作为 Fortran 子例程的输入

f2py: Pre-allocating arrays as input for Fortran subroutine

这是我想在 python 中调用的 Fortran 子例程的最小化片段。任务很简单。代码第一次被调用时,一个值被分配给数组的第一个条目iwk。然后第二次调用该子例程,预期的行为是分配的条目未更改。

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

(第一次调用:md=1,后续调用:md>1)。数组 iwk 应该分配在 python 中,数组中的值在调用之间应该保持不变。在 Fortran 中调用此函数没有问题:

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

2 次调用的输出:

10
10

在python中,用f2py编译子程序后,无法运行。 iwk 中的值更改:

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)

2 次调用的输出:

10
1686728152   

第二个数字是随机的。

我尝试以不同的方式在 python 中进行分配,np.empty_like、np.zeros。没有帮助。我认为问题在于如何分配 iwk 数组(因此问题标题),但不确定。我必须改变什么才能让它发挥作用?最好,我只想更改 python 脚本并保留 Fortran 代码原样。

你告诉python数组是intent(in):

  integer iwk(31*ndp + nip)
!f2py intent(in) :: iwk  

您不能更改它,希望保留更改。可能你想要 intent(inout).

更好的是,忘记!f2py intent直接使用:

  integer, intent(inout) :: iwk(31*ndp + nip)

如果您尝试修改 intent(in) 变量,编译器会告诉您错误。

注意在Python中使用正确的dtype,必须对应Fortran类型。 Fortran integer 通常等同于 int32,但有时可能是 int64。您也可以在 Fortran 中控制它(integer*4integer(int32)、...)。