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*4
、integer(int32)
、...)。
这是我想在 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*4
、integer(int32)
、...)。