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


SUBROUTINE setrastergrid(rasterdim,radar_lat,radar_lon,rasterdx,        & 1,2
                         rasterlat,rasterlon,rasterx,rastery,           &
                         rasterdata,missing)

!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate latitudes/longitudes and Cartesian coordinates (relative to
! radar) of NIDS raster grid points surrounding a radar.  Also, resets
! raster data to missing if raster point is beyond radar range.
!
!-----------------------------------------------------------------------
!
! AUTHOR:  Eric Kemp, 5 April 2001
!
! MODIFICATION HISTORY:
!
! Eric Kemp, 1 August 2001
! Changed rasterx and rastery to automatic arrays, and added USE
! statement to module n2aconst.
!
! Eric Kemp, 9 August 2001
! Reversed earlier changes -- rasterx and rastery are now arguments
! with INTENT(OUT).  Also, added rasterdata array and missing flag
! as arguments.
!
!-----------------------------------------------------------------------
!
! Use modules
!
!----------------------------------------------------------------------- 

  USE n2aconst

!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!----------------------------------------------------------------------- 

  IMPLICIT NONE

!-----------------------------------------------------------------------
! 
! Declare arguments
! 
!-----------------------------------------------------------------------
 
  INTEGER, INTENT(IN) :: rasterdim ! Dimension of raster grid
  REAL,INTENT(IN) :: radar_lat     ! Radar latitude (positive deg north)
  REAL,INTENT(IN) :: radar_lon     ! Radar longitude (positive deg east)
  REAL,INTENT(IN) :: rasterdx      ! Raster grid spacing (m)

  REAL,INTENT(OUT) :: rasterlat(rasterdim,rasterdim) ! Latitude of raster
                                                     ! grid points
                                                     ! (positive deg
                                                     !  north)
  REAL,INTENT(OUT) :: rasterlon(rasterdim,rasterdim) ! Longitude of raster
                                                     ! grid points
                                                     ! (positive deg east)
  REAL,INTENT(OUT) :: rasterx(rasterdim,rasterdim)   ! x-coordinate of
                                                     ! grid points
  REAL,INTENT(OUT) :: rastery(rasterdim,rasterdim)   ! y-coordinate of
                                                     ! grid points
  REAL,INTENT(INOUT) :: rasterdata(rasterdim,rasterdim) ! Raster data
                                                        ! array.
  REAL,INTENT(IN) :: missing                            ! Missing value
                                                        ! flag.
                  
!-----------------------------------------------------------------------
!
! Internal variables
!
!-----------------------------------------------------------------------

  REAL :: dist,head

  INTEGER :: istatus
  INTEGER :: i,j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

!-----------------------------------------------------------------------
!
! Construct raster Cartesian grid centered on and relative to the radar.
!
!-----------------------------------------------------------------------
  
  DO j = 1,rasterdim ! Column
    DO i = 1,rasterdim ! Row
      rasterx(i,j) = rasterdx*(REAL(i) - REAL(rasterdim*0.5) - 0.5) ! m  
      rastery(i,j) = rasterdx*(REAL(j) - REAL(rasterdim*0.5) - 0.5) ! m
    END DO ! Row
  END DO ! Column

!-----------------------------------------------------------------------
!
! Calculate latitudes and longitudes of each raster point by following
! the great circle path from the radar (lat and lon) to the raster
! point.  Also, set rasterdata to missing if it is beyond 230 km from 
! the radar.
!
!-----------------------------------------------------------------------

  DO j = 1,rasterdim ! Column
    DO i = 1,rasterdim ! Row
      dist = SQRT( (rasterx(i,j)*rasterx(i,j)) +                        &
                   (rastery(i,j)*rastery(i,j)) )

      IF (dist > 230000.) THEN
        rasterdata(i,j) = missing
      END IF

      IF (rasterx(i,j) == 0 .AND. rastery(i,j) == 0) THEN
        head = 0.
      ELSE
        head = ATAN2(rasterx(i,j),rastery(i,j))*rad2deg
      END IF
      CALL gcircle(radar_lat,radar_lon,head,dist,                       &
                   rasterlat(i,j),rasterlon(i,j))
    END DO ! Row
  END DO ! Column
      
  RETURN
END SUBROUTINE setrastergrid

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

SUBROUTINE remapraster(nx,ny,xs2d,ys2d,dx,rasterchek,datamiss,xrad,yrad,& 2,4
                       remapopt,radius,rnx,rny,rasterdata,              &
                       radx,rady,remdata,istatus)
  
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Remap 2d raster data to ARPS grid.  Several remapping methods are 
! available: 
!
! 1.  Bi-quadratic interpolation.  IMPORTANT:  Raster and ARPS
!     Cartesian coordinates must be in radar projection space.
!
! 2.  Bi-quadratic regression (requires radius of influence).
!
!     a.  If at least eight radar data points are matched to an ARPS
!         scalar point, a bi-quadratic regression equation of the
!         form V = A + B*x + C*y + D*x*x + E*y*y is solved for
!         to determine the data value at the scalar point.  A check
!         is made to make sure that the solution is within the
!         maximum and minimum radar point values; if this criteria
!         is not met, the minimum radar point value is substituted
!         for the regression solution.
!
!     b.  If between one and eight radar data points are matched to
!         an ARPS scalar point, the radar point values are simply
!         averaged.
!
! 3.  Using maximum raster value (requires radius of influence).
!     
!-----------------------------------------------------------------------
!         
! AUTHOR:  Eric Kemp, 27 April 2001
!          Based on subroutine 'remap' by Keith Brewster and
!          interpolation procedure used in program arpsextsnd.
!
! MODIFICATION HISTORY:
!
! Eric Kemp, 1 August 2001
! Reorganized code and updated documentation.
!          
! Eric Kemp, 9 August 2001
! Changed ARPS scalar grid point arguments to 2-dimensions.
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------

  IMPLICIT NONE
      
!-----------------------------------------------------------------------
!             
! Declare arguments
!     
!-----------------------------------------------------------------------
          
  INTEGER, INTENT(IN) :: nx,ny     ! Dimensions of ARPS grid
  INTEGER, INTENT(IN) :: rnx, rny  ! Dimensions of raster data
  INTEGER, INTENT(IN) :: remapopt  ! Remapping option.
                                   ! 1 = Bi-quadratic interpolation
                                   ! 2 = Bi-quadratic regreesion/mean
                                   ! 3 = Maximum raster value
  REAL, INTENT(IN) :: radius       ! Radius of influence used with
                                   ! remapopt = 2 or 3.
  REAL, INTENT(IN) :: dx           ! ARPS horizontal grid resolution (m)
  REAL, INTENT(IN) :: rasterchek   ! Flag for missing raster data.
  REAL, INTENT(IN) :: datamiss     ! Flag for missing remapped data.
  REAL, INTENT(IN) :: xs2d(nx,ny),ys2d(nx,ny) ! Scalar coordinates of
                                              ! ARPS grid points (m).
  REAL, INTENT(IN) :: xrad,yrad    ! Scalar coordinates of radar (m).
  REAL, INTENT(IN) :: rasterdata(rnx,rny) ! Raster data (VIL, echo top, 
                                          ! etc.)
  
  REAL, INTENT(IN) :: radx(rnx,rny)   ! x coordinate of raster point.
  REAL, INTENT(IN) :: rady(rnx,rny)   ! y coordinate of raster point.
  REAL, INTENT(OUT) :: remdata(nx,ny) ! Remapped radar data.
  INTEGER, INTENT(OUT) :: istatus     ! Status variable
                                   
!-----------------------------------------------------------------------
!
!  Declare functions
!
!-----------------------------------------------------------------------
  
   REAL :: pntint2d2d
  
!-----------------------------------------------------------------------
!
!  Interpolation arrays
!
!-----------------------------------------------------------------------
  
  INTEGER, ALLOCATABLE :: ipt(:,:)
  INTEGER, ALLOCATABLE :: jpt(:,:) 

  REAL, ALLOCATABLE :: dxfld(:,:)
  REAL, ALLOCATABLE :: dyfld(:,:)
  REAL, ALLOCATABLE :: rdxfld(:,:)
  REAL, ALLOCATABLE :: rdyfld(:,:)
  REAL, ALLOCATABLE :: slopey(:,:)
  REAL, ALLOCATABLE :: alphay(:,:)
  REAL, ALLOCATABLE :: betay(:,:)

!-----------------------------------------------------------------------
!  
! Declare internal variables for least-squares curve fitting.
!
!-----------------------------------------------------------------------
  
  INTEGER, PARAMETER :: n = 5   ! Quadratic

  REAL, ALLOCATABLE :: araster(:,:)
  REAL, ALLOCATABLE :: rhsraster(:)
  REAL, ALLOCATABLE :: sol(:)
  REAL, ALLOCATABLE :: work(:,:)
  REAL, ALLOCATABLE :: work1d(:)

!-----------------------------------------------------------------------
!
! Other internal variables
!
!-----------------------------------------------------------------------
   
  REAL :: ddx,ddy
  REAL :: dxthr
  LOGICAL :: rastergood
  REAL :: rastermax, rastermin, rastermean
  INTEGER :: i,j,ii,jj
  REAL :: delx, dely
  REAL :: slrange
  INTEGER :: knt
  
  REAL, PARAMETER :: eps = 1.0E-25
  
  INTEGER, PARAMETER :: iorder = 2 ! Bi-quadratic interpolation

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
! 
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  IF (remapopt < 1 .OR. remapopt > 3) THEN
    WRITE(6,*)'remapraster:  ERROR -- Invalid remap option.'
    WRITE(6,*)'remapraster:  remapopt = ',remapopt
    WRITE(6,*)'remapraster:  Aborting...'
    istatus = 1
    RETURN
  END IF  

  remdata(:,:) = datamiss
  
!-----------------------------------------------------------------------
!
! Allocate necessary arrays and coefficients.
!
!-----------------------------------------------------------------------
  
  IF (remapopt == 1) THEN ! Bi-quadratic interpolation

    ALLOCATE(ipt(nx,ny),STAT=istatus)
    ALLOCATE(jpt(nx,ny),STAT=istatus)
    ALLOCATE(dxfld(rnx,rny),STAT=istatus)
    ALLOCATE(dyfld(rny,rny),STAT=istatus)
    ALLOCATE(rdxfld(rnx,rny),STAT=istatus)
    ALLOCATE(rdyfld(rnx,rny),STAT=istatus)
    ALLOCATE(slopey(rnx,rny),STAT=istatus)
    ALLOCATE(alphay(rnx,rny),STAT=istatus)
    ALLOCATE(betay(rnx,rny),STAT=istatus)
    
    CALL setijloc2(rnx,rny,nx,ny,ipt,jpt,radx,rady,xs2d,ys2d)
  
    CALL setdxdy2d(rnx,rny,                                              &
               1,rnx,1,rny,                                              &
               radx,rady,dxfld,dyfld,rdxfld,rdyfld)
    
    CALL setdrvy2d(rnx,rny,1,                                            &
               1,rnx,1,rny,1,1,                                          &
               dyfld,rdyfld,rasterdata,                                  &
               datamiss,slopey,alphay,betay)

  ELSE

    ALLOCATE(araster(n,n),STAT=istatus)
    ALLOCATE(rhsraster(n),STAT=istatus)
    ALLOCATE(sol(n),STAT=istatus)
    ALLOCATE(work(n,n+1),STAT=istatus)
    ALLOCATE(work1d(n+1),STAT=istatus)

  END IF ! IF (remapopt == 1)
        
  DO j=1,ny
    DO i=1,nx

!-----------------------------------------------------------------------
!
!     Proceed with the bi-quadratic interpolation.
!
!-----------------------------------------------------------------------
               
      IF (remapopt == 1) THEN
        IF (ipt(i,j) <= rnx-1 .AND. ipt(i,j) >= 1 .AND.                 &
            jpt(i,j) <= rny-1 .AND. jpt(i,j) >= 1)  THEN
  
          remdata(i,j)=pntint2d2d(rnx,rny,                              &
               1,rnx-1,1,rny-1,                                         &
               iorder,radx,rady,xs2d(i,j),ys2d(i,j),                    &
               ipt(i,j),jpt(i,j),rasterdata,                            &
               dxfld,dyfld,rdxfld,rdyfld,                               &
               datamiss,slopey,alphay,betay)

          IF (remdata(i,j) /= datamiss) THEN
            remdata(i,j) = MAX(0.,remdata(i,j))
          END IF
        END IF
      ELSE ! remapopt /= 1
 
!-----------------------------------------------------------------------
!
!       Using an option that requires the radius of influence.  First,
!       determine the distance between the current ARPS grid point and 
!       the radar.              
!      
!----------------------------------------------------------------------- 

        delx=xs2d(i,j)-xrad
        dely=ys2d(i,j)-yrad
        slrange=SQRT(delx*delx + dely*dely)
    
        IF (slrange > 0.) THEN
               
          rastermax = -9999.
          rastermin = 9999.
        
          araster(:,:) = 0.
          rhsraster(:) = 0.

!-----------------------------------------------------------------------
!       
!         Loop through each raster data point, searching for valid
!         data.
!
!-----------------------------------------------------------------------
  
          DO jj = 1,rny
            DO ii = 1,rnx
              rastergood = (rasterdata(ii,jj) > rasterchek)
        
              IF (rastergood) THEN

!-----------------------------------------------------------------------
!       
!               For a "valid" raster data point, find the distance
!               between the data point and the current ARPS scalar
!               grid point.
!
!-----------------------------------------------------------------------

                ddx=radx(ii,jj)-xs2d(i,j)
                ddy=rady(ii,jj)-ys2d(i,j)

!-----------------------------------------------------------------------
!
!               Compare radius of influence with actual horizontal 
!               ddx and ddy) distances between the raster point and the
!               ARPS scalar point.  If actual distance is within the
!               threshold, we'll process the raster point.
!
!-----------------------------------------------------------------------

                dxthr = radius

                IF ( SQRT((ddx*ddx) + (ddy*ddy)) < dxthr ) THEN
                  rastermax=MAX(rastermax,rasterdata(ii,jj))
                  rastermin=MIN(rastermin,rasterdata(ii,jj))

                  IF (remapopt == 2) THEN ! Regression/average option

!-----------------------------------------------------------------------
!
!                   Save raster data and 2-D raster point to grid point
!                   data.  These data will be used to determine the
!                   grid point value using least squares curve fitting
!                   (Data = A + B*ddx + C*ddy + D*ddx*ddx + E*ddy*ddy).
!               
!-----------------------------------------------------------------------

                    rhsraster(1)=rhsraster(1)+rasterdata(ii,jj) 
                    rhsraster(2)=rhsraster(2)+rasterdata(ii,jj)*ddx
                    rhsraster(3)=rhsraster(3)+rasterdata(ii,jj)*ddy
                    rhsraster(4)=rhsraster(4)+rasterdata(ii,jj)*ddx*ddx
                    rhsraster(5)=rhsraster(5)+rasterdata(ii,jj)*ddy*ddy

                    araster(1,1)=araster(1,1)+1.  
                    araster(1,2)=araster(1,2)+ddx
                    araster(1,3)=araster(1,3)+ddy 
                    araster(1,4)=araster(1,4)+(ddx*ddx)
                    araster(1,5)=araster(1,5)+(ddy*ddy)
                    
                    araster(2,1)=araster(2,1)+ddx 
                    araster(2,2)=araster(2,2)+ddx*ddx 
                    araster(2,3)=araster(2,3)+ddx*ddy 
                    araster(2,4)=araster(2,4)+ddx*ddx*ddx
                    araster(2,5)=araster(2,5)+ddx*ddy*ddy

                    araster(3,1)=araster(3,1)+ddy
                    araster(3,2)=araster(3,2)+ddy*ddx
                    araster(3,3)=araster(3,3)+ddy*ddy
                    araster(3,4)=araster(3,4)+ddy*ddx*ddx
                    araster(3,5)=araster(3,5)+ddy*ddy*ddy

                    araster(4,1)=araster(4,1)+ddx*ddx
                    araster(4,2)=araster(4,2)+ddx*ddx*ddx
                    araster(4,3)=araster(4,3)+ddx*ddx*ddy
                    araster(4,4)=araster(4,4)+ddx*ddx*ddx*ddx
                    araster(4,5)=araster(4,5)+ddx*ddx*ddy*ddy
                    
                    araster(5,1)=araster(5,1)+ddy*ddy
                    araster(5,2)=araster(5,2)+ddy*ddy*ddx
                    araster(5,3)=araster(5,3)+ddy*ddy*ddy
                    araster(5,4)=araster(5,4)+ddy*ddy*ddx*ddx
                    araster(5,5)=araster(5,5)+ddy*ddy*ddy*ddy

                  END IF ! remapopt
                END IF ! (ABS(ddx) < dxthr .AND. ABS(ddy) < dxthr)
              END IF ! Is rastergood true?
            END DO ! ii loop
          END DO ! jj loop

!-----------------------------------------------------------------------
!
!         At this point we've gone through all the radar pixels to see
!         which one(s) can be matched to an ARPS grid point.  Now we'll
!         process the data we've saved.
!                   
!-----------------------------------------------------------------------
                    
          IF (remapopt == 3) THEN ! Use maximum value
            remdata(i,j) = rastermax

          ELSE ! remapopt == 2
            knt = NINT(araster(1,1)) ! Number of raster points matched
                                     ! to grid point.

            IF (knt >= 8) THEN
!            IF (knt >= 5) THEN

!-----------------------------------------------------------------------
!         
!             If at least eight raster points have been matched to the
!             grid point, use Gauss-Jordan elimination to calculate the 
!             constants in the least square curve equation.  The
!             resulting grid point value is then checked with the
!             maximum and minimum raster point values.
!
!-----------------------------------------------------------------------
                  
              CALL gjelim(n,araster,rhsraster,sol,work,work1d,eps,      &
                          istatus)
              remdata(i,j) = MIN(rastermax,MAX(rastermin,sol(1)))

!            ELSE IF (knt >= 4) THEN
            ELSE IF (knt >= 1) THEN

!-----------------------------------------------------------------------
!
!             If at least one (but less than eight) raster points have  
!             been matched to the grid point, simply calculate the
!             average raster value and assign it to the grid point.
!             
!-----------------------------------------------------------------------

              rastermean=rhsraster(1)/araster(1,1)
              remdata(i,j)=rastermean

            END IF ! knt
          END IF ! remapopt = 2 vs. 3
        END IF ! slrange > 0.
      END IF ! if remapopt = 1
    END DO ! i loop
  END DO ! j loop

!-----------------------------------------------------------------------
!             
! Deallocate arrays and return.
!
!-----------------------------------------------------------------------
              
  IF (remapopt == 1) THEN
    DEALLOCATE(ipt,jpt,dxfld,dyfld,rdxfld,rdyfld,slopey,alphay,betay,   &
               STAT=istatus)
  ELSE
    DEALLOCATE(araster,rhsraster,sol,work,work1d,STAT=istatus)
  END IF

  istatus = 0
  RETURN
END SUBROUTINE remapraster

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


SUBROUTINE setdxdy2d(nx,ny,                                             & 1
           ibeg,iend,jbeg,jend,                                         &
           x2d,y2d,dxfld,dyfld,rdxfld,rdyfld)

!-----------------------------------------------------------------------
!
!  PURPOSE:
!    Calculate the local delta-x, delta-y and their inverses.
!    Precalculating these variables speeds up later calculations.  
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Keith Brewster, CAPS, November, 1996
!
!  MODIFICATION HISTORY:
!
!  Eric Kemp, 27 April 2001
!  Modified to allow for two-dimensioned arrays.
!
!  Eric Kemp, 9 August 2001
!  Added INTENT statements.
!
!----------------------------------------------------------------------- 
!
! Force explicit declarations
!
!----------------------------------------------------------------------- 

  IMPLICIT NONE

!----------------------------------------------------------------------- 
!
!  INPUT:
!    nx       Number of model grid points in the x-direction (east/west)
!    ny       Number of model grid points in the y-direction (north/south)
!  
!    ibeg,iend   Range of x index to do interpolation
!    jbeg,jend   Range of y index to do interpolation
!
!    x2d     Array of x-coordinate grid locations (m)
!    y2d     Array of y-coordinate grid locations (m)
!  
!  OUTPUT:
!    dxfld    Vector of delta-x (m) of field to be interpolated
!    dyfld    Vector of delta-y (m) of field to be interpolated
!    rdxfld   Vector of 1./delta-x (1/m) of field to be interpolated
!    rdyfld   Vector of 1./delta-y (1/m) of field to be interpolated
!
!----------------------------------------------------------------------- 

  INTEGER, INTENT(IN) :: nx,ny
  INTEGER, INTENT(IN) :: ibeg,iend
  INTEGER, INTENT(IN) :: jbeg,jend
  REAL, INTENT(IN) :: x2d(nx,ny)
  REAL, INTENT(IN) :: y2d(nx,ny)
  REAL, INTENT(OUT) :: dxfld(nx,ny)
  REAL, INTENT(OUT) :: dyfld(nx,ny)
  REAL, INTENT(OUT) :: rdxfld(nx,ny)
  REAL, INTENT(OUT) :: rdyfld(nx,ny)

!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------
  
  INTEGER :: i,j,istop,jstop

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  
  istop=MIN((iend-1),(nx-1))
  jstop=MIN((jend-1),(ny-1))
 
  DO j=jbeg,jstop
    DO i=ibeg,istop
      dxfld(i,j)=(x2d(i+1,j)-x2d(i,j))
      rdxfld(i,j)=1./(x2d(i+1,j)-x2d(i,j))
      dyfld(i,j)=(y2d(i,j+1)-y2d(i,j))
      rdyfld(i,j)=1./(y2d(i,j+1)-y2d(i,j))
    END DO ! i loop
  END DO ! j loop

  RETURN
END SUBROUTINE setdxdy2d

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


SUBROUTINE setdrvy2d(nx,ny,nz,                                          & 1
           ibeg,iend,jbeg,jend,kbeg,kend,                               &
           dyfld,rdyfld,var,                                            &
           missing,slopey,alphay,betay)
    
!-----------------------------------------------------------------------
!
! PURPOSE:
!    Calculate the coefficients of interpolating polynomials
!    in the y-direction.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Keith Brewster, CAPS, November, 1996
!
! MODIFICATION HISTORY:
!
! Eric Kemp, 27 April 2001
! Modified to allow for 2D arrays
!
! Eric Kemp, 7 August 2001
! Modified to check for missing data, and added INTENT statements.
!
!----------------------------------------------------------------------- 
!
! Force explicit declarations.
!
!----------------------------------------------------------------------- 

  IMPLICIT NONE

!----------------------------------------------------------------------- 
!
! INPUT:
!    nx       Number of model grid points in the x-direction (east/west)
!    ny       Number of model grid points in the y-direction (north/south)
!    nz       Number of model grid points in the vertical
!    
!    ibeg,iend   Range of x index to do interpolation
!    jbeg,jend   Range of y index to do interpolation
!    kbeg,kend   Range of z index to do interpolation
!
!    dyfld    Vector of delta-y (m) of field to be interpolated
!    rdyfld   Vector of 1./delta-y (1/m) of field to be interpolated
!  
!    var      variable to be interpolated
!    missing  Value of missing data
!  
!    slopey   Piecewise linear df/dy
!    alphay   Coefficient of y-squared term in y quadratic interpolator
!    betay    Coefficient of y term in y quadratic interpolator
!
!-----------------------------------------------------------------------
   
  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: ibeg,iend,jbeg,jend,kbeg,kend
  REAL, INTENT(IN) :: dyfld(nx,ny)
  REAL, INTENT(IN) :: rdyfld(nx,ny)
  REAL, INTENT(IN) :: var(nx,ny,nz)
  REAL, INTENT(IN) :: missing
  REAL, INTENT(OUT) :: slopey(nx,ny,nz)
  REAL, INTENT(OUT) :: alphay(nx,ny,nz)
  REAL, INTENT(OUT) :: betay(nx,ny,nz)  
    
!-----------------------------------------------------------------------
!    
! Misc. local variables
!
!-----------------------------------------------------------------------

  INTEGER :: i,j,k   
  INTEGER :: jstart,jstop
  REAL :: rtwody

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  jstart=MAX(jbeg,2)
  jstop=MIN((jend-1),(ny-2))
  DO k=kbeg,kend
    DO j=jstart,jstop
      DO i=ibeg,iend 
        IF (var(i,j+1,k) == missing .OR.                                &
            var(i,j,k) == missing) THEN
          slopey(i,j,k) = missing
        ELSE
          slopey(i,j,k)=(var(i,j+1,k)-var(i,j,k))*rdyfld(i,j)
        END IF

        rtwody=1./(dyfld(i,j-1)+dyfld(i,j))

        IF (var(i,j+1,k) == missing .OR.                                &
            var(i,j,k) == missing .OR.                                  &
            var(i,j-1,k) == missing) THEN
          alphay(i,j,k) = missing
        ELSE
          alphay(i,j,k)=((var(i,j+1,k)-var(i,j,k))*rdyfld(i,j) +        &
                 (var(i,j-1,k)-var(i,j,k))*rdyfld(i,j-1))*rtwody
        END IF

        IF (var(i,j+1,k) == missing .OR.                                &
            var(i,j,k) == missing  .OR.                                 &
            alphay(i,j,k) == missing ) THEN
          betay(i,j,k)=missing
        ELSE
          betay(i,j,k)=(var(i,j+1,k)-var(i,j,k))*rdyfld(i,j) -          &
                   dyfld(i,j)*alphay(i,j,k)
        END IF

      END DO
    END DO
  END DO
  RETURN
END SUBROUTINE setdrvy2d

!########################################################################
!########################################################################
!#########                                                      #########
!#########                 FUNCTION pntint2d2d                  #########
!#########                                                      #########
!#########                     Developed by                     #########
!#########     Center for Analysis and Prediction of Storms     #########
!#########                University of Oklahoma                #########
!#########                                                      #########
!########################################################################
!########################################################################


REAL FUNCTION pntint2d2d(vnx,vny,ivbeg,ivend,jvbeg,jvend,iorder,vx,vy,  &
                         xpnt,ypnt,iloc,jloc,var,dxfld,dyfld,rdxfld,    &
                         rdyfld,missing,slopey,alphay,betay)

!-----------------------------------------------------------------------
!
! PURPOSE:
!
!    Interpolate a 2-d field for a single point on that plane.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Keith Brewster, CAPS, November, 1996
!
! MODIFICATION HISTORY:
!   
! Eric Kemp, 27 April 2001
! Modified to allow for 2D arrays
!
! Eric Kemp, 9 August 2001
! Modified to check for missing data, and added INTENT statements.
!
!----------------------------------------------------------------------- 
!
! Force explicit declarations
!
!----------------------------------------------------------------------- 

  IMPLICIT NONE

!----------------------------------------------------------------------- 
!
! INPUT:
!    vnx       Number of model grid points in the x-direction (east/west)
!    vny       Number of model grid points in the y-direction
!              (north/south)
!
!    ivbeg,ivend   Range of x index to use in verification array
!    jvbeg,jvend   Range of y index to use in verification array
!
!    iorder   Interpolation parameter.
!             iorder specifies the order of interpolation
!             1 = bi-linear
!             2 = bi-quadratic
!   
!    vx       x coordinate of verif scalar grid points in physical space
!             (m)
!    vy       y coordinate of verif scalar grid points in physical space
!             (m)
!
!    xpnt     x coordinate (m) of interpolation point
!    ypnt     y coordinate (m) of interpolation point
!
!    iloc     I-index of interpolation point in field to be interpolated
!    jloc     J-index of interpolation point in field to be interpolated
!    dxfld    Vector of delta-x (m) of field to be interpolated 
!    dyfld    Vector of delta-y (m) of field to be interpolated 
!    rdxfld   Vector of 1./delta-x (1/m) of field to be interpolated
!    rdyfld   Vector of 1./delta-y (1/m) of field to be interpolated
!    missing  Value of missing data
!             
!    slopey   Piecewise linear df/dy
!    alphay   Coefficient of y-squared term in y quadratic interpolator
!    betay    Coefficient of y term in y quadratic interpolator
!    
!-----------------------------------------------------------------------

  INTEGER, INTENT(IN) :: vnx,vny
  INTEGER, INTENT(IN) :: ivbeg,ivend,jvbeg,jvend
  INTEGER, INTENT(IN) :: iorder
  REAL, INTENT(IN) :: vx(vnx,vny)
  REAL, INTENT(IN) :: vy(vnx,vny)
  REAL, INTENT(IN) :: xpnt
  REAL, INTENT(IN) :: ypnt
  INTEGER, INTENT(IN) :: iloc
  INTEGER, INTENT(IN) :: jloc
  REAL, INTENT(IN) :: var(vnx,vny)
  REAL, INTENT(IN) :: dxfld(vnx,vny)
  REAL, INTENT(IN) :: dyfld(vnx,vny)
  REAL, INTENT(IN) :: rdxfld(vnx,vny)
  REAL, INTENT(IN) :: rdyfld(vnx,vny)
  REAL, INTENT(IN) :: slopey(vnx,vny)
  REAL, INTENT(IN) :: alphay(vnx,vny)
  REAL, INTENT(IN) :: betay(vnx,vny)
  REAL, INTENT(IN) :: missing

!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------

  INTEGER :: ii,jj   
  REAL :: delx,dely  
  REAL :: alpha,beta,rtwodx
  REAL :: varm1,var00,varp1
  REAL :: varint

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

!-----------------------------------------------------------------------
!
! Compute bilinear interpolated value
!
!-----------------------------------------------------------------------

  IF(iorder == 1) THEN
    ii=MIN(MAX(iloc,ivbeg),(ivend-1))
    jj=MIN(MAX(jloc,jvbeg),(jvend-1))
  
    delx=(xpnt-vx(ii,jj))
    dely=(ypnt-vy(ii,jj))

    IF (var(ii,jj) == missing .OR.                                      &
        slopey(ii,jj) == missing .OR.                                   &
        var(ii+1,jj) == missing .OR.                                    &
        slopey(ii+1,jj) == missing) THEN
      varint = missing
    ELSE
      varint=(1.-delx*rdxfld(ii,jj))*                                   &
               (var(ii  ,jj)+slopey(ii  ,jj)*dely)+                     &
               (delx*rdxfld(ii,jj))*                                    &
               (var(ii+1,jj)+slopey(ii+1,jj)*dely)
    END IF

!-----------------------------------------------------------------------
!
! Compute biquadratic
! 
!-----------------------------------------------------------------------

  ELSE

    ii=MIN(MAX(iloc,(ivbeg+1)),(ivend-1))
    jj=MIN(MAX(jloc,(jvbeg+1)),(jvend-1))
    
    delx=(xpnt-vx(ii,jj))
    dely=(ypnt-vy(ii,jj))

!-----------------------------------------------------------------------
!
!   Stencil is ii-1 to ii+1 and jj-1 to jj + 1
!
!   Interpolate in y.
! 
!-----------------------------------------------------------------------

    IF (alphay(ii-1,jj) == missing .OR. betay(ii-1,jj) == missing .OR.  &
        var(ii-1,jj) == missing) THEN
      varm1 = missing
    ELSE
      varm1=(alphay(ii-1,jj)*dely+betay(ii-1,jj))*dely+var(ii-1,jj)
    END IF

    IF (alphay(ii,jj) == missing .OR. betay(ii,jj) == missing .OR.      &
        var(ii,jj) == missing) THEN
      varm1 = missing
    ELSE
      var00=(alphay(ii  ,jj)*dely+betay(ii  ,jj))*dely+var(ii  ,jj)
    END IF

    IF (alphay(ii+1,jj) == missing .OR. betay(ii+1,jj) == missing .OR.  &
        var(ii+1,jj) == missing) THEN
      varm1 = missing
    ELSE
      varp1=(alphay(ii+1,jj)*dely+betay(ii+1,jj))*dely+var(ii+1,jj)
    END IF

!-----------------------------------------------------------------------
!    
!   Interpolate intermediate results in x.
!
!-----------------------------------------------------------------------

    rtwodx=1./(dxfld(ii-1,jj)+dxfld(ii,jj))
    IF (varp1 == missing .OR. var00 == missing .OR.                     &
        varm1 == missing) THEN
      varint = missing
    ELSE
      alpha=((varp1-var00)*rdxfld(ii  ,jj) +                            &
           (varm1-var00)*rdxfld(ii-1,jj))*rtwodx
      beta=(varp1-var00)*rdxfld(ii,jj) -                                &
             dxfld(ii,jj)*alpha
      varint=(alpha*delx+beta)*delx+var00
    END IF       
  END IF
  pntint2d2d=varint
  RETURN
END FUNCTION pntint2d2d

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


SUBROUTINE setijloc2(fnx,fny,anx,any,iloc,jloc,fx2d,fy2d,ax2d,ay2d) 4

!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Find i,j indicies in forecast grid of each analysis grid point.
! No indicies are returned if the analysis grid point is outside
! of the forecast grid.
!
! NOTE:  The forecast and analysis grid points are assumed to have 
! the same origin and map projection.
!
!-----------------------------------------------------------------------
!
! AUTHOR:  Eric Kemp, November 1999.
!
! Based on subroutine setijloc
!
! MODIFICATION HISTORY:
! 
! Eric Kemp, 9 August 2001
! Added INTENT statements.
!
!-----------------------------------------------------------------------
!
! Force explicit declarations.
! 
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
! Arguments
! 
!-----------------------------------------------------------------------

  INTEGER,INTENT(IN) :: fnx,fny,anx,any
  REAL,INTENT(IN) :: fx2d(fnx,fny),fy2d(fnx,fny)
  REAL,INTENT(IN) :: ax2d(anx,any),ay2d(anx,any)
  INTEGER,INTENT(INOUT) :: iloc(anx,any),jloc(anx,any)

!-----------------------------------------------------------------------
! 
! Miscellaneous variables
! 
!-----------------------------------------------------------------------

  INTEGER :: i,j,m,n
  INTEGER :: fimid,fjmid
  REAL :: fxmid,fymid

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

!-----------------------------------------------------------------------
!
! Initialize iloc and jloc to -9999 (i.e., outside the forecast grid)   
! 
!-----------------------------------------------------------------------
  
  DO n = 1,any
    DO m = 1,anx
      iloc(m,n) = -9999
      jloc(m,n) = -9999 
    END DO
  END DO

!-----------------------------------------------------------------------
! 
! Determine the scalar coordinates of the middle of the forecast field.
!
!-----------------------------------------------------------------------

  fimid = fnx/2
  fjmid = fny/2
  
  fxmid = fx2d(fimid,fjmid)
  fymid = fy2d(fimid,fjmid)
  
!-----------------------------------------------------------------------
!
! Find the forecast i,j of each analysis grid point.
!
!-----------------------------------------------------------------------

  DO n = 1,any-1
    analysism: DO m = 1,anx-1

      IF (ax2d(m,n) < fxmid) THEN
        IF (ay2d(m,n) < fymid) THEN
          DO j = fjmid,2,-1
            DO i = fimid,2,-1  
              IF (fx2d(i,j) <= ax2d(m,n) .AND.                          &
                  fx2d(i+1,j) > ax2d(m,n) .AND.                         &
                  fy2d(i,j) <= ay2d(m,n) .AND.                          &
                  fy2d(i,j+1) > ay2d(m,n)) THEN
                iloc(m,n) = i
                jloc(m,n) = j
                CYCLE analysism
              END IF
            END DO
          END DO
        ELSE
          DO j = fjmid,fny-1
            DO i = fimid,2,-1
              IF (fx2d(i,j) <= ax2d(m,n) .AND.                          &
                  fx2d(i+1,j) > ax2d(m,n) .AND.                         &
                  fy2d(i,j-1) < ay2d(m,n) .AND.                         &
                  fy2d(i,j) >= ay2d(m,n)) THEN
                iloc(m,n) = i
                jloc(m,n) = j-1
                CYCLE analysism
              END IF
            END DO
          END DO
        END IF
      ELSE
        IF (ay2d(m,n) < fymid) THEN
          DO j = fjmid,2,-1
            DO i = fimid,fnx-1
              IF (fx2d(i-1,j) < ax2d(m,n) .AND.                         &
                  fx2d(i,j) >= ax2d(m,n) .AND.                          &
                  fy2d(i,j) <= ay2d(m,n) .AND.                          &
                  fy2d(i,j+1) > ay2d(m,n)) THEN
                iloc(m,n) = i-1
                jloc(m,n) = j
                CYCLE analysism
              END IF
            END DO
          END DO
        ELSE
          DO j = fjmid,fny-1
            DO i = fimid,fnx-1
              IF (fx2d(i-1,j) < ax2d(m,n) .AND.                         &
                  fx2d(i,j) >= ax2d(m,n) .AND.                          &
                  fy2d(i,j-1) < ay2d(m,n) .AND.                         &
                  fy2d(i,j) >= ay2d(m,n)) THEN
                iloc(m,n) = i-1
                jloc(m,n) = j-1
                CYCLE analysism
              END IF
            END DO
          END DO
        END IF
      END IF
    END DO analysism
  END DO              
END SUBROUTINE setijloc2

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


SUBROUTINE dpalatlon(nrow,ncol,radarlat,radarlon,dpalat,dpalon),1

!------------------------------------------------------------------------
!
! PURPOSE:
!
! Determines latitude and longitude of each NIDS Digital Precipitation
! Array (DPA) point for a given radar latitude and longitude.  The DPA 
! is on a "1/40 LFM grid", i.e., a polar stereographic grid nested within 
! the old Limited Fine Mesh model grid.  Equations for calculating
! latitudes and longitudes on the DPA grid are taken from Appendix C 
! of Fulton (1998).
!
! IMPORTANT:  The NEXRAD equations assume that the DPA grid is such that 
! i increases to the right and j increases *downward*.  An easy 
! correction is made so that the output arrays follow the ARPS grid, 
! i.e., i increases to the right and j increases *upward*.
!
!------------------------------------------------------------------------
!
! REFERENCE:
!
! Fulton, R. A., 1998:  WSR-88D Polar-to-HRAP Mapping.  Technical
!   Memorandum, Hydrologic Research Laboratory, 33 pp.  Available at:
!   http://hsp.nws.noaa.gov/oh/hrl/papers/wsr88d/hrapmap.pdf
!
!------------------------------------------------------------------------
!
! AUTHOR:
! 
! Eric Kemp, 3 August 2001.
!
! MODIFICATION HISTORY:
!
! Eric Kemp, 9 August 2001.
! Now uses module N2ACONST.
!
!------------------------------------------------------------------------
!
! Use modules
!
!------------------------------------------------------------------------

  USE n2aconst

!------------------------------------------------------------------------
!
! Force explicit declarations.
!
!------------------------------------------------------------------------

  IMPLICIT NONE

!------------------------------------------------------------------------
!
! Arguments
!
!------------------------------------------------------------------------

  INTEGER, INTENT(IN) :: nrow,ncol       ! Dimensions of DPA product
  REAL, INTENT(IN) :: radarlat,radarlon  ! Lat/Lon of radar.
  REAL, INTENT(OUT) :: dpalat(nrow,ncol) ! Lat of DPA points.
  REAL, INTENT(OUT) :: dpalon(nrow,ncol) ! Lon of DPA points.

!------------------------------------------------------------------------
!
! Grid scale factor.
!
!------------------------------------------------------------------------

  REAL, PARAMETER :: Kc = 249.6348607

!------------------------------------------------------------------------
!
! Global grid coordinates of the North Pole in units of 1/4 LFM
! boxes.
!
!------------------------------------------------------------------------

  INTEGER, PARAMETER :: Ip = 433
  INTEGER, PARAMETER :: Jp = 433

!------------------------------------------------------------------------
!
! Global grid coordinates of radar site in units of 1/4 LFM boxes.
!
!------------------------------------------------------------------------

  REAL :: GIs, GJs

!------------------------------------------------------------------------
!
! Global grid box number for 0,0 of 1/40 LFM grid
!
!------------------------------------------------------------------------

  INTEGER :: Is3, Js3

!------------------------------------------------------------------------
!
! Coefficients used to calculate coordinates of box centers in units
! of 1/4 LFM boxes.
!
!------------------------------------------------------------------------

  REAL :: AI3, AJ3
  REAL, PARAMETER :: B3 = 0.1

!------------------------------------------------------------------------
!
! Coordinates of box centers in units of 1/4 LFM boxes.
!
!------------------------------------------------------------------------

  REAL :: CIi, CJj
 
!------------------------------------------------------------------------
!
! Misc. variables.
!
!------------------------------------------------------------------------

  REAL :: sinls, cosls, coslambdaplus, sinlambdaplus
  INTEGER :: i,j

  REAL :: tmplat, tmplon
  INTEGER :: I3,J3

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
! 
! Beginning of executable code...
!                       
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

!------------------------------------------------------------------------
!
! Calculate GIs, GJs.  See Appendix C, Sections 30.6.2 and 30.6.3 of
! Fulton (1998).
!
!------------------------------------------------------------------------

  sinls = SIN(radarlat*deg2rad)
  cosls = COS(radarlat*deg2rad)
  coslambdaplus = COS((radarlon + 105.)*deg2rad)
  sinlambdaplus = SIN((radarlon + 105.)*deg2rad)

  GIs = 1. + sinls
  GIs = Kc*cosls*sinlambdaplus/GIs
  GIs = GIs + REAL(Ip)

  GJs = 1 + sinls
  GJs = Kc*cosls*coslambdaplus/GJs
  GJs = GJs + REAL(Jp)

!------------------------------------------------------------------------
!
! Calculate Is3 and Js3.  See Appendix C, Section 30.6.3 of Fulton 
! (1998).  Note that GIs and GJs are multiplied by 10 to make Is3 and 
! Js3 valid on the 1/40 LFM grid.  This corrects an error in the
! NEXRAD documentation.
!
!------------------------------------------------------------------------

  Is3 = INT(10.*GIs) - 66
  Js3 = INT(10.*GJs) - 66
 
!------------------------------------------------------------------------
!
! Calculate AI3 and AJ3 (B3 is already set as a parameter).  See
! Appendix C, Section 30.6.4 of Fulton (1998).  
!
!------------------------------------------------------------------------

  AI3 = -10.*REAL(Ip)
  AI3 = (REAL(Is3) + AI3 + 0.5)/10.

  AJ3 = -10.*REAL(Jp)
  AJ3 =  (REAL(Js3) + AJ3 + 0.5)/10.

!------------------------------------------------------------------------
!
! Begin looping through the DPA points.
!
!------------------------------------------------------------------------

  DO j = 1, ncol
    DO i = 1, nrow

!------------------------------------------------------------------------
!
!     Calculate CIi and CJj for a given DPA point.  See Appendix C, 
!     Section 30.6.4 of Fulton (1998).
!
!------------------------------------------------------------------------

      CIi = AI3 + (B3*REAL(i))
      CJj = AJ3 + (B3*REAL(j))

!------------------------------------------------------------------------
!
!     Now calculate latitude and longitude of a given DPA point.  See
!     Section 30.6.4 of Fulton (1998).  Note that the output array will
!     follow the ARPS grid, i.e., i increases to the right and j 
!     increases *upward*.
!
!------------------------------------------------------------------------

      tmplat = (CIi*CIi) + (CJj*CJj)
      tmplat = SQRT(tmplat)/Kc
      tmplat = 2.*ATAN(tmplat)*rad2deg

      tmplat = 90. - tmplat
      dpalat(i,ncol-j+1) = tmplat

      tmplon = -105. + (ATAN2(CIi,CJj)*rad2deg)
      dpalon(i,ncol-j+1) = tmplon

    END DO ! i loop
  END DO ! j loop

!------------------------------------------------------------------------
!
! The end.
!
!------------------------------------------------------------------------

  RETURN
END SUBROUTINE dpalatlon

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


SUBROUTINE getarpsrasterxy(nx,ny,arpslat,arpslon,radarlat,radarlon,      & 1,2
                           arpsrasterx,arpsrastery)

!------------------------------------------------------------------------
!
! PURPOSE:
!
! Calculates Cartesian coordinates of ARPS scalar points relative to
! a radar using spherical geometry.
!
!------------------------------------------------------------------------
!
! AUTHOR:
!
! Eric Kemp, 8 August 2001.
!    
!------------------------------------------------------------------------
!
! Use modules.
!
!------------------------------------------------------------------------

  USE n2aconst

!------------------------------------------------------------------------
!
! Force explicit declarations
!
!------------------------------------------------------------------------

  IMPLICIT NONE

!------------------------------------------------------------------------
!
! Declare arguments
!  
!------------------------------------------------------------------------

  INTEGER, INTENT(IN) :: nx,ny              ! Dimensions of ARPS grid  
  REAL, INTENT(IN) :: arpslat(nx,ny)        ! Latitude of ARPS point
  REAL, INTENT(IN) :: arpslon(nx,ny)        ! Longitude of ARPS point
  REAL, INTENT(IN) :: radarlat,radarlon     ! Lat/Lon of radar.
  REAL, INTENT(OUT) :: arpsrasterx(nx,ny)   ! x-coordinate of ARPS point.
  REAL, INTENT(OUT) :: arpsrastery(nx,ny)   ! y-coordinate of ARPS point.

!------------------------------------------------------------------------
!
! Internal variables.
!
!------------------------------------------------------------------------

  INTEGER :: i,j
  REAL :: headng,dist

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  DO j = 1,ny-1
    DO i = 1,nx-1
      CALL disthead(radarlat,radarlon,arpslat(i,j),arpslon(i,j),         &
                    headng,dist)
      arpsrasterx(i,j) = dist*SIN(deg2rad*headng)
      arpsrastery(i,j) = dist*COS(deg2rad*headng)
    END DO ! i loop
  END DO ! j loop

  RETURN
END SUBROUTINE getarpsrasterxy

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


SUBROUTINE getarpsdpaxy(nx,ny,arpslat,arpslon,radarlat,radarlon,         &,1
                           arpsdpax,arpsdpay)

!------------------------------------------------------------------------
!
! PURPOSE:
!
! Calculates Cartesian coordinates of ARPS scalar points relative to
! a radar in HRAP (1/40 LFM) polar stereographic grid projection (used
! by NIDS DPA product).
!
!------------------------------------------------------------------------
!
! AUTHOR:
!
! Eric Kemp, 8 August 2001.
!    
!------------------------------------------------------------------------
!
! REFERENCE:
!
! Fulton, R. A., 1998:  WSR-88D Polar-to-HRAP Mapping.  Technical
!   Memorandum, Hydrologic Research Laboratory, 33 pp.  Available at:
!   http://hsp.nws.noaa.gov/oh/hrl/papers/wsr88d/hrapmap.pdf
!
!------------------------------------------------------------------------
!
! Use modules.
!
!------------------------------------------------------------------------

  USE n2aconst

!------------------------------------------------------------------------
!
! Force explicit declarations
!
!------------------------------------------------------------------------

  IMPLICIT NONE

!------------------------------------------------------------------------
!
! Declare arguments.
! 
!------------------------------------------------------------------------

  INTEGER, INTENT(IN) :: nx,ny              ! Dimensions of ARPS grid  
  REAL, INTENT(IN) :: arpslat(nx,ny)        ! Latitude of ARPS point
  REAL, INTENT(IN) :: arpslon(nx,ny)        ! Longitude of ARPS point
  REAL, INTENT(IN) :: radarlat,radarlon     ! Lat/Lon of radar.
  REAL, INTENT(OUT) :: arpsdpax(nx,ny)   ! x-coordinate of ARPS point.
  REAL, INTENT(OUT) :: arpsdpay(nx,ny)   ! y-coordinate of ARPS point.

!------------------------------------------------------------------------
!
! Internal variables
! 
!------------------------------------------------------------------------
  
  INTEGER :: i,j
  INTEGER :: I3, J3
  INTEGER :: Is3, Js3
  REAL :: GIs, GJs
  INTEGER, PARAMETER :: Ip = 433
  INTEGER, PARAMETER :: Jp = 433
  REAL, PARAMETER :: Kc = 249.6348607
  REAL :: GI, GJ
  REAL :: sinls, cosls, coslambdaplus, sinlambdaplus
  REAL :: sindeltalambda,cosdeltalambda,deltalambda, sinl,cosl
  REAL :: Rl

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  

!------------------------------------------------------------------------
!
! Calculate GIs, GJs.  See Appendix C, Sections 30.6.2 and 30.6.3 of
! Fulton (1998).
!
!------------------------------------------------------------------------

  sinls = SIN(radarlat*deg2rad)
  cosls = COS(radarlat*deg2rad)
  coslambdaplus = COS((radarlon + 105.)*deg2rad)
  sinlambdaplus = SIN((radarlon + 105.)*deg2rad)

  GIs = 1. + sinls
  GIs = Kc*cosls*sinlambdaplus/GIs
  GIs = GIs + REAL(Ip)

  GJs = 1 + sinls
  GJs = Kc*cosls*coslambdaplus/GJs
  GJs = GJs + REAL(Jp)

!------------------------------------------------------------------------
!
! Calculate Is3 and Js3.  See Appendix C, Section 30.6.3 of Fulton 
! (1998).  Note that GIs and GJs are multiplied by 10 to make Is3 and 
! Js3 valid on the 1/40 LFM grid.  This corrects an error in the
! NEXRAD documentation.
!
!------------------------------------------------------------------------

  DO j = 1,ny-1
    DO i = 1,nx-1

      deltalambda = arpslon(i,j) - radarlon
      sinl = SIN(arpslat(i,j)*deg2rad)
      cosl = COS(arpslat(i,j)*deg2rad)
    
      Rl = Kc*cosl/(1. + sinl)

      sindeltalambda = SIN(deltalambda*deg2rad)
      cosdeltalambda = COS(deltalambda*deg2rad)
             
      GI = Rl*sindeltalambda*coslambdaplus
      GI = GI + (Rl*cosdeltalambda*sinlambdaplus) + REAL(Ip)

      GJ = Rl*cosdeltalambda*coslambdaplus
      GJ = GJ + (Rl*sindeltalambda*sinlambdaplus) + REAL(Jp)

      arpsdpax(i,j) = DPAdx*(GI - GIs)*10.
      arpsdpay(i,j) = DPAdx*(GJ - GJs)*10.

    END DO ! i loop
  END DO ! j loop

  RETURN
END SUBROUTINE getarpsdpaxy