<p><b>mpetersen@lanl.gov</b> 2011-03-14 15:57:46 -0600 (Mon, 14 Mar 2011)</p><p>BRANCH COMMIT: Added Richardson-number based vertical mixing (Pacanowski and Philander)<br>
</p><hr noshade><pre><font color="gray">Modified: branches/ocean_projects/imp_vert_mix_mrp/namelist.input.ocean
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/namelist.input.ocean        2011-03-11 23:38:00 UTC (rev 757)
+++ branches/ocean_projects/imp_vert_mix_mrp/namelist.input.ocean        2011-03-14 21:57:46 UTC (rev 758)
@@ -1,10 +1,10 @@
 &amp;sw_model
    config_test_case = 0
    config_time_integration = 'RK4'
-   config_dt = 90.0
-   config_ntimesteps = 1920000
-   config_output_interval = 19200
-   config_stats_interval = 1920
+   config_dt = 120.0
+   config_ntimesteps = 100
+   config_output_interval = 100 
+   config_stats_interval = 100 
 /
 
 &amp;io
@@ -14,35 +14,45 @@
 /
 
 &amp;restart
-   config_restart_interval = 115200
+   config_restart_interval = 10000000 
    config_do_restart = .false.
-   config_restart_time = 31104000
+   config_restart_time = 1036800.0
 /
 
 &amp;grid
-   config_vert_grid_type = 'isopycnal'
-   config_rho0 = 1015
+   config_vert_grid_type = 'zlevel'
+   config_rho0 = 1000
 /
 &amp;hmix
-   config_h_mom_eddy_visc2 = 0.0
-   config_h_mom_eddy_visc4 = 5.0e8
-   config_h_tracer_eddy_diff2 = 10.0
+   config_h_mom_eddy_visc2 = 1.0e5
+   config_h_mom_eddy_visc4 = 0.0
+   config_h_tracer_eddy_diff2 = 1.0e4
    config_h_tracer_eddy_diff4 = 0.0
 /
 &amp;vmix
-   config_vert_visc_type  = 'const'
-   config_vert_diff_type  = 'const'
-   config_vmixTanhViscMax = 2.5e-1
-   config_vmixTanhViscMin = 1.0e-4
-   config_vmixTanhDiffMax = 2.5e-2
-   config_vmixTanhDiffMin = 1.0e-5
-   config_vmixTanhZMid    = -100
-   config_vmixTanhZWidth  = 100
-   config_vert_viscosity  = 1.0e-4
-   config_vert_diffusion  = 1.0e-4
+   config_vert_visc_type  = 'rich'
+   config_vert_diff_type  = 'rich'
+   config_implicit_vertical_mix = .true.
 /
+&amp;vmix_const
+   config_vert_viscosity  = 2.5e-5
+   config_vert_diffusion  = 2.5e-5 
+/
+&amp;vmix_rich
+   config_bkrd_vert_visc  = 1.0e-4
+   config_bkrd_vert_diff  = 1.0e-5
+   config_rich_mix        = 50.0
+/
+&amp;vmix_tanh
+   config_max_visc_tanh = 2.5e-1
+   config_min_visc_tanh = 1.0e-4
+   config_max_diff_tanh = 2.5e-2
+   config_min_diff_tanh = 1.0e-5
+   config_zMid_tanh    = -100
+   config_zWidth_tanh  = 100
+/
 &amp;eos
-   config_eos_type = 'linear'
+   config_eos_type = 'jm'
 /
 &amp;advection
    config_vert_tracer_adv = 'spline'

Modified: branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry        2011-03-11 23:38:00 UTC (rev 757)
+++ branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry        2011-03-14 21:57:46 UTC (rev 758)
@@ -23,14 +23,18 @@
 namelist real      hmix     config_apvm_upwinding       0.5
 namelist character vmix     config_vert_visc_type    const
 namelist character vmix     config_vert_diff_type    const
-namelist real      vmix     config_vert_viscosity    2.5e-4
-namelist real      vmix     config_vert_diffusion    2.5e-5
-namelist real      vmix     config_vmixTanhViscMax   2.5e-1
-namelist real      vmix     config_vmixTanhViscMin   1.0e-4
-namelist real      vmix     config_vmixTanhDiffMax   2.5e-2
-namelist real      vmix     config_vmixTanhDiffMin   1.0e-5
-namelist real      vmix     config_vmixTanhZMid      -100
-namelist real      vmix     config_vmixTanhZWidth    100
+namelist logical   vmix     config_implicit_vertical_mix  .true.
+namelist real      vmix_const   config_vert_viscosity    2.5e-4
+namelist real      vmix_const   config_vert_diffusion    2.5e-5
+namelist real      vmix_rich    config_bkrd_vert_visc    1.0e-4
+namelist real      vmix_rich    config_bkrd_vert_diff    1.0e-5
+namelist real      vmix_rich    config_rich_mix          50
+namelist real      vmix_tanh    config_max_visc_tanh     2.5e-1
+namelist real      vmix_tanh    config_min_visc_tanh     1.0e-4
+namelist real      vmix_tanh    config_max_diff_tanh     2.5e-2
+namelist real      vmix_tanh    config_min_diff_tanh     1.0e-5
+namelist real      vmix_tanh    config_zMid_tanh         -100
+namelist real      vmix_tanh    config_zWidth_tanh       100
 namelist character eos       config_eos_type         linear
 namelist character advection config_vert_tracer_adv  stencil
 namelist integer   advection config_vert_tracer_adv_order 4
@@ -177,6 +181,7 @@
 var persistent real    MontPot ( nVertLevels nCells Time ) 2 o MontPot state - -
 var persistent real    pressure ( nVertLevels nCells Time ) 2 o pressure state - -
 var persistent real    wTop ( nVertLevelsP1 nCells Time ) 2 o wTop state - -
+var persistent real    rhoDisplaced ( nVertLevels nCells Time ) 2 o rhoDisplaced state - -
 
 # Other diagnostic variables: neither read nor written to any files
 var persistent real    vh ( nVertLevels nEdges Time ) 2 - vh state - -
@@ -193,3 +198,10 @@
 var persistent real    volumeEdgeGlobal ( Time ) 2 o volumeEdgeGlobal state - -
 var persistent real    CFLNumberGlobal ( Time ) 2 o CFLNumberGlobal state - -
 
+# Diagnostics fields, only one time level required
+var persistent real    RiTopOfCell ( nVertLevelsP1 nCells ) 0 o RiTopOfCell diagnostics - -
+var persistent real    RiTopOfEdge ( nVertLevelsP1 nEdges ) 0 o RiTopOfEdge diagnostics - -
+var persistent real    vertViscTopOfEdge ( nVertLevelsP1 nEdges ) 0 o vertViscTopOfEdge diagnostics - -
+var persistent real    vertDiffTopOfCell ( nVertLevelsP1 nCells ) 0 o vertDiffTopOfCell diagnostics - -
+
+

Modified: branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F        2011-03-11 23:38:00 UTC (rev 757)
+++ branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F        2011-03-14 21:57:46 UTC (rev 758)
@@ -143,8 +143,11 @@
 
         block =&gt; domain % blocklist
         do while (associated(block))
-           call compute_tend(block % tend, provis, block % mesh)
-           call compute_scalar_tend(block % tend, provis, block % mesh)
+           if (.not.config_implicit_vertical_mix) then
+              call compute_vertical_mix_coefficients(provis, block % diagnostics, block % mesh)
+           end if
+           call compute_tend(block % tend, provis, block % diagnostics, block % mesh)
+           call compute_scalar_tend(block % tend, provis, block % diagnostics, block % mesh)
            call enforce_boundaryEdge(block % tend, block % mesh)
            block =&gt; block % next
         end do
@@ -189,6 +192,7 @@
                  provis % u % array(:,:) = block % state % time_levs(1) % state % u % array(:,:)
               end if
               call compute_solve_diagnostics(dt, provis, block % mesh)
+
               block =&gt; block % next
            end do
         end if
@@ -225,13 +229,33 @@
       !
       block =&gt; domain % blocklist
       do while (associated(block))
-         do iCell=1,block % mesh % nCells
-            do k=1,block % mesh % maxLevelCell % array(iCell)
-               block % state % time_levs(2) % state % tracers % array(:,k,iCell) = &amp;
-                                                                     block % state % time_levs(2) % state % tracers % array(:,k,iCell)  &amp;
-                                                                   / block % state % time_levs(2) % state % h % array(k,iCell)
+
+         if (config_implicit_vertical_mix) then
+
+            call compute_vertical_mix_coefficients(block % state % time_levs(2) % state, block % diagnostics, block % mesh)
+
+            do iCell=1,block % mesh % nCells
+               !N=maxLevelCell(iCell)
+
+            !   do k=1,maxLevelCell(iCell)
+               ! Compute A(k), C(k), R(k) for momentum
+             !  enddo
+               !call tridiagonal_solve(u(:,iCell),A(2:N),C(1:N),A(1:N-1),R)
+
+              ! do k=1,maxLevelCell(iCell)
+               ! Compute A(k), C(k), R(iTracer,k) for tracers
+               !enddo
+               !call tridiagonal_solve_mult(tracers(:,:,iCell),A(2:N),C(1:N),A(1:N-1),R)
             end do
-         end do
+         else
+            do iCell=1,block % mesh % nCells
+               do k=1,block % mesh % maxLevelCell % array(iCell)
+                  block % state % time_levs(2) % state % tracers % array(:,k,iCell) = &amp;
+                        block % state % time_levs(2) % state % tracers % array(:,k,iCell)  &amp;
+                       / block % state % time_levs(2) % state % h % array(k,iCell)
+               end do
+            end do
+         end if
 
          if (config_test_case == 1) then    ! For case 1, wind field should be fixed
             block % state % time_levs(2) % state % u % array(:,:) = block % state % time_levs(1) % state % u % array(:,:)
@@ -249,7 +273,7 @@
    end subroutine rk4
 
 
-   subroutine compute_tend(tend, s, grid)
+   subroutine compute_tend(tend, s, d, grid)
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ! Compute height and normal wind tendencies, as well as diagnostic variables
    !
@@ -263,6 +287,7 @@
 
       type (tend_type), intent(inout) :: tend
       type (state_type), intent(in) :: s
+      type (diagnostics_type), intent(in) :: d
       type (mesh_type), intent(in) :: grid
 
       integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
@@ -277,7 +302,7 @@
       real (kind=RKIND), dimension(:,:), pointer :: &amp;
         weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
         tend_h, tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
-        MontPot, wTop, divergence
+        MontPot, wTop, divergence, vertViscTopOfEdge
       type (dm_info) :: dminfo
 
       integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
@@ -286,7 +311,7 @@
         cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
         edgesOnEdge, edgesOnVertex
       real (kind=RKIND) :: u_diffusion
-      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge, vertViscTop
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
 
       real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
       real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
@@ -309,6 +334,7 @@
       pv_edge     =&gt; s % pv_edge % array
       MontPot     =&gt; s % MontPot % array
       pressure    =&gt; s % pressure % array
+      vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
 
       weightsOnEdge     =&gt; grid % weightsOnEdge % array
       kiteAreasOnVertex =&gt; grid % kiteAreasOnVertex % array
@@ -640,33 +666,12 @@
       !
       ! velocity tendency: vertical mixing d/dz( nu_v du/dz))
       !
-      allocate(vertViscTop(nVertLevels+1))
-      if (config_vert_visc_type.eq.'const') then
-        vertViscTop = config_vert_viscosity
-      elseif (config_vert_visc_type.eq.'tanh') then
-        if (config_vert_grid_type.ne.'zlevel') then
-          write(0,*) 'Abort: config_vert_visc_type.eq.tanh may only', &amp;
-            ' use config_vert_grid_type of zlevel at this time'
-          call dmpar_abort(dminfo)
-        endif
-  
-        do k=1,nVertLevels+1
-          vertViscTop(k) = -(config_vmixTanhViscMax-config_vmixTanhViscMin)/2.0 &amp;
-            *tanh(-(zTopZLevel(k)-config_vmixTanhZMid) &amp;
-                  /config_vmixTanhZWidth) &amp;
-            + (config_vmixTanhViscMax+config_vmixTanhViscMin)/2
-        enddo
-      else
-        write(0,*) 'Abort: unrecognized config_vert_visc_type'
-        call dmpar_abort(dminfo)
-      endif
-
       allocate(fluxVertTop(nVertLevels+1))
       fluxVertTop(1) = 0.0
       do iEdge=1,grid % nEdgesSolve
          
          do k=2,maxLevelEdgeTop(iEdge)
-           fluxVertTop(k) = vertViscTop(k) &amp;
+           fluxVertTop(k) = vertViscTopOfEdge(k,iEdge) &amp;
               * ( u(k-1,iEdge) - u(k,iEdge) ) &amp;
               * 2 / (h_edge(k-1,iEdge) + h_edge(k,iEdge))
          enddo
@@ -679,12 +684,12 @@
          enddo
 
       end do
-      deallocate(fluxVertTop, vertViscTop)
+      deallocate(fluxVertTop)
 
    end subroutine compute_tend
 
 
-   subroutine compute_scalar_tend(tend, s, grid)
+   subroutine compute_scalar_tend(tend, s, d, grid)
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !
    ! Input: s - current model state
@@ -697,6 +702,7 @@
 
       type (tend_type), intent(inout) :: tend
       type (state_type), intent(in) :: s
+      type (diagnostics_type), intent(in) :: d
       type (mesh_type), intent(in) :: grid
 
       integer :: i, k, iCell, iEdge, iTracer, cell1, cell2, upwindCell,&amp;
@@ -706,7 +712,7 @@
       real (kind=RKIND), dimension(:), pointer :: &amp;
         h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle
       real (kind=RKIND), dimension(:,:), pointer :: &amp;
-        u,h,wTop, h_edge
+        u,h,wTop, h_edge, vertDiffTopOfCell
       real (kind=RKIND), dimension(:,:,:), pointer :: &amp;
         tracers, tend_tr
       integer, dimension(:,:), pointer :: boundaryEdge
@@ -717,7 +723,7 @@
       integer, dimension(:,:), pointer :: cellsOnEdge, boundaryCell
       real (kind=RKIND), dimension(:), pointer :: zTopZLevel,zMidZLevel, &amp;
          hRatioZLevelK, hRatioZLevelKm1
-      real (kind=RKIND), dimension(:), allocatable:: vertDiffTop, tracer2ndDer, tracersIn, tracersOut, posZMidZLevel, &amp;
+      real (kind=RKIND), dimension(:), allocatable:: tracer2ndDer, tracersIn, tracersOut, posZMidZLevel, &amp;
             posZTopZLevel
       real (kind=RKIND), dimension(:,:), allocatable:: fluxVertTop, boundaryMask
       real (kind=RKIND), dimension(:,:,:), allocatable::tr_flux, tr_div, delsq_tracer, tracerTop
@@ -733,6 +739,7 @@
       wTop        =&gt; s % wTop % array
       tracers     =&gt; s % tracers % array
       h_edge      =&gt; s % h_edge % array
+      vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
 
       tend_tr     =&gt; tend % tracers % array
                   
@@ -1185,27 +1192,6 @@
       !
       ! tracer tendency: vertical diffusion h d/dz( \kappa_v d\phi/dz)
       !
-      allocate(vertDiffTop(nVertLevels+1))
-      if (config_vert_diff_type.eq.'const') then
-        vertDiffTop = config_vert_diffusion
-      elseif (config_vert_diff_type.eq.'tanh') then
-        if (config_vert_grid_type.ne.'zlevel') then
-          write(0,*) 'Abort: config_vert_diff_type.eq.tanh may only', &amp;
-            ' use config_vert_grid_type of zlevel at this time'
-          call dmpar_abort(dminfo)
-        endif
-  
-        do k=1,nVertLevels+1
-          vertDiffTop(k) = -(config_vmixTanhDiffMax-config_vmixTanhDiffMin)/2.0 &amp;
-            *tanh(-(zTopZLevel(k)-config_vmixTanhZMid) &amp;
-                  /config_vmixTanhZWidth) &amp;
-            + (config_vmixTanhDiffMax+config_vmixTanhDiffMin)/2
-        enddo
-      else
-        write(0,*) 'Abort: unrecognized config_vert_diff_type'
-        call dmpar_abort(dminfo)
-      endif
-
       allocate(fluxVertTop(num_tracers,nVertLevels+1))
       fluxVertTop(:,1) = 0.0
       do iCell=1,nCellsSolve 
@@ -1213,7 +1199,7 @@
          do k=2,maxLevelCell(iCell)
            do iTracer=1,num_tracers
              ! compute \kappa_v d\phi/dz
-             fluxVertTop(iTracer,k) = vertDiffTop(k) &amp;
+             fluxVertTop(iTracer,k) = vertDiffTopOfCell(k,iCell) &amp;
                 * (tracers(iTracer,k-1,iCell) - tracers(iTracer,k,iCell) )&amp;
                 * 2 / (h(k-1,iCell) + h(k,iCell))
            enddo
@@ -1230,7 +1216,7 @@
          enddo
 
       enddo ! iCell loop
-      deallocate(fluxVertTop, vertDiffTop)
+      deallocate(fluxVertTop)
 
           ! print some diagnostics - for debugging
 !         print *, 'after vertical mixing',&amp;
@@ -1735,7 +1721,296 @@
 
    end subroutine compute_solve_diagnostics
 
+   subroutine compute_vertical_mix_coefficients(s, d, grid)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute diagnostic fields used in the tendency computations
+   !
+   ! Input: grid - grid metadata
+   !
+   ! Output: s - computed diagnostics
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+      implicit none
+
+      type (state_type), intent(inout) :: s
+      type (diagnostics_type), intent(inout) :: d
+      type (mesh_type), intent(in) :: grid
+
+      type (dm_info) :: dminfo
+
+
+! mrp clean out these after subroutine complete
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, vertex1, vertex2, eoe, i, j, cov
+      real (kind=RKIND) :: flux, vorticity_abs, h_vertex, workpv, rho0Inv
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, vertexDegree
+
+      real (kind=RKIND), dimension(:,:), allocatable:: &amp;
+        drhoTopOfCell, drhoTopOfEdge, &amp;
+        du2TopOfCell, du2TopOfEdge
+      real (kind=RKIND) :: coef
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        vertViscTopOfEdge, vertDiffTopOfCell, &amp;
+        RiTopOfEdge, RiTopOfCell, rhoDisplaced, &amp;
+        kiteAreasOnVertex, h_edge, h, u
+
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        hZLevel, zTopZLevel  
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        v, w, pressure,&amp;
+        circulation, vorticity, ke, ke_edge, MontPot, wTop, &amp;
+        pv_edge, pv_vertex, pv_cell, gradPVn, gradPVt, divergence, &amp;
+         temperature, salinity
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+      real (kind=RKIND), dimension(:), allocatable:: pTop
+      real (kind=RKIND), dimension(:,:), allocatable:: div_u
+      character :: c1*6
+
+      integer, dimension(:,:), pointer :: cellsOnEdge, cellsOnVertex, &amp;
+        verticesOnEdge, edgesOnCell, edgesOnEdge, edgesOnVertex, &amp;
+        boundaryEdge, boundaryCell
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelEdgeBot, &amp;
+        maxLevelVertexBot,  maxLevelVertexTop
+      real (kind=RKIND) :: d2fdx2_cell1, d2fdx2_cell2
+      real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
+      real (kind=RKIND) :: coef_3rd_order
+      real (kind=RKIND) :: r, h1, h2
+
+      rhoDisplaced =&gt; s % rhoDisplaced % array
+
+      vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
+      vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
+      RiTopOfEdge =&gt; d % RiTopOfEdge % array
+      RiTopOfCell =&gt; d % RiTopOfCell % array
+
+      h           =&gt; s % h % array
+      u           =&gt; s % u % array
+      v           =&gt; s % v % array
+      wTop        =&gt; s % wTop % array
+      h_edge      =&gt; s % h_edge % array
+      circulation =&gt; s % circulation % array
+      vorticity   =&gt; s % vorticity % array
+      divergence  =&gt; s % divergence % array
+      ke          =&gt; s % ke % array
+      ke_edge     =&gt; s % ke_edge % array
+      pv_edge     =&gt; s % pv_edge % array
+      pv_vertex   =&gt; s % pv_vertex % array
+      pv_cell     =&gt; s % pv_cell % array
+      gradPVn     =&gt; s % gradPVn % array
+      gradPVt     =&gt; s % gradPVt % array
+      tracers     =&gt; s % tracers % array
+      MontPot     =&gt; s % MontPot % array
+      pressure    =&gt; s % pressure % array
+
+
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+
+      kiteAreasOnVertex =&gt; grid % kiteAreasOnVertex % array
+      cellsOnEdge       =&gt; grid % cellsOnEdge % array
+      cellsOnVertex     =&gt; grid % cellsOnVertex % array
+      verticesOnEdge    =&gt; grid % verticesOnEdge % array
+      nEdgesOnCell      =&gt; grid % nEdgesOnCell % array
+      edgesOnCell       =&gt; grid % edgesOnCell % array
+      nEdgesOnEdge      =&gt; grid % nEdgesOnEdge % array
+      edgesOnEdge       =&gt; grid % edgesOnEdge % array
+      edgesOnVertex     =&gt; grid % edgesOnVertex % array
+      dcEdge            =&gt; grid % dcEdge % array
+      dvEdge            =&gt; grid % dvEdge % array
+      areaCell          =&gt; grid % areaCell % array
+      areaTriangle      =&gt; grid % areaTriangle % array
+      h_s               =&gt; grid % h_s % array
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      hZLevel           =&gt; grid % hZLevel % array
+      deriv_two         =&gt; grid % deriv_two % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop   =&gt; grid % maxLevelEdgeTop % array
+      maxLevelEdgeBot   =&gt; grid % maxLevelEdgeBot % array
+      maxLevelVertexBot =&gt; grid % maxLevelVertexBot % array
+      maxLevelVertexTop =&gt; grid % maxLevelVertexTop % array
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+      vertexDegree = grid % vertexDegree
+
+      boundaryEdge =&gt; grid % boundaryEdge % array
+      boundaryCell =&gt; grid % boundaryCell % array
+
+   !
+   !  Compute Richardson Number
+   !
+   if (config_vert_visc_type.eq.'rich'.or. &amp;
+       config_vert_diff_type.eq.'rich') then
+      allocate( &amp;
+         drhoTopOfCell(nVertLevels+1,nCells+1), drhoTopOfEdge(nVertLevels+1,nEdges+1), &amp;
+         du2TopOfCell(nVertLevels+1,nCells+1), du2TopOfEdge(nVertLevels+1,nEdges+1))
+
+      ! compute density of parcel displaced to surface, $\rho^*$,
+      ! in state % rhoDisplaced
+      call equation_of_state(s, grid, 1)
+
+      ! drhoTopOfCell(k) = $\rho^*_{k-1}-\rho^*_k$
+      drhoTopOfCell = 0.0
+      do iCell=1,nCells
+         do k=2,maxLevelCell(iCell)
+            drhoTopOfCell(k,iCell) = rhoDisplaced(k-1,iCell) - rhoDisplaced(k,iCell)
+          end do
+      end do
+
+      ! interpolate drhoTopOfCell to drhoTopOfEdge
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=2,maxLevelEdgeTop(iEdge)
+            drhoTopOfEdge(k,iEdge) = &amp;
+               (drhoTopOfCell(k,cell1) + &amp;
+                drhoTopOfCell(k,cell2))/2  
+         end do
+       end do
+
+      ! du2TopOfEdge(k) = $u_{k-1}-u_k$
+      du2TopOfEdge=0.0
+      do iEdge=1,nEdges
+         do k=2,maxLevelEdgeTop(iEdge)
+            du2TopOfEdge(k,iEdge) = (u(k-1,iEdge) - u(k,iEdge))**2
+         end do
+      end do
+
+      ! interpolate du2TopOfEdge to du2TopOfCell
+      du2TopOfCell(:,:) = 0.0
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=2,maxLevelEdgeBot(iEdge)
+            du2TopOfCell(k,cell1) = du2TopOfCell(k,cell1) &amp;
+               + 0.5 * dcEdge(iEdge) * dvEdge(iEdge) * du2TopOfEdge(k,iEdge)
+            du2TopOfCell(k,cell2) = du2TopOfCell(k,cell2) &amp;
+               + 0.5 * dcEdge(iEdge) * dvEdge(iEdge) * du2TopOfEdge(k,iEdge)
+         end do
+      end do
+      do iCell = 1,nCells
+         do k = 2,maxLevelCell(iCell)
+            du2TopOfCell(k,iCell) = du2TopOfCell(k,iCell) / areaCell(iCell)
+         end do
+      end do
+
+!test this interp
+
+      ! compute RiTopOfEdge using drhoTopOfEdge and du2TopOfEdge
+      ! coef = -g/rho_0/2
+      RiTopOfEdge = 0.0
+      coef = -gravity/1000.0/2.0
+      do iEdge = 1,nEdges
+         do k = 2,maxLevelEdgeTop(iEdge)
+            RiTopOfEdge(k,iEdge) = coef*drhoTopOfEdge(k,iEdge) &amp;
+               *(h_edge(k-1,iEdge)+h_edge(k,iEdge)) &amp;
+               / (du2TopOfEdge(k,iEdge) + 1e-20)
+         end do
+      end do
+
+      ! compute RiTopOfCell using drhoTopOfCell and du2TopOfCell
+      ! coef = -g/rho_0/2
+      RiTopOfCell = 0.0
+      coef = -gravity/1000.0/2.0
+      do iCell = 1,nCells
+         do k = 2,maxLevelCell(iCell)
+            RiTopOfCell(k,iCell) = coef*drhoTopOfCell(k,iCell) &amp;
+               *(h(k-1,iCell)+h(k,iCell)) &amp;
+               / (du2TopOfCell(k,iCell) + 1e-20)
+         end do
+      end do
+
+      
+! what about boundary update?
+
+
+      deallocate(drhoTopOfCell, drhoTopOfEdge, &amp;
+        du2TopOfCell, du2TopOfEdge)
+   endif
+
+   if (config_vert_visc_type.eq.'const') then
+
+      vertViscTopOfEdge = config_vert_viscosity
+
+   elseif (config_vert_visc_type.eq.'tanh') then
+
+      if (config_vert_grid_type.ne.'zlevel') then
+         write(0,*) 'Abort: config_vert_visc_type.eq.tanh may only', &amp;
+            ' use config_vert_grid_type of zlevel at this time'
+         call dmpar_abort(dminfo)
+      endif
+  
+      do k=1,nVertLevels+1
+          vertViscTopOfEdge(k,:) = -(config_max_visc_tanh-config_min_visc_tanh)/2.0 &amp;
+            *tanh(-(zTopZLevel(k)-config_ZMid_tanh) &amp;
+                  /config_zWidth_tanh) &amp;
+            + (config_max_visc_tanh+config_min_visc_tanh)/2
+      end do
+
+   elseif (config_vert_visc_type.eq.'rich') then
+
+      vertViscTopOfEdge = 0.0
+      do iEdge = 1,nEdges
+         do k = 2,maxLevelEdgeTop(iEdge)
+            vertViscTopOfEdge(k,iEdge) = config_bkrd_vert_visc &amp;
+               + config_rich_mix / (1.0 + 5.0*RiTopOfEdge(k,iEdge))**2
+         end do
+      end do
+
+   else
+
+      write(0,*) 'Abort: unrecognized config_vert_visc_type'
+      call dmpar_abort(dminfo)
+
+   endif
+
+   if (config_vert_diff_type.eq.'const') then
+
+      vertDiffTopOfCell = config_vert_diffusion
+
+   elseif (config_vert_diff_type.eq.'tanh') then
+
+      if (config_vert_grid_type.ne.'zlevel') then
+         write(0,*) 'Abort: config_vert_diff_type.eq.tanh may only', &amp;
+            ' use config_vert_grid_type of zlevel at this time'
+         call dmpar_abort(dminfo)
+      endif
+
+      do k=1,nVertLevels+1
+         vertDiffTopOfCell(k,:) = -(config_max_diff_tanh-config_min_diff_tanh)/2.0 &amp;
+            *tanh(-(zTopZLevel(k)-config_ZMid_tanh) &amp;
+                  /config_zWidth_tanh) &amp;
+            + (config_max_diff_tanh+config_min_diff_tanh)/2
+      end do
+
+   elseif (config_vert_diff_type.eq.'rich') then
+
+      vertDiffTopOfCell = 0.0
+      coef = -gravity/1000.0/2.0
+      do iCell = 1,nCells
+         do k = 2,maxLevelCell(iCell)
+            vertDiffTopOfCell(k,iCell) = config_bkrd_vert_diff &amp;
+               + (config_bkrd_vert_visc &amp; 
+                  + config_rich_mix / (1.0 + 5.0*RiTopOfCell(k,iCell))**2) &amp;
+               / (1.0 + 5.0*RiTopOfCell(k,iCell))**2
+         end do
+      end do
+
+   else
+
+      write(0,*) 'Abort: unrecognized config_vert_diff_type'
+      call dmpar_abort(dminfo)
+
+   endif
+
+
+   end subroutine compute_vertical_mix_coefficients
+
+
    subroutine enforce_boundaryEdge(tend, grid)
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ! Enforce any boundary conditions on the normal velocity at each edge
@@ -1779,7 +2054,7 @@
    end subroutine enforce_boundaryEdge
 
 
-   subroutine equation_of_state(s, grid,k_displaced)
+   subroutine equation_of_state(s, grid, k_displaced)
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !  This module contains routines necessary for computing the density
    !  from model temperature and salinity using an equation of state.
@@ -1787,9 +2062,9 @@
    ! Input: grid - grid metadata
    !        s - state: tracers
    !        k_displaced 
-   !  If k_displaced&lt;=0, density is returned with no displaced
-   !  If k_displaced&gt;0,the density returned is that for a parcel
-   !  adiabatically displaced from its original level to level 
+   !  If k_displaced&lt;=0, state % rho is returned with no displaced
+   !  If k_displaced&gt;0,the state % rhoDisplaced is returned, and is for
+   !  a parcel adiabatically displaced from its original level to level 
    !  k_displaced.  This does not effect the linear EOS.
    !
    ! Output: s - state: computed density
@@ -1806,14 +2081,13 @@
       integer :: nCells, iCell, k
       type (dm_info) :: dminfo
 
-      rho         =&gt; s % rho % array
-      tracers     =&gt; s % tracers % array
+      if (config_eos_type.eq.'linear') then
 
-      maxLevelCell      =&gt; grid % maxLevelCell % array
-      nCells      = grid % nCells
+         rho         =&gt; s % rho % array
+         tracers     =&gt; s % tracers % array
+         maxLevelCell      =&gt; grid % maxLevelCell % array
+         nCells      = grid % nCells
 
-      if (config_eos_type.eq.'linear') then
-
          do iCell=1,nCells
             do k=1,maxLevelCell(iCell)
                ! Linear equation of state
@@ -1874,7 +2148,7 @@
       real (kind=RKIND), dimension(:), pointer :: &amp;
         zMidZLevel, pRefEOS
       real (kind=RKIND), dimension(:,:), pointer :: &amp;
-        rho
+        rhoPointer
       real (kind=RKIND), dimension(:,:,:), pointer :: tracers
 
       integer, dimension(:), pointer :: maxLevelCell
@@ -1966,7 +2240,6 @@
       bup2s1t1 =  6.128773e-8,       &amp;
       bup2s1t2 =  6.207323e-10
 
-      rho         =&gt; s % rho % array
       tracers     =&gt; s % tracers % array
 
       nCells      = grid % nCells
@@ -2002,11 +2275,13 @@
    !  adiabatically displaced from its original level to level 
    !  k_displaced.
    if (k_displaced.le.0) then
+      rhoPointer =&gt; s % rho % array
       do k=1,nVertLevels
          p(k)   = pRefEOS(k)
          p2(k)  = p(k)*p(k)
       enddo
    elseif (k_displaced.le.nVertLevels) then
+      rhoPointer =&gt; s % rhoDisplaced % array
       do k=1,nVertLevels
          p(k)   = pRefEOS(k_displaced)
          p2(k)  = p(k)*p(k)
@@ -2058,7 +2333,7 @@
 
       DENOMK = 1.0/(BULK_MOD - p(k))
 
-      rho(k,iCell) = (unt0 + RHO_S)*BULK_MOD*DENOMK
+      rhoPointer(k,iCell) = (unt0 + RHO_S)*BULK_MOD*DENOMK
 
     end do
   end do

</font>
</pre>