<p><b>mhoffman@lanl.gov</b> 2012-06-26 13:52:13 -0600 (Tue, 26 Jun 2012)</p><p>BRANCH COMMIT -- land ice<br>
<br>
Modifications to advection that 1) don't assume that all layers move in the same direction and 2) don't assume that all layers move in the downslope direction.<br>
Also added calculation of lower ice surface for floating ice (which was previously missing).<br>
</p><hr noshade><pre><font color="gray">Modified: branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_tendency.F
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_tendency.F        2012-06-25 23:43:39 UTC (rev 2002)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_tendency.F        2012-06-26 19:52:13 UTC (rev 2003)
@@ -13,6 +13,8 @@
 !
 !-----------------------------------------------------------------------
 
+#include &quot;mpas_land_ice_mask.inc&quot;
+
 module land_ice_tendency
 
    use mpas_grid_types
@@ -342,35 +344,40 @@
       ! local variables
       !
       !-----------------------------------------------------------------
-      integer :: iCell, iLevel, nCells, nVertLevels, nVertices
+      integer :: iCell, iLevel, nCells, nVertLevels
       real (kind=RKIND), dimension(:), pointer :: thickness, upperSurface, &amp;
-        lowerSurface, bedTopography, layerThicknessFractions, thicknessEdge
-      real (kind=RKIND), dimension(:,:), pointer :: layerThickness, layerThicknessEdge
-      integer, dimension(:), pointer :: vertexMask
-      integer, dimension(:,:), pointer :: cellsOnVertex, cellsOnEdge
-      integer :: keep_vertex, i, k, iEdge, nEdges, cell1, cell2
+        lowerSurface, bedTopography, layerThicknessFractions
+      integer, dimension(:), pointer :: cellMask
+      real (kind=RKIND), dimension(:,:), pointer :: layerThickness
 
-
       nCells = mesh % nCells
-      nEdges = mesh % nEdges
-      nVertices = mesh % nVertices
       nVertLevels = mesh % nVertLevels
       layerThicknessFractions =&gt; mesh % layerThicknessFractions % array
-      cellsOnVertex =&gt; mesh % cellsOnVertex % array
-      cellsOnEdge =&gt; mesh % cellsOnEdge % array
 
       thickness =&gt; state % thickness % array
       upperSurface =&gt; state % upperSurface % array
       lowerSurface =&gt; state % lowerSurface % array
       bedTopography =&gt; state % bedTopography % array
       layerThickness =&gt; state % layerThickness % array
-      vertexMask =&gt; state % vertexMask % array
-      layerThicknessEdge =&gt; state % layerThicknessEdge % array
+      cellMask =&gt; state % cellMask % array
 
 
+      ! Calculate masks - needs to happen before calculating lower surface so we know where the ice is floating
+      call land_ice_calculate_mask(mesh, state, err)
+
       ! no ice shelves -- lower surface same as bed topography
       ! Eventually this should consider floatation!
-      lowerSurface(:) = bedTopography(:)
+      where ( MASK_IS_FLOATING(cellMask) )
+         lowerSurface = config_sealevel - thickness * (config_ice_density / config_ocean_density)
+      elsewhere
+         lowerSurface = bedTopography
+      end where
+      ! Make sure lowerSurface calculation is reasonable.  This check could be deleted once this has been throroughly tested.
+      do iCell = 1, nCells
+         if (lowerSurface(iCell) &lt; bedTopography(iCell)) then
+            write (0,*) 'lowerSurface less than bedTopography at cell:', iCell
+         endif
+      end do
 
       ! as always, upper surface is the lower surface plus the thickness
       upperSurface(:) = lowerSurface(:) + thickness(:)
@@ -382,7 +389,69 @@
          end do
       end do
 
-      ! Calculate h_edge.  This is used by both thickness and tracer advection.  
+   end subroutine land_ice_diagnostic_solve
+
+
+!***********************************************************************
+!
+!  subroutine land_ice_diagnostic_solve_using_velocity
+!
+!&gt; \brief   Computes diagnostic variables that require knowing velocity
+!&gt; \author  Matt Hoffman
+!&gt; \date    19 April 2012
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt; This routine computes the diagnostic variables that require knowing velocity for land ice
+!
+!-----------------------------------------------------------------------
+   subroutine land_ice_diagnostic_solve_using_velocity(mesh, state, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         mesh          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (state_type), intent(inout) :: &amp;
+         state         !&lt; Input/Output: state for which to update diagnostic variables
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+      real (kind=RKIND), dimension(:,:), pointer :: layerThickness, layerThicknessEdge, normalVelocity
+      integer, dimension(:,:), pointer :: cellsOnEdge
+      integer :: nVertLevels, iEdge, nEdges, cell1, cell2, k
+      real (kind=RKIND) :: VelSign
+
+      nEdges = mesh % nEdges
+      nVertLevels = mesh % nVertLevels
+      cellsOnEdge =&gt; mesh % cellsOnEdge % array
+
+      layerThickness =&gt; state % layerThickness % array
+      normalVelocity =&gt; state % normalVelocity % array
+      layerThicknessEdge =&gt; state % layerThicknessEdge % array
+
+
+      ! Calculate h_edge.  This is used by both thickness and tracer advection on the following Forward Euler time step.  
       ! Note: FO-Upwind thickness advection does not explicitly use h_edge but a FO h_edge is implied.
       ! Note: SIA velocity solver uses its own local calculation of h_edge that is always 2nd order.
       ! Note: ocn_diagnostic_solve in mpas_ocn_tendency.F has 2, 3, &amp; 4th order calculations for h_edge that can be used.  
@@ -396,7 +465,8 @@
             cell2 = cellsOnEdge(2,iEdge)
             do k=1, nVertLevels
                ! Calculate h on edges using first order
-               layerThicknessEdge(k,iEdge) = max(layerThickness(k, cell1), layerThickness(k, cell2))
+               VelSign = sign(1.0, normalVelocity(k, iEdge))
+               layerThicknessEdge(k,iEdge) = max(VelSign * layerThickness(k, cell1), VelSign * (-1.0) * layerThickness(k, cell2))  ! + velocity goes from index 1 to 2 in the cellsOnEdge array.  !  Doug does the calculation as: h_edge = max(VelSign, 0.0) * h1 - min(VelSign, 0.0) * h2
             end do
             ! thickness_edge is not currently in registry and not currenly needed.  If it is, uncomment the next line
             !h_edge = max(thickness(cell1), thickness(cell2))
@@ -406,139 +476,134 @@
           print *,'layerThicknessEdge not calculated!'
       endif
 
-      ! Calculate masks
-      call land_ice_calculate_mask(mesh, state, err)
+      ! Note: no halo update needed on layerThicknessEdge because normalVelocity has already been halo updated.
 
+   end subroutine land_ice_diagnostic_solve_using_velocity
 
-   end subroutine land_ice_diagnostic_solve
-
-
-
-
    ! private subroutines================================================
 
 
 
 
-!***********************************************************************
-!
-!  subroutine land_ice_tend_h_fo_upwind
-!
-!&gt; \brief   Computes tendency term from horizontal advection of thickness
-!&gt; \author  Matt Hoffman
-!&gt; \date    16 April 2012
-!&gt; \version SVN:$Id$
-!&gt; \details 
-!&gt;  This routine computes the horizontal advection tendency for
-!&gt;  thickness based on current state and user choices of forcings. Based on
-!&gt;  ocn_thick_hadv_tend in the ocean core.
-!
-!-----------------------------------------------------------------------
+!!***********************************************************************
+!!
+!!  subroutine land_ice_tend_h_fo_upwind
+!!
+!!&gt; \brief   Computes tendency term from horizontal advection of thickness
+!!&gt; \author  Matt Hoffman
+!!&gt; \date    16 April 2012
+!!&gt; \version SVN:$Id$
+!!&gt; \details 
+!!&gt;  This routine computes the horizontal advection tendency for
+!!&gt;  thickness based on current state and user choices of forcings. Based on
+!!&gt;  ocn_thick_hadv_tend in the ocean core.
+!!
+!!-----------------------------------------------------------------------
 
-   subroutine land_ice_tend_h_fo_upwind(grid, normalVelocity, layerThickness, thickness, thickness_tend, dt, err)!{{{
+!   subroutine land_ice_tend_h_fo_upwind(grid, normalVelocity, layerThickness, thickness, thickness_tend, dt, err)!{{{
 
-      !-----------------------------------------------------------------
-      !
-      ! input variables
-      !
-      !-----------------------------------------------------------------
+!      !-----------------------------------------------------------------
+!      !
+!      ! input variables
+!      !
+!      !-----------------------------------------------------------------
 
-      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
-         normalVelocity    !&lt; Input: velocity
+!      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+!         normalVelocity    !&lt; Input: velocity
 
-      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
-         layerThickness    !&lt; Input: thickness of each layer
+!      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+!         layerThickness    !&lt; Input: thickness of each layer
 
-      real (kind=RKIND), dimension(:), intent(in) :: &amp;
-         thickness    !&lt; Input: thickness
+!      real (kind=RKIND), dimension(:), intent(in) :: &amp;
+!         thickness    !&lt; Input: thickness
 
-      type (mesh_type), intent(in) :: &amp;
-         grid          !&lt; Input: grid information
+!      type (mesh_type), intent(in) :: &amp;
+!         grid          !&lt; Input: grid information
 
-      real (kind=RKIND) :: dt
+!      real (kind=RKIND) :: dt
 
-      !-----------------------------------------------------------------
-      !
-      ! input/output variables
-      !
-      !-----------------------------------------------------------------
+!      !-----------------------------------------------------------------
+!      !
+!      ! input/output variables
+!      !
+!      !-----------------------------------------------------------------
 
-      real (kind=RKIND), dimension(:), intent(inout) :: &amp;
-         thickness_tend        !&lt; Input/Output: thickness tendency
+!      real (kind=RKIND), dimension(:), intent(inout) :: &amp;
+!         thickness_tend        !&lt; Input/Output: thickness tendency
 
-      !-----------------------------------------------------------------
-      !
-      ! output variables
-      !
-      !-----------------------------------------------------------------
+!      !-----------------------------------------------------------------
+!      !
+!      ! output variables
+!      !
+!      !-----------------------------------------------------------------
 
-      integer, intent(out) :: err !&lt; Output: error flag
+!      integer, intent(out) :: err !&lt; Output: error flag
 
-      !-----------------------------------------------------------------
-      !
-      ! local variables
-      !
-      !-----------------------------------------------------------------
+!      !-----------------------------------------------------------------
+!      !
+!      ! local variables
+!      !
+!      !-----------------------------------------------------------------
 
-      integer :: iEdge, nEdges, cell1, cell2, nVertLevels, k, CellUpwind, CellDownwind
+!      integer :: iEdge, nEdges, cell1, cell2, nVertLevels, k, CellUpwind, CellDownwind
 
-      integer, dimension(:,:), pointer :: cellsOnEdge
+!      integer, dimension(:,:), pointer :: cellsOnEdge
 
-      real (kind=RKIND) :: flux, VelSign, h_edge, ubar, maxAllowableDt
-      real (kind=RKIND), dimension(:), pointer :: dvEdge, areaCell, dcEdge
+!      real (kind=RKIND) :: flux, VelSign, h_edge, ubar, maxAllowableDt
+!      real (kind=RKIND), dimension(:), pointer :: dvEdge, areaCell, dcEdge
 
-      err = 0
-      maxAllowableDt = 1.0e36
+!      err = 0
+!      maxAllowableDt = 1.0e36
 
-      nEdges = grid % nEdges
-      nVertLevels = grid % nVertLevels
-      cellsOnEdge =&gt; grid % cellsOnEdge % array
-      dvEdge =&gt; grid % dvEdge % array
-      dcEdge =&gt; grid % dcEdge % array
-      areaCell =&gt; grid % areaCell % array
+!      nEdges = grid % nEdges
+!      nVertLevels = grid % nVertLevels
+!      cellsOnEdge =&gt; grid % cellsOnEdge % array
+!      dvEdge =&gt; grid % dvEdge % array
+!      dcEdge =&gt; grid % dcEdge % array
+!      areaCell =&gt; grid % areaCell % array
 
-      !print *,'Max velocity magn.:', maxval(abs(normalVelocity))
+!      !print *,'Max velocity magn.:', maxval(abs(normalVelocity))
 
-      ! Zero the tendency before accumulating
-      thickness_tend = 0.0
+!      ! Zero the tendency before accumulating
+!      thickness_tend = 0.0
 
-      do iEdge=1,nEdges
-         cell1 = cellsOnEdge(1,iEdge)
-         cell2 = cellsOnEdge(2,iEdge)
+!      do iEdge=1,nEdges
+!         cell1 = cellsOnEdge(1,iEdge)
+!         cell2 = cellsOnEdge(2,iEdge)
 
-         VelSign = sign(1.0, normalVelocity(1, iEdge))
-         if (VelSign .gt. 0.0) then
-            CellUpwind = cell1
-            CellDownwind = cell2
-         else
-            CellUpwind = cell2
-            CellDownwind = cell1
-         endif
-         if (thickness(cellUpwind) .gt. 0.0) then  ! Don't calculate for non-ice cells - would result in divide by 0
-                 h_edge = thickness(CellUpwind)
-                 flux = 0.0
-                 do k=1, nVertLevels
-                    ! Calculate thickness averaged velocity  -  this make be calculated externally and passed in
-                    flux = flux + layerThickness(k, cellUpwind) * abs(normalVelocity(k, iEdge))
-                 enddo
-                 ubar = flux / thickness(cellUpwind)
-                 if ( (abs(ubar) * dt/SecondsInYear) .gt. (0.5 * dcEdge(iEdge))) then
-                      !maxAllowableDt = min(maxAllowableDt, (0.5 * dcEdge)/ubar )
-                      write(0,*) 'CFL violation at edge', iEdge
-                      err = err + 1
-                 endif
-                 thickness_tend(cellUpwind) = thickness_tend(cellUpwind) - flux * dvEdge(iEdge) / areaCell(cellUpwind)
-                 thickness_tend(cellDownwind) = thickness_tend(cellDownwind) + flux * dvEdge(iEdge) / areaCell(cellDownwind)
-         endif
-      end do
+!         VelSign = sign(1.0, normalVelocity(1, iEdge))
+!         if (VelSign .gt. 0.0) then
+!            CellUpwind = cell1
+!            CellDownwind = cell2
+!         else
+!            CellUpwind = cell2
+!            CellDownwind = cell1
+!         endif
+!         if (thickness(cellUpwind) .gt. 0.0) then  ! Don't calculate for non-ice cells - would result in divide by 0
+!                 h_edge = thickness(CellUpwind)
+!                 flux = 0.0
+!                 do k=1, nVertLevels
+!                    ! Calculate thickness averaged velocity  -  this make be calculated externally and passed in
+!                    flux = flux + layerThickness(k, cellUpwind) * abs(normalVelocity(k, iEdge))
+!                 enddo
+!                 ubar = flux / thickness(cellUpwind)
+!                 if ( (abs(ubar) * dt/SecondsInYear) .gt. (0.5 * dcEdge(iEdge))) then
+!                      !maxAllowableDt = min(maxAllowableDt, (0.5 * dcEdge)/ubar )
+!                      write(0,*) 'CFL violation at edge', iEdge
+!                      err = err + 1
+!                 endif
+!                 thickness_tend(cellUpwind) = thickness_tend(cellUpwind) - flux * dvEdge(iEdge) / areaCell(cellUpwind)
+!                 thickness_tend(cellDownwind) = thickness_tend(cellDownwind) + flux * dvEdge(iEdge) / areaCell(cellDownwind)
+!         endif
+!      end do
 
-      if (err .gt. 0) then
-         write(6,*) 'CFL violation at ', err, ' edges!  Maximum time step should be ', maxAllowableDt
-         err = 1
-      endif
-   !--------------------------------------------------------------------
+!      if (err .gt. 0) then
+!         write(6,*) 'CFL violation at ', err, ' edges!  Maximum time step should be ', maxAllowableDt
+!         err = 1
+!      endif
+!   !--------------------------------------------------------------------
 
-   end subroutine land_ice_tend_h_fo_upwind !}}}
+!   end subroutine land_ice_tend_h_fo_upwind !}}}
 
 
 
@@ -606,7 +671,7 @@
 
       integer, dimension(:,:), pointer :: cellsOnEdge
 
-      real (kind=RKIND) :: flux, VelSign, maxAllowableDt
+      real (kind=RKIND) :: flux, VelSign, maxAllowableDt, VelSignSum
       real (kind=RKIND), dimension(:), pointer :: dvEdge, areaCell, dcEdge
 
       err = 0
@@ -623,16 +688,20 @@
       do iEdge=1,nEdges
          cell1 = cellsOnEdge(1,iEdge)
          cell2 = cellsOnEdge(2,iEdge)
-         VelSign = sign(1.0, normalVelocity(1, iEdge))
-         if (VelSign .gt. 0.0) then
-            CellUpwind = cell1
-            CellDownwind = cell2
-         else
-            CellUpwind = cell2
-            CellDownwind = cell1
-         endif
-         if (layerThickness(1,cellUpwind) .gt. 0.0) then  ! Don't calculate for non-ice cells - would result in divide by 0 (just need to check one layer)
+         if ( (layerThickness(1,cell1) .gt. 0.0) .or. (layerThickness(1,cell2) .gt. 0.0) ) then  ! Don't calculate for non-ice cells - would result in divide by 0 (just need to check one layer)  \todo: this should use the edgeMask and use the dynamic thickness limit
+
+            VelSignSum = 0.0
             do k=1, nVertLevels
+               ! Don't assume all layers are flowing the same direction, so determine the upwind direction separately for each layer
+               VelSign = sign(1.0, normalVelocity(k, iEdge))
+               VelSignSum = VelSignSum + VelSign
+               if (VelSign .gt. 0.0) then
+                  CellUpwind = cell1
+                  CellDownwind = cell2
+               else
+                  CellUpwind = cell2
+                  CellDownwind = cell1
+               endif
                maxAllowableDt = (0.5 * dcEdge(iEdge)) / (abs(normalVelocity(k, iEdge)) + 1.0e-36) ! in years 
                if ( (dt/SecondsInYear) .gt. maxAllowableDt ) then
                     !write(0,*) 'CFL violation at level, edge', k, iEdge                      
@@ -644,6 +713,10 @@
                tend(k,cell1) = tend(k,cell1) - flux / areaCell(cell1)
                tend(k,cell2) = tend(k,cell2) + flux / areaCell(cell2)
             end do
+            ! Sanity check on ice motion:
+            if (abs(VelSignSum) .ne. nVertLevels) then
+               write (6,*) 'Unusual occurrence: Not all layers are moving the same direction on edge ', iEdge
+            endif
          end if
       end do
 

Modified: branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_time_integration_forwardeuler.F
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_time_integration_forwardeuler.F        2012-06-25 23:43:39 UTC (rev 2002)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_time_integration_forwardeuler.F        2012-06-26 19:52:13 UTC (rev 2003)
@@ -20,6 +20,7 @@
    use mpas_constants
    use mpas_dmpar
    use mpas_timer
+   use mpas_vector_reconstruction
    use land_ice_vel, only: land_ice_vel_solve
    use land_ice_tendency
 
@@ -197,7 +198,7 @@
             thicknessNew = 0.0
          end where
          if (sum(mask) .gt. 0) then
-                 print *,'  Cells with negative thickness (set to 0):',sum(mask)
+            print *,'  Cells with negative thickness (set to 0):',sum(mask)
          endif
 
          mask = 0
@@ -271,16 +272,34 @@
          ! Compute the diagnostic velocity for this time step using the updated (new) state
          ! Pass in the old velocity to be used as an initial guess for velocity solvers that need one.
          normalVelocityNew = normalVelocityOld 
-         call land_ice_vel_solve(mesh, stateNew, err)
+         call land_ice_vel_solve(mesh, stateNew, err)    ! ****** Calculate Velocity ******
          ! update halos on velocity
          call mpas_dmpar_exch_halo_field2d_real(dminfo, normalVelocityNew, &amp;
                                             nVertLevels, mesh % nEdges, &amp;
                                             block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
 
+         ! Calculate reconstructed velocities for this time step - do this after velocity halo update in case velocities on the 1-halo edge are wrong (depends on velocity solver)
+         call mpas_reconstruct(mesh, stateNew % normalVelocity % array,&amp;
+                       stateNew % uReconstructX % array,            &amp;
+                       stateNew % uReconstructY % array,            &amp;
+                       stateNew % uReconstructZ % array,            &amp;
+                       stateNew % uReconstructZonal % array,        &amp;
+                       stateNew % uReconstructMeridional % array    &amp;
+                      )
+
          block =&gt; block % next
       end do
       call mpas_timer_stop(&quot;velocity solve&quot;)
 
+
+      call mpas_timer_start(&quot;calc. diagnostic vars except vel&quot;)
+      block =&gt; domain % blocklist
+      do while (associated(block))
+         call land_ice_diagnostic_solve(mesh, stateNew, err)  ! Some diagnostic variables require velocity to compute
+         block =&gt; block % next
+      end do
+      call mpas_timer_stop(&quot;calc. diagnostic vars except vel&quot;)
+
 ! === Cleanup &amp; Misc. =============================
 
 

Modified: branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_vel.F
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_vel.F        2012-06-25 23:43:39 UTC (rev 2002)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_vel.F        2012-06-26 19:52:13 UTC (rev 2003)
@@ -254,7 +254,6 @@
    subroutine land_ice_vel_solve(mesh, state, err)
 
       use land_ice_SIA
-      use mpas_vector_reconstruction
 
       !-----------------------------------------------------------------
       !
@@ -305,14 +304,6 @@
           return
       end select
 
-      ! Calculate reconstructed velocities for this time step 
-      call mpas_reconstruct(mesh, state % normalVelocity % array,&amp;
-                       state % uReconstructX % array,            &amp;
-                       state % uReconstructY % array,            &amp;
-                       state % uReconstructZ % array,            &amp;
-                       state % uReconstructZonal % array,        &amp;
-                       state % uReconstructMeridional % array    &amp;
-                      )
 
    !--------------------------------------------------------------------
 

</font>
</pre>