<p><b>duda</b> 2011-01-25 17:17:05 -0700 (Tue, 25 Jan 2011)</p><p>BRANCH COMMIT<br>
<br>
Add code to extend the set of fields that are interpolated for<br>
nonhydrostatic real-data initialization to include all fields needed for<br>
a dynamics-only run, plus a few land-surface fields. <br>
<br>
Several parts of the initialization code are still hard-wired to use GFS<br>
data processed by the ungrib.exe program from the WPS.<br>
<br>
<br>
M    src/core_init_nhyd_atmos/module_test_cases.F<br>
M    src/core_init_nhyd_atmos/Registry<br>
</p><hr noshade><pre><font color="gray">Modified: branches/atmos_physics/src/core_init_nhyd_atmos/Registry
===================================================================
--- branches/atmos_physics/src/core_init_nhyd_atmos/Registry        2011-01-25 00:54:44 UTC (rev 704)
+++ branches/atmos_physics/src/core_init_nhyd_atmos/Registry        2011-01-26 00:17:05 UTC (rev 705)
@@ -122,8 +122,12 @@
 var persistent real    cf2 ( ) 0 io cf2 mesh - -
 var persistent real    cf3 ( ) 0 io cf3 mesh - -
 
-# land use
+# static terrestrial fields
+var persistent real    ter      ( nCells ) 0 io ter      mesh - -
+var persistent integer landmask ( nCells ) 0 io landmask mesh - -
 var persistent integer lu_index ( nCells ) 0 io lu_index mesh - -
+var persistent integer soilcat_top ( nCells ) 0 io soilcat_top mesh - -
+var persistent integer soilcat_bot ( nCells ) 0 io soilcat_bot mesh - -
 
 # description of the vertical grid structure
 
@@ -156,6 +160,22 @@
 var persistent real    psfc_fg ( nCells ) 0 o psfc fg - -
 var persistent real    pmsl_fg ( nCells ) 0 o pmsl fg - -
 
+# Horizontally interpolated from first-guess data
+#    and should be read in by model
+var persistent real    sm000010 ( nCells ) 0 o sm000010 fg - -
+var persistent real    sm010040 ( nCells ) 0 o sm010040 fg - -
+var persistent real    sm040100 ( nCells ) 0 o sm040100 fg - -
+var persistent real    sm100200 ( nCells ) 0 o sm100200 fg - -
+var persistent real    st000010 ( nCells ) 0 o st000010 fg - -
+var persistent real    st010040 ( nCells ) 0 o st010040 fg - -
+var persistent real    st040100 ( nCells ) 0 o st040100 fg - -
+var persistent real    st100200 ( nCells ) 0 o st100200 fg - -
+var persistent real    skintemp ( nCells ) 0 o skintemp fg - -
+var persistent real    snow ( nCells ) 0 o snow fg - -
+var persistent real    seaice ( nCells ) 0 o seaice fg - -
+var persistent real    gfs_z ( nVertLevels nCells ) 0 o gfs_z fg - -
+var persistent real    gfs_p ( nVertLevelsP1 nCells ) 0 o gfs_p fg - -
+
 # Prognostic variables: read from input, saved in restart, and written to output
 var persistent real    u ( nVertLevels nEdges Time ) 2 io u state - -
 var persistent real    w ( nVertLevelsP1 nCells Time ) 2 io w state - -

Modified: branches/atmos_physics/src/core_init_nhyd_atmos/module_test_cases.F
===================================================================
--- branches/atmos_physics/src/core_init_nhyd_atmos/module_test_cases.F        2011-01-25 00:54:44 UTC (rev 704)
+++ branches/atmos_physics/src/core_init_nhyd_atmos/module_test_cases.F        2011-01-26 00:17:05 UTC (rev 705)
@@ -5,6 +5,7 @@
    use constants
    use dmpar
    use advection
+   use sort
 
 
    contains
@@ -1992,7 +1993,7 @@
       type (proj_info) :: proj
 
       real (kind=RKIND), dimension(:), pointer :: rdzw, dzu, rdzu, fzm, fzp
-      real (kind=RKIND), dimension(:), pointer :: vert_level, latPoints, lonPoints
+      real (kind=RKIND), dimension(:), pointer :: vert_level, latPoints, lonPoints, ter
       real (kind=RKIND), dimension(:,:), pointer :: zgrid, zx, zz, hx
       real (kind=RKIND), dimension(:,:), pointer :: pressure, ppb, pb, rho, rb, rr, tb, rtb, p, pp, dss, t, rt
       real (kind=RKIND), dimension(:), pointer :: destField1d
@@ -2001,17 +2002,26 @@
       real (kind=RKIND), dimension(:,:,:), pointer :: scalars
       real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
 
+      real (kind=RKIND) :: target_z
       integer :: iCell, iCell1, iCell2 , iEdge, vtx1, vtx2, ivtx, i, k, nz, nz1, itr, itrp, cell1, cell2, nCellsSolve
       integer :: nInterpPoints, ndims
 
       !This is temporary variable here. It just need when calculate tangential velocity v.
       integer :: eoe, j
-      integer, dimension(:), pointer :: nEdgesOnEdge 
-      integer, dimension(:,:), pointer :: edgesOnEdge, CellsOnEdge, cellsOnCell
-      real (kind=RKIND), dimension(:), pointer :: dvEdge, AreaCell 
+      integer, dimension(:), pointer :: nEdgesOnEdge, nEdgesOnCell
+      integer, dimension(:,:), pointer :: edgesOnEdge, cellsOnEdge, edgesOnCell, cellsOnCell
+      real (kind=RKIND), dimension(:), pointer :: dvEdge, dcEdge, AreaCell 
       real (kind=RKIND), dimension(:,:), pointer :: weightsOnEdge
       real (kind=RKIND), dimension(:,:), pointer :: v
+      real (kind=RKIND), dimension(:,:), pointer :: sorted_arr
 
+      real(kind=RKIND), dimension(:), pointer :: hs, hs1
+      real(kind=RKIND) :: hm, zh, dzmin, dzmina, dzminf, sm
+      integer :: nsmterrain, kz, sfc_k
+      logical :: hybrid, smooth
+
+      logical :: config_do_static
+
       ! For interpolating terrain and land use
       integer :: nx, ny, nzz, iPoint, subx, suby
       integer :: isigned, endian, wordsize, istatus
@@ -2033,7 +2043,7 @@
       real (kind=RKIND) :: r_earth, etavs, ztemp, zd, zt, dz, gam, delt, str
 
       real (kind=RKIND), dimension(grid % nVertLevels, grid % nCells) :: rel_hum, temperature, qv
-      real (kind=RKIND) :: ptmp, es, qvs, xnutr, znut, ptemp
+      real (kind=RKIND) :: ptmp, es, rs, rgas_moist, qvs, xnutr, znut, ptemp, rcv
       integer :: iter
 
       real (kind=RKIND), dimension(grid % nVertLevels + 1) :: hyai, hybi, znu, znw, znwc, znwv, hyam, hybm
@@ -2043,8 +2053,6 @@
       real (kind=RKIND), dimension(grid % nVertLevels) :: zu, dzw, rdzwp, rdzwm
       real (kind=RKIND), dimension(grid % nVertLevels) :: eta, etav, teta, ppi, tt
 
-      real (kind=RKIND), dimension(grid % nCells) :: hs
-
       real (kind=RKIND) :: d1, d2, d3, cf1, cf2, cf3, cof1, cof2, psurf
 
       !  storage for (lat,z) arrays for zonal velocity calculation
@@ -2053,14 +2061,18 @@
       real (kind=RKIND), dimension(grid % nVertLevels + 1) :: zz_1d, zgrid_1d, hx_1d
       real (kind=RKIND), dimension(grid % nVertLevels) :: flux_zonal
       real (kind=RKIND), dimension(nlat, grid % nVertLevels) :: u_2d, etavs_2d
+      real (kind=RKIND), dimension(grid % nVertLevels + 1) :: fsum
       real (kind=RKIND), dimension(nlat) :: lat_2d
       real (kind=RKIND) :: dlat
       real (kind=RKIND) :: z_edge, z_edge3, d2fdx2_cell1, d2fdx2_cell2
 
       weightsOnEdge     =&gt; grid % weightsOnEdge % array
       nEdgesOnEdge      =&gt; grid % nEdgesOnEdge % array
+      nEdgesOnCell      =&gt; grid % nEdgesOnCell % array
       edgesOnEdge       =&gt; grid % edgesOnEdge % array
+      edgesOnCell       =&gt; grid % edgesOnCell % array
       dvEdge            =&gt; grid % dvEdge % array
+      dcEdge            =&gt; grid % dcEdge % array
       AreaCell          =&gt; grid % AreaCell % array
       CellsOnEdge       =&gt; grid % CellsOnEdge % array
       cellsOnCell       =&gt; grid % cellsOnCell % array
@@ -2080,6 +2092,7 @@
       zx =&gt; grid % zx % array
       zz =&gt; grid % zz % array
       hx =&gt; grid % hx % array
+      ter =&gt; grid % ter % array
       dss =&gt; grid % dss % array
 
       pb =&gt; diag % exner_base % array
@@ -2102,10 +2115,24 @@
       nz = nz1 + 1
       nCellsSolve = grid % nCellsSolve
 
+      xnutr = 0.
+      zd = 12000.
+      znut = eta_t
 
+      etavs = (1.-0.252)*pii/2.
+      rcv = rgas/(cp-rgas)
+      r_earth = a
+      p0 = 1.e+05
+
+
+      config_do_static = .true.
+
       !
       ! Scale all distances and areas from a unit sphere to one with radius a
       !
+
+      if (config_do_static) then
+
       grid % xCell % array = grid % xCell % array * a
       grid % yCell % array = grid % yCell % array * a
       grid % zCell % array = grid % zCell % array * a
@@ -2126,16 +2153,7 @@
       call initialize_advection_rk(grid) 
       call initialize_deformation_weights(grid) 
 
-      xnutr = 0.
-      zd = 12000.
-      znut = eta_t
 
-      etavs = (1.-0.252)*pii/2.
-      r_earth = a
-      p0 = 1.e+05
-
-
-#if 0
       !
       ! Interpolate HGT
       !
@@ -2151,7 +2169,7 @@
       allocate(rarray(nx,ny,nzz))
       allocate(nhs(grid % nCells))
       nhs(:) = 0
-      grid % hx % array(:,:) = 0.0
+      grid % ter % array(:) = 0.0
 
 !      do jTileStart=1,20401,ny-6
       do jTileStart=1,961,ny-6
@@ -2184,7 +2202,7 @@
                                      grid % nCells, grid % maxEdges, grid % nEdgesOnCell % array, grid % cellsOnCell % array, &amp;
                                      grid % latCell % array, grid % lonCell % array)
 
-               grid % hx % array(1,iPoint) = grid % hx % array(1,iPoint) + rarray(i,j,1)
+               grid % ter % array(iPoint) = grid % ter % array(iPoint) + rarray(i,j,1)
                nhs(iPoint) = nhs(iPoint) + 1
 
             end do
@@ -2194,42 +2212,13 @@
        end do
 
       do iCell=1, grid % nCells
-         grid % hx % array(1,iCell) = grid % hx % array(1,iCell) / real(nhs(iCell))
+         grid % ter % array(iCell) = grid % ter % array(iCell) / real(nhs(iCell))
       end do
 
       deallocate(rarray)
       deallocate(nhs)
 

-      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-      ! SMOOTH TOPOGRAPHY TO CREATE 3D HX FIELD
-      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-      do k=2,grid%nVertLevels
-         grid % hx % array(k,:) = grid % hx % array(k-1,:)
-         do i=1,4
-            do iCell=1,grid%nCells
-               hs(iCell) = grid % hx % array(k,iCell)
-               do j = 1,grid % nEdgesOnCell % array(iCell)
-                  hs(iCell) = hs(iCell) + grid % hx % array(k,cellsOnCell(j,iCell))
-               end do
-               hs(iCell) = hs(iCell) / real(grid%nEdgesOnCell%array(iCell)+1)
-            end do
-            do iCell=1,grid%nCells
-               grid % hx % array(k,iCell) = hs(iCell)
-               do j = 1,grid % nEdgesOnCell % array(iCell)
-                  grid % hx % array(k,iCell) = grid % hx % array(k,iCell) + hs(cellsOnCell(j,iCell))
-               end do
-               grid % hx % array(k,iCell) = grid % hx % array(k,iCell) / real(grid%nEdgesOnCell%array(iCell)+1)
-            end do
-         end do
-      end do
 
-
-      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-      ! CREATE VERTICAL GRID
-      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-
       !
       ! Interpolate LU_INDEX
       !
@@ -2291,8 +2280,438 @@
       deallocate(rarray)
       deallocate(ncat)
 
+      !
+      ! Derive LANDMASK
+      !
+      grid % landmask % array(:) = 0
+      do iCell=1, grid % nCells
+         if (grid % lu_index % array(iCell) /= 16) grid % landmask % array(iCell) = 1
+      end do
 
+
       !
+      ! Interpolate SOILCAT_TOP
+      !
+      nx = 1200
+      ny = 1200
+      nzz = 1
+      isigned = 1
+      endian = 0
+      wordsize = 1
+      scalefactor = 1.0
+      allocate(rarray(nx,ny,nzz))
+      allocate(ncat(16,grid % nCells))
+      ncat(:,:) = 0
+      grid % soilcat_top % array(:) = 0.0
+
+      do jTileStart=1,20401,ny
+         jTileEnd = jTileStart + ny - 1
+         do iTileStart=1,42001,nx
+            iTileEnd = iTileStart + nx - 1
+            write(fname,'(a,i5.5,a1,i5.5,a1,i5.5,a1,i5.5)') trim(config_geog_data_path)//'/soiltype_top_30s/',iTileStart,'-',iTileEnd,'.',jTileStart,'-',jTileEnd
+write(0,*) trim(fname)
+
+            call read_geogrid(fname, len_trim(fname), &amp;
+                              rarray, &amp;
+                              nx, ny, nzz, &amp;
+                              isigned, endian, scalefactor, wordsize, istatus)
+write(0,*) istatus
+
+            iPoint = 1
+            do j=1,ny
+            do i=1,nx
+               lat_pt = -89.99583 + (jTileStart + j - 2) * 0.0083333333
+               lon_pt = -179.99583 + (iTileStart + i - 2) * 0.0083333333
+               lat_pt = lat_pt * pii / 180.0
+               lon_pt = lon_pt * pii / 180.0
+
+               iPoint = nearest_cell(lat_pt, lon_pt, &amp;
+                                     iPoint, &amp;
+                                     grid % nCells, grid % maxEdges, grid % nEdgesOnCell % array, grid % cellsOnCell % array, &amp;
+                                     grid % latCell % array, grid % lonCell % array)
+
+               ncat(int(rarray(i,j,1)),iPoint) = ncat(int(rarray(i,j,1)),iPoint) + 1
+
+            end do
+            end do
+
+         end do
+      end do
+
+      do iCell=1, grid % nCells
+         grid % soilcat_top % array(iCell) = 1
+         do i=2,16
+            if (ncat(i,iCell) &gt; ncat(grid % soilcat_top % array(iCell),iCell)) then
+               grid % soilcat_top % array(iCell) = i
+            end if
+         end do
+      end do
+
+      deallocate(rarray)
+      deallocate(ncat)
+
+
+      !
+      ! Interpolate SOILCAT_BOT
+      !
+      nx = 1200
+      ny = 1200
+      nzz = 1
+      isigned = 1
+      endian = 0
+      wordsize = 1
+      scalefactor = 1.0
+      allocate(rarray(nx,ny,nzz))
+      allocate(ncat(16,grid % nCells))
+      ncat(:,:) = 0
+      grid % soilcat_bot % array(:) = 0.0
+
+      do jTileStart=1,20401,ny
+         jTileEnd = jTileStart + ny - 1
+         do iTileStart=1,42001,nx
+            iTileEnd = iTileStart + nx - 1
+            write(fname,'(a,i5.5,a1,i5.5,a1,i5.5,a1,i5.5)') trim(config_geog_data_path)//'/soiltype_bot_30s/',iTileStart,'-',iTileEnd,'.',jTileStart,'-',jTileEnd
+write(0,*) trim(fname)
+
+            call read_geogrid(fname, len_trim(fname), &amp;
+                              rarray, &amp;
+                              nx, ny, nzz, &amp;
+                              isigned, endian, scalefactor, wordsize, istatus)
+write(0,*) istatus
+
+            iPoint = 1
+            do j=1,ny
+            do i=1,nx
+               lat_pt = -89.99583 + (jTileStart + j - 2) * 0.0083333333
+               lon_pt = -179.99583 + (iTileStart + i - 2) * 0.0083333333
+               lat_pt = lat_pt * pii / 180.0
+               lon_pt = lon_pt * pii / 180.0
+
+               iPoint = nearest_cell(lat_pt, lon_pt, &amp;
+                                     iPoint, &amp;
+                                     grid % nCells, grid % maxEdges, grid % nEdgesOnCell % array, grid % cellsOnCell % array, &amp;
+                                     grid % latCell % array, grid % lonCell % array)
+
+               ncat(int(rarray(i,j,1)),iPoint) = ncat(int(rarray(i,j,1)),iPoint) + 1
+
+            end do
+            end do
+
+         end do
+      end do
+
+      do iCell=1, grid % nCells
+         grid % soilcat_bot % array(iCell) = 1
+         do i=2,16
+            if (ncat(i,iCell) &gt; ncat(grid % soilcat_bot % array(iCell),iCell)) then
+               grid % soilcat_bot % array(iCell) = i
+            end if
+         end do
+      end do
+
+      deallocate(rarray)
+      deallocate(ncat)

+      end if    ! config_do_static
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! BEGIN ADOPT GFS TERRAIN HEIGHT
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      call read_met_init(trim(config_met_prefix), .false., trim(config_init_date), istatus)
+
+      if (istatus /= 0) then
+         write(0,*) 'Error reading initial met data'
+         return
+      end if
+
+      call read_next_met_field(field, istatus)
+      do while (istatus == 0)
+         if (index(field % field, 'SOILHGT') /= 0) then
+
+            !
+            ! Set up projection
+            !
+            call map_init(proj)
+          
+            if (field % iproj == PROJ_LATLON) then
+               call map_set(PROJ_LATLON, proj, &amp;
+                            latinc = field % deltalat, &amp;
+                            loninc = field % deltalon, &amp;
+                            knowni = 1.0_4, &amp;
+                            knownj = 1.0_4, &amp;
+                            lat1 = field % startlat, &amp;
+                            lon1 = field % startlon)
+            end if
+
+
+            if (index(field % field, 'SOILHGT') /= 0) then
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; grid % ter % array
+               ndims = 1
+            end if
+
+            do i=1,nInterpPoints
+               lat = latPoints(i)*DEG_PER_RAD
+               lon = lonPoints(i)*DEG_PER_RAD
+               call latlon_to_ij(proj, lat, lon, x, y)
+               if (x &lt; 0.0) then
+                  lon = lon + 360.0
+                  call latlon_to_ij(proj, lat, lon, x, y)
+               end if
+               if (ndims == 1) then
+                  destField1d(i) = four_pt(field % nx, field % ny, field % slab, x, y)
+               else if (ndims == 2) then
+                  destField2d(k,i) = four_pt(field % nx, field % ny, field % slab, x, y)
+               end if
+            end do
+         end if
+   
+         deallocate(field % slab)
+         call read_next_met_field(field, istatus)
+      end do
+
+      call read_met_close()
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! END ADOPT GFS TERRAIN HEIGHT
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+      !
+      ! Vertical grid setup
+      !
+      allocate(hs (grid%nCells))
+      allocate(hs1(grid%nCells))
+
+!     Fourth order smoother for terrain
+
+!      nsmterrain = 2
+      nsmterrain = 0   ! NO SMOOTHING WHEN USING GFS TERRAIN HEIGHT DIRECTLY
+
+      do i=1,nsmterrain
+
+         do iCell=1,grid%nCells
+            hs(iCell) = 0.
+            do j = 1,nEdgesOnCell(iCell)
+               hs(iCell) = hs(iCell) + dvEdge(edgesOnCell(j,iCell))    &amp;
+                                     / dcEdge(edgesOnCell(j,iCell))    &amp;
+                                     *   (ter(cellsOnCell(j,iCell))-ter(iCell))
+            end do
+            hs(iCell) = ter(iCell) + 0.125*hs(iCell)
+         end do
+
+         do iCell=1,grid %nCells
+            ter(iCell) = 0.
+            do j = 1,nEdgesOnCell(iCell)
+               ter(iCell) = ter(iCell) + dvEdge(edgesOnCell(j,iCell))    &amp;
+                                     / dcEdge(edgesOnCell(j,iCell))    &amp;
+                                     *    (hs(cellsOnCell(j,iCell))-hs(iCell))
+            end do
+            ter(iCell) = hs(iCell) - 0.125*ter(iCell)
+         end do
+
+      end do
+
+      do iCell=1,grid % nCells
+         hx(:,iCell) = ter(iCell)
+      end do
+
+      hm = maxval(ter(:))
+      write(6,*) &quot;max ter = &quot;, hm
+
+!     Metrics for hybrid coordinate and vertical stretching
+
+      str = 1.5
+!      str = 1.
+      zt = 24000.
+      dz = zt/float(nz1)
+
+      do k=1,nz
+         zw(k) = (real(k-1)/real(nz1))**str*zt
+         if (k &gt; 1) dzw(k-1) = zw(k)-zw(k-1)
+      end do
+
+!     ah(k) governs the transition between terrain-following 
+!        and pure height coordinates
+!           ah(k) = 1           is a smoothed terrain-following coordinate
+!           ah(k) = 1.-zw(k)/zt is the basic terrain-following coordinate
+!           ah(k) = 0           is a height coordinate

+!      hybrid = .true.
+      hybrid = .false.
+
+      kz = nz
+      if (hybrid) then
+      
+         zh = zt
+
+         do k=1,nz
+            if (zw(k) &lt; zh) then
+               ah(k) = cos(.5*pii*zw(k)/zh)**6
+
+!!!               ah(k) = ah(k)*(1.-zw(k)/zt)
+
+            else
+               ah(k) = 0.
+               kz = min(kz,k)
+            end if
+         end do
+
+      else
+        
+         do k=1,nz
+            ah(k) = 1.-zw(k)/zt
+         end do
+
+      end if
+
+      do k=1,nz
+         write(6,*) k,zw(k), ah(k)
+      end do
+
+      do k=1,nz1
+         dzw (k) = zw(k+1)-zw(k)
+         rdzw(k) = 1./dzw(k)
+         zu(k  ) = .5*(zw(k)+zw(k+1))
+      end do
+      do k=2,nz1
+         dzu (k)  = .5*(dzw(k)+dzw(k-1))
+         rdzu(k)  =  1./dzu(k)
+         fzp (k)  = .5* dzw(k  )/dzu(k)
+         fzm (k)  = .5* dzw(k-1)/dzu(k)
+         rdzwp(k) = dzw(k-1)/(dzw(k  )*(dzw(k)+dzw(k-1)))
+         rdzwm(k) = dzw(k  )/(dzw(k-1)*(dzw(k)+dzw(k-1)))
+      end do
+
+!**********  how are we storing cf1, cf2 and cf3?
+
+      COF1 = (2.*DZU(2)+DZU(3))/(DZU(2)+DZU(3))*DZW(1)/DZU(2) 
+      COF2 =     DZU(2)        /(DZU(2)+DZU(3))*DZW(1)/DZU(3) 
+      CF1  = FZP(2) + COF1
+      CF2  = FZM(2) - COF1 - COF2
+      CF3  = COF2       
+
+!      d1  = .5*dzw(1)
+!      d2  = dzw(1)+.5*dzw(2)
+!      d3  = dzw(1)+dzw(2)+.5*dzw(3)
+!      cf1 = d2*d3*(d3-d2)/(d2*d3*(d3-d2)+d1*d3*(d1-d3)+d1*d2*(d2-d1))
+!      cf2 = d1*d3*(d1-d3)/(d2*d3*(d3-d2)+d1*d3*(d1-d3)+d1*d2*(d2-d1))
+!      cf3 = d1*d2*(d2-d1)/(d2*d3*(d3-d2)+d1*d3*(d1-d3)+d1*d2*(d2-d1))
+
+      write(0,*) ' cf1, cf2, cf3 = ',cf1,cf2,cf3
+
+      grid % cf1 % scalar = cf1
+      grid % cf2 % scalar = cf2
+      grid % cf3 % scalar = cf3
+
+!     Smoothing algorithm for coordinate surfaces 
+
+      smooth = .true.
+!      smooth = .false.
+
+      if (smooth) then
+
+         dzmin = 0.2
+!         dzmin = 0.4
+
+         do k=2,kz-1
+            hx(k,:) = hx(k-1,:)
+            dzminf = zw(k)-zw(k-1)
+
+!            dzmin = max(.5,1.-.5*zw(k)/hm)
+
+            sm = .0625*min(.5*zw(k)/hm,1.)
+
+            do i=1,50
+               do iCell=1,grid %nCells
+                  hs1(iCell) = 0.
+                  do j = 1,nEdgesOnCell(iCell)
+
+                     hs1(iCell) = hs1(iCell) + dvEdge(edgesOnCell(j,iCell))    &amp;
+                                           / dcEdge(edgesOnCell(j,iCell))    &amp;
+                                           *  (hx(k,cellsOnCell(j,iCell))-hx(k,iCell))
+                  end do
+                  hs1(iCell) = hx(k,iCell) + sm*hs1(iCell)
+
+                  hs(iCell) = 0.
+                  do j = 1,nEdgesOnCell(iCell)
+                     hs(iCell) = hs(iCell) + dvEdge(edgesOnCell(j,iCell))    &amp;
+                                           / dcEdge(edgesOnCell(j,iCell))    &amp;
+                                           *  (hs1(cellsOnCell(j,iCell))-hs1(iCell))
+                  end do
+                  hs(iCell) = hs1(iCell) - 0.*hs(iCell)
+
+               end do
+               dzmina = minval(hs(:)-hx(k-1,:))
+               if (dzmina &gt;= dzmin*(zw(k)-zw(k-1))) then
+                  hx(k,:)=hs(:)
+                  dzminf = dzmina
+               else
+                  exit
+               end if
+            end do
+            write(6,*) k,i,sm,dzminf/(zw(k)-zw(k-1)),dzmina/(zw(k)-zw(k-1))
+         end do
+
+         do k=kz,nz
+               hx(k,:) = 0.
+         end do
+      else
+
+         do k=2,nz1
+            dzmina = minval(zw(k)+ah(k)*hx(k,:)-zw(k-1)-ah(k-1)*hx(k-1,:))
+            write(6,*) k,dzmina/(zw(k)-zw(k-1))
+         end do
+
+      end if
+
+      deallocate(hs )
+      deallocate(hs1)
+
+!     Height of coordinate levels (calculation of zgrid)
+
+      do iCell=1,grid % nCells
+         do k=1,nz        
+            zgrid(k,iCell) = zw(k) + ah(k)*hx(k,iCell)
+         end do
+         do k=1,nz1
+            zz (k,iCell) = (zw(k+1)-zw(k))/(zgrid(k+1,iCell)-zgrid(k,iCell))
+         end do
+      end do
+
+      do i=1, grid % nEdges
+         iCell1 = grid % CellsOnEdge % array(1,i)
+         iCell2 = grid % CellsOnEdge % array(2,i)
+         do k=1,nz
+            zx (k,i) = (zgrid(k,iCell2)-zgrid(k,iCell1)) / grid % dcEdge % array(i)
+         end do
+      end do
+      do i=1, grid % nCells
+         do k=1,nz1
+           ztemp = .5*(zgrid(k+1,i)+zgrid(k,i))
+           dss(k,i) = 0.
+           ztemp = zgrid(k,i)
+           if (ztemp.gt.zd+.1)  then
+               dss(k,i) = dss(k,i)+xnutr*sin(.5*pii*(ztemp-zd)/(zt-zd))**2
+           end if
+         end do
+      enddo
+
+!      do k=1,nz1
+!         write(0,*) ' k, zgrid(k,1),hx(k,1) ',k,zgrid(k,1),hx(k,1)
+!      enddo
+
+!      do k=1,nz1
+!         write(0,*) ' k, zx(k,1) ',k,zx(k,1)
+!      enddo
+
+      write(0,*) ' grid metrics setup complete '
+
+
+      !
       ! Horizontally interpolate meteorological data
       !
       allocate(vert_level(config_nfglevels))
@@ -2315,11 +2734,34 @@
              index(field % field, 'PMSL') /= 0 .or. &amp;
              index(field % field, 'PSFC') /= 0 .or. &amp;
              index(field % field, 'SOILHGT') /= 0 .or. &amp;
-             index(field % field, 'PRES') /= 0) then
+             index(field % field, 'SM000010') /= 0 .or. &amp;
+             index(field % field, 'SM010040') /= 0 .or. &amp;
+             index(field % field, 'SM040100') /= 0 .or. &amp;
+             index(field % field, 'SM100200') /= 0 .or. &amp;
+             index(field % field, 'ST000010') /= 0 .or. &amp;
+             index(field % field, 'ST010040') /= 0 .or. &amp;
+             index(field % field, 'ST040100') /= 0 .or. &amp;
+             index(field % field, 'ST100200') /= 0 .or. &amp;
+             index(field % field, 'PRES') /= 0 .or. &amp;
+             index(field % field, 'SNOW') /= 0 .or. &amp;
+             index(field % field, 'SEAICE') /= 0 .or. &amp;
+             index(field % field, 'SKINTEMP') /= 0) then
 
-            if (index(field % field, 'PMSL') == 0 .and. &amp;
-                index(field % field, 'PSFC') == 0 .and. &amp;
-                index(field % field, 'SOILHGT') == 0) then
+            if (index(field % field, 'SM000010') /= 0 .or. &amp;
+                index(field % field, 'SM010040') /= 0 .or. &amp;
+                index(field % field, 'SM040100') /= 0 .or. &amp;
+                index(field % field, 'SM100200') /= 0 .or. &amp;
+                index(field % field, 'ST000010') /= 0 .or. &amp;
+                index(field % field, 'ST010040') /= 0 .or. &amp;
+                index(field % field, 'ST040100') /= 0 .or. &amp;
+                index(field % field, 'ST100200') /= 0 .or. &amp;
+                index(field % field, 'SNOW') /= 0 .or. &amp;
+                index(field % field, 'SEAICE') /= 0 .or. &amp;
+                index(field % field, 'SKINTEMP') /= 0) then
+               k = 1
+            else if (index(field % field, 'PMSL') == 0 .and. &amp;
+                     index(field % field, 'PSFC') == 0 .and. &amp;
+                     index(field % field, 'SOILHGT') == 0) then
                do k=1,config_nfglevels
                   if (vert_level(k) == field % xlvl .or. vert_level(k) == -1.0) exit
                end do
@@ -2411,6 +2853,83 @@
                lonPoints =&gt; grid % lonCell % array
                destField1d =&gt; fg % soilz % array
                ndims = 1
+            else if (index(field % field, 'SM000010') /= 0) then
+write(0,*) 'Interpolating SM000010'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % sm000010 % array
+               ndims = 1
+            else if (index(field % field, 'SM010040') /= 0) then
+write(0,*) 'Interpolating SM010040'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % sm010040 % array
+               ndims = 1
+            else if (index(field % field, 'SM040100') /= 0) then
+write(0,*) 'Interpolating SM040100'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % sm040100 % array
+               ndims = 1
+            else if (index(field % field, 'SM100200') /= 0) then
+write(0,*) 'Interpolating SM100200'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % sm100200 % array
+               ndims = 1
+            else if (index(field % field, 'ST000010') /= 0) then
+write(0,*) 'Interpolating ST000010'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % st000010 % array
+               ndims = 1
+            else if (index(field % field, 'ST010040') /= 0) then
+write(0,*) 'Interpolating ST010040'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % st010040 % array
+               ndims = 1
+            else if (index(field % field, 'ST040100') /= 0) then
+write(0,*) 'Interpolating ST040100'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % st040100 % array
+               ndims = 1
+            else if (index(field % field, 'ST100200') /= 0) then
+write(0,*) 'Interpolating ST100200'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % st100200 % array
+               ndims = 1
+            else if (index(field % field, 'SNOW') /= 0) then
+write(0,*) 'Interpolating SNOW'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % snow % array
+               ndims = 1
+            else if (index(field % field, 'SEAICE') /= 0) then
+write(0,*) 'Interpolating SEAICE'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % seaice % array
+               ndims = 1
+            else if (index(field % field, 'SKINTEMP') /= 0) then
+write(0,*) 'Interpolating SKINTEMP'
+               nInterpPoints = grid % nCells
+               latPoints =&gt; grid % latCell % array
+               lonPoints =&gt; grid % lonCell % array
+               destField1d =&gt; fg % skintemp % array
+               ndims = 1
             end if
 
             do i=1,nInterpPoints
@@ -2435,7 +2954,19 @@
 
       call read_met_close()
 
+      ! Fix for isobaric data
+      if (minval(fg % p % array(:,:)) == 0.0) then
+         write(0,*) 'Setting pressure field for isobaric data'
+         do k=1,config_nfglevels
+            if (vert_level(k) /= 200100.0) then
+               fg % p % array(k,:) = vert_level(k)
+            else
+               fg % p % array(k,:) = fg % psfc % array(:)
+            end if
+         end do
+      end if
 
+
       !  
       ! Compute normal wind component and store in fg%u
       !  
@@ -2450,31 +2981,304 @@
       !  
       ! Vertically interpolate meteorological data
       !  
+      allocate(sorted_arr(2,config_nfglevels))
+
       do iCell=1,grid%nCells
+
+         ! T
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = fg % z % array(k,iCell)
+!NOSFC            if (vert_level(k) == 200100.0) sorted_arr(1,k) = fg % soilz % array(iCell)
+            if (vert_level(k) == 200100.0) sorted_arr(1,k) = 99999.0
+            sorted_arr(2,k) = fg % t % array(k,iCell)
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
          do k=1,grid%nVertLevels
-            ! HGT
-            ! PRES
-            ! THETA
-            ! RH
-            ! T
+            target_z = 0.5 * (grid % zgrid % array(k,iCell) + grid % zgrid % array(k+1,iCell))
+            state % theta % array(k,iCell) = vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=1)
          end do
+
+
+         ! RH
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = fg % z % array(k,iCell)
+!NOSFC            if (vert_level(k) == 200100.0) sorted_arr(1,k) = fg % soilz % array(iCell)
+            if (vert_level(k) == 200100.0) sorted_arr(1,k) = 99999.0
+            sorted_arr(2,k) = fg % rh % array(k,iCell)
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
+         do k=1,grid%nVertLevels
+            target_z = 0.5 * (grid % zgrid % array(k,iCell) + grid % zgrid % array(k+1,iCell))
+            state % scalars % array(state % index_qv,k,iCell) = vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=0)
+         end do
+
+
+         ! GHT
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = fg % z % array(k,iCell)
+!NOSFC            if (vert_level(k) == 200100.0) sorted_arr(1,k) = fg % soilz % array(iCell)
+            if (vert_level(k) == 200100.0) sorted_arr(1,k) = 99999.0
+            sorted_arr(2,k) = fg % z % array(k,iCell)
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
+         do k=1,grid%nVertLevels
+            target_z = 0.5 * (grid % zgrid % array(k,iCell) + grid % zgrid % array(k+1,iCell))
+            fg % gfs_z % array(k,iCell) = vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=1)
+         end do
+
+
+         ! PRESSURE
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = fg % z % array(k,iCell)
+            if (vert_level(k) == 200100.0) then 
+!NOSFC               sorted_arr(1,k) = fg % soilz % array(iCell)
+               sorted_arr(1,k) = 99999.0
+               sfc_k = k
+            end if
+            sorted_arr(2,k) = log(fg % p % array(k,iCell))
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
+         do k=1,grid%nVertLevels
+            target_z = 0.5 * (grid % zgrid % array(k,iCell) + grid % zgrid % array(k+1,iCell))
+            diag % pressure_base % array(k,iCell) = exp(vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=1))
+         end do
+
+
+         ! PRESSURE
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = fg % z % array(k,iCell)
+            if (vert_level(k) == 200100.0) then 
+!NOSFC               sorted_arr(1,k) = fg % soilz % array(iCell)
+               sorted_arr(1,k) = 99999.0
+               sfc_k = k
+            end if
+            sorted_arr(2,k) = log(fg % p % array(k,iCell))
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
+         do k=1,grid%nVertLevels+1
+            target_z = grid % zgrid % array(k,iCell)
+            fg % gfs_p % array(k,iCell) = exp(vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=1))
+         end do
+
       end do
 
+
       do iEdge=1,grid%nEdges
+
+         ! U
+         sorted_arr(:,:) = -999.0
+         do k=1,config_nfglevels
+            sorted_arr(1,k) = 0.5 * (fg % z % array(k,cellsOnEdge(1,iEdge)) + fg % z % array(k,cellsOnEdge(2,iEdge)))
+!NOSFC            if (vert_level(k) == 200100.0) sorted_arr(1,k) = 0.5 * (fg % soilz % array(cellsOnEdge(1,iEdge)) + fg % soilz % array(cellsOnEdge(2,iEdge)))
+            if (vert_level(k) == 200100.0) sorted_arr(1,k) = 99999.0
+            sorted_arr(2,k) = fg % u % array(k,iEdge)
+         end do
+         call quicksort(config_nfglevels, sorted_arr)
          do k=1,grid%nVertLevels
-            ! U
+            target_z = 0.25 * (grid % zgrid % array(k,cellsOnEdge(1,iEdge)) + grid % zgrid % array(k+1,cellsOnEdge(1,iEdge)) + grid % zgrid % array(k,cellsOnEdge(2,iEdge)) + grid % zgrid % array(k+1,cellsOnEdge(2,iEdge)))
+            state % u % array(k,iEdge) = vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=0)
          end do
+
       end do
 
 
       !
+      ! Adjust surface pressure for difference in topography
+      !
+      do sfc_k=1,config_nfglevels
+         if (vert_level(sfc_k) == 200100.) exit
+      end do 
+      do iCell=1,grid%nCells
+
+         ! We need to extrapolate
+            sorted_arr(:,:) = -999.0
+            do k=1,config_nfglevels
+               sorted_arr(1,k) = fg % z % array(k,iCell)
+               if (vert_level(k) == 200100.0) then 
+!NOSFC                  sorted_arr(1,k) = fg % soilz % array(iCell)
+                  sorted_arr(1,k) = 99999.0
+               end if
+               sorted_arr(2,k) = log(fg % p % array(k,iCell))
+            end do
+            call quicksort(config_nfglevels, sorted_arr)
+            target_z = grid % zgrid % array(1,iCell)
+            fg % psfc % array(iCell) = exp(vertical_interp(target_z, config_nfglevels, sorted_arr, order=1, extrap=1))
+
+      end do
+
+      deallocate(sorted_arr)
+
+
+
+      !
       ! Diagnose fields needed in initial conditions file (u, w, rho, theta, scalars)
       !
+      do iCell=1,grid%nCells
+         do k=1,grid%nVertLevels
+            es = 6.112 * exp((17.27*(state % theta % array(k,iCell) - 273.16))/(state % theta % array(k,iCell) - 35.86))
+            rs = 0.622 * es / (diag % pressure_base % array(k,iCell) - es)
+            state % scalars % array(state % index_qv,k,iCell) = rs * state % scalars % array(state % index_qv,k,iCell)
 
-      deallocate(vert_level)
+            rgas_moist = (1.0 + 0.61 * state % scalars % array(state % index_qv,k,iCell)) * rgas
+            state % rho % array(k,iCell) = diag % pressure_base % array(k,iCell) / (rgas_moist * state % theta % array(k,iCell))
+            state % rho % array(k,iCell) = state % rho % array(k,iCell) / (1.0 + state % scalars % array(state % index_qv,k,iCell))
+            state % rho % array(k,iCell) = state % rho % array(k,iCell) / zz(k,iCell)
+
+            state % theta % array(k,iCell) = state % theta % array(k,iCell) * (p0 / diag % pressure_base % array(k,iCell)) ** (rgas / cp)
+            state % theta % array(k,iCell) = state % theta % array(k,iCell) * (1.0 + 1.61*state % scalars % array(state % index_qv,k,iCell))
+         end do
+      end do
+
+#if 0
+      do iCell=1,grid%nCells
+
+         fsum(:) = 0.0
+         do k=2,grid%nVertLevels+1
+            rgas_moist = (1.0 + 0.61 * state % scalars % array(state % index_qv,k-1,iCell)) * rgas
+!RGAS            rgas_moist = rgas
+            ptmp = fg % gfs_p % array(k,iCell)
+            state % theta % array(k-1,iCell) = -gravity * (zgrid(k,iCell) - zgrid(k-1,iCell)) / (rgas_moist * (log(ptmp / fg % gfs_p % array(1,iCell)) + fsum(k-1)))
+            fsum(k) = fsum(k-1) + gravity * (zgrid(k,iCell) - zgrid(k-1,iCell)) / (rgas_moist * state % theta % array(k-1,iCell))
+
+            state % theta % array(k-1,iCell) = state % theta % array(k-1,iCell) * (p0 / diag % pressure_base % array(k-1,iCell)) ** (rgas / cp)
+            state % theta % array(k-1,iCell) = state % theta % array(k-1,iCell) * (1.0 + 1.61*state % scalars % array(state % index_qv,k-1,iCell))
+         end do
+      end do
+
 #endif
 
+#if 0
+      do iCell=1,grid%nCells
+         do k=2,grid%nVertLevels+1
+            rgas_moist = (1.0 + 0.61 * state % scalars % array(state % index_qv,k-1,iCell)) * rgas
+            state % theta % array(k-1,iCell) = -gravity * (zgrid(k,iCell) - zgrid(k-1,iCell)) / (rgas_moist * log(fg % gfs_p % array(k,iCell) / fg % gfs_p % array(k-1,iCell)))
 
+            state % theta % array(k-1,iCell) = state % theta % array(k-1,iCell) * (p0 / diag % pressure_base % array(k-1,iCell)) ** (rgas / cp)
+            state % theta % array(k-1,iCell) = state % theta % array(k-1,iCell) * (1.0 + 1.61*state % scalars % array(state % index_qv,k-1,iCell))
+         end do
+      end do
+#endif
+
+
+
+      !
+      ! Reference state based on a dry isothermal atmosphere
+      !
+      do iCell=1,grid % nCells
+         do k=1,nz1
+            ztemp    = 0.5*(zgrid(k+1,iCell)+zgrid(k,iCell))
+            ppb(k,iCell) = p0*exp(-gravity*ztemp/(rgas*t0b))      ! pressure_base
+            pb (k,iCell) = (ppb(k,iCell)/p0)**(rgas/cp)           ! exner_base
+            rb (k,iCell) = ppb(k,iCell)/(rgas*t0b*zz(k,iCell))    ! rho_base
+            tb (k,iCell) = t0b/pb(k,iCell)                        ! theta_base
+            rtb(k,iCell) = rb(k,iCell)*tb(k,iCell)                ! rtheta_base
+            p  (k,iCell) = pb(k,iCell)                            ! exner
+            pp (k,iCell) = 0.                                     ! pressure_p
+            rr (k,iCell) = 0.                                     ! rho_p
+         end do
+      end do
+
+      do iEdge=1,grid%nEdges
+         do k=1,grid%nVertLevels
+            diag % ru % array(k,iEdge) = state % u % array(k,iEdge) * 0.5*(state % rho % array(k,cellsOnEdge(1,iEdge)) + state % rho % array(k,cellsOnEdge(2,iEdge)))
+         end do
+      end do
+
+
+      ! For z-metric term in omega equation
+      do iEdge = 1,grid % nEdges
+         cell1 = CellsOnEdge(1,iEdge)
+         cell2 = CellsOnEdge(2,iEdge)
+         if (cell1 &lt;= nCellsSolve .or. cell2 &lt;= nCellsSolve ) then
+
+            do k = 1, grid%nVertLevels
+
+               if (config_theta_adv_order == 2) then
+
+                  z_edge = (zgrid(k,cell1)+zgrid(k,cell2))/2.
+
+               else !theta_adv_order == 3 or 4 
+
+                  d2fdx2_cell1 = deriv_two(1,1,iEdge) * zgrid(k,cell1)
+                  d2fdx2_cell2 = deriv_two(1,2,iEdge) * zgrid(k,cell2)
+                  do i=1, grid % nEdgesOnCell % array (cell1)
+                     if ( grid % CellsOnCell % array (i,cell1) &gt; 0)       &amp;
+                     d2fdx2_cell1 = d2fdx2_cell1 + deriv_two(i+1,1,iEdge) * zgrid(k,grid % CellsOnCell % array (i,cell1))
+                  end do
+                  do i=1, grid % nEdgesOnCell % array (cell2)
+                     if ( grid % CellsOnCell % array (i,cell2) &gt; 0)       &amp;
+                     d2fdx2_cell2 = d2fdx2_cell2 + deriv_two(i+1,2,iEdge) * zgrid(k,grid % CellsOnCell % array (i,cell2))
+                  end do             
+             
+                  z_edge =  0.5*(zgrid(k,cell1) + zgrid(k,cell2))         &amp;
+                                - (grid % dcEdge % array(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12. 
+
+                  if (config_theta_adv_order == 3) then
+                     z_edge3 =  - (grid % dcEdge % array(iEdge) **2) * (d2fdx2_cell1 - d2fdx2_cell2) / 12.   
+                  else 
+                     z_edge3 = 0.
+                  end if
+
+               end if
+
+                  zb(k,1,iEdge) = (z_edge-zgrid(k,cell1))*dvEdge(iEdge)/AreaCell(cell1) 
+                  zb(k,2,iEdge) = (z_edge-zgrid(k,cell2))*dvEdge(iEdge)/AreaCell(cell2) 
+                  zb3(k,1,iEdge)=  z_edge3*dvEdge(iEdge)/AreaCell(cell1) 
+                  zb3(k,2,iEdge)=  z_edge3*dvEdge(iEdge)/AreaCell(cell2) 
+  
+                  if (k /= 1) then
+                     zf(k,1,iEdge) = ( fzm(k)*zz(k,cell1)+fzp(k)*zz(k-1,cell1) )*zb(k,1,iEdge)
+                     zf(k,2,iEdge) = ( fzm(k)*zz(k,cell2)+fzp(k)*zz(k-1,cell2) )*zb(k,2,iEdge)
+                     zf3(k,1,iEdge)= ( fzm(k)*zz(k,cell1)+fzp(k)*zz(k-1,cell1) )*zb3(k,1,iEdge)
+                     zf3(k,2,iEdge)= ( fzm(k)*zz(k,cell2)+fzp(k)*zz(k-1,cell2) )*zb3(k,2,iEdge)
+                  end if
+
+            end do
+
+         end if
+      end do
+
+      diag % rw % array = 0.
+      state % w % array = 0.
+      do iEdge = 1,grid % nEdges
+
+         cell1 = CellsOnEdge(1,iEdge)
+         cell2 = CellsOnEdge(2,iEdge)
+
+         if (cell1 &lt;= nCellsSolve .or. cell2 &lt;= nCellsSolve ) then
+         do k = 2, grid%nVertLevels
+            flux =  (fzm(k)*diag % ru % array(k,iEdge)+fzp(k)*diag % ru % array(k-1,iEdge))
+            diag % rw % array(k,cell2) = diag % rw % array(k,cell2) + zf(k,2,iEdge)*flux
+            diag % rw % array(k,cell1) = diag % rw % array(k,cell1) - zf(k,1,iEdge)*flux
+
+            if (config_theta_adv_order ==3) then 
+               diag % rw % array(k,cell2) = diag % rw % array(k,cell2)    &amp;
+                                            - sign(1.,diag % ru % array(k,iEdge))*config_coef_3rd_order*zf3(k,2,iEdge)*flux
+               diag % rw % array(k,cell1) = diag % rw % array(k,cell1)    &amp;
+                                            + sign(1.,diag % ru % array(k,iEdge))*config_coef_3rd_order*zf3(k,1,iEdge)*flux
+            end if
+
+         end do
+         end if
+
+      end do
+
+      ! Compute w from rho and rw
+      do iCell=1,grid%nCells
+         do k=2,grid%nVertLevels
+            state % w % array(k,iCell) = diag % rw % array(k,iCell)     &amp;
+                                       / (fzp(k) * state % rho % array(k-1,iCell) + fzm(k) * state % rho % array(k,iCell))
+         end do
+      end do
+   
+      deallocate(vert_level)
+
+
    end subroutine nhyd_test_case_gfs
 
 
@@ -2640,4 +3444,91 @@
 
    end function nearest_edge
 
+
+   real function vertical_interp(target_z, nz, zf, order, extrap, surface_val, sealev_val)
+
+      implicit none
+
+      real (kind=RKIND), intent(in) :: target_z
+      integer, intent(in) :: nz 
+      real (kind=RKIND), dimension(2,nz), intent(in) :: zf      ! zf(1,:) is column of vertical coordinate values, zf(2,:) is column of field values
+      integer, intent(in), optional :: order
+      integer, intent(in), optional :: extrap
+      real (kind=RKIND), intent(in), optional :: surface_val
+      real (kind=RKIND), intent(in), optional :: sealev_val
+
+      integer :: k, lm, lp
+      real (kind=RKIND) :: wm, wp
+      real (kind=RKIND) :: slope
+
+      integer :: interp_order, extrap_type
+      real (kind=RKIND) :: surface, sealevel
+
+
+      if (present(order)) then
+         interp_order = order
+      else
+         interp_order = 2
+      end if
+
+      if (present(extrap)) then
+         extrap_type = extrap
+      else
+         interp_order = 1
+      end if
+
+      if (present(surface_val)) then
+         surface = surface_val
+      else
+         surface = 200100.0
+      end if
+
+      if (present(sealev_val)) then
+         sealevel = sealev_val
+      else
+         sealevel = 201300.0
+      end if
+
+      !
+      ! Extrapolation required
+      !
+      if (target_z &lt; zf(1,1)) then
+         if (extrap_type == 0) then
+            vertical_interp = zf(2,1)
+         else if (extrap_type == 1) then
+            slope = (zf(2,2) - zf(2,1)) / (zf(1,2) - zf(1,1))
+            vertical_interp = zf(2,1) + slope * (target_z - zf(1,1))
+         end if
+         return
+      end if
+      if (target_z &gt;= zf(1,nz)) then
+         if (extrap_type == 0) then
+            vertical_interp = zf(2,nz)
+         else if (extrap_type == 1) then
+            slope = (zf(2,nz) - zf(2,nz-1)) / (zf(1,nz) - zf(1,nz-1))
+            vertical_interp = zf(2,nz) + slope * (target_z - zf(1,nz))
+         end if
+         return
+      end if
+
+
+      !
+      ! No extrapolation required
+      !
+      do k=1,nz-1
+         if (target_z &gt;= zf(1,k) .and. target_z &lt; zf(1,k+1)) then
+            lm = k
+            lp = k+1
+            wm = (zf(1,k+1) - target_z) / (zf(1,k+1) - zf(1,k))
+            wp = (target_z - zf(1,k)) / (zf(1,k+1) - zf(1,k))
+            exit
+         end if
+      end do
+
+      vertical_interp = wm*zf(2,lm) + wp*zf(2,lp)
+
+      return
+
+   end function vertical_interp
+
 end module test_cases

</font>
</pre>