在 geany 中除以零

Division by zero in geany

我正在尝试 运行 geany 中的子例程,但它让我不断发出以下警告

NPJ(I,J) = DBLE(((2)/((X(I+1))-(X(I-1))))*DBLE(-((1)/(X(I+1)-X(I)))-((1)/(X(I)-
X(I-1)))))+  & 

             1
Warning: Possible change of value in conversion from REAL(8) to INTEGER(4) at (1)

代码后跟

C(I,J) = -(RE(I,J))/NPJ(I,J)

在下一行。

每次我 运行 它给出的程序都会被零除。

代码在这里:

!   PROJETO 1 - MÉTODOS EXPERIMENTAIS EM HIDRODINÂMICA
!******************************************
!                                                                                  *
!         PROGRAMA PRINCIPAL                                   *
!                                                                                  *
!******************************************

    IMPLICIT DOUBLE PRECISION (A-H,O-Z)
    Parameter (NX = 100, NY = 100)

!   DECLARAÇÃO DE VARIÁVEIS
    COMMON/GRID/X(NX),Y(NY)
    COMMON/RESI/RE(NX,NY)
    COMMON/PTN/ POT(NX,NY)    
    CHARACTER*30 BOBO

!   DEFINIÇÃO DOS ARQUIVOS DE ENTRADA E SAÍDA

    OPEN(3,FILE = 'placa.dat')
    OPEN(4,FILE = 'output.dat')

!   ENTRADA DE DADOS

      READ(3,*) BOBO,IMAX
      WRITE(*,'(A30,I10)')BOBO,IMAX

      READ(3,*) BOBO,JMAX
      WRITE(*,'(A30,I10)')BOBO,JMAX

      READ(3,*) BOBO,t
      WRITE(*,'(A30,F10.3)')BOBO,t

      READ(3,*) BOBO,NMAX
      WRITE(*,'(A30,I10)')BOBO,NMAX

      READ(3,*) BOBO,UA
      WRITE(*,'(A30,D10.3)')BOBO,UA

      READ(3,*) BOBO,UB
      WRITE(*,'(A30,D10.3)')BOBO,UB

      READ(3,*) BOBO,UC
      WRITE(*,'(A30,D10.3)')BOBO,UC

      READ(3,*) BOBO,UD
      WRITE(*,'(A30,D10.3)')BOBO,UD

      READ(3,*) BOBO,UP
      WRITE(*,'(A30,D10.3)')BOBO,UP

      READ(3,*) BOBO,PREC
      WRITE(*,'(A30,D10.3)')BOBO,PREC

      READ(3,*) BOBO,NPR
      WRITE(*,'(A30,I10)')BOBO,NPR

      READ(3,*) BOBO,ITE
      WRITE(*,'(A30,I10)')BOBO,ITE

      READ(3,*) BOBO,ILE
      WRITE(*,'(A30,I10)')BOBO,ILE

      READ(3,*) BOBO,XSF
      WRITE(*,'(A30,F10.3)')BOBO,XSF

      READ(3,*) BOBO,YSF
      WRITE(*,'(A30,F10.3)')BOBO,YSF

!$$$$$$ 
!$$$$$$       WRITE(*,*)"Os dados de entrada estao corretos?"
!$$$$$$       WRITE(*,*)"1--------SIM"
!$$$$$$       WRITE(*,*)"2--------NAO"
!$$$$$$       READ(*,*)INF
!$$$$$$       IF(INF.EQ.2) STOP

!     GERAÇÃO DA MALHA COMPUTACIONAL      

      CALL MALHA(IMAX,JMAX,DX,ITE,ILE,XSF,YSF,DY)

! !     CONDIÇÃO INICIAL

      CALL INICIAL(IMAX,JMAX,UP)


!!!     INÍCIO DAS ITERAÇÕES

     CALL SOLVER(IMAX,JMAX,NMAX,PREC,N,NPR,DY,UA,UB,UD,ILE,ITE,t)

!!     FIM DA EXECUÇÃO

      STOP
      END     

!******************************************
!                                                                                   *
!           SUBROTINA MALHA                                     *
!                                                                                   *
!******************************************      

    SUBROUTINE MALHA(IMAX,JMAX,DX,ITE,ILE,XSF,YSF,DY)
    IMPLICIT DOUBLE PRECISION (A-H,O-Z)
    PARAMETER (NX=100,NY=100)
    COMMON/GRID/ X(NX),Y(NY)

    DX=1.0D0/DBLE(ITE-ILE)


    DO I=ILE,ITE
        X(I)=DX*DBLE(I-ILE)
    END DO

    DO I=ITE,IMAX
        X(I)=X(I-1)+((X(I-1)-X(I-2))*XSF)     
    END DO

    DO I=ILE-1,1,-1
        X(I)=X(I+1)+((X(I+1)-X(I+2))*XSF)     
    END DO

      Y(1) = (-DX)/2.0D0
      Y(2) = DX/2.0D0
      DY = Y(2)-Y(1)
    DO J=3, JMAX
        Y(J)=Y(J-1)+((Y(J-1)-Y(J-2))*YSF)
    END DO  

    RETURN
    END

 !******************************************
!                                                                                                       *
!           SUBROTINA INICIAL                                                   *
!                                                                                                       *
!******************************************

      SUBROUTINE INICIAL(IMAX,JMAX,UP)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
      PARAMETER (NX=100,NY=100)
      COMMON/PTN/ POT(NX,NY)
      COMMON/GRID/ X(NX),Y(NY)

      UP = 1.0D0
      DO J=1,JMAX
      DO I = 1,IMAX
        POT(I,J)=UP*X(I)

      END DO
      END DO

      RETURN
      END   

!******************************************
!                                                                                                       *
!           SUBROTINA CONTORNO                                          *
!                                                                                                       *
!******************************************

      SUBROUTINE CONTORNO(IMAX,JMAX,UA,UB,UD,ILE,ITE,DY,t)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
      PARAMETER (NX=100, NY=100)
      COMMON/GRID/ X(NX),Y(NY)
      COMMON/PTN/ POT(NX,NY)

! Entrada e Saída
      DO J=1,JMAX
        POT(1,J)=UA*X(1)
        POT(IMAX,J)=UB*X(IMAX)
      END DO

! Fronteira Superior 
      DO I=1, IMAX
        POT(I,JMAX)=UD*X(I)
      END DO

!Simetria     
      DO I=1, IMAX
      POT(I,1) = POT(I,2) 
      END DO

! Sobre o Corpo
      DO I=ILE,ITE
      POT(I,1) = POT(I,2) - 2.0D0*DY*UA*t*(1-(2.0D0*X(I)))   
      END DO

      RETURN
      END


!******************************************
!                                                               *
!           SUBROTINA RESIDUO                             *
!                                                               *
!******************************************

      SUBROUTINE RESIDUO(IMAX,JMAX,TESTE)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
      PARAMETER (NX=100, NY=100)
      COMMON/RESI/ RE(NX,NY)
      COMMON/GRID/ X(NX),Y(NY)
      COMMON/PTN/ POT(NX,NY)


!     CALCULO DO RESIDUO
      DO J=2,JMAX-1
      DO I=2,IMAX-1 
      RE(I,J) = ((2.0D0/((X(I+1))-(X(I-1))))*(((POT(I+1,J)-POT(I,J))/(X(I+1)-X(I)))-((POT(I,J)-POT(I-1,J))/(X(I)-X(I-1)))))+ &
                &((2.0D0/((Y(J+1))-(Y(J-1))))*(((POT(I,J+1)-POT(I,J))/(Y(J+1)-Y(J)))-((POT(I,J)-POT(I,J-1))/(Y(J)-Y(J-1)))))

      END DO
      END DO

!     CALCULO DO RESIDUO MAXIMO

      TESTE=0.0D0

      DO J=2,JMAX-1
      DO I=2,IMAX-1
      IF(DABS(RE(I,J)).GT.TESTE) THEN
        TESTE=DABS(RE(I,J))
      END IF
      END DO
      END DO

      RETURN
      END      

!******************************************
!                                                                                                       *
!           SUBROTINA SOLVER                                                    *
!                                                                                                       *
!******************************************

      SUBROUTINE SOLVER(IMAX,JMAX,NMAX,PREC,N,NPR,DY,UA,UB,UD,ILE,ITE,t)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
      PARAMETER (NX=100,NY=100)
      COMMON/GRID/ X(NX),Y(NY)
      COMMON/RESI/ RE(NX,NY)
      COMMON/NPJACO/ NPJ(NX,NY)
      COMMON/CORREC/ C(NX,NY)
      COMMON/PTN/ POT(NX,NY)

      TESTE=100.0D0
      N=1
      IMP=NPR-1
      OPEN(10,FILE='remax.dat')

!     INICIO DAS ITERAÇÕES
      CALL CONTORNO(IMAX,JMAX,UA,UB,UD,ILE,ITE,DY,t)
      DO WHILE((N.NE.(NMAX+1)).AND.(TESTE.GT.PREC))



      CALL RESIDUO(IMAX,JMAX,TESTE)

      WRITE(*,*) N,TESTE
      WRITE(10,*) N,TESTE

      DO J=2,JMAX-1
      DO I=2,IMAX-1
        NPJ(I,J) = (((2.0D0)/((X(I+1))-(X(I-1))))*(-((1.0D0)/(X(I+1)-X(I)))-((1.0D0)/(X(I)-X(I-1)))))+  &
            & (((2.0D0)/((Y(J+1))-(Y(J-1))))*(-((1.0D0)/(Y(J+1)-Y(J)))-((1.0D0)/(Y(J)-Y(J-1)))))

        C(I,J) = -(RE(I,J))/NPJ(I,J)

        POT(I,J) = POT(I,J)+C(I,J)   
      END DO
      END DO

      N=N+1
      IMP=IMP+1

!==========================================================================================================
!     SAÍDA DE RESULTADOS

      IF(IMP.EQ.NPR) THEN

      WRITE(4,10) IMAX,JMAX
10  FORMAT('TITLE = " Malha Cartesiana "',/,&
     &       'VARIABLES = X, Y, POT, NPJ, RE',/,&
     &       'ZONE T ="Zone-one", I=',I5,'J=',I5,',F=POINT')   

      DO J=1,JMAX
      DO I=1,IMAX
      WRITE(4,*) 'X',I,':', X(I),Y(J), POT(I,J), NPJ(I,J), RE(I,J)
      END DO
      END DO

      IMP=0
      END IF
!
      END DO

!     FIM DAS ITERAÇÕES

      RETURN 
      END

您没有在代码中声明变量,而是依靠隐式类型。因此 NPJ 是一个整数数组。这是一个坏习惯。始终声明类型,并在每个程序单元中放入 IMPLICIT NONE。它可能需要更多编码,但这是值得的。

在对NPJ(I,J)的赋值中,如果右边较小,则截断为零[1]。由于此行后跟 C(I,J) = -(RE(I,J))/NPJ(I,J),因此除以零。

在您的情况下,NPJ 可能应该声明为双精度。但是我并没有调查太多它应该做什么。


[1] 更准确地说,双精度值(称为 A)的转换就像代码中存在 INT(A,K) 一样,其中 K 是 NPJ 的整数类型(此处应为默认整数).请参阅 Fortran 2008 标准的第 7.2.1.3 节#8。您会在 13.7.81 #5 节中发现当 |A|<1.

时 INT(A) 为零