f2py:输入不是 Fortran 连续的
f2py: input not fortran contiguous
我用 f2py 包装了一些 Fortran 代码。这是 Fortran 代码:
MODULE iteration
implicit none
contains
SUBROUTINE iterate(alpha, beta, e, es, rank, omega, smearing, prec, max_step)
REAL(kind=8), INTENT(in) :: omega, smearing, prec
INTEGER :: max_step, step, rank, cnt
COMPLEX(kind=16) :: alpha(rank,rank), beta(rank,rank), omega_mat(rank, rank), green(rank, rank)
COMPLEX(kind=16), INTENT(inout) :: e(rank,rank), es(rank,rank)
step = 0
omega_mat = 0
DO cnt=1, rank
omega_mat(cnt, cnt) = 1.0
ENDDO
omega_mat = omega_mat * (omega + (0.0, 1.0) * smearing)
DO WHILE (minval(abs(alpha)) .gt. prec .or. minval(abs(beta)) .gt. prec .and. step .lt. max_step)
green = zInverse(rank, omega_mat - e)
e = e + matmul(alpha, matmul(green, beta)) + matmul(beta, matmul(green, alpha))
es = es + matmul(alpha, matmul(green, beta))
alpha = matmul(alpha, matmul(green, alpha))
beta = matmul(beta, matmul(green, beta))
step = step + 1
ENDDO
END SUBROUTINE iterate
FUNCTION zInverse(n, a) result(ra)
INTEGER :: n,lda,ipiv(n),info,lwork
COMPLEX(kind=16)::a(n,n),ra(n,n),work(n)
ra=a
lwork=n
lda=n
CALL zgetrf(n, n, ra, lda, ipiv, info)
IF(info/=0) WRITE(0,*) 'Error occured in zgetrf!'
CALL zgetri(n, ra, lda, ipiv, work, lwork, info)
IF(info/=0) WRITE(0,*) 'Error occured in zgetri!'
END FUNCTION zInverse
END MODULE iteration
然后我用 f2py -L/usr/lib -llapack -m pyiteration -c iteration.F90
编译代码,并用
测试
import numpy as np
import pyiteration
alpha = np.array([[1,0],[0,1]], dtype='complex')
beta = np.array([[1,0],[0,1]], dtype='complex')
e = np.array([[1,0],[0,1]], dtype='complex')
es = np.array([[1,0],[0,1]], dtype='complex')
# f2py is automatically generating rank for me
pyiteration.iteration.iterate(alpha,beta, e, es, 1.0, 0.001, 0.001, 100)
但是,我收到以下错误:ValueError: failed to initialize intent(inout) array -- input not fortran contiguous
。
我用谷歌搜索发现 f2py 应该自动使数组 fortran 连续。那这里发生了什么?
在 Fortran 中创建的数组(即 out
)将 return 作为 Fortran 连续数组。但是,我的理解是,所有传入的数组(即 in
和 inout
)必须指定为 Python 中的 Fortran 连续数组。如果 f2py 将它们从连续的 C 更改为 F,那可能意味着创建一个副本,这会占用额外的内存,效率不高。
要解决此问题,您需要做的就是在每个 np.array
调用中添加一个 order='F'
kwarg。
您必须使用 order='F'
按照 Fortran 连续顺序创建数组,以便:
alpha = np.array([[1,0],[0,1]], dtype='complex', order='F')
beta = np.array([[1,0],[0,1]], dtype='complex', order='F')
e = np.array([[1,0],[0,1]], dtype='complex', order='F')
es = np.array([[1,0],[0,1]], dtype='complex', order='F')
我也遇到了这个 fortran contiguous
错误,通过将 .pyf
签名文件中的一些 intent(intout)
更改为 intent(in)
使其消失,例如:
real(kind=8) dimension(:,:),intent(in) :: kernel
integer dimension(:,:),intent(in) :: kernelmask
根据代码 kernel
和 kernelmask
都是 intent(in)
,但是 f2py
生成 .pyf
给它们 intent(inout)
。以某种方式纠正这个问题解决了连续的错误。它可能不适用于其他情况,但考虑到那里的信息太少,如果发生类似问题,您可能想尝试一下。
我用 f2py 包装了一些 Fortran 代码。这是 Fortran 代码:
MODULE iteration
implicit none
contains
SUBROUTINE iterate(alpha, beta, e, es, rank, omega, smearing, prec, max_step)
REAL(kind=8), INTENT(in) :: omega, smearing, prec
INTEGER :: max_step, step, rank, cnt
COMPLEX(kind=16) :: alpha(rank,rank), beta(rank,rank), omega_mat(rank, rank), green(rank, rank)
COMPLEX(kind=16), INTENT(inout) :: e(rank,rank), es(rank,rank)
step = 0
omega_mat = 0
DO cnt=1, rank
omega_mat(cnt, cnt) = 1.0
ENDDO
omega_mat = omega_mat * (omega + (0.0, 1.0) * smearing)
DO WHILE (minval(abs(alpha)) .gt. prec .or. minval(abs(beta)) .gt. prec .and. step .lt. max_step)
green = zInverse(rank, omega_mat - e)
e = e + matmul(alpha, matmul(green, beta)) + matmul(beta, matmul(green, alpha))
es = es + matmul(alpha, matmul(green, beta))
alpha = matmul(alpha, matmul(green, alpha))
beta = matmul(beta, matmul(green, beta))
step = step + 1
ENDDO
END SUBROUTINE iterate
FUNCTION zInverse(n, a) result(ra)
INTEGER :: n,lda,ipiv(n),info,lwork
COMPLEX(kind=16)::a(n,n),ra(n,n),work(n)
ra=a
lwork=n
lda=n
CALL zgetrf(n, n, ra, lda, ipiv, info)
IF(info/=0) WRITE(0,*) 'Error occured in zgetrf!'
CALL zgetri(n, ra, lda, ipiv, work, lwork, info)
IF(info/=0) WRITE(0,*) 'Error occured in zgetri!'
END FUNCTION zInverse
END MODULE iteration
然后我用 f2py -L/usr/lib -llapack -m pyiteration -c iteration.F90
编译代码,并用
import numpy as np
import pyiteration
alpha = np.array([[1,0],[0,1]], dtype='complex')
beta = np.array([[1,0],[0,1]], dtype='complex')
e = np.array([[1,0],[0,1]], dtype='complex')
es = np.array([[1,0],[0,1]], dtype='complex')
# f2py is automatically generating rank for me
pyiteration.iteration.iterate(alpha,beta, e, es, 1.0, 0.001, 0.001, 100)
但是,我收到以下错误:ValueError: failed to initialize intent(inout) array -- input not fortran contiguous
。
我用谷歌搜索发现 f2py 应该自动使数组 fortran 连续。那这里发生了什么?
在 Fortran 中创建的数组(即 out
)将 return 作为 Fortran 连续数组。但是,我的理解是,所有传入的数组(即 in
和 inout
)必须指定为 Python 中的 Fortran 连续数组。如果 f2py 将它们从连续的 C 更改为 F,那可能意味着创建一个副本,这会占用额外的内存,效率不高。
要解决此问题,您需要做的就是在每个 np.array
调用中添加一个 order='F'
kwarg。
您必须使用 order='F'
按照 Fortran 连续顺序创建数组,以便:
alpha = np.array([[1,0],[0,1]], dtype='complex', order='F')
beta = np.array([[1,0],[0,1]], dtype='complex', order='F')
e = np.array([[1,0],[0,1]], dtype='complex', order='F')
es = np.array([[1,0],[0,1]], dtype='complex', order='F')
我也遇到了这个 fortran contiguous
错误,通过将 .pyf
签名文件中的一些 intent(intout)
更改为 intent(in)
使其消失,例如:
real(kind=8) dimension(:,:),intent(in) :: kernel
integer dimension(:,:),intent(in) :: kernelmask
根据代码 kernel
和 kernelmask
都是 intent(in)
,但是 f2py
生成 .pyf
给它们 intent(inout)
。以某种方式纠正这个问题解决了连续的错误。它可能不适用于其他情况,但考虑到那里的信息太少,如果发生类似问题,您可能想尝试一下。