!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE POIS3D                     ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE pois3d(nx,ny,nz,dx,dy,dz,eps,hole_id,                        & 7
           tem3,tem4,tem5,tem6,tem7)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:This program is designed to fill-in the holes for missing
!          single-Doppler data on a Cartesian grid.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Code originally authored by Tzvi Gal-Chen with mods by
!          Mei Xu 12-93, and Steven Lazarus 6-94.
!
!
!  MODIFICATION HISTORY:
!
!  06/94 (Steven Lazarus)
!  All logical statements removed.
!
!  03/10/96 (Limin Zhao)
!  Added an option to use a 3-D/2-D hole-filler
!
!-----------------------------------------------------------------------
!
!  INPUT ARRAYS:
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (vertical)
!
!    dx       Grid spacing in the x-direction (east/west)
!    dy       Grid spacing in the y-direction (north/south)
!    dz       Grid spacing in the z-direction (vertical)
!
!    tem3     Right hand side of the Poisson Eqn.
!    tem4     Radial velocity data
!
!  OUTPUT ARRAYS:
!
!    tem5     Data grid to be filled
!
!  WORK ARRAYS:
!
!    tem6     Check for convergence, where
!    tem7     (n,1) = Difference in tem1 between two successive iter.
!             (n,2) = tem1 at previous iteration
!
!-----------------------------------------------------------------------
!

!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE             ! Force explicit declarations

  INTEGER :: nx, ny, nz        ! Number of grid points in 3 directions
  INTEGER :: iprnt,ier

  REAL :: tem3  (nx,ny,nz)     ! RHS of Poisson Equation
  REAL :: tem4  (nx,ny,nz)     ! Radial velocity data
  REAL :: tem5  (nx,ny,nz)     ! Data grid to be filled
  REAL :: tem6  (nx,ny,nz)     ! Work array
  REAL :: tem7  (nx,ny,nz)     ! Work array

  PARAMETER(iprnt=10)       ! Controls frequency of printed output

  REAL :: dx,dy,dz             ! Grid spacing
  REAL :: tetx,tety            ! Coefficients of the 3-D Poisson
  REAL :: tetz,delt2           ! equation

!
!-----------------------------------------------------------------------
!
!  Miscellaneous local variables:
!
!-----------------------------------------------------------------------
!
  INTEGER :: i,j,k             ! Do-loop indices
  INTEGER :: iter,itmx,ki      ! Iteration control parameters
  INTEGER :: istor,jstor,kstor ! Grid location of max error

  REAL :: omeg,eps             ! Relaxation coef.,error tolerance
  REAL :: tol                  ! User-specified tolerance level
  REAL :: denom                ! Coef. ued in 3-D solver
  REAL :: dx2,dy2,dz2          ! Square of the grid spacing

  REAL :: hole_id
!
!-----------------------------------------------------------------------
!
!  Include files:
!
!-----------------------------------------------------------------------
!
  INCLUDE 'assim.inc'       ! Assim/Retr control parameters
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  PRINT *,'Entering POIS3D '
  PRINT *,'The tolerance level was set at ',eps
  PRINT *,'The option for hole-filler is ',hole_id
!
!-----------------------------------------------------------------------
!
!   Initialize the variables
!
!-----------------------------------------------------------------------
!
  DO i=1,nx
    DO j=1,ny
      DO k=1,nz
        tem6(i,j,k) =0.0
        tem7(i,j,k) =0.0
      END DO
    END DO
  END DO

!
!-----------------------------------------------------------------------
!
!   Define iteration constants:
!
!  itmx   maximum number of iterations
!  omeg   relaxation factor
!  eps    solver convergence criteria
!  denom  2.0*[(dy**2)*(dz**2)+(dx**2)*(dz**2)+(dx**2)*(dy**2)]
!  tetx   (dy**2)*(dz**2)/denom
!  tety   (dx**2)*(dz**2)/denom
!  tetz   (dx**2)*(dy**2)/denom
!  delt2  (dx**2)*(dy**2)*(dz**2)/denom
!
!-----------------------------------------------------------------------
!
  itmx=2000
  omeg=1.90

  dx2=dx*dx
  dy2=dy*dy
  dz2=dz*dz

  denom=2.0*(dy2*dz2+dx2*dz2+dx2*dy2)
  tetx=dy2*dz2/denom
  tety=dx2*dz2/denom
  tetz=dx2*dy2/denom
  delt2=dx2*dy2*dz2/denom

  IF (hole_id == 2) THEN
    denom=2.0*(dy2+dx2)
    tetx=dy2/denom
    tety=dx2/denom
    tetz=0.0
    delt2=dx2*dy2/denom
    WRITE(6,*)'I am doing 2-D hole-filling'
  END IF

  WRITE(6,*) 'dx2,dy2, dz2: ',dx2,dy2, dz2
  WRITE(6,*) 'denom,tetx,tety,tetz,delt2: ',                            &
              denom,tetx,tety,tetz,delt2
!
!-----------------------------------------------------------------------
!
!   Begin iterations
!
!-----------------------------------------------------------------------
!
  iter =0

  50    iter =iter + 1

!
!-----------------------------------------------------------------------
!
!   Store the current field every iteration
!
!-----------------------------------------------------------------------
!
  ki = MOD(iter,1)

  IF(ki == 0) THEN

    DO i=1,nx-1
      DO j=1,ny-1
        DO k=1,nz-1
          tem7(i,j,k) = tem5(i,j,k)
        END DO
      END DO
    END DO
  END IF
!
!-----------------------------------------------------------------------
!
!   Terminate the iterations after itmx times
!
!-----------------------------------------------------------------------
!
  IF(iter > itmx) THEN
    WRITE(6,60) itmx
    60      FORMAT(' after',i4,' iterations tem5 did not converge')
    ier =1
    WRITE(6,*)'Please increase iterations or check the code'
    STOP
  END IF
!
!-----------------------------------------------------------------------
!
!   Begin iterations.  Check the template (tem4) to ensure that the
!   poisson solver is applied to "non-data" points only. To preserve
!   the original data, tem5 is filled in the tem4 non-data regions and
!   is equal to tem4 in the data regions.
!
!   Fill the non-data points in the interior area.
!
!-----------------------------------------------------------------------
!
  DO k=2,nz-2
    DO j=2,ny-2
      DO i=2,nx-2
        IF(tem4(i,j,k) == spval) THEN
          tem5(i,j,k)=(tetx*(tem5(i+1,j,k)+tem5(i-1,j,k))               &
                     + tety*(tem5(i,j+1,k)+tem5(i,j-1,k))               &
                     + tetz*(tem5(i,j,k+1)+tem5(i,j,k-1))               &
                     - delt2*tem3(i,j,k))*omeg+(1.-omeg)*tem5(i,j,k)
        END IF

      END DO
    END DO
  END DO

!
!-----------------------------------------------------------------------
!
!  Handle the perimeter points separately. Here we apply mixed
!  boundary conditions, with zero normal gradient at non-data
!  points (Neumann) and Dirichlet at data points.
!
!  NOTE:  The choice of which boundary condition is determined
!         in the driver ASSIMDRIV.
!
!-----------------------------------------------------------------------
!
  DO k=2,nz-2
    DO i=2,nx-2
      IF(tem4(i,1,k) == spval) THEN
        tem5(i,1,k) = tem5(i,2,k)
      END IF
      IF(tem4(i,ny-1,k) == spval) THEN
        tem5(i,ny-1,k)= tem5(i,ny-2,k)
      END IF
    END DO
  END DO

  DO k=2,nz-2
    DO j=2,ny-2
      IF(tem4(1,j,k) == spval) THEN
        tem5(1,j,k) = tem5(2,j,k)
      END IF
      IF(tem4(nx-1,j,k) == spval) THEN
        tem5(nx-1,j,k)= tem5(nx-2,j,k)
      END IF
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!   Apply the top and bottom boundary conditions.
!
!-----------------------------------------------------------------------
!
  DO i= 2,nx-2
    DO j= 2,ny-2
      IF(tem4(i,j,1) == spval) THEN
        tem5(i,j,1) = tem5(i,j,2)
      END IF
      IF(tem4(i,j,nz-1) == spval) THEN
        tem5(i,j,nz-1) = tem5(i,j,nz-2)
      END IF
    END DO
  END DO
  DO j = 2, ny-2
    IF(tem4(1,j,1) == spval) THEN
      tem5(1,j,1) = tem5(2,j,1)
    END IF
    IF(tem4(1,j,nz-1) == spval) THEN
      tem5(1,j,nz-1) = tem5(2,j,nz-1)
    END IF
    IF(tem4(nx-1,j,nz-1) == spval) THEN
      tem5(nx-1,j,nz-1) = tem5(nx-2,j,nz-1)
    END IF
    IF(tem4(nx-1,j,1) == spval) THEN
      tem5(nx-1,j,1) = tem5(nx-2,j,1)
    END IF
  END DO

  DO i = 2, nx-2
    IF(tem4(i,1,1) == spval) THEN
      tem5(i,1,1) = tem5(i,2,1)
    END IF
    IF(tem4(i,1,nz-1) == spval) THEN
      tem5(i,1,nz-1) = tem5(i,2,nz-1)
    END IF
    IF(tem4(i,ny-1,1) == spval) THEN
      tem5(i,ny-1,1)    = tem5(i,ny-2,1)
    END IF
    IF(tem4(i,ny-1,nz-1) == spval) THEN
      tem5(i,ny-1,nz-1) = tem5(i,ny-2,nz-1)
    END IF
  END DO

!
!-----------------------------------------------------------------------
!
!  Handle the corner points separately
!
!-----------------------------------------------------------------------
!
  DO k=1,nz-1
    IF(tem4(1,1,k) == spval) THEN
      tem5(1,1,k) = tem5(2,2,k)
    END IF
    IF(tem4(1,ny-1,k) == spval) THEN
      tem5(1,ny-1,k) = tem5(2,ny-2,k)
    END IF
    IF(tem4(nx-1,1,k) == spval) THEN
      tem5(nx-1,1,k) = tem5(nx-2,2,k)
    END IF
    IF(tem4(nx-1,ny-1,k) == spval) THEN
      tem5(nx-1,ny-1,k) = tem5(nx-2,ny-2,k)
    END IF
  END DO

!-----------------------------------------------------------------------
!
!    Check convergence every iteration
!
!-----------------------------------------------------------------------
!
  ki=MOD(iter,1)

  IF(ki /= 0) GO TO 50

  DO i=2,nx-2
    DO j=2,ny-2
      DO k=2,nz-2
        IF(tem4(i,j,k) == spval) THEN
          tem6(i,j,k)= ABS(tem5(i,j,k)-tem7(i,j,k))
        END IF
      END DO
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!   Determine the largest value of tem6(i,j,k) and store its location
!
!-----------------------------------------------------------------------
!
  tol =0.0

  DO i=2,nx-2
    DO j=2,ny-2
      DO k=2,nz-2
        IF(tem4(i,j,k) == spval) THEN
          tol=MAX(tol,tem6(i,j,k))
          IF(tol == tem6(i,j,k)) THEN
            istor = i
            jstor = j
            kstor = k
          END IF
        END IF
      END DO
    END DO
  END DO

  IF((MOD(iter,iprnt)) == 0) THEN
    PRINT 110, iter, tol
    110     FORMAT(3X,'At iteration',i4,' tol is',g16.8)
    PRINT 115, istor,jstor,kstor
    115     FORMAT(3X,'The max tol appears at (i,j,k)=',3I4)
  END IF

!
!-----------------------------------------------------------------------
!
!   If the tolerance is greater than the acceptable error (eps)
!   continue iterations.
!
!-----------------------------------------------------------------------
!
  IF((tol >= eps).AND.(iter < itmx)) GO TO 50
!
!-----------------------------------------------------------------------
!
!    Cease iterations when the tolerance is less than the acceptable
!    error (eps). Solution has converged.
!
!-----------------------------------------------------------------------
!
  IF(tol < eps) THEN
    WRITE(6,120) iter
    120     FORMAT('Solution converged, # of iterations in pois3d was ',i4)
    ier=0
    RETURN
  END IF

!
!-----------------------------------------------------------------------
!
!    Cease iterations if the tolerance is greater than the acceptable
!    error and the maximum number of iterations (itmx) has been exceeded.
!
!-----------------------------------------------------------------------
!
  WRITE(6,130) iter
  130   FORMAT(' After',i4,' iterations tem5(i,j,k) did not converge')
  ier=1

  RETURN
END SUBROUTINE pois3d