      Program Converge02

      INTEGER   Ntime, Np1, Np2, Np4, Ngraph, Nbound, Nx1
      PARAMETER ( Np1 = 400, Np2 = 800, Np4 = 1600 )
      REAL*8    DT, DX, Delta, Q1(-1:1,-Np4:Np4), Q2(-1:1,-Np2:Np2), 
     /          Q4(-1:1,-Np1:Np1), Time

      OPEN(7, FILE = 'Converge02.dat' , FORM = 'formatted'  )
         READ(7, 200, ERR = 1000 ) DT, DX, Delta, Time
 200     FORMAT(3(11X,E10.4 / ),11X,E10.4)
         READ(7, 210, ERR = 1000 ) Ngraph, Nbound
 210     FORMAT(1(11X,I5 / ),11X,I5)
      CLOSE(7)

      Nx1 = NINT( 1.0D0 / DX )
      IF ( Nx1 .GT. Np1 ) THEN
         PRINT *, 'The coarsest grid is too fine.'
         STOP
      ENDIF
      IF ( DT .GE. DX ) THEN
         PRINT *, 'DT is too large.'
         STOP
      ENDIF

      CALL CONFAC(DT,DX,Delta,Time,Ngraph,Nbound,Q1,4*Nx1,Q2,2*Nx1,
     /            Q4,Nx1)
      STOP

 1000 PRINT *, "Error in reading file"
      STOP
      END

C***********************************************************************

      SUBROUTINE CONFAC(DT,DX,Delta,Time,Ngraph,Nbound,Q1,Nx4,Q2,Nx2,
     /                  Q4,Nx1)

      INTEGER   i, j, k, l, Ntime, Nx1, Nx2, Nx4, Nnon0, Ngraph, Nbound, 
     /          Npa
      REAL*8    DT, DX, Delta, Q1(-1:1,-Nx4:Nx4), Q2(-1:1,-Nx2:Nx2),
     /          Q4(-1:1,-Nx1:Nx1), Time, norm1, norm2, norm4, factor42,
     /          factor21, dx2, dx4, dt2, dt4, pi
      PARAMETER ( Npa = 1600, pi = 3.141593D0 )
      REAL*8    QA(-Npa:Npa)

C Initialize all Data. 
      
      Nnon0 = INT(Nx4*0.2D0)
      Dx4 = DX / 4.0D0
      DO j = -Nx4, -Nnon0-1
         Q1(1,j) = 0.0D0
      ENDDO 
      DO j = -Nnon0, Nnon0
         IF ( Ngraph .EQ. 1 ) THEN
            Q1(1,j) = COS(pi/Delta*(Dx4*j))/2.0D0 + 0.5D0
         ELSE
            Q1(1,j) = 0.04D0*EXP( -(Dx4*j)**2 / Delta**2 )
         ENDIF
      ENDDO 
      DO j = Nnon0+1, Nx4
         Q1(1,j) = 0.0D0
      ENDDO 

      DO j = -Nx2, Nx2
         Q2(1,j) = Q1(1,2*j)
      ENDDO

      DO j = -Nx1, Nx1
         Q4(1,j) = Q1(1,4*j)
      ENDDO

C Take a backwards step using the analytic solution.

      Dt4 = DT / 4.0D0
      DO j = -Nx4, -Nnon0-1
         Q1(0,j) = 0.0D0
      ENDDO 
      DO j = -Nnon0, Nnon0-1
         IF ( Ngraph .EQ. 1 ) THEN
            Q1(0,j) = COS(pi/Delta*(Dx4*j+Dt4))/2.0D0 + 0.5D0
         ELSE
            Q1(0,j) = 0.04D0*EXP( -(Dx4*j+Dt4)**2 / Delta**2 )
         ENDIF
      ENDDO 
      DO j = Nnon0, Nx4
         Q1(0,j) = 0.0D0
      ENDDO 

      Nnon0 = INT(Nx2*0.2D0)
      Dx2 = DX / 2.0D0
      Dt2 = DT / 2.0D0
      DO j = -Nx2, -Nnon0-1
         Q2(0,j) = 0.0D0
      ENDDO 
      DO j = -Nnon0, Nnon0-1
         IF ( Ngraph .EQ. 1 ) THEN
            Q2(0,j) = COS(pi/Delta*(Dx2*j+Dt2))/2.0D0 + 0.5D0
         ELSE
            Q2(0,j) = 0.04D0*EXP( -(Dx2*j+Dt2)**2 / Delta**2 )
         ENDIF
      ENDDO 
      DO j = Nnon0, Nx2
         Q2(0,j) = 0.0D0
      ENDDO 

      Nnon0 = INT(Nx1*0.2D0)
      DO j = -Nx1, -Nnon0-1
         Q4(0,j) = 0.0D0
      ENDDO 
      DO j = -Nnon0, Nnon0-1
         IF ( Ngraph .EQ. 1 ) THEN
            Q4(0,j) = COS(pi/Delta*(DX*j+DT))/2.0D0 + 0.5D0
         ELSE
            Q4(0,j) = 0.04D0*EXP( -(DX*j+DT)**2 / Delta**2 )
         ENDIF
      ENDDO 
      DO j = Nnon0, Nx1
         Q4(0,j) = 0.0D0
      ENDDO 

C Now get the norm for each timestep.  Be careful to evolve all three grids to
C the SAME moment in time.

      OPEN( UNIT = 11, file = 'Factor02a.dat' )
      OPEN( UNIT = 12, file = 'Factor02b.dat' )

      Ntime = INT(Time/DT)
      DO i = 1, Ntime
         DO k = 2*i-1, 2*i
            DO l = 2*k-1, 2*k
               CALL GETNORM(l,DT4,DX4,Delta,Ngraph,Nbound,Q1,QA,Nx4,
     /                      norm1)
            ENDDO
            CALL GETNORM(k,DT2,DX2,Delta,Ngraph,Nbound,Q2,QA,Nx2,norm2)
            factor21 = norm2 / norm1
            WRITE(11,500) DT*i, factor21
         ENDDO
         CALL GETNORM(i,DT,DX,Delta,Ngraph,Nbound,Q4,QA,Nx1,norm4)
         factor42 = norm4 / norm2
         WRITE(12,500) DT*i, factor42
 500     FORMAT(1X,F9.6,1P,2X,E13.6)
      ENDDO

      CLOSE(11)
      RETURN
      END

C***********************************************************************

      SUBROUTINE GETNORM(i,DT,DX,Delta,Ngraph,Nbound,Q,QA,Nx,norm)

      INTEGER   i, j, Nx, Nnon0f, Nnon0b, Nnon0l, Nnon0t, Ngraph, Nbound
      REAL*8    DT, DX, Delta, Q(-1:1,-Nx:Nx), QA(-Nx:Nx), norm, front,
     /          back, lead, tail, test

      DO j = -Nx, Nx
         Q(-1,j) = Q(0,j)
         Q(0,j) = Q(1,j)
      ENDDO

C Evolve to the next timestep.

      DO j = -Nx+1, Nx-1
         Q(1,j) = 2.0D0*Q(0,j) - Q(-1,j) + ( Q(0,j+1) 
     /            - 2.0D0*Q(0,j) + Q(0,j-1) )*( DT/DX )**2
      ENDDO

      IF ( Nbound .EQ. -1 ) THEN
         Q(1,Nx) = 2.0D0*Q(0,Nx) - Q(-1,Nx) + ( Q(0,-Nx+1) 
     /             - 2.0D0*Q(0,Nx) + Q(0,Nx-1) )*( DT/DX )**2
         Q(1,-Nx) = Q(1,Nx)
      ELSEIF ( Nbound .EQ. 0 ) THEN
         Q(1,Nx) = 0.0D0
         Q(1,-Nx) = 0.0D0
      ELSEIF ( Nbound .EQ. 1 ) THEN
         Q(1,Nx) = ( 4.0D0*Q(0,Nx) - Q(-1,Nx) + ( DT/DX )
     /             *( 4.0D0*Q(1,Nx-1) - Q(1,Nx-2) ) ) /
     /             ( 3.0D0*( 1.0D0 +( DT/DX ) ) )
         Q(1,-Nx) = ( 4.0D0*Q(0,-Nx) - Q(-1,-Nx) + ( DT/DX )
     /              *( 4.0D0*Q(1,-Nx+1) - Q(1,-Nx+2) ) ) /
     /              ( 3.0D0*( 1.0D0 +( DT/DX ) ) )
      ELSE
         PRINT *, 'Invalid value of Nbound' 
         STOP
      ENDIF

C Calculate the Analytic Solution.:

C The Periodic Boundary Condition

      DO j = -Nx, Nx
         QA(j) = 0.0D0
      ENDDO

      IF ( Nbound .EQ. -1 ) THEN
         front = DMOD((1.2D0 + i*DT),2.0D0) - 1.0D0
         IF ( front .GE. 0.0D0 ) THEN
            Nnon0f = INT(front/DX)
         ELSE
            Nnon0f = INT(front/DX) - 1
         ENDIF
         back = DMOD((0.8D0 + i*DT),2.0D0) - 1.0D0
         IF ( back .LE. 0.0D0 ) THEN
            Nnon0b = INT(back/DX)
         ELSE
            Nnon0b = INT(back/DX) + 1
         ENDIF
         test = ABS( NINT(front/DX) - front/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0f = NINT(front/DX)
         test = ABS( NINT(back/DX) - back/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0b = NINT(back/DX)
         IF ( front .LT. back ) THEN
            DO j = -Nx, Nnon0f
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - front + 0.2D0 ))/2.0D0
     /                    + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - front + 0.2D0 )**2
     /                     / Delta**2 )
               ENDIF
            ENDDO
            DO j = Nnon0b, Nx
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - back - 0.2D0 ))/2.0D0
     /                    + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - back - 0.2D0 )**2 
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ELSE
            DO j = Nnon0b, Nnon0f
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - front + 0.2D0 ))/2.0D0
     /                    + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - front + 0.2D0 )**2
     /                    / Delta**2 )
               ENDIF
            ENDDO
         ENDIF
      ENDIF

C The Fixed Boundary Condition

      IF ( Nbound .EQ. 0 ) THEN
         front = DMOD((2.2D0 + i*DT),4.0D0) - 2.0D0
         IF ( front .GE. 0.0D0 ) THEN
            Nnon0f = INT(front/DX)
         ELSE
            Nnon0f = INT(front/DX) - 1
         ENDIF
         back = DMOD((1.8D0 + i*DT),4.0D0) - 2.0D0
         IF ( back .LE. 0.0D0 ) THEN
            Nnon0b = INT(back/DX)
         ELSE
            Nnon0b = INT(back/DX) + 1
         ENDIF
         test = ABS( NINT(front/DX) - front/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0f = NINT(front/DX)
         test = ABS( NINT(back/DX) - back/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0b = NINT(back/DX)
         IF ( front .LT. -1.0D0 .OR. back .GT. 1.0D0 ) GOTO 400
         IF ( front .LT. -0.6D0 ) THEN
            DO j = -Nx, Nnon0f
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - front + 0.2D0 ))/2.0D0
     /                    + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - front + 0.2D0 )**2
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ELSEIF ( back .GT. 0.6D0 ) THEN
            DO j = Nnon0b, Nx
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - back - 0.2D0 ))
     /                      /2.0D0 + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - back - 0.2D0 )**2 
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ELSE
            DO j = Nnon0b, Nnon0f
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = COS(pi/Delta*( DX*j - front + 0.2D0 ))/2.0D0
     /                    + 0.5D0
               ELSE
                  QA(j) = 0.04D0*EXP( -( DX*j - front + 0.2D0 )**2
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ENDIF

 400     IF ( (3.8D0 - i*DT) .LT. 0.0D0 ) THEN
            lead = 2.0D0 + DMOD((3.8D0 - i*DT),4.0D0) 
         ELSE
            lead = DMOD((3.8D0 - i*DT),4.0D0) - 2.0D0
         ENDIF
         IF ( lead .LE. 0.0D0 ) THEN
            Nnon0l = INT(lead/DX)
         ELSE
            Nnon0l = INT(lead/DX) + 1
         ENDIF
         IF ( (0.2D0 - i*DT) .LT. 0.0D0 ) THEN
            tail = 2.0D0 + DMOD((0.2D0 - i*DT),4.0D0) 
         ELSE
            tail = DMOD((0.2D0 - i*DT),4.0D0) - 2.0D0
         ENDIF
         IF ( tail .GE. 0.0D0 ) THEN
            Nnon0t = INT(tail/DX)
         ELSE
            Nnon0t = INT(tail/DX) - 1
         ENDIF
         test = ABS( NINT(lead/DX) - lead/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0l = NINT(lead/DX)
         test = ABS( NINT(tail/DX) - tail/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0t = NINT(tail/DX)
         IF ( lead .GT. 1.0D0 .OR. tail .LT. -1.0D0 ) GOTO 500
         IF ( lead .GT. 0.6D0 ) THEN
            DO j = Nnon0l, Nx
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = QA(j)
     /                    - COS(pi/Delta*( DX*j - lead - 0.2D0 ))/2.0D0
     /                    - 0.5D0
               ELSE
                  QA(j) = QA(j)
     /                    - 0.04D0*EXP( -( DX*j - lead - 0.2D0 )**2 
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ELSEIF ( tail .LT. -0.6D0 ) THEN
            DO j = -Nx, Nnon0t
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = QA(j)
     /                    - COS(pi/Delta*( DX*j - tail + 0.2D0 ))/2.0D0
     /                    - 0.5D0
               ELSE
                  QA(j) = QA(j) 
     /                    - 0.04D0*EXP( -( DX*j - tail + 0.2D0 )**2
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ELSE
            DO j = Nnon0l, Nnon0t
               IF ( Ngraph .EQ. 1 ) THEN
                  QA(j) = QA(j)
     /                    - COS(pi/Delta*( DX*j - lead - 0.2D0 ))/2.0D0
     /                    - 0.5D0
               ELSE
                  QA(j) = QA(j)
     /                    - 0.04D0*EXP( -( DX*j - lead - 0.2D0 )**2
     /                      / Delta**2 )
               ENDIF
            ENDDO
         ENDIF
      ENDIF

C The Radiation Boundary Condition

      IF ( Nbound .EQ. 1 ) THEN
         front = 0.2D0 + i*DT
         back = -0.2D0 + i*DT
         IF ( back .GT. 1.0D0 ) GOTO 500
         IF ( back .LE. 0.0D0 ) THEN
            Nnon0b =  INT(back/DX)
         ELSE
            Nnon0b =  INT(back/DX) + 1
         ENDIF
         test = ABS( NINT(back/DX) - back/DX )
         IF ( test .LE. 1.0D-7 ) Nnon0b = NINT(back/DX)
         IF ( front .LE. 1.0D0 ) THEN
            Nnon0f = INT(front/DX)
            test = ABS( NINT(front/DX) - front/DX )
            IF ( test .LE. 1.0D-7 ) Nnon0f = NINT(front/DX)
         ELSE
            Nnon0f = Nx
         ENDIF
         DO j = Nnon0b, Nnon0f
            IF ( Ngraph .EQ. 1 ) THEN
               QA(j) = COS(pi/Delta*(DX*j-DT*i))/2.0D0 + 0.5D0
            ELSE
               QA(j) = 0.04D0*EXP( -(DX*j-DT*i)**2 / Delta**2 )
            ENDIF
         ENDDO
      ENDIF

C Now calculate the norm.

 500  norm = 0.0D0
      DO j = -Nx, Nx
         norm = norm + ( Q(1,j) - QA(j) )**2
      ENDDO
      norm = SQRT( norm / ( 2.0D0*Nx + 1.0D0 ) )

      RETURN
      END
