0

我已经用 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 
4

0 回答 0