使用f2py从Python即时分配Fortran中的向量

2 投票
1 回答
534 浏览
提问于 2025-04-17 14:53

我有一个在Python中调用的子程序,开头是这样的:

在Python中调用它的方式是:libomp.cic(pos,mpart,boxsize,dim,npart)

subroutine cic(pos,mpart,boxsize,dim,npart,mesh)
use omp_lib
implicit none 
real*8 mpart
!f2py intent(in) :: mpart
real*8 boxsize
!f2py intent(in) :: boxsize
integer dim
!f2py intent(in) :: dim
integer*8 npart
!f2py intent(in) :: npart
real*8, dimension(0:dim-1,0:dim-1,0:dim-1) :: mesh
!f2py intent(out) :: mesh
real*8, dimension(npart,3) :: pos
!f2py intent(in) :: pos

运行Python脚本时出现错误:

error: (shape(pos,0)==npart) failed for 1st keyword npart: cic:npart=47099622
WARNING: Failure executing file: <test.py>

奇怪的是,当我把npart设置为一个整数时,它可以正常工作,但它无法从Python接收npart,也不能动态创建数组pos。使用dim时,mesh可以正常工作,但pos却不行,为什么呢?这和它们被调用的顺序有关系吗?

1 个回答

3

pos 被声明为 intent(in),这意味着在进入这个程序时,pos 应该已经被分配好内存。需要注意的是,这和在 Fortran 中使用自动数组是完全不同的,因为 pos 是一个虚拟参数。问题在于,由于 posintent(in),所以 f2py 会检查你传入的维度(mpart)和它声明的维度,因为 npart 也应该是 intent(in)。由于这两个维度不匹配,所以你会遇到错误。

换句话说,你有两个 intent(in) 的变量,而你传入的值不兼容。实际的解决方案取决于这个子程序应该做什么,以及这些虚拟参数的真正意图是什么。

如果 pos 确实是 intent(in),那么原则上你可以把 npart 改成 intent(hide),这样的话,numpy 会根据 pos 的分配维度来传递 npart 给你的子程序。例如,我相信它会被调用如下:

libomp.cic(pos,mpart,boxsize,dim)

撰写回答