我已经用 f2py 编译了我的一些 fortran 子例程,所以我可以在 python 中运行它们。起初它们似乎运行良好,但后来我遇到了一个在不应该产生影响的情况下发生的错误。
基本上我有一个 fortran 子程序,它有一个名为 death 的 inout 变量。当我在 python 循环中运行它时,它不断增加死亡人数。它一直在生成正确的死亡数字,直到我在 python 循环中添加了一个 print 语句,该语句输出了一个与子例程没有任何关系的变量。
我尝试直接从 fortran 代码中打印死亡变量,并且当它应该增加一时,死亡变量以大的随机步骤增加。当我在 python 文件的其他地方添加完全不相关的代码时,也会触发此错误。
可能相关的一件事是,我使用 fortran 子例程作为单值数组创建了 death 变量,因为这是我能够制作可由 fortran 子例程修改的变量的唯一方法。
关于如何进行调试的任何建议?我尝试使用 --debug-capi 标志进行编译。我用 Ubuntu 的 Geany 编译 python 代码。有没有更好的方法来包装 fortran 子例程?
我的编译:f2py -c -m fann FANN.f
或者
f2py --debug-capi -c -m fann FANN.f
#Here are some code samples:
import fann
deaths = fann.make_integers(1)
#below code produces the correct deaths value
for i in range(steps):
fann.walk(W,signs,3,M,N,Dm,deaths,bohr)
#below code produces the wrong deaths value
for i in range(steps):
fann.walk(W,signs,3,M,N,Dm,deaths,bohr)
if(1%20): print Rf
!我被要求显示 fortran 代码:
SUBROUTINE walk(W,sgn,potentialType,M,N,Dm,deaths,bohr)
IMPLICIT NONE
INTEGER, PARAMETER :: sizeGr = 20000
INTEGER :: potentialType
INTEGER :: i , j , k , l , d , q, M, N, Dm
INTEGER, INTENT(INOUT) :: deaths
REAL*4 :: dx1(N,Dm), W(M,N,Dm), bohr
REAL*4, SAVE :: rand, green(sizeGr)
LOGICAL, SAVE :: first_iter = .TRUE.
LOGICAL :: deleted(M), sgn(M)
Cf2py intent(in) N
Cf2py intent(in) Dm
Cf2py intent(in) M
Cf2py intent(inout) sgn(M)
Cf2py intent(inout) W
Cf2py intent(inout) deaths
Cf2py depend(M,N,Dm) W
Cf2py depend(M) sgn
Cf2py intent(in) potentialType
Cf2py intent(in) bohr
IF(first_iter) THEN
CALL tabulate_green()
first_iter = .FALSE.
deleted = .FALSE.
END IF
! iterate over walkers
DO i = 1, M
! stochastically move walker to new possition with a gaussian probability
DO k = 1, N
DO d = 1, Dm
CALL RANDOM_NUMBER(rand)
W(i,k,d) = W(i,k,d) + green( INT( rand * sizeGr ) + 1 )
END DO
END DO
CALL potential(i)
END DO
DO i = 1, M
IF( deleted(i) ) CALL death(i)
END DO
deleted = .FALSE.
CONTAINS
SUBROUTINE tabulate_green()
IMPLICIT NONE
INTEGER :: p , n , sizeGr2 = sizeGr/2
REAL*8 :: x , xol , Sy , dx , pi , halfGreen(sizeGr/2)
dx = 1.0/10000000
pi = 4.d0*atan(1.d0)
n = 0
x = 0.0
Sy = 0.0
DO p=1,100000000
Sy = Sy + dx*SQRT(1/(pi*2))*EXP(-(x**2/2))
x = x + dx
IF(Sy.GT.(n/(2.d0*sizeGr2))) THEN
halfGreen(n) = (x + xol - dx)/2
xol = x
n = n + 1
END IF
IF(n.GT.sizeGr2) EXIT
END DO
DO n=1,SIZE(green)
IF(n.LE.sizeGr2) THEN
green(n) = -halfGreen( sizeGr2 - n + 1 )
ELSE
green(n) = halfGreen( n - sizeGr2 )
END IF
END DO
END
SUBROUTINE potential(itt)
IMPLICIT NONE
INTEGER, INTENT(IN) :: itt
INTEGER :: s, l
REAL*4 :: v, work
REAL*4, SAVE :: const
LOGICAL, SAVE :: first_itt = .TRUE.
SELECT CASE (potentialType)
CASE(1)
CASE(2)
CASE(3)
IF(first_itt) THEN
const = 1/(2*bohr**4)
first_itt = .FALSE.
END IF
v = 1/(2*bohr**4)*SUM( W(itt,:,:)**2 )
CALL RANDOM_NUMBER(rand)
IF (rand.GT.EXP(-v)) THEN
CALL death(itt)
END IF
END SELECT
END
SUBROUTINE death(itt)
IMPLICIT NONE
INTEGER, INTENT(IN) :: itt
INTEGER :: jt
REAL :: rand2
CALL RANDOM_NUMBER(rand2)
jt = INT(rand2*M) + 1
DO WHILE( jt .EQ. itt )
CALL RANDOM_NUMBER(rand2)
jt = INT(rand2*M) + 1
END DO
W(itt,:,:) = W(jt,:,:)
sgn(itt) = sgn(jt)
END
END