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

SUBROUTINE build_wrf_grid(nx_wrf,ny_wrf,nxlg_wrf,nylg_wrf,dx_wrf,dy_wrf,&,24
                    mapproj_wrf,sclfct_wrf,lattru_wrf,lontru_wrf,       &
                    ctrlat_wrf,ctrlon_wrf,swx_wrf,swy_wrf,              &
                    lat_wrf,lon_wrf,lat_ll,lat_ul,lat_ur,lat_lr,        &
                    lon_ll,lon_ul,lon_ur,lon_lr,istatus)

!-----------------------------------------------------------------------
!
! PURPOSE:
!
!   Set up WRF mapprojection and get lat/lon of the WRF grid points.
!
!   Get lat/lon at the four corners of the WRF domain. After the call
!   Only processor 0 has valid lat/lon at corners.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN)  :: nx_wrf,   ny_wrf
  INTEGER, INTENT(IN)  :: nxlg_wrf, nylg_wrf
  REAL,    INTENT(IN)  :: dx_wrf,   dy_wrf
  INTEGER, INTENT(IN)  :: mapproj_wrf
  REAL,    INTENT(INOUT):: sclfct_wrf
  REAL,    INTENT(IN)  :: lattru_wrf(2),lontru_wrf
  REAL,    INTENT(IN)  :: ctrlat_wrf,ctrlon_wrf
  REAL,    INTENT(OUT) :: swx_wrf,swy_wrf
  REAL,    INTENT(OUT) :: lat_wrf(nx_wrf,ny_wrf,3)
  REAL,    INTENT(OUT) :: lon_wrf(nx_wrf,ny_wrf,3)

  REAL,    INTENT(OUT) :: lat_ll(4), lon_ll(4)
  REAL,    INTENT(OUT) :: lat_ul(4), lon_ul(4)
  REAL,    INTENT(OUT) :: lat_ur(4), lon_ur(4)
  REAL,    INTENT(OUT) :: lat_lr(4), lon_lr(4)

  INTEGER, INTENT(OUT) :: istatus

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

  INTEGER :: i, j
  REAL :: sclf_wrf
  REAL :: dx_wrfscl, dy_wrfscl
  REAL :: ctrx, ctry
  REAL :: xsub0, ysub0

  INTEGER   :: mptag, source
  INTEGER, PARAMETER :: fzone_wrf = 1
    
  REAL, ALLOCATABLE ::  x_wrf(:),  y_wrf(:)
  REAL, ALLOCATABLE :: xs_wrf(:), ys_wrf(:)

  INCLUDE 'mp.inc'

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Begin of executable code ... ...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  IF( sclfct_wrf /= 1.0) THEN
    sclf_wrf  = 1.0/sclfct_wrf
    dx_wrfscl = dx_wrf*sclf_wrf
    dy_wrfscl = dy_wrf*sclf_wrf
  ELSE
    sclf_wrf  = 1.0
    dx_wrfscl = dx_wrf
    dy_wrfscl = dy_wrf
  END IF
  sclfct_wrf = sclf_wrf
 
  CALL setmapr(mapproj_wrf,sclf_wrf,lattru_wrf,lontru_wrf)
  CALL lltoxy( 1,1, ctrlat_wrf,ctrlon_wrf, ctrx, ctry )
  swx_wrf = ctrx - 0.5*(nxlg_wrf-1) * dx_wrfscl
  swy_wrf = ctry - 0.5*(nylg_wrf-1) * dy_wrfscl
  CALL setorig( 1, swx_wrf, swy_wrf)

  xsub0 = dx_wrf * (nx_wrf-fzone_wrf) * (loc_x-1)
  ysub0 = dy_wrf * (ny_wrf-fzone_wrf) * (loc_y-1)

!-----------------------------------------------------------------------
!
! Assign WRF grid arrays
!
!-----------------------------------------------------------------------

  ALLOCATE(x_wrf (nx_wrf), STAT = istatus)
  ALLOCATE(y_wrf (ny_wrf), STAT = istatus)
  ALLOCATE(xs_wrf(nx_wrf), STAT = istatus)
  ALLOCATE(ys_wrf(ny_wrf), STAT = istatus)

  DO i=1,nx_wrf
    x_wrf(i)= sclf_wrf*xsub0 + (i-1)*dx_wrfscl
  END DO
  DO j=1,ny_wrf
    y_wrf(j)= sclf_wrf*ysub0 + (j-1)*dy_wrfscl
  END DO
 
  DO i=1,nx_wrf-1
    xs_wrf(i)=0.5*(x_wrf(i)+x_wrf(i+1))
  END DO
  xs_wrf(nx_wrf)=2.*xs_wrf(nx_wrf-1)-xs_wrf(nx_wrf-2)

  DO j=1,ny_wrf-1
    ys_wrf(j)=0.5*(y_wrf(j)+y_wrf(j+1))
  END DO
  ys_wrf(ny_wrf)=2.*ys_wrf(ny_wrf-1)-ys_wrf(ny_wrf-2)

!-----------------------------------------------------------------------
!
!  Find latitude and longitude of WRF grid.
!
!   1 -- T point, 2 -- U point, 3 -- V point, 4 -- massless point
!
!-----------------------------------------------------------------------
 
  CALL xytoll(nx_wrf,ny_wrf,xs_wrf,ys_wrf,lat_wrf(:,:,1),lon_wrf(:,:,1))
  CALL xytoll(nx_wrf,ny_wrf, x_wrf,ys_wrf,lat_wrf(:,:,2),lon_wrf(:,:,2))
  CALL xytoll(nx_wrf,ny_wrf,xs_wrf, y_wrf,lat_wrf(:,:,3),lon_wrf(:,:,3))

!-----------------------------------------------------------------------
!
! Get lat/lon at each corners
!
!    ul - upper left corner           ur - upper right corner
!    ll - lower left corner           lr - lower right corner
!
!-----------------------------------------------------------------------

  lat_ll(1) = lat_wrf(       1,       1,1)
  lat_ul(1) = lat_wrf(       1,ny_wrf-1,1)
  lat_ur(1) = lat_wrf(nx_wrf-1,ny_wrf-1,1)
  lat_lr(1) = lat_wrf(nx_wrf-1,       1,1)

  lon_ll(1) = lon_wrf(       1,       1,1)
  lon_ul(1) = lon_wrf(       1,ny_wrf-1,1)
  lon_ur(1) = lon_wrf(nx_wrf-1,ny_wrf-1,1)
  lon_lr(1) = lon_wrf(nx_wrf-1,       1,1)

  lat_ll(2) = lat_wrf(       1,       1,2)
  lat_ul(2) = lat_wrf(       1,ny_wrf-1,2)
  lat_ur(2) = lat_wrf(nx_wrf,  ny_wrf-1,2)
  lat_lr(2) = lat_wrf(nx_wrf,         1,2)

  lon_ll(2) = lon_wrf(       1,       1,2)
  lon_ul(2) = lon_wrf(       1,ny_wrf-1,2)
  lon_ur(2) = lon_wrf(nx_wrf,  ny_wrf-1,2)
  lon_lr(2) = lon_wrf(nx_wrf,         1,2)

  lat_ll(3) = lat_wrf(       1,       1,3)
  lat_ul(3) = lat_wrf(       1,  ny_wrf,3)
  lat_ur(3) = lat_wrf(nx_wrf-1,  ny_wrf,3)
  lat_lr(3) = lat_wrf(nx_wrf-1,       1,3)

  lon_ll(3) = lon_wrf(       1,       1,3)
  lon_ul(3) = lon_wrf(       1,  ny_wrf,3)
  lon_ur(3) = lon_wrf(nx_wrf-1,  ny_wrf,3)
  lon_lr(3) = lon_wrf(nx_wrf-1,       1,3)

  CALL xytoll(1,1,x_wrf(1),     y_wrf(1),     lat_ll(4),lon_ll(4))
  CALL xytoll(1,1,x_wrf(1),     y_wrf(ny_wrf),lat_ul(4),lon_ul(4))
  CALL xytoll(1,1,x_wrf(nx_wrf),y_wrf(ny_wrf),lat_ur(4),lon_ur(4))
  CALL xytoll(1,1,x_wrf(nx_wrf),y_wrf(1),     lat_lr(4),lon_lr(4))

  IF (mp_opt > 0 ) THEN

    CALL inctag

    mptag  = gentag + 2                      ! passing UL to 0
    source = (nproc_y-1)*nproc_x
    IF (myproc == source)  THEN
      CALL mpsendr(lat_ul,4,0,mptag,  istatus)
      CALL mpsendr(lon_ul,4,0,mptag+1,istatus)
    END IF

    IF (myproc == 0) THEN
      CALL mprecvr(lat_ul,4,source,mptag,  istatus)
      CALL mprecvr(lon_ul,4,source,mptag+1,istatus)
    END IF

    mptag  = gentag + 4                     ! Pasing UR to 0
    source = (nproc_y-1)*nproc_x + nproc_x-1
    IF (myproc == source) THEN
      CALL mpsendr(lat_ur,4,0,mptag,  istatus)
      CALL mpsendr(lon_ur,4,0,mptag+1,istatus)
    END IF

    IF (myproc == 0) THEN
      CALL mprecvr(lat_ur,4,source,mptag,  istatus)
      CALL mprecvr(lon_ur,4,source,mptag+1,istatus)
    END IF

    mptag  = gentag + 6                     ! Passing LR to 0
    source = nproc_x-1
    IF (myproc == source) THEN
      CALL mpsendr(lat_lr,4,0,mptag,istatus)
      CALL mpsendr(lon_lr,4,0,mptag+1,istatus)
    END IF

    IF (myproc == 0) THEN
      CALL mprecvr(lat_lr,4,source,mptag,  istatus)
      CALL mprecvr(lon_lr,4,source,mptag+1,istatus)
    END IF

    CALL mpbarrier

  END IF

!-----------------------------------------------------------------------
!
! Returning
!
!-----------------------------------------------------------------------

  DEALLOCATE( x_wrf, y_wrf)
  DEALLOCATE(xs_wrf,ys_wrf)

  istatus = 0
  RETURN
END SUBROUTINE build_wrf_grid
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE prepinterp                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE prepinterp(nx,ny,nxlg,nylg,nx_wrf,ny_wrf,dx,dy,x,y,xs,ys,    & 1,14
                mapproj,scalef,latnot,trulon,ctrlat,ctrlon,swx,swy,     &
                lat_wrf,lon_wrf,x2d,y2d,iloc,jloc,                      &
                dxfld,rdxfld,dyfld,rdyfld,istatus)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
!   Prepare horizontal interpolation arrays.
!
!   Do NOT support MPI.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN)  :: nx,     ny
  INTEGER, INTENT(IN)  :: nxlg,   nylg
  INTEGER, INTENT(IN)  :: nx_wrf, ny_wrf
  REAL,    INTENT(IN)  :: dx,     dy
  REAL,    INTENT(IN)  :: x(nx),  y(ny)
  REAL,    INTENT(IN)  :: xs(nx), ys(ny)
  INTEGER, INTENT(IN)  :: mapproj
  REAL,    INTENT(IN)  :: scalef
  REAL,    INTENT(IN)  :: latnot(2)
  REAL,    INTENT(IN)  :: trulon
  REAL,    INTENT(IN)  :: ctrlat,ctrlon
  REAL,    INTENT(OUT) :: swx,  swy
  REAL,    INTENT(IN)  :: lat_wrf(nx_wrf,ny_wrf,3)
  REAL,    INTENT(IN)  :: lon_wrf(nx_wrf,ny_wrf,3)
  REAL,    INTENT(OUT) :: x2d(nx_wrf,ny_wrf,3)
  REAL,    INTENT(OUT) :: y2d(nx_wrf,ny_wrf,3)
  INTEGER, INTENT(OUT) :: iloc(nx_wrf,ny_wrf,3)
  INTEGER, INTENT(OUT) :: jloc(nx_wrf,ny_wrf,3)
  REAL,    INTENT(OUT) :: dxfld(nx,3)
  REAL,    INTENT(OUT) :: rdxfld(nx,3)
  REAL,    INTENT(OUT) :: dyfld(ny,3)
  REAL,    INTENT(OUT) :: rdyfld(ny,3)

  INTEGER, INTENT(OUT) :: istatus

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

  INTEGER  :: n

  INTEGER  :: iproj
  REAL     :: scl, trlat(2), trlon,x0,y0

  REAL     :: ctrx, ctry

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Begin of executable code ... ...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
!  Save previous map projection values
!
!-----------------------------------------------------------------------
!
  CALL getmapr(iproj,scl,trlat,trlon,x0,y0)

!-----------------------------------------------------------------------
!
!  Set ARPS map projection
!
!-----------------------------------------------------------------------

  CALL setmapr(mapproj,scalef,latnot,trulon)
  CALL lltoxy( 1,1, ctrlat,ctrlon, ctrx, ctry )
  swx = ctrx - (FLOAT((nxlg-3))/2.) * dx*scalef
  swy = ctry - (FLOAT((nylg-3))/2.) * dy*scalef
  CALL setorig(1,swx,swy)

  DO n = 1,3   ! For T, U, V three staggers
    CALL lltoxy(nx_wrf,ny_wrf,lat_wrf(:,:,n),lon_wrf(:,:,n),        &
                x2d(:,:,n),y2d(:,:,n))
  END DO

  IF(MAXVAL(x2d) > x(nx) .OR. MINVAL(x2d) < x(1) .OR.          &
     MAXVAL(y2d) > y(ny) .OR. MINVAL(y2d) < y(1) ) THEN

    WRITE(6,'(/,a,/,2(4(a,F15.2),a,/))')                                &
     'It seems that WRF domain is outside of the ARPS physical domain.',&
     'ARPS domain [',x(1),' -- ',x(nx),' ; ',y(1), ' -- ', y(ny), '  ]',&
     'WRF  domain [',MINVAL(x2d),' -- ', MAXVAL(x2d), ' ; ',            &
                     MINVAL(y2d),' -- ', MAXVAL(y2d), '  ]'

    CALL arpsstop('Domain error.',1)
  END IF

  CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,1),y2d(:,:,1),          &
                xs,ys,iloc(:,:,1),jloc(:,:,1))  ! T points
  CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,2),y2d(:,:,2),          &
                x,ys,iloc(:,:,2),jloc(:,:,2))   ! U points
  CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,3),y2d(:,:,3),          &
                xs,y,iloc(:,:,3),jloc(:,:,3))   ! V points

  CALL setdxdy(nx,ny,1,nx,1,ny,xs,ys,                               &
               dxfld(:,1),dyfld(:,1),rdxfld(:,1),rdyfld(:,1))
  CALL setdxdy(nx,ny,1,nx,1,ny,x,ys,                                &
               dxfld(:,2),dyfld(:,2),rdxfld(:,2),rdyfld(:,2)) 
  CALL setdxdy(nx,ny,1,nx,1,ny,xs,y,                                &
               dxfld(:,3),dyfld(:,3),rdxfld(:,3),rdyfld(:,3))
!
!-----------------------------------------------------------------------
!
!  Reset map projection to previous values
!
!-----------------------------------------------------------------------
!
  CALL setmapr(iproj,scl,trlat,trlon)
  CALL setorig(1,x0,y0)

  istatus = 0

  RETURN
END SUBROUTINE prepinterp
!
!##################################################################
!##################################################################
!######                                                      ######
!######                  SUBROUTINE hinterp                  ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE hinterp(nx,ny,nz,nx_ext,ny_ext,iorder,                    & 18,1
                   iloc,jloc,x,y,x2d,y2d,                            &
                   varin,dxfld,dyfld,rdxfld,rdyfld,                  &
                   varout,slopey,alphay,betay)

!-----------------------------------------------------------------------
!  PURPOSE:
! 
!    Interpolates ARPS 3D array varin horizontally to WRF or other
!    grids. The output array varout is a 3D interplation array with
!    the same vertical coordinate as the input array varin. 
! 
!  NOTE:
!    Refer to function pntint2d in src/adas/intfield.f90.
!
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER, INTENT(IN) :: nx,ny,nz            ! Grid size for input array
  INTEGER, INTENT(IN) :: nx_ext,ny_ext       ! Horizontal grid size of the 
                                             ! interpolated array
  INTEGER, INTENT(IN) :: iorder              ! polynomial order of the interpolation
                                             ! = 1 bi-linear
                                             ! > 2 quadratic
  INTEGER, INTENT(IN) :: iloc(nx_ext,ny_ext) ! ARPS index of external grid points
  INTEGER, INTENT(IN) :: jloc(nx_ext,ny_ext) ! ARPS index of external grid points
  REAL,    INTENT(IN) :: x(nx), y(ny)        ! Grid coordiate of the input array
  REAL,    INTENT(IN) :: x2d(nx_ext,ny_ext), y2d(nx_ext,ny_ext)
             ! x and y coordinate of external grid point in ARPS coordinate
  REAL,    INTENT(IN) :: varin(nx,ny,nz)
  REAL,    INTENT(IN) :: dxfld(nx),rdxfld(nx)
  REAL,    INTENT(IN) :: dyfld(ny),rdyfld(ny)

  REAL,    INTENT(OUT) :: varout(nx_ext,ny_ext,nz)
  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 :: ii,jj
  REAL    :: delx,dely
  REAL    :: varm1,var00,varp1
  REAL    :: rtwodx, alpha, beta

!----------------------------------------------------------------------
!
! External interpolation function
! Interpolate a 2-d field for a single point on that plane.
!
!----------------------------------------------------------------------
!  REAL :: pntint2d             ! the function doing horizontal 
                                ! interpolation for one grid point
!
! On some platform, it is hard to make pntint2d inline for efficiency.
! So we hardcoded the function pntint2d inside this subroutine.
!
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
!-----------------------------------------------------------------------
!
!  Compute derivative terms
!
!-----------------------------------------------------------------------
!
  CALL setdrvy(nx,ny,nz,1,nx,1,ny,1,nz,                                 &
               dyfld,rdyfld,varin,slopey,alphay,betay)

!
!-----------------------------------------------------------------------
!
!    Horizontal interpolation
!
!-----------------------------------------------------------------------
!
  IF(iorder == 1) THEN
!
!-----------------------------------------------------------------------
!
!  Loop through all WRF grid points
!
!-----------------------------------------------------------------------
!
    DO k = 1,nz
      DO j = 1,ny_ext
        DO i = 1,nx_ext
!
!-----------------------------------------------------------------------
!
!  Compute bilinear interpolated value
!
!-----------------------------------------------------------------------
!
           ii=MIN(MAX(iloc(i,j),2),(nx-2))
           jj=MIN(MAX(jloc(i,j),2),(ny-2))
           delx=(x2d(i,j)-x(ii))
           dely=(y2d(i,j)-y(jj))
           varout(i,j,k)= (1.-delx*rdxfld(ii))*                         &
                          (varin(ii,  jj,k)+slopey(ii,  jj,k)*dely)     &
                        + (delx*rdxfld(ii))*                            &
                          (varin(ii+1,jj,k)+slopey(ii+1,jj,k)*dely)
        END DO
      END DO
    END DO

  ELSE
!
!-----------------------------------------------------------------------
!
!  Loop through all WRF grid points
!
!-----------------------------------------------------------------------
!
    DO k = 1,nz
      DO j = 1,ny_ext
        DO i = 1,nx_ext
!
!-----------------------------------------------------------------------
!
!  Compute biquadratic
!
!-----------------------------------------------------------------------
!
           ii=MIN(MAX(iloc(i,j),(2+1)),(nx-2))
           jj=MIN(MAX(jloc(i,j),(2+1)),(ny-2))
           delx=(x2d(i,j)-x(ii))
           dely=(y2d(i,j)-y(jj))
!
!-----------------------------------------------------------------------
!
!    Stencil is ii-1 to ii+1 and jj-1 to jj + 1
!
!    Interpolate in y.
!
!-----------------------------------------------------------------------
!
          varm1=(alphay(ii-1,jj,k)*dely+betay(ii-1,jj,k))*dely          &
               + varin(ii-1,jj,k)
          var00=(alphay(ii  ,jj,k)*dely+betay(ii  ,jj,k))*dely          &
               + varin(ii  ,jj,k)
          varp1=(alphay(ii+1,jj,k)*dely+betay(ii+1,jj,k))*dely          &
               + varin(ii+1,jj,k)
!
!-----------------------------------------------------------------------
!
!    Interpolate intermediate results in x.
!
!-----------------------------------------------------------------------
!
          rtwodx=1./(dxfld(ii-1)+dxfld(ii))
          alpha=((varp1-var00)*rdxfld(ii  )                            &
               + (varm1-var00)*rdxfld(ii-1))*rtwodx
          beta= (varp1-var00)*rdxfld(ii)                               &
              - dxfld(ii)*alpha
          varout(i,j,k)=(alpha*delx+beta)*delx+var00
        END DO
      END DO
    END DO

  END IF

!         varout(i,j,k) = pntint2d(nx,ny,2,nx-1,2,ny-1,                  &
!               iorder,x,y,x2d(i,j),y2d(i,j),iloc(i,j),jloc(i,j),        &
!               varin(:,:,k),dxfld,dyfld,rdxfld,rdyfld,                  &
!               slopey(:,:,k),alphay(:,:,k),betay(:,:,k))

  RETURN
END SUBROUTINE hinterp
!
!##################################################################
!##################################################################
!######                                                      ######
!######               SUBROUTINE compute_eta_3d              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE compute_eta_3d(nx,ny,nz,p,t,mix,zp,ztopo,ptop,eta,mu) 1,1

!-------------------------------------------------------------------
!
! PURPOSE
!
! Subroutine to compute eta on a 3D grid.  Also computes mu as a 
! function of the terrain passed in.
!
! The Eta-P coordinate.
!
!                Pdry - Ptop       Pdry = Dry pressure (Pa)
!         EtaP = ----------        Ptop = Pressure at model top (Pa)
!                    mu            mu   = Psfc - Pvapor_bottom - Ptop
!
!  General Procedure:
!
!     1.  Compute downward integrated vapor-pressure for each gridpoint
!          ( Pvapor)
!     2.  Subtract the Pvapor value from the pressure at each point to
!         get the dry pressure (Pdry) at each point
!     3.  Compute mu (dry surface pressure minus top pressure)
!     4.  Compute EtaP value using newly compute dry pressure for each
!         point
!
! NOTE:
!   refer to subroutine compute_eta_3d in WRFSI src/mod/module_vinterp_utils.F
!   ARPS physical domain is from 2 to nz-1.
!   Water mixing ratio "mix" is passed in instead of RH.
!
!-------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: nx,ny        ! Horizontal dimensions of array 
                                      ! in WRF grid
  INTEGER, INTENT(IN) :: nz           ! Horizontal dimensions of array 
                                      ! in ARPS grid
  REAL,    INTENT(IN) :: p(nx,ny,nz)  ! 3D Pressure (Pa)
  REAL,    INTENT(IN) :: t(nx,ny,nz)  ! 3D Temperature (K)
  REAL,    INTENT(IN) :: mix(nx,ny,nz)! 3D water vapor mixing ratio
  REAL,    INTENT(IN) :: zp(nx,ny,nz) ! 3D GPH (gpm)
  REAL,    INTENT(IN) :: ztopo(nx,ny) ! WRF Topography
  REAL,    INTENT(IN) :: ptop         ! Top pressure (Pa)

  REAL,    INTENT(OUT) :: eta(nx,ny,nz) ! Eta values
  REAL,    INTENT(OUT) :: mu(nx,ny)     ! Mu

!------------------------------------------------------------------
!
! Misc. Local variables
!
!------------------------------------------------------------------
  REAL, ALLOCATABLE :: rho(:)
  REAL, ALLOCATABLE :: pdry(:)
  REAL, ALLOCATABLE :: iqvp(:)

  REAL    :: tsfc, psfc, qvsfc, dz, qvbar,iqvp_sfc
  REAL    :: wgt0, wgt1
  LOGICAL :: found_level

  INTEGER :: i,j,k

  REAL, PARAMETER :: g = 9.81

!------------------------------------------------------------------
!
! External functions
!
!------------------------------------------------------------------
  REAL :: compute_density  ! function to compute grid point density
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  ALLOCATE (rho (nz))      ! Density for each level in a column
  ALLOCATE (pdry(nz))      ! Dry air pressure (iqvp removed)
  ALLOCATE (iqvp(nz))      ! Integrated (downward) vapor pressure

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

      ! Compute density and qv in the column
      DO k = 1,nz
        rho(k)= compute_density(t(i,j,k),p(i,j,k))
      ENDDO

      ! Compute the dry pressure values and iqvp for the column
      ! (pdry+iqvp = p)
      CALL compute_column_pdry(nz,p(i,j,:),rho,mix(i,j,:),zp(i,j,:),    &
                               pdry,iqvp)

      ! Compute mu at this point using the terrain height. Mu is just
      ! the dry surface pressure, which would be the model-adjusted
      ! surface pressure minus the integrated water vapor.

      IF (ztopo(i,j) .LE. zp(i,j,2) ) THEN  ! ARPS physical domain is 
                                            ! 2 -> (nz-1)

        ! WRF terrain below lowest BG model level.  Make crude adjustment
        ! using 10 Pa per meter to get surface pressure and assume a
        ! constant qv for moisture.  Assume a standard 6.5 K/km lapse rate
        ! for temperature
        k = 2
        dz    = zp(i,j,2)-ztopo(i,j)
        psfc  = p(i,j,2) + dz*10.
        qvbar = mix(i,j,2)
        tsfc  = t(i,j,2) + dz*.0065
      ELSE
        found_level = .false.
        find_level: DO k = 3, nz-1
          IF ( (ztopo(i,j) .LE. zp(i,j,k)) .AND.                        &
               (ztopo(i,j) .GT. zp(i,j,k-1)) ) THEN
            found_level = .true.
            EXIT find_level
          END IF
        END DO find_level
        IF (.NOT. found_level) THEN
          PRINT *, 'COMPUTE_ETA_3D: This should not happen.'
          PRINT *, 'Could not find where to insert WRF surface.'
          PRINT *, 'I/J = ',i,j
          PRINT *, 'Topo = ', ztopo(i,j)
          PRINT *, 'Z in column = ', zp(i,j,:)
          STOP 'level_problem'
        END IF

        ! Determine pressure, temperature, and qv
        psfc = EXP ( ( ztopo(i,j)*ALOG(p(i,j,k-1)/p(i,j,k)) -           &
                       zp(i,j,k)*ALOG(p(i,j,k-1))           +           &
                       zp(i,j,k-1)*ALOG(p(i,j,k))  )          /         &
                     ( zp(i,j,k-1) - zp(i,j,k)     )    )
        IF ( (zp(i,j,k)-zp(i,j,k-1)) .GE. 1.) THEN
          wgt0 = (zp(i,j,k)-ztopo(i,j)) / (zp(i,j,k)-zp(i,j,k-1))
          wgt1 = 1 - wgt0
        ELSE
          wgt0 = 0.0
          wgt1 = 1.0
        ENDIF

        tsfc = t(i,j,k-1)*wgt0 + t(i,j,k)*wgt1
        qvsfc = mix(i,j,k-1)*wgt0 + mix(i,j,k)*wgt1
        qvbar = (qvsfc + mix(i,j,k))*0.5
        dz = zp(i,j,k) - ztopo(i,j)
      ENDIF

      ! Now compute the integrated vapor pressure between
      ! the surface and the next lowest level 
      iqvp_sfc = iqvp(k)+g*qvbar*rho(k)*dz/(1.+qvbar)
      mu(i,j) = psfc - iqvp_sfc - ptop

      ! We now have everything we need to compute eta for the column
      DO k = 1,nz
        eta(i,j,k) = (pdry(k) - ptop) / mu(i,j)
      END DO
      IF ((i == nx/2) .AND. (j == ny/2)) THEN
        ! Some diagnostic prints from the center of the column
        PRINT *, 'Eta values on background grid center column:'
        PRINT *, 'TOPO/PSFC/MU = ',ztopo(i,j), psfc, mu(i,j)
        PRINT *, 'Z          PRESS      PRESSDRY   IQVAPORP   ETA'
        PRINT *, '---------- ---------- ---------- ---------- ----------'
        DO k=1,nz-1
          PRINT '(F10.1,1x,F10.1,1x,F10.1,1x,F10.6,1x,F10.6)',zp(i,j,k), &
            p(i,j,k), pdry(k),iqvp(k),eta(i,j,k)
        END DO
        PRINT *, ' '
      END IF

    END DO
  END DO

  DEALLOCATE (rho)
  DEALLOCATE (pdry)
  DEALLOCATE (iqvp)

  RETURN
END SUBROUTINE compute_eta_3d

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

SUBROUTINE vinterp(nx,ny,nz_in,nz_out,korder,eta_in, eta_out,           & 9
                   data_in, data_out, extrapolate)

!-------------------------------------------------------------------
!
! PURPOSE:
!
!   Interpolates each column of data from ARPS height surface 
!   to WRF mass vertical coordinate.
!
! NOTE:
!   Refer to subroutine interp_eta2eta_lin in WRFSI src/mod/module_vinterp_utils.F
!    o ARPS vertical physical domain is from 2 to nz-1
!    o We added two supported interpolations method, linear and 
!      quadratic while WRFSI only support linear interoplation so far.
!
!-------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: nx      ! X dimension of WRF grid
  INTEGER, INTENT(IN) :: ny      ! Y dimension of WRF grid
  INTEGER, INTENT(IN) :: nz_in   ! Vertical dimension of ARPS grid
  INTEGER, INTENT(IN) :: nz_out  ! Vertical dimension of WRF grid (mass)
  INTEGER, INTENT(IN) :: korder  ! polyn. interpolation order
  REAL,    INTENT(IN) :: eta_in(nx,ny,nz_in)
                                 ! mass value at ARPS grid
  REAL,    INTENT(IN) :: eta_out(nz_out)
                                 ! Desired mass levels
  REAL,    INTENT(IN) :: data_in(nx,ny,nz_in)
  REAL,    INTENT(OUT):: data_out(nx,ny,nz_out)
  LOGICAL, INTENT(IN) :: extrapolate
                                 ! Whether to do extrapolation

!------------------------------------------------------------------
!
! External function
!
!------------------------------------------------------------------
  REAL :: intpnt_lin             ! do vertical interpolation linearly
  REAL :: intpnt_quad            ! do vertical interpolation quadratically
!
!-----------------------------------------------------------------
!
! Misc. Local variables
!
!-----------------------------------------------------------------

  INTEGER :: i,j,k,kk, ki
  REAL    :: desired_eta
  REAL    :: dvaldeta
  INTEGER :: nz_top

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

  data_out(:,:,:) = -99999.9
  nz_top = nz_in - 1

  DO j = 1, ny
    DO i = 1, nx
      output_loop: DO k = 1, nz_out

        desired_eta = eta_out(k)
        IF (desired_eta .GT. eta_in(i,j,2)) THEN

          IF ((desired_eta - eta_in(i,j,2)).LT. 0.0001) THEN
             data_out(i,j,k) = data_in(i,j,2)
          ELSE
            IF (extrapolate) THEN
              ! Extrapolate downward because desired eta level is below
              ! the lowest level in our input data.  Extrapolate using simple
              ! 1st derivative of value with respect to eta for the bottom 2
              ! input layers.

              ! Add a check to make sure we are not using the gradient of
              ! a very thin layer

              IF ( (eta_in(i,j,2)-eta_in(i,j,3)) .GT. 0.001) THEN
                dvaldeta = (data_in(i,j,2) - data_in(i,j,3)) /          &
                           (eta_in(i,j,2) - eta_in(i,j,3) )
              ELSE
                dvaldeta = (data_in(i,j,2) - data_in(i,j,4)) /          &
                            (eta_in(i,j,2) - eta_in(i,j,4) )
              ENDIF
              data_out(i,j,k) = data_in(i,j,2) +                        &
                              dvaldeta * (desired_eta-eta_in(i,j,2))
            ELSE
              data_out(i,j,k) = data_in(i,j,2)

            ENDIF
          ENDIF
        ELSE IF (desired_eta .LE. eta_in(i,j,nz_top)) THEN
          IF ( abs(eta_in(i,j,nz_top) - desired_eta) .LT. 0.0001) THEN
             data_out(i,j,k) = data_in(i,j,nz_top)
          ELSE
            IF (extrapolate) THEN
              ! Extrapolate upward
              IF ( (eta_in(i,j,nz_top-1)-eta_in(i,j,nz_top)) .GT. 0.0005) THEN
                dvaldeta = (data_in(i,j,nz_top) - data_in(i,j,nz_top-1)) / &
                           (eta_in(i,j,nz_top)  - eta_in(i,j,nz_top-1))
              ELSE
                dvaldeta = (data_in(i,j,nz_top) - data_in(i,j,nz_top-2)) / &
                           (eta_in(i,j,nz_top)  - eta_in(i,j,nz_top-2))
              ENDIF
              data_out(i,j,k) =  data_in(i,j,nz_top) +                     &
                                 dvaldeta * (desired_eta-eta_in(i,j,nz_top))
            ELSE
              data_out(i,j,k) = data_in(i,j,nz_top)
            ENDIF
          ENDIF
        ELSE
          ! We can trap between two levels and linearly interpolate

          input_loop:  DO kk = 2, nz_top-1
            IF (desired_eta .EQ. eta_in(i,j,kk) )THEN
              data_out(i,j,k) = data_in(i,j,kk)
              EXIT input_loop
            ELSE IF ( (desired_eta .LT. eta_in(i,j,kk)) .AND.           &
                      (desired_eta .GT. eta_in(i,j,kk+1)) ) THEN
              IF(korder == 1) THEN      
                data_out(i,j,k) = intpnt_lin( eta_in(i,j,kk),           &
                                    eta_in(i,j,kk+1), desired_eta,      &
                                    data_in(i,j,kk), data_in(i,j,kk+1) )
              ELSE IF(korder == 2)  THEN
                IF ( ABS(desired_eta - eta_in(i,j,kk)) <=               &
                     ABS(desired_eta - eta_in(i,j,kk+1)) ) THEN
                  ki = kk
                ELSE IF ( kk == nz_top-1 ) THEN
                  ki = kk
                ELSE
                  ki = kk+1
                END IF
                data_out(i,j,k) = intpnt_quad( eta_in(i,j,ki-1),        &
                                    eta_in(i,j,ki),eta_in(i,j,ki+1),    &
                                    desired_eta, data_in(i,j,ki-1),     &
                                    data_in(i,j,ki),data_in(i,j,ki+1) )
              ELSE
                WRITE(6,*) 'Unsupported polynomial interpolation order:',korder
                STOP 'Unsupported korder'
              END IF

              EXIT input_loop
            ENDIF
          ENDDO input_loop
        ENDIF

      ENDDO output_loop

    ENDDO   ! i
  ENDDO   ! j

  RETURN
END SUBROUTINE vinterp

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

FUNCTION intpnt_lin(x1,x2,x,d1,d2) RESULT(d)

!------------------------------------------------------------------
!
! PURPOSE:
!   Fuction to do vertical interpolation linearly
!
!-----------------------------------------------------------------------
!
! Author: Yunheng Wang.
!  
!-----------------------------------------------------------------

  IMPLICIT NONE

  REAL, INTENT(IN)  :: x1    ! coordinate of first point
  REAL, INTENT(IN)  :: x2    ! coordinate of second point
  REAL, INTENT(IN)  :: x     ! coordinate of desired point
  REAL, INTENT(IN)  :: d1    ! data at first point
  REAL, INTENT(IN)  :: d2    ! data at second point
  REAL              :: d     ! Interpolated value
  
!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------

  REAL    :: wgt

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

  wgt = (x - x2) / (x1 - x2)
  d   = wgt*d1 + (1.-wgt)*d2

  RETURN
END FUNCTION intpnt_lin

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

FUNCTION intpnt_quad(x0,x1,x2,x,d0,d1,d2) RESULT(d)

!-------------------------------------------------------------------
!
! PURPOSE:
!
!   Quadratically interpolates from the given three points 
!
!-----------------------------------------------------------------------
!
! Author: Yunheng Wang.
!
!-------------------------------------------------------------------

  IMPLICIT NONE

  REAL, INTENT(IN) :: x0     ! coordinate of the first point
  REAL, INTENT(IN) :: x1     ! coordinate of the second point
  REAL, INTENT(IN) :: x2     ! coordinate of the third point
  REAL, INTENT(IN) :: x      ! coordinate of the desired point
  REAL, INTENT(IN) :: d0     ! value at the first point
  REAL, INTENT(IN) :: d1     ! value at the second point
  REAL, INTENT(IN) :: d2     ! value at the third point

  REAL             :: d      ! value to be calculated
!
!-----------------------------------------------------------------
!
! Misc. Local variables
!
!-----------------------------------------------------------------

  REAL    :: b1,b2, tmp

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

!-----------------------------------------------------------------------
!
!  Quadratic interpolation
!
!             f(x) = f(x0) + b1*(x-x0) + b2*(x-x0)(x-x1)
!
!                    f(x1)-f(x0)
!             b1   = ----------
!                     x1 - x0
!
!                    f(x2)-f(x1)   f(x1)-f(x0)
!                    ----------- - ------------
!                     x2 - x1        x1 - x0
!             b2   = -----------------------------
!                             x2 - x0
!
!------------------------------------------------------------------------
!
  b1  = (d1  - d0) / (x1 - x0)
  tmp = (d2  - d1) / (x2 - x1)
  b2  = (tmp - b1) / (x2 - x0)
  
  d   = d0 + b1*(x-x0) + b2*(x-x0)*(x-x1)

  RETURN
END FUNCTION intpnt_quad

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

FUNCTION compute_density(t_k, p_pa) RESULT(rho)

!-----------------------------------------------------------------
!
! PURPOSE:
! Computes density (kg/m{-3}) given temperature (K) and pressure (Pa)
!
! NOTE:
!   Refer to the same function in WRFSI src/mode/module_diagnostic_vars.F.
!
!-----------------------------------------------------------------

  IMPLICIT NONE
  REAL, INTENT(IN) :: t_k
  REAL, INTENT(IN) :: p_pa
  REAL             :: rho

  REAL, PARAMETER  :: Rd =  287.04  ! J deg{-1} kg{-1}
                                    ! Gas constant for dry air

  rho = p_pa / (Rd * t_k)

  RETURN
END FUNCTION compute_density

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

SUBROUTINE compute_column_pdry(nz,p,rho,qv,z,pdry,pvapor) 1

!-----------------------------------------------------------------
!
! PURPOSE:
!
! Given full pressure in Pascals (p), dry air density in kg/m^3 (rho),
! water vapor mixing ratio in kg/kg (qv), compute the dry pressure value
! at each grid point in the column of nz elements.
! This routine assumes the pressure array decreases monotonically from
! 1->nz and that the rho and qv arrays match the pressure array.
!
! NOTE:
!   Refer to subroutine compute_column_pdry in WRFSI src/mod/module_vinterp_utils.F.
!
!-----------------------------------------------------------------

  IMPLICIT NONE
  INTEGER, INTENT(IN)                    :: nz
  REAL, INTENT(IN)                       :: p  (nz)
  REAL, INTENT(IN)                       :: rho(nz)
  REAL, INTENT(IN)                       :: qv (nz)
  REAL, INTENT(IN)                       :: z  (nz)
  REAL, INTENT(OUT)                      :: pdry  (nz)
  REAL, INTENT(OUT)                      :: pvapor(nz)

  INTEGER                                :: kbot, k
  REAL                                   :: qv_mean,dz

  REAL, PARAMETER :: g = 9.8

! Set top vapor pressure to zero and top dry pressure equal to
! top total pressure

    pvapor(nz) = 0.
    pdry(nz) = p(nz)

    ! Integrate moisture downward

    main_loop:  DO kbot = nz-1, 1, -1

      ! Initialize for upcoming sums.
      pvapor(kbot) = 0.

      ! Integrate downward
      down_to_here:  DO k = nz-1,kbot,-1
        ! Compute delta-Z and mean Qv for this layer
        dz = z(k+1) - z(k)
        qv_mean = (qv(k) + qv(k+1)) * 0.5

        ! Compute pvapor for this layer and sum with previous layer
        pvapor(kbot) = pvapor(kbot)+g*qv_mean*rho(k)*dz/(1.+qv_mean)
      END DO down_to_here

      ! Subtract the integrated vapor pressure from the total pressure
      pdry(kbot) = p(kbot) - pvapor(kbot)
    END DO main_loop

END SUBROUTINE compute_column_pdry
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE compute_ph                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE compute_ph(nx,ny,nz,ht,znw,ptop,mu_input,                    & 1,2
                      pt_input,qv,mu,mub,ph,phb,pt,p,pb,                &
                      t_init,alb,alt,al)
!------------------------------------------------------------------
!
! PURPOSE:
!
!   Compute WRF variables, such as geopotential, air mass and potential
!   temperature etc.
!
! NOTE:
!   Refered to subroutine init_domain_rk in WRF dyn_em/module_initialize_real.f.
!
!------------------------------------------------------------------

  USE wrf_metadata

  IMPLICIT NONE
  INTEGER, INTENT(IN)  :: nx,ny,nz     ! WRF dimension size
  REAL,    INTENT(IN)  :: ht(nx,ny)    ! Topographic height
  REAL,    INTENT(IN)  :: znw(nz)      ! full vertical levels
  REAL,    INTENT(IN)  :: ptop         ! model top pressure (Pa)
  REAL,    INTENT(IN)  :: mu_input(nx,ny)    ! Total air mass in column
  REAL,    INTENT(IN)  :: pt_input(nx,ny,nz) ! potential temperature
  REAL,    INTENT(IN)  :: qv(nx,ny,nz) ! water vapor mixing ratio
  
  REAL,    INTENT(OUT) :: ph(nx,ny,nz) ! base-state geopotential
  REAL,    INTENT(OUT) :: phb(nx,ny,nz)! perturbation geopotential
  REAL,    INTENT(OUT) :: mu(nx,ny)    ! perturbation dry air mass in column
  REAL,    INTENT(OUT) :: mub(nx,ny)   ! base state dry air mass in column
  REAL,    INTENT(OUT) :: pt(nx,ny,nz) ! perturbation potential temperature
  REAL,    INTENT(OUT) :: p(nx,ny,nz)
  REAL,    INTENT(OUT) :: pb(nx,ny,nz) ! base state pressure
                        ! work arrays below
  REAL,    INTENT(OUT) :: t_init(nx,ny,nz) ! 
  REAL,    INTENT(OUT) :: alb(nx,ny,nz)    ! inverse of reference density
  REAL,    INTENT(OUT) :: alt(nx,ny,nz)    ! inverse of perturb. density
  REAL,    INTENT(OUT) :: al(nx,ny,nz)     ! inverse of density
!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------

  REAL    :: p00,t00,a
  REAL    :: p_surf                ! surface pressure
  REAL    :: qvf1,qvf2,qvf

  REAL    :: znu(nz-1)             ! half level locations
  REAL    :: dnw(nz-1)             ! layer thickness
  REAL    :: rdn(nz-1)

  INTEGER :: i,j,k

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

  DO k = 1, nz-1
    znu(k) = 0.5*( znw(k+1) + znw(k) )
    dnw(k) = znw(k+1) - znw(k)
  END DO
  DO k = 2, nz-1
    rdn(k) = 1.0/(0.5*(dnw(k)+dnw(k-1)))
  END DO

  !  To define the base state, we call a USER MODIFIED routine to set the three
  !  necessary constants:  p00 (sea level pressure, Pa), t00 (sea level temperature, K),
  !  and A (temperature difference, from 1000 mb to 300 mb, K).

  CALL const_module_initialize ( p00 , t00 , a )

  ! bast state pressure is a function of eta level and terrain only

  DO j = 1, ny-1
    DO i = 1,nx-1
      p_surf = p00*EXP(-t00/a + ((t00/a)**2 - 2.*g_wrf*ht(i,j)/a/r_d)**0.5)

      DO k = 1,nz-1
        pb(i,j,k) = znu(k)*(p_surf-ptop) + ptop
        t_init(i,j,k) = (t00 + a*LOG(pb(i,j,k)/p00))*(p00/pb(i,j,k))**(r_d/cp_wrf) - t0
        alb(i,j,k) = (r_d/p1000mb)*(t_init(i,j,k)+t0)*(pb(i,j,k)/p1000mb)**cvpm
      END DO
      
      mub(i,j) = p_surf - ptop   ! base state dry air mass
      mu(i,j)  = mu_input(i,j) + ptop - p_surf ! perturbation dry air mass

      phb(i,j,1) = g_wrf*ht(i,j)  ! base geopotential at the lowest level 
                                  ! is terrain elevation * gravity
      ! Integerate base geopotential. this assures that the base state
      ! is in exact hydrostatic balance with respect to the model equations.
      ! this field is on full levels.
      DO k = 2, nz
        phb(i,j,k) = phb(i,j,k-1) - dnw(k-1)*mub(i,j)*alb(i,j,k-1)
      END DO
    END DO
  END DO

  ! Filling edges
  mub(nx,:)           = mub(nx-1,:)
  mu (nx,:)           = mu(nx-1,:)
  pb (nx,:,1:nz-1)    = pb(nx-1,:,1:nz-1)
  alb(nx,:,1:nz-1)    = alb(nx-1,:,1:nz-1)
  t_init(nx,:,1:nz-1) = t_init(nx-1,:,1:nz-1)
  phb(nx,:,:)         = pb(nx-1,:,:)

  mub(:,ny)           = mub(:,ny-1)
  mu (:,ny)           = mu(:,ny-1)
  pb (:,ny,1:nz-1)    = pb(:,ny-1,1:nz-1)
  alb(:,ny,1:nz-1)    = alb(:,ny-1,1:nz-1)
  t_init(:,ny,1:nz-1) = t_init(:,ny-1,1:nz-1)
  phb (:,ny,:)        = pb(:,ny-1,:)

  pt = pt_input - t0
  DO j = 1, ny-1
    DO i = 1, nx-1

      ! first get the pressure perturbation, moisture and inverse density
      ! at the top-most level

      qvf1 = qv(i,j,nz-1)
      qvf2 = 1./(1.+qvf1)
      qvf1 = qvf1*qvf2
      p(i,j,nz-1) = - 0.5*(mu(i,j) + qvf1*mub(i,j))*dnw(nz-1)/qvf2
      qvf  = 1.0 + rvovrd*qv(i,j,nz-1)
      alt(i,j,nz-1) = (r_d/p1000mb)*(pt(i,j,nz-1)+t0)*qvf*              &
                      (((p(i,j,nz-1)+pb(i,j,nz-1))/p1000mb)**cvpm)
      al(i,j,nz-1)  = alt(i,j,nz-1) - alb(i,j,nz-1)
    
     
      ! now, integrate down the column.
      DO k = nz-2,1,-1
        qvf1 = 0.5*(qv(i,j,k)+ qv(i,j,k+1))
        qvf2 = 1./(1.+qvf1)
        qvf1 = qvf1*qvf2
        p(i,j,k) = p(i,j,k+1) - (mu(i,j) + qvf1*mub(i,j))/qvf2/rdn(k+1)
        qvf  = 1.0 + rvovrd*qv(i,j,k)
        alt(i,j,k) = (r_d/p1000mb)*(pt(i,j,k)+t0)*qvf*                  &
                        (((p(i,j,k)+pb(i,j,k))/p1000mb)**cvpm)
        al(i,j,k)  = alt(i,j,k) - alb(i,j,k)
      END DO

      ph(i,j,1) = 0.0
      DO k = 2, nz
        ph(i,j,k) = ph(i,j,k-1) - dnw(k-1) *                            &
                    ( (mub(i,j)+mu(i,j))*al(i,j,k-1)+mu(i,j)*alb(i,j,k-1))
      END DO

    END DO
  END DO

  RETURN
END SUBROUTINE compute_ph
!
!##################################################################
!##################################################################
!######                                                      ######
!######            SUBROUTINE init_soil_depth                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################


SUBROUTINE init_soil_depth(sfcphys, zs,dzs,nzsoil) 1

!------------------------------------------------------------------
!
!  Define layers (top layer = 0.01 m).  Double the thicknesses at 
!  each step (dzs values). The distance from the ground level to 
!  the midpoint of the layer is given by zs.
!
!    -------   Ground Level   ----------      ||      ||   ||  ||
!                                             ||      ||   ||  || zs(1) = 0.005 m
!    --  --  --  --  --  --  --  --  --       ||      ||   ||  \/
!                                             ||      ||   ||
!    -----------------------------------      ||  ||  ||   \/   dzs(1) = 0.01 m
!                                             ||  ||  ||
!                                             ||  ||  || zs(2) = 0.02
!    --  --  --  --  --  --  --  --  --       ||  ||  \/
!                                             ||  ||
!                                             ||  ||
!    -----------------------------------  ||  ||  \/   dzs(2) = 0.02 m
!                                         ||  ||
!                                         ||  ||
!                                         ||  ||
!                                         ||  || zs(3) = 0.05
!    --  --  --  --  --  --  --  --  --   ||  \/
!                                         ||
!                                         ||
!                                         ||
!                                         ||
!    -----------------------------------  \/   dzs(3) = 0.04 m
!
!----------------------------------------------------------------------

  IMPLICIT NONE
  INTEGER, INTENT(IN)  :: sfcphys
  REAL,    INTENT(OUT) :: zs(6), dzs(6)
  INTEGER, INTENT(OUT) :: nzsoil
  
!------------------------------------------------------------------
!
!  Misc. local variables
!
!------ -----------------------------------------------------------
   INTEGER :: k

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

  IF(sfcphys == 1) THEN
    nzsoil = 5
    dzs(1) = 0.01
    zs(1)  = 0.5*dzs(1)
    DO k=2,nzsoil
       dzs(k)=2*dzs(k-1)
       zs(k)=zs(k-1)+.5*dzs(k-1)+.5*dzs(k)
    END DO

  ELSE IF(sfcphys == 2) THEN
    nzsoil = 4
    dzs(1:4) = (/ 0.1 , 0.3 , 0.6 , 1.0 /)
    zs(1)=.5*dzs(1)
    DO k=2,nzsoil
       zs(k)=zs(k-1)+.5*dzs(k-1)+.5*dzs(k)
    END DO

  ELSE IF(sfcphys == 3) THEN
    nzsoil = 6
    zs(1:6)  = (/ 0.00 , 0.05 , 0.20 , 0.40 , 1.60 , 3.00 /)
    dzs(1:6) = (/ 0.00 , 0.125, 0.175 , 0.70 , 1.30 , 1.40 /)
  ELSE
    WRITE(6,*) ' Wrong bl_surface_physics option', sfcphys
    WRITE(6,*) ' Must be 1, 2 or 3'
    STOP
  END IF

  RETURN
END SUBROUTINE init_soil_depth
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE vinterp_soil               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE vinterp_soil(nx,ny,nzsoil_in,zs_in,tsoil_in,qsoil_in,        & 1
                      nzsoil_out,zs_out,tsoil_out,qsoil_out)

!------------------------------------------------------------------
!
! PURPOSE:
!
!  Vertically interpolate ARPS soil variables to WRF soil layers.
!
!------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN)  :: nx,ny                     ! WRF horizontal grid size
  INTEGER, INTENT(IN)  :: nzsoil_in                 ! ARPS soil layer size
  REAL,    INTENT(IN)  :: zs_in(nx,ny,nzsoil_in)    ! ARPS soil layer depth
  REAL,    INTENT(IN)  :: tsoil_in(nx,ny,nzsoil_in)
  REAL,    INTENT(IN)  :: qsoil_in(nx,ny,nzsoil_in)
 
  INTEGER, INTENT(IN)  :: nzsoil_out                ! WRF soil layer size
  REAL,    INTENT(IN)  :: zs_out(nzsoil_out)        ! WRF soil layer depth
  REAL,    INTENT(OUT) :: tsoil_out(nx,ny,nzsoil_out)
  REAL,    INTENT(OUT) :: qsoil_out(nx,ny,nzsoil_out)

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

  INTEGER :: i,j,k,m
  REAL    :: w1,w2
  REAL    :: dist,wt,wq

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

  IF(nzsoil_in == 2) THEN    ! suppose ARPS old soil model
                             ! contains two layers, 
                             ! soil layer -- 0-10 cm,  (0.05m)and 
                             ! deep soil  -- 10-100 cm (0.55m)
    DO k = 1, nzsoil_out
      IF(zs_out(k) < 0.05) THEN            ! extrapolation
        dist = 0.05 - zs_out(k)
        DO j = 1,ny
          DO i = 1,nx
            wt = (tsoil_in(i,j,1) - tsoil_in(i,j,2))/0.5
            tsoil_out(i,j,k) = tsoil_in(i,j,1) + wt*dist
            wq = (qsoil_in(i,j,1) - qsoil_in(i,j,2))/0.5
            qsoil_out(i,j,k) = qsoil_in(i,j,1) + wq*dist
          END DO
        END DO
      ELSE IF(zs_out(k) >= 0.55) THEN      ! constant layers
        tsoil_out(:,:,k) = tsoil_in(:,:,2)
        qsoil_out(:,:,k) = qsoil_in(:,:,2)
      ELSE
        w1 = ( 0.55      - zs_out(k) )/0.5        
        w2 = ( zs_out(k) - 0.05      )/0.5        
        DO j = 1,ny
          DO i = 1,nx
             tsoil_out(i,j,k) = tsoil_in(i,j,1)*w1 + tsoil_in(i,j,2)*w2
             qsoil_out(i,j,k) = qsoil_in(i,j,1)*w1 + qsoil_in(i,j,2)*w2
          END DO
        END DO
      END IF
    END DO

  ELSE IF(nzsoil_in > 2) THEN  ! ARPS new soil model

    DO j = 1,ny
      DO i = 1,nx
        DO k = 1, nzsoil_out
          IF(zs_out(k) < zs_in(i,j,1)) THEN            ! extrapolation
            dist = zs_in(i,j,1) - zs_out(k)
            wt = (tsoil_in(i,j,1) - tsoil_in(i,j,2))/(zs_in(i,j,2)-zs_in(i,j,1))
            wq = (qsoil_in(i,j,1) - qsoil_in(i,j,2))/(zs_in(i,j,2)-zs_in(i,j,1))
            tsoil_out(i,j,k) = tsoil_in(i,j,1) + wt*dist
            qsoil_out(i,j,k) = qsoil_in(i,j,1) + wq*dist
          ELSE IF(zs_out(k) >= zs_in(i,j,nzsoil_in)) THEN ! constant layers
            tsoil_out(i,j,k) = tsoil_in(i,j,nzsoil_in)
            qsoil_out(i,j,k) = qsoil_in(i,j,nzsoil_in)
          ELSE                         ! linear interpolation
            DO m = 1, nzsoil_in
              IF(zs_in(i,j,m) > zs_out(k)) EXIT
            END DO
            w1 = (zs_in(i,j,m) - zs_out(k))/(zs_in(i,j,m)-zs_in(i,j,m-1))
            w2 = (zs_out(k) - zs_in(i,j,m-1) )/(zs_in(i,j,m)-zs_in(i,j,m-1))
            tsoil_out(:,:,k) = tsoil_in(:,:,m-1)*w1 + tsoil_in(:,:,m)*w2
            qsoil_out(:,:,k) = qsoil_in(:,:,m-1)*w1 + qsoil_in(:,:,m)*w2
          END IF

        END DO   ! k
      END DO   ! i
    END DO  ! j
  ELSE
    WRITE(6,*) ' Wrong soil levels, nzsoil_arps = ',nzsoil_in
    STOP
  END IF

  RETURN
END SUBROUTINE vinterp_soil
!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROUTINE get_sfcdt                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE get_sfcdt(sfcinitopt,sfcdtfl,ncompressx,ncompressy,nxsm,nysm,& 1,5
            nx,ny,nstyps,dx,dy,mapproj,trulat1,trulat2,trulon,sclfct,  &
            ctrlat,ctrlon,soiltyp,stypfrct,vegtyp,veg,tem1,            &
            hinterp_needed,nx_wrf,ny_wrf,dx_wrf,dy_wrf,                &
            mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday,       &
            x2d,y2d,xs,ys,iloc,jloc,                                   &
            hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,xland,     &
            tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus)

!-----------------------------------------------------------------------
!
! PURPOSE:
!   Read in surface characteristic data to intialize
!
!     ARPS         WRF              ARPS          WRF
!  ===========   ============    ============   ============== 
!   soiltyp      soiltyp_wrf      stypfrct       stypfrct_wrf
!   vegtyp       vegtyp_wrf       veg            veg_wrf
!                vegfrct_wrf
!                xice                            xland
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  CHARACTER(LEN=*), INTENT(IN) :: sfcinitopt
  CHARACTER(LEN=*), INTENT(IN) :: sfcdtfl
  INTEGER,          INTENT(IN) :: ncompressx,ncompressy
  INTEGER,          INTENT(IN) :: nxsm, nysm
  INTEGER,          INTENT(IN) :: nx,   ny,  nstyps, nx_wrf, ny_wrf
  REAL,             INTENT(IN) :: dx,   dy,          dx_wrf, dy_wrf
  INTEGER,          INTENT(IN) :: mapproj,           mapproj_wrf
  REAL,             INTENT(IN) :: trulat1,trulat2, trulat1_wrf,trulat2_wrf
  REAL,             INTENT(IN) :: trulon,          trulon_wrf
  REAL,             INTENT(IN) :: ctrlat,ctrlon
  INTEGER,          INTENT(IN) :: sclfct, jday
  LOGICAL,          INTENT(IN) :: hinterp_needed
  REAL,             INTENT(IN) :: x2d(nx_wrf,ny_wrf),  y2d(nx_wrf,ny_wrf)
  INTEGER,          INTENT(IN) :: iloc(nx_wrf,ny_wrf), jloc(nx_wrf,ny_wrf)
  REAL,             INTENT(IN) :: xs(nx), ys(ny)
  INTEGER                      :: soiltyp (nx,ny,nstyps)  ! ARPS arrays
  REAL                         :: stypfrct(nx,ny,nstyps)
  INTEGER                      :: vegtyp(nx,ny)
  REAL                         :: veg(nx,ny)
  REAL                         :: tem1(nx,ny,3)           ! ARPS work arrays
  REAL,            INTENT(OUT) :: hgt_wrf(nx_wrf,ny_wrf)  ! WRF arrays
  INTEGER,         INTENT(OUT) :: soiltyp_wrf(nx_wrf,ny_wrf)
  INTEGER,         INTENT(OUT) :: vegtyp_wrf(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: vegfrct_wrf(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: xice(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: xland(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: tmn_wrf(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: shdmax(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: shdmin(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: albbck(nx_wrf,ny_wrf)
  REAL,            INTENT(OUT) :: snoalb(nx_wrf,ny_wrf)
  INTEGER,         INTENT(OUT) :: istatus

  INCLUDE 'mp.inc'

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

  INTEGER, ALLOCATABLE :: soiltypsm (:,:,:)
  REAL,    ALLOCATABLE :: stypfrctsm(:,:,:)
  INTEGER, ALLOCATABLE :: vegtypsm  (:,:)
  REAL,    ALLOCATABLE :: vegsm     (:,:)

  INTEGER :: i, j, ii, jj, ia, ja
  INTEGER :: lenfil

  CHARACTER(LEN=256) :: tmpstr

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Begin of executable code ...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  lenfil = LEN_TRIM(sfcdtfl)
  WRITE(tmpstr,'(a)') TRIM(sfcdtfl)

  IF(sfcinitopt(1:4) == 'ARPS') THEN
    
    DO jj = 1, ncompressy
      DO ii = 1, ncompressx
        IF (mp_opt > 0 .AND. readsplit <= 0) THEN
          WRITE(tmpstr(lenfil+1:lenfil+5),'(a,i2.2,i2.2)') '_',         &
                 ncompressx*(loc_x-1)+ii,ncompressy*(loc_y-1)+jj
          lenfil= lenfil + 5
        END IF

        IF (mp_opt > 0 .AND. readsplit > 0) THEN
          CALL readsplitsfcdt(nx,ny,nstyps,TRIM(tmpstr),dx,dy,          &
                   mapproj,trulat1,trulat2,trulon,sclfct,ctrlat,ctrlon, &
                   soiltyp,stypfrct,vegtyp,tem1(:,:,1),tem1(:,:,2),     &
                   veg, tem1(:,:,3))
        ELSE

          ALLOCATE(soiltypsm (nxsm,nysm,nstyps), STAT = istatus)
          ALLOCATE(stypfrctsm(nxsm,nysm,nstyps), STAT = istatus)
          ALLOCATE(vegtypsm  (nxsm,nysm),        STAT = istatus)
          ALLOCATE(vegsm     (nxsm,nysm),        STAT = istatus)

          CALL readsfcdt(nx,ny,nstyps,TRIM(tmpstr),dx,dy,               &
                 mapproj,trulat1,trulat2,trulon,sclfct,ctrlat,ctrlon,   &
                 soiltypsm,stypfrctsm,vegtypsm,tem1(:,:,1),tem1(:,:,2), &
                 vegsm, tem1(:,:,3))
        END IF
      END DO
    END DO

    IF(ncompressx > 1 .OR. ncompressy > 1) THEN    ! need join
      DO j = 1, nysm
        ja = (jj-1)*(nysm-3)+j
        DO i = 1, nxsm
          ia = (ii-1)*(nxsm-3)+i
          soiltyp(ia,ja,:)  = soiltypsm(i,j,:)
          stypfrct(ia,ja,:) = stypfrctsm(i,j,:)
          vegtyp(ia,ja)     = vegtypsm(i,j)
          veg(ia,ja)        = vegsm(i,j)
        END DO
      END DO
    END IF

    IF (ALLOCATED(soiltypsm))  DEALLOCATE(soiltypsm)
    IF (ALLOCATED(stypfrctsm)) DEALLOCATE(stypfrctsm)
    IF (ALLOCATED(vegtypsm))   DEALLOCATE(vegtypsm)
    IF (ALLOCATED(vegsm))      DEALLOCATE(vegsm)

    CALL sfcinterp(nx_wrf,ny_wrf,nx,ny,nstyps,hinterp_needed,           &
                   x2d,y2d,xs,ys,iloc,jloc,                             &
                   soiltyp,stypfrct,vegtyp,veg,                         &
                   soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,xland)

    vegfrct_wrf(:,:) = vegfrct_wrf(:,:)*100.

    IF (myproc == 0) THEN
      WRITE(6,'(/,2(a,/),3(10x,a/),a,/)')                               &
        ' ************************** WARNING ************************', &             
  ' WARNING: Noah land-surface model, sf_surface_physics = 2, requires',&
  'annual MAX/MIN veg fraction, MAX snow albedo, background albedo.',   &
  'However, ARPSSFC does not provide such variables. You had better ',  &
  'use sfcinitopt = "WRFSI" or "WRF". see arps2wrf.input.',             &
        ' ************************** WARNING ************************'
    END IF
    hgt_wrf(:,:) = 0.0
    tmn_wrf(:,:) = -999.0 ! indicates it is not available
    shdmax(:,:)  = 0.0
    shdmin(:,:)  = 0.0
    snoalb(:,:)  = 0.0
    albbck(:,:)  = 0.0

    istatus = 1           ! change to 0 if you want to read ARPSSFC data

  ELSE IF(sfcinitopt(1:5) == 'WRFSI') THEN

    CALL get_sfcdt_wrfsi(TRIM(tmpstr),nx_wrf,ny_wrf,dx_wrf,dy_wrf,      &
                   mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday, &
                   hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,     &
                   xland,tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus)

  ELSE IF (sfcinitopt(1:3) == 'WRF') THEN

    CALL get_sfcdt_wrf(TRIM(tmpstr),nx_wrf,ny_wrf,dx_wrf,dy_wrf,        &
                   mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday, &
                   hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,     &
                   xland,tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus)

  ELSE
    WRITE(6,*) 'Unsupported surface data format: ',sfcinitopt
    istatus = -1
  END IF

  RETURN
END SUBROUTINE get_sfcdt
!
!##################################################################
!##################################################################
!######                                                      ######
!######                  SUBROUTINE sfcinterp                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE sfcinterp(nx,ny,nx_ext,ny_ext,nstyps_ext,interp,             & 1
                    x2d,y2d,x_ext,y_ext,iloc,jloc,                      &
                    soiltyp_ext,stypfrct_ext,vegtyp_ext,vegfrct_ext,    &
                    soiltyp,vegtyp,vegfrct,xice,xland)

!------------------------------------------------------------------
!
! Purpose:
!   Interpolate ARPS surface variables to WRF grid. Those variables
!   include soil types, vegtation types, vegatation fraction
!   ice flage and land flage etc.
!
!------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN)  :: nx,ny          ! WRF grid size
  INTEGER, INTENT(IN)  :: nx_ext,ny_ext  ! ARPS grid size
  INTEGER, INTENT(IN)  :: nstyps_ext     ! ARPS soil type size

  LOGICAL, INTENT(IN)  :: interp         ! whether interpolation is needed

  REAL,    INTENT(IN)  :: x2d(nx,ny)
  REAL,    INTENT(IN)  :: y2d(nx,ny)
  INTEGER, INTENT(IN)  :: iloc(nx,ny)
  INTEGER, INTENT(IN)  :: jloc(nx,ny)
  REAL,    INTENT(IN)  :: x_ext(nx_ext)  ! ARPS grid coordinate
  REAL,    INTENT(IN)  :: y_ext(ny_ext)

  INTEGER, INTENT(IN)  :: soiltyp_ext(nx_ext,ny_ext,nstyps_ext)
  INTEGER, INTENT(IN)  :: vegtyp_ext(nx_ext,ny_ext)
  REAL,    INTENT(IN)  :: stypfrct_ext(nx_ext,ny_ext,nstyps_ext)
  REAL,    INTENT(IN)  :: vegfrct_ext(nx_ext,ny_ext)

  INTEGER, INTENT(OUT) :: soiltyp(nx,ny)
  INTEGER, INTENT(OUT) :: vegtyp(nx,ny)
  REAL,    INTENT(OUT) :: vegfrct(nx,ny)

  REAL,    INTENT(OUT) :: xice(nx,ny)
  REAL,    INTENT(OUT) :: xland(nx,ny)

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
  INTEGER :: i,j
  INTEGER :: ii,jj
  INTEGER :: k
  REAL    :: dx,dy
  REAL    :: dxmid,dymid
  INTEGER :: itmp(1)

  INTEGER, PARAMETER :: veg_table(14)  = (/19,22, 7, 9, 6,11,14,        &
                                           13,24, 3,17, 8,19,16  /)
!
!  ARPS                                     WRF
!  ====                                    ====
!     1  ! Desert                            19      ! Bar. Sparse Veg.
!     2  ! Tundra                            22      ! Mixed Tundra
!     3  ! Grassland                          7      ! Grassland
!     4  ! Grassland with shrub cover         9      ! Mix Shrb./Grs.
!     5  ! Grassland with tree cover          6      ! Crop./Wood Mosc
!     6  ! Deciduous forest                  11      ! Decids. Broadlf.
!     7  ! Evergreen forest                  14      ! Evergrn. Needlf.
!     8  ! Rain forest                       13      ! Evergn Broadlf Forest
!     9  ! Ice                               24      ! Snow or Ice
!    10  ! Cultivation                        3      ! Irrg. Crop. Past.
!    11  ! Bog or marsh                      17      ! Herb. Wetland
!    12  ! Dwarf shrub                        8      ! Shrubland
!    13  ! Semidesert                        19      ! Bar. Sparse Veg.
!    14  ! Water                             16      ! Water bodies
!

  INTEGER, PARAMETER :: soil_table(13) = (/ 1, 2, 3, 4, 6, 7, 8,        &
                                            9,10,11,12,14,14  /)
!
!  ARPS    WRF                       ||   ARPS     WRF
! =====   ====                       ||  =====    ====
!     1      1  ! Sand               ||      8       9  ! Clay loam
!     2      2  ! Loamy sand         ||      9      10  ! Sandy clay
!     3      3  ! Sandy loam         ||     10      11  ! Silty clay
!     4      4  ! Silt loam          ||     11      12  ! Clay
!     5      6  ! Loam               ||     12      16  ! Ice     
!     6      7  ! Sandy clay loam    ||                 ! Changed to 14 by Jerry, 10/20/2003
!     7      8  ! Silty clay loam    ||     13      14  ! Water
!

  INTEGER, PARAMETER :: ice   = 24            ! vegetation type
  INTEGER, PARAMETER :: water = 16            ! vegetation type

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

  dxmid = (x_ext(3)-x_ext(2))/2.0
  dymid = (y_ext(3)-y_ext(2))/2.0

!
!(ii,jj+1)                (ii+1,jj+1)
!       _____________________
!       |         |          |
!       |         |          |
!       |         |          |
!       |---------|----------|
!       |         |          |
! dymid{|  dxmid  |          |
!       |_________|__________|
!      (ii,jj)             (ii+1,jj)
!

! nearest neighbor interpolation

  DO j = 1,ny
    DO i = 1,nx
      IF(interp) THEN
        ii = iloc(i,j)
        jj = jloc(i,j)
        dx = x2d(i,j) - x_ext(ii)
        dy = y2d(i,j) - y_ext(jj)
        IF(dx > dxmid) ii = ii + 1
        IF(dy > dymid) jj = jj + 1
      ELSE
        ii = i+1
        jj = j+1
      END IF

      vegtyp(i,j)  = veg_table(vegtyp_ext(ii,jj))
      vegfrct(i,j) = vegfrct_ext(ii,jj)
      itmp = MAXLOC(stypfrct_ext(ii,jj,:))
      k = itmp(1)
      soiltyp(i,j) = soil_table(soiltyp_ext(ii,jj,k))

      xice(i,j) = 0.0
      IF(vegtyp(i,j) == ice) xice(i,j) = 1.

      xland(i,j) = 1.0
      IF(vegtyp(i,j) == water) THEN
        xland(i,j)   = 2.0
        vegfrct(i,j) = 0
      END IF

      IF(soiltyp(i,j) == 14 .AND. xland(i,j) < 1.5) THEN
         soiltyp(i,j) = 7
      ELSE IF(xland(i,j) > 1.5) THEN
         soiltyp(i,j) = 14
      END IF

!      IF(vegtyp(i,j) == 0)   &
!        WRITE(6,*) 'Vegtyp is zero at i = ',i,' j = ',j
!      IF(soiltyp(i,j) == 0)  &
!        WRITE(6,*) 'Soiltyp is zero at i = ',i,' j = ',j

    END DO
  END DO
  
  RETURN
END SUBROUTINE sfcinterp
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE get_sfcdt_wrfsi            ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE get_sfcdt_wrfsi(filnam,nx,ny,dx,dy,                          & 1,17
                     mapproj,trulat1,trulat2,trulon,jday,               &
                     hgt,soiltyp,vegtyp,vegfrct,xice,                   &
                     xland,tmn,shdmin,shdmax,albbck,snoalb,istatus)

!------------------------------------------------------------------
!
! PURPOSE:
!   Read surface variables from NetCDF static file created by
!   gridgen_model of WRFSI package
!   
! NOTE:
!   Those data must be at the same WRF grid as that specified
!   by the arguments.
!
!------------------------------------------------------------------

  USE wrf_metadata

  IMPLICIT NONE

  CHARACTER(LEN=*), INTENT(IN) :: filnam           ! static file name
  INTEGER, INTENT(IN)  :: nx,ny                    ! WRF grid size
  INTEGER, INTENT(IN)  :: mapproj                  ! Map projection
  REAL,    INTENT(IN)  :: dx,dy                    ! WRF grid length
  REAL,    INTENT(IN)  :: trulat1,trulat2,trulon   ! Map projection specification
  INTEGER, INTENT(IN)  :: jday                     ! julian day of the year

  REAL,    INTENT(OUT) :: hgt    (nx,ny)
  INTEGER, INTENT(OUT) :: soiltyp(nx,ny)
  INTEGER, INTENT(OUT) :: vegtyp (nx,ny)
  REAL,    INTENT(OUT) :: vegfrct(nx,ny)
  REAL,    INTENT(OUT) :: xice   (nx,ny)
  REAL,    INTENT(OUT) :: xland  (nx,ny)
  REAL,    INTENT(OUT) :: tmn    (nx,ny)
  REAL,    INTENT(OUT) :: shdmin (nx,ny)
  REAL,    INTENT(OUT) :: shdmax (nx,ny)
  REAL,    INTENT(OUT) :: albbck (nx,ny)
  REAL,    INTENT(OUT) :: snoalb (nx,ny)
  INTEGER, INTENT(OUT) :: istatus

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

  LOGICAL :: ISAME

  INTEGER :: nscid

  REAL, ALLOCATABLE :: landusef(:,:,:)
  REAL, ALLOCATABLE :: soiltyp_top(:,:,:),soiltyp_bot(:,:,:)

  INTEGER :: i,j,k

  INTEGER :: nxlg, nylg

  REAL, ALLOCATABLE :: var3d1(:,:,:), var3d2(:,:,:), var3d3(:,:,:)
  REAL, ALLOCATABLE :: var2d(:,:)

  REAL              :: rdummy(1,1,12)

  INCLUDE   'mp.inc'

!-----------------------------------------------------------------

  INTERFACE

    SUBROUTINE get_static_landusef(ncid,var3d)
      INTEGER,          INTENT(IN)  :: ncid
      REAL,             INTENT(OUT) :: var3d(:,:,:)
    END SUBROUTINE get_static_landusef

    SUBROUTINE get_static_soil(ncid,var3d1,var3d2)
      INTEGER,          INTENT(IN)  :: ncid
      REAL,             INTENT(OUT) :: var3d1(:,:,:)
      REAL,             INTENT(OUT) :: var3d2(:,:,:)
    END SUBROUTINE get_static_soil

    SUBROUTINE get_static_monthly(staticopt,ncid, vartype, jday,        &
                                  var2d, varin3d, istatus)
      INTEGER,          INTENT(IN)  :: staticopt
      INTEGER,          INTENT(IN)  :: ncid
      CHARACTER(LEN=1), INTENT(IN)  :: vartype
      INTEGER,          INTENT(IN)  :: jday
      REAL,             INTENT(OUT) :: var2d(:,:)
      REAL,             INTENT(IN)  :: varin3d(:,:,:)
      INTEGER,          INTENT(OUT) :: istatus
    END SUBROUTINE get_static_monthly

    SUBROUTINE get_static_2d(ncid,varname,var2d)
      INTEGER,          INTENT(IN)  :: ncid
      CHARACTER(LEN=3), INTENT(IN)  :: varname
      REAL,             INTENT(OUT) :: var2d(:,:)
    END SUBROUTINE get_static_2d

  END INTERFACE

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

  nxlg = (nx - 1)*nproc_x + 1
  nylg = (ny - 1)*nproc_y + 1

!  write(0,*) 'nx = ',nx, 'ny = ',ny, 'nxlg = ',nxlg, 'nylg = ',nylg

  ALLOCATE(landusef(nx,ny,LanduseCategories), STAT = istatus)
  ALLOCATE(soiltyp_top(nx,ny,SoilCategories), STAT = istatus)
  ALLOCATE(soiltyp_bot(nx,ny,SoilCategories), STAT = istatus)

  ALLOCATE(var3d1(nxlg,nylg,LanduseCategories), STAT = istatus)
  ALLOCATE(var3d2(nxlg,nylg,SoilCategories),    STAT = istatus)
  ALLOCATE(var3d3(nxlg,nylg,SoilCategories),    STAT = istatus)
  ALLOCATE(var2d (nxlg,nylg),                   STAT = istatus)
!
! Open the static NetCDF file which is created by gridgen_model.
!

  IF(myproc == 0) CALL open_static_file(filnam,nscid)

! we need to check whether the static file is
! on the same grid as WRF grid

  IF(myproc == 0) THEN 
    CALL check_static_grid(0,nscid,nx,ny,dx,dy,mapproj,                   &
                         trulat1,trulat2,trulon,isame)
    IF(.NOT. ISAME) CALL mpexit(1)
  END IF

  IF (myproc == 0) THEN
    CALL get_static_landusef(nscid,var3d1)
    CALL get_static_soil(nscid,var3d2,var3d3)
  END IF
  CALL wrf_split3d(var3d1,nx,ny,LanduseCategories,1,landusef)
  CALL wrf_split3d(var3d2,nx,ny,SoilCategories,1,soiltyp_top)
  CALL wrf_split3d(var3d3,nx,ny,SoilCategories,1,soiltyp_bot)

  IF (myproc == 0) CALL get_static_monthly (0,nscid, 'g', jday, var2d, rdummy,istatus)
  IF (istatus /= 0) CALL mpexit(1)
  CALL wrf_split2d(var2d,nx,ny,1,vegfrct)

  IF (myproc == 0) CALL get_static_monthly (0,nscid, 'a', jday, var2d, rdummy,istatus)
  IF (istatus /= 0) CALL mpexit(1)
  CALL wrf_split2d(var2d,nx,ny,1,albbck)
  
  IF (myproc == 0) CALL get_static_2d(nscid,'gnn',var2d)
  CALL wrf_split2d(var2d,nx,ny,1,shdmin)

  IF (myproc == 0) CALL get_static_2d(nscid,'gnx',var2d)
  CALL wrf_split2d(var2d,nx,ny,1,shdmax)

  IF (myproc == 0) CALL get_static_2d(nscid,'alb',var2d)
  CALL wrf_split2d(var2d,nx,ny,1,snoalb)

  IF (myproc == 0) CALL get_static_2d(nscid,'avc',var2d)
  CALL wrf_split2d(var2d,nx,ny,1,hgt)

  IF (myproc == 0) CALL get_static_2d(nscid,'tmp',var2d)
  CALL wrf_split2d(var2d,nx,ny,1,tmn)

  IF(myproc == 0) CALL close_static_file(nscid)

  DEALLOCATE(var3d1,var3d2,var3d3)
  DEALLOCATE(var2d)

!--------------------------------------------------------------------
!
! Vegetation index and soil texture indexSoilCategories
!
!--------------------------------------------------------------------

  CALL land_soil_cat(nx,ny,LanduseCategories,SoilCategories,            &
                     landusef,soiltyp_top,soiltyp_bot,                  &
                     vegtyp,soiltyp,xland,xice,istatus)

  DEALLOCATE(landusef, soiltyp_top, soiltyp_bot)

  RETURN
END SUBROUTINE get_sfcdt_wrfsi

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

SUBROUTINE get_sfcdt_wrf(filnam,nx,ny,dx,dy,                            & 1,30
                     mapproj,trulat1,trulat2,trulon,jday,               &
                     hgt,soiltyp,vegtyp,vegfrct,xice,                   &
                     xland,tmn,shdmin,shdmax,albbck,snoalb,istatus)

!------------------------------------------------------------------
!
! PURPOSE:
!   Read surface variables from NetCDF static file created by
!   staticpost of WRFSI package or wrfstatic from ARPS package
!   
! NOTE:
!   Those data must be at the same WRF grid as that specified
!   by the arguments.
!
!------------------------------------------------------------------

  USE wrf_metadata

  IMPLICIT NONE

  CHARACTER(LEN=*), INTENT(IN) :: filnam           ! static file name
  INTEGER, INTENT(IN)  :: nx,ny                    ! WRF grid size
  INTEGER, INTENT(IN)  :: mapproj                  ! Map projection
  REAL,    INTENT(IN)  :: dx,dy                    ! WRF grid length
  REAL,    INTENT(IN)  :: trulat1,trulat2,trulon   ! Map projection specification
  INTEGER, INTENT(IN)  :: jday                     ! julian day of the year

  REAL,    INTENT(OUT) :: hgt    (nx,ny)
  INTEGER, INTENT(OUT) :: soiltyp(nx,ny)
  INTEGER, INTENT(OUT) :: vegtyp (nx,ny)
  REAL,    INTENT(OUT) :: vegfrct(nx,ny)
  REAL,    INTENT(OUT) :: xice   (nx,ny)
  REAL,    INTENT(OUT) :: xland  (nx,ny)
  REAL,    INTENT(OUT) :: tmn    (nx,ny)
  REAL,    INTENT(OUT) :: shdmin (nx,ny)
  REAL,    INTENT(OUT) :: shdmax (nx,ny)
  REAL,    INTENT(OUT) :: albbck (nx,ny)
  REAL,    INTENT(OUT) :: snoalb (nx,ny)
  INTEGER, INTENT(OUT) :: istatus

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

  LOGICAL :: ISAME

  INTEGER :: nscid

  REAL, ALLOCATABLE :: landusef(:,:,:)
  REAL, ALLOCATABLE :: soiltyp_top(:,:,:),soiltyp_bot(:,:,:)

  INTEGER :: i,j,k

  INTEGER :: nxlg, nylg

  REAL, ALLOCATABLE :: temdm(:,:,:)
  REAL, ALLOCATABLE :: var3d1(:,:,:), var3d2(:,:,:), var3d3(:,:,:)
  REAL, ALLOCATABLE :: var2d(:,:)

  INCLUDE   'mp.inc'

!-----------------------------------------------------------------

  INTERFACE 

    SUBROUTINE get_static_monthly(staticopt,ncid, vartype, jday,        &
                                  var2d, varin3d, istatus)
      INTEGER,          INTENT(IN)  :: staticopt
      INTEGER,          INTENT(IN)  :: ncid
      CHARACTER(LEN=1), INTENT(IN)  :: vartype
      INTEGER,          INTENT(IN)  :: jday
      REAL,             INTENT(OUT) :: var2d(:,:)
      REAL,             INTENT(IN)  :: varin3d(:,:,:)
      INTEGER,          INTENT(OUT) :: istatus
    END SUBROUTINE get_static_monthly

  END INTERFACE

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

  nxlg = (nx - 1)*nproc_x + 1
  nylg = (ny - 1)*nproc_y + 1

!  write(0,*) 'nx = ',nx, 'ny = ',ny, 'nxlg = ',nxlg, 'nylg = ',nylg

  ALLOCATE(landusef(nx,ny,LanduseCategories), STAT = istatus)
  ALLOCATE(soiltyp_top(nx,ny,SoilCategories), STAT = istatus)
  ALLOCATE(soiltyp_bot(nx,ny,SoilCategories), STAT = istatus)

  ALLOCATE(var3d1(nxlg,nylg,LanduseCategories), STAT = istatus)
  ALLOCATE(var3d2(nxlg,nylg,SoilCategories),    STAT = istatus)
  ALLOCATE(var3d3(nxlg,nylg,SoilCategories),    STAT = istatus)
  ALLOCATE(var2d (nxlg,nylg),                   STAT = istatus)

  ALLOCATE(temdm(nxlg-1,nylg-1,MAX(LanduseCategories,SoilCategories)), STAT = istatus)
!
! Open the static NetCDF file which is created by wrfstatic.
!

  IF(myproc == 0) CALL open_static_file(filnam,nscid)

! we need to check whether the static file is
! on the same grid as WRF grid

  IF(myproc == 0) THEN 
    CALL check_static_grid(1,nscid,nx,ny,dx,dy,mapproj,                 &
                         trulat1,trulat2,trulon,isame)
    IF(.NOT. ISAME) CALL mpexit(1)
  END IF

  IF (myproc == 0) THEN
    CALL get_ncd_3d(nscid,1,'LANDUSEF',nxlg-1,nylg-1,LanduseCategories,temdm,istatus)
    DO k = 1, LanduseCategories
      DO j = 1,nylg-1
        DO i = 1,nxlg-1
          var3d1(i,j,k) = temdm(i,j,k)
        END DO
      END DO
    END DO

    CALL get_ncd_3d(nscid,1,'SOILCTOP',nxlg-1,nylg-1,SoilCategories,temdm,istatus)
    DO k = 1, SoilCategories
      DO j = 1,nylg-1
        DO i = 1,nxlg-1
          var3d2(i,j,k) = temdm(i,j,k)
        END DO
      END DO
    END DO

    CALL get_ncd_3d(nscid,1,'SOILCBOT',nxlg-1,nylg-1,SoilCategories,temdm,istatus)
    DO k = 1, SoilCategories
      DO j = 1,nylg-1
        DO i = 1,nxlg-1
          var3d3(i,j,k) = temdm(i,j,k)
        END DO
      END DO
    END DO

    CALL edgfill(var3d1,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,LanduseCategories,1,LanduseCategories)
    CALL edgfill(var3d2,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,SoilCategories,1,SoilCategories)
    CALL edgfill(var3d3,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,SoilCategories,1,SoilCategories)
  END IF
  CALL wrf_split3d(var3d1,nx,ny,LanduseCategories,1,landusef)
  CALL wrf_split3d(var3d2,nx,ny,SoilCategories,1,soiltyp_top)
  CALL wrf_split3d(var3d3,nx,ny,SoilCategories,1,soiltyp_bot)

  IF (myproc == 0) THEN
    CALL get_ncd_3d(nscid,1,'GREEN12M',nxlg-1,nylg-1,12,temdm,istatus)
    DO k = 1, 12
      DO j = 1,nylg-1
        DO i = 1,nxlg-1
          var3d1(i,j,k) = temdm(i,j,k)
        END DO
      END DO
    END DO
    CALL edgfill(var3d1,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,12,1,12)

    CALL get_static_monthly (1,nscid, 'g', jday, var2d, var3d1,istatus)
  END IF
  IF (istatus /= 0) CALL mpexit(1)
  CALL wrf_split2d(var2d,nx,ny,1,vegfrct)

  IF (myproc == 0) THEN
    CALL get_ncd_3d(nscid,1,'ALBDO12M',nxlg-1,nylg-1,12,temdm,istatus)
    DO k = 1, 12
      DO j = 1,nylg-1
        DO i = 1,nxlg-1
          var3d2(i,j,k) = temdm(i,j,k)
        END DO
      END DO
    END DO
    CALL edgfill(var3d2,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,12,1,12)

    CALL get_static_monthly (1,nscid, 'a', jday, var2d, var3d2,istatus)
  END IF
  IF (istatus /= 0) CALL mpexit(1)
  CALL wrf_split2d(var2d,nx,ny,1,albbck)
  
  IF (myproc == 0) THEN
    CALL get_ncd_2d(nscid,1,'SHDMIN',nxlg-1,nylg-1,temdm,istatus)
    DO j = 1,nylg-1
      DO i = 1,nxlg-1
        var2d(i,j) = temdm(i,j,1)
      END DO
    END DO
    CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1)
  END IF
  CALL wrf_split2d(var2d,nx,ny,1,shdmin)

  IF (myproc == 0) THEN
    CALL get_ncd_2d(nscid,1,'SHDMAX',nxlg-1,nylg-1,temdm,istatus)
    DO j = 1,nylg-1
      DO i = 1,nxlg-1
        var2d(i,j) = temdm(i,j,1)
      END DO
    END DO
    CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1)
  END IF
  CALL wrf_split2d(var2d,nx,ny,1,shdmax)

  IF (myproc == 0) THEN
    CALL get_ncd_2d(nscid,1,'SNOALB',nxlg-1,nylg-1,temdm,istatus)
    DO j = 1,nylg-1
      DO i = 1,nxlg-1
        var2d(i,j) = temdm(i,j,1)
      END DO
    END DO
    CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1)
  END IF
  CALL wrf_split2d(var2d,nx,ny,1,snoalb)

  IF (myproc == 0) THEN
    CALL get_ncd_2d(nscid,1,'HGT',nxlg-1,nylg-1,temdm,istatus)
    DO j = 1,nylg-1
      DO i = 1,nxlg-1
        var2d(i,j) = temdm(i,j,1)
      END DO
    END DO
    CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1)
  END IF
  CALL wrf_split2d(var2d,nx,ny,1,hgt)

  IF (myproc == 0) THEN
    CALL get_ncd_2d(nscid,1,'TMN',nxlg-1,nylg-1,temdm,istatus)
    DO j = 1,nylg-1
      DO i = 1,nxlg-1
        var2d(i,j) = temdm(i,j,1)
      END DO
    END DO
    CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1)
  END IF
  CALL wrf_split2d(var2d,nx,ny,1,tmn)

  IF(myproc == 0) CALL close_static_file(nscid)

  DEALLOCATE(temdm)
  DEALLOCATE(var3d1,var3d2,var3d3)
  DEALLOCATE(var2d)

  CALL land_soil_cat(nx,ny,LanduseCategories,SoilCategories,            &
                     landusef,soiltyp_top,soiltyp_bot,                  &
                     vegtyp,soiltyp,xland,xice,istatus)

  DEALLOCATE(landusef, soiltyp_top, soiltyp_bot)

  RETURN
END SUBROUTINE get_sfcdt_wrf
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE land_soil_cat              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE land_soil_cat(nx,ny,land_cat,soil_cat,                       & 2,1
                     landusef,soiltyp_top,soiltyp_bot,                  &
                     vegtyp,soiltyp,xland,xice,istatus)

!-----------------------------------------------------------------------
!
! PURPOSE
!   Extract dominant landuse and soil texture index
!
!   See subroutine process_percent_cat_new in share/module_soil_pre.F
!
!-----------------------------------------------------------------------

  use wrf_metadata

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: nx, ny
  INTEGER, INTENT(IN) :: land_cat, soil_cat
  REAL,    INTENT(IN) :: landusef(nx,ny,land_cat)
  REAL,    INTENT(IN) :: soiltyp_top(nx,ny,soil_cat)
  REAL,    INTENT(IN) :: soiltyp_bot(nx,ny,soil_cat)
  INTEGER, INTENT(OUT) :: soiltyp(nx,ny)
  INTEGER, INTENT(OUT) :: vegtyp (nx,ny)
  REAL,    INTENT(OUT) :: xice   (nx,ny)
  REAL,    INTENT(OUT) :: xland  (nx,ny)
  INTEGER, INTENT(OUT) :: istatus

  INTEGER  :: i,j,k
  REAL     :: dominant_value
  INTEGER  :: dominant_index
  
!--------------------------------------------------------------------
!
! Vegetation index and soil texture index SoilCategories
!
!--------------------------------------------------------------------

  DO j = 1, ny
    DO i = 1,nx
      dominant_value = landusef(i,j,1)
      dominant_index = 1
      DO k = 2,LanduseCategories
        IF(k == ISWATER .AND. landusef(i,j,k) >= 0.5) THEN
          dominant_value = landusef(i,j,ISWATER)
          dominant_index = k
        ELSE IF(k /= ISWATER .AND. landusef(i,j,k) > dominant_value) THEN
          dominant_value = landusef(i,j,k)
          dominant_index = k
        END IF
      END DO
      IF(dominant_index == ISWATER) THEN
        xland(i,j) = 2.
      ELSE
        xland(i,j) = 1.
      END IF
      vegtyp(i,j) = dominant_index
    END DO
  END DO

  !  Compute the dominant SOIL TEXTURE INDEX, TOP.

  DO j = 1, ny
    DO i = 1,nx
      dominant_value = soiltyp_top(i,j,1)
      dominant_index = 1
      IF(xland(i,j) < 1.5) THEN
        DO k = 2,SoilCategories 
          IF(k /= ISWATER_SOIL .AND. soiltyp_top(i,j,k) > dominant_value) THEN
            dominant_value = soiltyp_top(i,j,k)
            dominant_index = k
          END IF
        END DO
        IF(dominant_value < 0.01) THEN
          dominant_index = 8
        END IF
      ELSE
        dominant_index = ISWATER_SOIL
      END IF
      soiltyp(i,j) = dominant_index
    END DO
  END DO

  xice = 0.
  WHERE(vegtyp == ISICE) xice = 1.

  istatus = 0

  RETURN
END SUBROUTINE land_soil_cat
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE couple                     ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE couple(nx,ny,nz,vname,mu,mub,var3d,msf,out3d,tem) 10

!-----------------------------------------------------------------
!
! PURPOSE
!   Couple the input variable with the air mass and the map scale
!   factor.
!
! NOTE: Refer to the same subroutine in WRF dyn_em/module_big_step_utilities_em.f.
!
!----------------------------------------------------------------
  IMPLICIT NONE
  INTEGER,      INTENT(IN)  :: nx,ny,nz
  CHARACTER(1), INTENT(IN)  :: vname
  REAL,         INTENT(IN)  :: mu(nx,ny), mub(nx,ny)
  REAL,         INTENT(IN)  :: var3d(nx,ny,nz)
  REAL,         INTENT(IN)  :: msf(nx,ny)
  REAL,         INTENT(OUT) :: out3d(nx,ny,nz)
  REAL,         INTENT(OUT) :: tem(nx,ny)

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
!
  INTEGER :: i,j,k

  INCLUDE   'mp.inc'

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  tem = 0.0

  IF(vname == 'U') THEN
    CALL wrf_mpsendrecv1de(mu, nx,ny,tem)  ! to make sure the fake zone, mu(nx,:)
    CALL wrf_mpsendrecv1de(mub,nx,ny,tem)  ! & mub(nx,:) contains valid data
    DO j = 1,ny
      DO i = 2,nx
        tem(i,j) = 0.5*(mu(i-1,j)+mub(i-1,j)+mu(i,j)+mub(i,j))
      END DO
    END DO
    tem(1,:) = mu(1,:) + mub(1,:)      ! The first row may be invalid
    !tem(nx,:) = mu(nx-1,:) + mub(nx-1,:)

    DO k = 1, nz
      DO j = 1, ny
        DO i = 1, nx
          out3d(i,j,k) = var3d(i,j,k)*tem(i,j)/msf(i,j)
        END DO
      END DO
    END DO

  ELSE IF(vname == 'V') THEN

    CALL wrf_mpsendrecv1dn(mu, nx,ny,tem)  ! to make sure the fake zone, mu(:,ny)
    CALL wrf_mpsendrecv1dn(mub,nx,ny,tem)  ! & mub(:,ny) contains valid data
    DO j = 2,ny
      DO i = 1,nx
        tem(i,j) = 0.5*(mu(i,j-1)+mub(i,j-1)+mu(i,j)+mub(i,j))
      END DO
    END DO
    tem(:,1)  = mu(:,1) + mub(:,1)     ! The firs column may be invalid
    !tem(:,ny) = mu(:,ny-1) + mub(:,ny-1)

    DO k = 1, nz
      DO j = 1, ny
        DO i = 1, nx
          out3d(i,j,k) = var3d(i,j,k)*tem(i,j)/msf(i,j)
        END DO
      END DO
    END DO

  ELSE IF(vname == 'W') THEN          ! No variable uses this "vname" so far

    DO k = 1, nz
      DO j = 1, ny
        DO i = 1, nx
          out3d(i,j,k) = var3d(i,j,k)*(mu(i,j)+mub(i,j))/msf(i,j)
        END DO
      END DO
    END DO

  ELSE      ! vname == 'H', or 'T', vertical does not matter here

    DO k = 1, nz
      DO j = 1, ny
        DO i = 1, nx
          out3d(i,j,k) = var3d(i,j,k)*(mu(i,j)+mub(i,j))
        END DO
      END DO
    END DO
  END IF
  
  RETURN
END SUBROUTINE couple
!
!##################################################################
!##################################################################
!######                                                      ######
!######                  FUNCTION stuff_bdy                  ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE stuff_bdy(nx,ny,nz,bdy_width,stag,var3d,bs,bn,bw,be)

!-----------------------------------------------------------------
!
! Assign boundary arrays
!
! NOTE: Refer to the same subroutine in WRF share/module_bc.f.
!
!-----------------------------------------------------------------

  IMPLICIT NONE
 
  ! nx,ny and nz must be the non-staggered values

  INTEGER,          INTENT(IN) :: nx,ny,nz,bdy_width
  CHARACTER(LEN=1), INTENT(IN) :: stag
  REAL,             INTENT(IN) :: var3d(nx,ny,nz)       ! coupled variable

  REAL,    INTENT(OUT) :: bs(nx,nz,bdy_width)   ! south boundary
  REAL,    INTENT(OUT) :: bn(nx,nz,bdy_width)   ! north boundary
  REAL,    INTENT(OUT) :: bw(ny,nz,bdy_width)   ! west boundary
  REAL,    INTENT(OUT) :: be(ny,nz,bdy_width)   ! east boundary

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
!
  INTEGER :: i,j,k
  INTEGER :: ii,jj

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ! X start boundary  WEST
  DO k = 1,nz
    DO j = 1,ny
      DO i = 1, bdy_width
        bw(j,k,i) = var3d(i,j,k)
      END DO
    END DO
  END DO

  ! X end boundary    EAST
  IF(stag == 'U') THEN
    DO k = 1,nz
      DO j = 1,ny
        DO i = nx, nx-bdy_width+1,-1
          ii = nx - i + 1
          be(j,k,ii) = var3d(i,j,k)
        END DO
      END DO
    END DO
  ELSE
    DO k = 1,nz
      DO j = 1,ny
        DO i = nx-1, nx-bdy_width,-1
          ii = nx - i
          be(j,k,ii) = var3d(i,j,k)
        END DO
      END DO
    END DO
  END IF

  ! Y start boundary  SOUTH
  DO k = 1, nz
    DO j = 1, bdy_width
      DO i = 1, nx
        bs(i,k,j) = var3d(i,j,k)
      END DO
    END DO
  END DO

  ! Y end boundary    NORTH
  IF(stag == 'V') THEN
    DO k = 1, nz
      DO j = ny, ny-bdy_width+1,-1
        DO i = 1, nx
          jj = ny - j + 1
          bn(i,k,jj) = var3d(i,j,k)
        END DO
      END DO
    END DO
  ELSE
    DO k = 1, nz
      DO j = ny-1, ny-bdy_width,-1
        DO i = 1, nx
          jj = ny - j
          bn(i,k,jj) = var3d(i,j,k)
        END DO
      END DO
    END DO
  END IF

  RETURN
END SUBROUTINE stuff_bdy
!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROTINE stuff_bdytend              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE stuff_bdytend(nx,ny,nz,bdy_width,stag,var3dold,var3dnew,     &
                         time_diff,bs,bn,bw,be)

!-----------------------------------------------------------------
!
! Compute and assign boundary tendency.
!
! NOTE: Refer to the same subroutine in WRF share/module_bc.f.
!
!-----------------------------------------------------------------

  IMPLICIT NONE
 
  ! nx,ny and nz must be the non-staggered values

  INTEGER, INTENT(IN)  :: nx,ny,nz,bdy_width
  CHARACTER(LEN=1), INTENT(IN) :: stag
  REAL,    INTENT(IN)  :: var3dold(nx,ny,nz)
  REAL,    INTENT(IN)  :: var3dnew(nx,ny,nz)
  REAL,    INTENT(IN)  :: time_diff
  REAL,    INTENT(OUT) :: bs(nx,nz,bdy_width)  ! south boundary tendency
  REAL,    INTENT(OUT) :: bn(nx,nz,bdy_width)  ! north
  REAL,    INTENT(OUT) :: bw(ny,nz,bdy_width)  ! west
  REAL,    INTENT(OUT) :: be(ny,nz,bdy_width)  ! east

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
!
  INTEGER :: i,j,k
  INTEGER :: ii,jj

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ! X start boundary  WEST
  DO k = 1,nz
    DO j = 1,ny
      DO i = 1, bdy_width
        bw(j,k,i) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
      END DO
    END DO
  END DO

  ! X end boundary    EAST
  IF(stag == 'U') THEN
    DO k = 1,nz
      DO j = 1,ny
        DO i = nx, nx-bdy_width+1,-1
          ii = nx - i + 1
          be(j,k,ii) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
        END DO
      END DO
    END DO
  ELSE
    DO k = 1,nz
      DO j = 1,ny
        DO i = nx-1, nx-bdy_width,-1
          ii = nx - i
          be(j,k,ii) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
        END DO
      END DO
    END DO
  END IF

  ! Y start boundary  SOUTH
  DO k = 1, nz
    DO j = 1, bdy_width
      DO i = 1, nx
        bs(i,k,j) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
      END DO
    END DO
  END DO

  ! Y end boundary    NORTH
  IF(stag == 'V') THEN
    DO k = 1, nz
      DO j = ny, ny-bdy_width+1,-1
        DO i = 1, nx
          jj = ny - j + 1
          bn(i,k,jj) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
        END DO
      END DO
    END DO
  ELSE
    DO k = 1, nz
      DO j = ny-1, ny-bdy_width,-1
        DO i = 1, nx
          jj = ny - j
          bn(i,k,jj) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff
        END DO
      END DO
    END DO
  END IF

  RETURN
END SUBROUTINE stuff_bdytend
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE stuff_bdy2d                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE stuff_bdy2d(nx,ny,nz,bdy_width,var2d,bs,bn,bw,be)

!------------------------------------------------------------------
!
!  Assign boundary arrays for 2D array.
!
!-----------------------------------------------------------------

  IMPLICIT NONE
 
  ! nx,ny and nz must be the non-staggered values

  INTEGER, INTENT(IN)  :: nx,ny,nz,bdy_width
  REAL,    INTENT(IN)  :: var2d(nx,ny)
  REAL,    INTENT(OUT) :: bs(nx,nz,bdy_width)  ! south boundary array
  REAL,    INTENT(OUT) :: bn(nx,nz,bdy_width)  ! north
  REAL,    INTENT(OUT) :: bw(ny,nz,bdy_width)  ! west
  REAL,    INTENT(OUT) :: be(ny,nz,bdy_width)  ! east

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
!
  INTEGER :: i,j,k
  INTEGER :: ii,jj

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ! X start boundary  WEST
  DO k = 1,nz
    DO j = 1,ny
      DO i = 1, bdy_width
        bw(j,k,i) = var2d(i,j)
      END DO
    END DO
  END DO

  ! X end boundary    EAST
  DO k = 1,nz
    DO j = 1,ny
      DO i = nx-1, nx-bdy_width,-1
        ii = nx - i
        be(j,k,ii) = var2d(i,j)
      END DO
    END DO
  END DO

  ! Y start boundary  SOUTH
  DO k = 1, nz
    DO j = 1, bdy_width
      DO i = 1, nx
        bs(i,k,j) = var2d(i,j)
      END DO
    END DO
  END DO

  ! Y end boundary    NORTH
  DO k = 1, nz
    DO j = ny-1, ny-bdy_width,-1
      DO i = 1, nx
        jj = ny - j
        bn(i,k,jj) = var2d(i,j)
      END DO
    END DO
  END DO

  RETURN
END SUBROUTINE stuff_bdy2d
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE stuff_bdytend2d            ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE stuff_bdytend2d(nx,ny,nz,bdy_width,var2dold,var2dnew,   &
                         time_diff,bs,bn,bw,be)

  IMPLICIT NONE
 
  ! nx,ny and nz must be the non-staggered values

  INTEGER, INTENT(IN)  :: nx,ny,nz,bdy_width
  REAL,    INTENT(IN)  :: var2dold(nx,ny)
  REAL,    INTENT(IN)  :: var2dnew(nx,ny)
  REAL,    INTENT(IN)  :: time_diff
  REAL,    INTENT(OUT) :: bs(nx,nz,bdy_width)
  REAL,    INTENT(OUT) :: bn(nx,nz,bdy_width)
  REAL,    INTENT(OUT) :: bw(ny,nz,bdy_width)
  REAL,    INTENT(OUT) :: be(ny,nz,bdy_width)

!------------------------------------------------------------------
!
!  Misc. local variables
!
!------------------------------------------------------------------
!
  INTEGER :: i,j,k
  INTEGER :: ii,jj

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ! X start boundary  WEST
  DO k = 1,nz
    DO j = 1,ny
      DO i = 1, bdy_width
        bw(j,k,i) = (var2dnew(i,j)-var2dold(i,j))/time_diff
      END DO
    END DO
  END DO

  ! X end boundary    EAST
  DO k = 1,nz
    DO j = 1,ny
      DO i = nx-1, nx-bdy_width,-1
        ii = nx - i
        be(j,k,ii) = (var2dnew(i,j)-var2dold(i,j))/time_diff
      END DO
    END DO
  END DO

  ! Y start boundary  SOUTH
  DO k = 1, nz
    DO j = 1, bdy_width
      DO i = 1, nx
        bs(i,k,j) = (var2dnew(i,j)-var2dold(i,j))/time_diff
      END DO
    END DO
  END DO

  ! Y end boundary    NORTH
  DO k = 1, nz
    DO j = ny-1, ny-bdy_width,-1
      DO i = 1, nx
        jj = ny - j
        bn(i,k,jj) = (var2dnew(i,j)-var2dold(i,j))/time_diff
      END DO
    END DO
  END DO

  RETURN
END SUBROUTINE stuff_bdytend2d
!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROUTINE rotate_UV                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE rotate_UV(nx_wrf,ny_wrf,nz_wrf,mapproj,sclfct,latnot,trulon, & 1,11
                     swx_arps,swy_arps,mapproj_wrf,                     &
                     sclfct_wrf,lattru_wrf,lontru_wrf,swx_wrf,swy_wrf,  &
                     lonu_wrf,lonv_wrf,u_wrf,v_wrf,uatv_wrf,vatu_wrf,   &
                     tem1,tem2,tem3,tem4,istatus)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
!   Get uatv_wrf & vatu_wrf for doing horizontal interpolation.
!   Do not support mpi.
!
!-----------------------------------------------------------------------
  IMPLICIT NONE

  INTEGER, INTENT(IN)  :: nx_wrf, ny_wrf, nz_wrf
  INTEGER, INTENT(IN)  :: mapproj, mapproj_wrf
  REAL,    INTENT(IN)  :: sclfct,  sclfct_wrf
  REAL,    INTENT(IN)  :: latnot(2),lattru_wrf(2)
  REAL,    INTENT(IN)  :: trulon,  lontru_wrf
  REAL,    INTENT(IN)  :: swx_arps,  swx_wrf
  REAL,    INTENT(IN)  :: swy_arps,  swy_wrf
  REAL,    INTENT(IN)  :: lonu_wrf(nx_wrf,ny_wrf)
  REAL,    INTENT(IN)  :: lonv_wrf(nx_wrf,ny_wrf)
  REAL,    INTENT(INOUT) :: u_wrf(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(INOUT) :: v_wrf(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: uatv_wrf(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: vatu_wrf(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: tem1(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: tem2(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: tem3(nx_wrf,ny_wrf,nz_wrf)
  REAL,    INTENT(OUT)   :: tem4(nx_wrf,ny_wrf,nz_wrf)
  INTEGER, INTENT(OUT)   :: istatus

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

  INTEGER  :: i, j, k

  INTEGER  :: iproj
  REAL     :: scl, trlat(2), trlon,x0,y0

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Begin of executable code ... ...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
!  Save previous map projection values
!
!-----------------------------------------------------------------------
!
  CALL getmapr(iproj,scl,trlat,trlon,x0,y0)
!
!-----------------------------------------------------------------------
!
!  Get uatv and vatu
!
!-----------------------------------------------------------------------
!
  DO k=1,nz_wrf

    ! get u at v grid point locations
    DO j=2,ny_wrf
      DO i=1,nx_wrf-1
        uatv_wrf(i,j,k) = 0.25*(u_wrf(i,j-1,k)+u_wrf(i+1,j-1,k)  &
                                + u_wrf(i,j,k)+u_wrf(i+1,j,k))
      END DO
    END DO
    DO i=1,nx_wrf-1
      uatv_wrf(i,1,k) = 0.5*(u_wrf(i,1,k)+u_wrf(i+1,1,k))
    END DO
    DO j=2,ny_wrf
      uatv_wrf(nx_wrf,j,k) = 0.5*(u_wrf(nx_wrf,j-1,k)+u_wrf(nx_wrf,j,k))
    END DO
    uatv_wrf(nx_wrf,1,k) = u_wrf(nx_wrf,1,k)

    ! get v at u grid point locations
    DO j=1,ny_wrf-1
      DO i=2,nx_wrf
        vatu_wrf(i,j,k) = 0.25*(v_wrf(i-1,j,k)+v_wrf(i,j,k)  &
                                +v_wrf(i-1,j+1,k)+v_wrf(i,j+1,k))
      END DO
    END DO
    DO j=1,ny_wrf-1
      vatu_wrf(1,j,k) = 0.5*(v_wrf(1,j,k)+v_wrf(1,j+1,k))
    END DO
    DO i=2,nx_wrf
      vatu_wrf(i,ny_wrf,k) = 0.5*(v_wrf(i-1,ny_wrf,k)+v_wrf(i,ny_wrf,k))
    END DO
    vatu_wrf(1,ny_wrf,k) = v_wrf(1,ny_wrf,k)

  END DO

!
!-----------------------------------------------------------------------
!
!  Establish ARPS map projection
!
!-----------------------------------------------------------------------
!
  CALL setmapr(mapproj,sclfct,latnot,trulon)
  CALL setorig(1,swx_arps,swy_arps)
!
!-----------------------------------------------------------------------
!
!  Rotate from ARPS grid to earth-relative
!
!-----------------------------------------------------------------------
!
  DO k = 1,nz_wrf
    CALL uvmptoe(nx_wrf,ny_wrf,u_wrf(:,:,k),vatu_wrf(:,:,k),        &
                 lonu_wrf,tem1(:,:,k),tem2(:,:,k))

    CALL uvmptoe(nx_wrf,ny_wrf,uatv_wrf(:,:,k),v_wrf(:,:,k),        &
                 lonv_wrf,tem3(:,:,k),tem4(:,:,k))
  END DO
  ! tem1 = u,    tem2 = vatu
  ! tem3 = uatv, tem4 = v
!
!-----------------------------------------------------------------------
!
!  Establish WRF map projection
!
!-----------------------------------------------------------------------
!
  CALL setmapr(mapproj_wrf,sclfct_wrf,lattru_wrf,lontru_wrf)
  CALL setorig( 1, swx_wrf, swy_wrf)

!
!-----------------------------------------------------------------------
!
!  Rotate from earth to WRF grid-relative
!
!-----------------------------------------------------------------------
!
  DO k = 1,nz_wrf
    CALL uvetomp(nx_wrf,ny_wrf,tem1(:,:,k),tem2(:,:,k),        &
                 lonu_wrf,u_wrf(:,:,k),vatu_wrf(:,:,k))

    CALL uvetomp(nx_wrf,ny_wrf,tem3(:,:,k),tem4(:,:,k),        &
                 lonv_wrf,uatv_wrf(:,:,k),v_wrf(:,:,k))
  END DO
!
!-----------------------------------------------------------------------
!
!  Reset map projection to previous values
!
!-----------------------------------------------------------------------
!
  CALL setmapr(iproj,scl,trlat,trlon)
  CALL setorig(1,x0,y0)

  istatus = 0

  RETURN
END SUBROUTINE rotate_UV