<p><b>dwj07@fsu.edu</b> 2011-09-30 12:04:47 -0600 (Fri, 30 Sep 2011)</p><p><br>
        Commiting re-org of mpas-ocean to trunk/mpas/src/core-ocean.<br>
<br>
        This includes separating module_time_integration.F out into individual modules.<br>
<br>
        Doxygen comments were added to most modules, to allow for auto-generation of documentation of core_ocean.<br>
<br>
        This also includes a change to the new naming scheme for files.<br>
<br>
        The branch this was based on included a split_explicit time stepping method writtin by Mark Peterson, which is now included in this commit.<br>
</p><hr noshade><pre><font color="gray">Modified: trunk/mpas/namelist.input.ocean
===================================================================
--- trunk/mpas/namelist.input.ocean        2011-09-30 17:04:51 UTC (rev 1045)
+++ trunk/mpas/namelist.input.ocean        2011-09-30 18:04:47 UTC (rev 1046)
@@ -1,34 +1,53 @@
 &amp;sw_model
    config_test_case = 0
-   config_time_integration = 'RK4'
-   config_dt = 90.0
+   config_time_integration = 'rk4'
+   config_rk_filter_btr_mode = .false.
+   config_dt = 10.0
    config_start_time = '0000-01-01_00:00:00'
    config_run_duration = '2000_00:00:00'
    config_stats_interval = 1920
 /
-
 &amp;io
    config_input_name = 'grid.nc'
    config_output_name = 'output.nc'
    config_restart_name = 'restart.nc'
    config_output_interval = '20_00:00:00'
-   config_frames_per_outfile = 0
+   config_frames_per_outfile = 1000000
 /
-
 &amp;restart
    config_do_restart = .false.
    config_restart_interval = '120_00:00:00'
 /
-
 &amp;grid
    config_vert_grid_type = 'zlevel'
    config_rho0 = 1000
 /
+&amp;split_explicit_ts
+   config_n_ts_iter  =  2 
+   config_n_bcl_iter_beg =  1
+   config_n_bcl_iter_mid =  2
+   config_n_bcl_iter_end =  2
+   config_n_btr_subcycles = 10
+   config_n_btr_cor_iter = 2
+   config_compute_tr_midstage = .true.
+   config_u_correction = .true.
+   config_filter_btr_mode = .false.
+   config_btr_mom_decay  = .false.
+   config_btr_mom_decay_time =   3600.0
+   config_btr_flux_coef = 1.0
+   config_btr_mom_eddy_visc2 =   0.0
+   config_btr_subcycle_loop_factor =  2
+   config_SSH_from =  'avg_flux'
+   config_new_btr_variables_from = 'btr_avg'
+/
 &amp;hmix
    config_h_mom_eddy_visc2 = 1.0e5
    config_h_mom_eddy_visc4 = 0.0
+   config_visc_vorticity_term = .true.
    config_h_tracer_eddy_diff2 = 1.0e4
    config_h_tracer_eddy_diff4 = 0.0
+   config_mom_decay      = .false.
+   config_mom_decay_time = 3600.0
 /
 &amp;vmix
    config_vert_visc_type  = 'rich'
@@ -36,6 +55,7 @@
    config_implicit_vertical_mix = .true.
    config_convective_visc       = 1.0
    config_convective_diff       = 1.0
+   config_bottom_drag_coeff     = 1.0e-3
 /
 &amp;vmix_const
    config_vert_visc       = 2.5e-5
@@ -58,15 +78,15 @@
    config_eos_type = 'jm'
 /
 &amp;advection
-   config_vert_tracer_adv = 'spline'
-   config_vert_tracer_adv_order = 3
+   config_vert_tracer_adv = 'stencil'
+   config_vert_tracer_adv_order = 2
    config_tracer_adv_order = 2
    config_thickness_adv_order = 2
    config_positive_definite = .false.
    config_monotonic = .false.
 /
 &amp;restore
-config_restoreTS = .false.
-config_restoreT_timescale = 90.0
-config_restoreS_timescale = 90.0
+   config_restoreTS = .false.
+   config_restoreT_timescale = 90.0
+   config_restoreS_timescale = 90.0
 /

Modified: trunk/mpas/src/core_ocean/Makefile
===================================================================
--- trunk/mpas/src/core_ocean/Makefile        2011-09-30 17:04:51 UTC (rev 1045)
+++ trunk/mpas/src/core_ocean/Makefile        2011-09-30 18:04:47 UTC (rev 1046)
@@ -1,26 +1,179 @@
 .SUFFIXES: .F .o
 
-OBJS = module_mpas_core.o \
-       module_test_cases.o \
-       module_advection.o \
-       module_time_integration.o \
-       module_global_diagnostics.o
+OBJS = mpas_ocn_mpas_core.o \
+       mpas_ocn_test_cases.o \
+       mpas_ocn_advection.o \
+           mpas_ocn_thick_hadv.o \
+           mpas_ocn_thick_vadv.o \
+           mpas_ocn_vel_coriolis.o \
+           mpas_ocn_vel_vadv.o \
+           mpas_ocn_vel_hmix.o \
+           mpas_ocn_vel_hmix_del2.o \
+           mpas_ocn_vel_hmix_del4.o \
+           mpas_ocn_vel_forcing.o \
+           mpas_ocn_vel_forcing_windstress.o \
+           mpas_ocn_vel_forcing_bottomdrag.o \
+           mpas_ocn_vel_pressure_grad.o \
+           mpas_ocn_tracer_vadv.o \
+           mpas_ocn_tracer_vadv_spline.o \
+           mpas_ocn_tracer_vadv_spline2.o \
+           mpas_ocn_tracer_vadv_spline3.o \
+           mpas_ocn_tracer_vadv_stencil.o \
+           mpas_ocn_tracer_vadv_stencil2.o \
+           mpas_ocn_tracer_vadv_stencil3.o \
+           mpas_ocn_tracer_vadv_stencil4.o \
+           mpas_ocn_tracer_hadv.o \
+           mpas_ocn_tracer_hadv2.o \
+           mpas_ocn_tracer_hadv3.o \
+           mpas_ocn_tracer_hadv4.o \
+           mpas_ocn_tracer_hmix.o \
+           mpas_ocn_tracer_hmix_del2.o \
+           mpas_ocn_tracer_hmix_del4.o \
+           mpas_ocn_vmix.o \
+           mpas_ocn_vmix_coefs_const.o \
+           mpas_ocn_vmix_coefs_rich.o \
+           mpas_ocn_vmix_coefs_tanh.o \
+           mpas_ocn_restoring.o \
+           mpas_ocn_tendency.o \
+       mpas_ocn_time_integration.o \
+       mpas_ocn_time_integration_rk4.o \
+       mpas_ocn_time_integration_split.o \
+           mpas_ocn_equation_of_state.o \
+           mpas_ocn_equation_of_state_jm.o \
+           mpas_ocn_equation_of_state_linear.o \
+       mpas_ocn_global_diagnostics.o
 
+
 all: core_hyd
 
 core_hyd: $(OBJS)
         ar -ru libdycore.a $(OBJS)
 
-module_test_cases.o:
+mpas_ocn_test_cases.o:
 
-module_advection.o:
+mpas_ocn_advection.o:
 
-module_time_integration.o: 
+mpas_ocn_time_integration.o: mpas_ocn_time_integration_rk4.o mpas_ocn_time_integration_split.o
 
-module_global_diagnostics.o: 
+mpas_ocn_time_integration_rk4.o:
 
-module_mpas_core.o: module_advection.o module_global_diagnostics.o module_test_cases.o module_time_integration.o
+mpas_ocn_time_integration_split.o:
 
+mpas_ocn_tendency.o:
+
+mpas_ocn_global_diagnostics.o: 
+
+mpas_ocn_thick_hadv.o:
+
+mpas_ocn_thick_vadv.o:
+
+mpas_ocn_vel_pressure_grad.o:
+
+mpas_ocn_vel_vadv.o:
+
+mpas_ocn_vel_hmix.o: mpas_ocn_vel_hmix_del2.o mpas_ocn_vel_hmix_del4.o
+
+mpas_ocn_vel_hmix_del2.o:
+
+mpas_ocn_vel_hmix_del4.o:
+
+mpas_ocn_vel_forcing.o: mpas_ocn_vel_forcing_windstress.o mpas_ocn_vel_forcing_bottomdrag.o
+
+mpas_ocn_vel_forcing_windstress.o:
+
+mpas_ocn_velforcing_bottomdrag.o:
+
+mpas_ocn_vel_coriolis.o:
+
+mpas_ocn_tracer_hadv.o:  mpas_ocn_tracer_hadv2.o  mpas_ocn_tracer_hadv3.o  mpas_ocn_tracer_hadv4.o
+
+mpas_ocn_tracer_hadv2.o:
+
+mpas_ocn_tracer_hadv3.o:
+
+mpas_ocn_tracer_hadv4.o:
+
+mpas_ocn_tracer_vadv.o: mpas_ocn_tracer_vadv_spline.o mpas_ocn_tracer_vadv_stencil.o
+
+mpas_ocn_tracer_vadv_spline.o: mpas_ocn_tracer_vadv_spline2.o  mpas_ocn_tracer_vadv_spline3.o
+
+mpas_ocn_tracer_vadv_spline2.o:
+
+mpas_ocn_tracer_vadv_spline3.o:
+
+mpas_ocn_tracer_vadv_stencil.o: mpas_ocn_tracer_vadv_stencil2.o mpas_ocn_tracer_vadv_stencil3.o  mpas_ocn_tracer_vadv_stencil4.o 
+
+mpas_ocn_tracer_vadv_stencil2.o:
+
+mpas_ocn_tracer_vadv_stencil3.o:
+
+mpas_ocn_tracer_vadv_stencil4.o:
+
+mpas_ocn_tracer_hmix.o: mpas_ocn_tracer_hmix_del2.o mpas_ocn_tracer_hmix_del4.o
+
+mpas_ocn_tracer_hmix_del2.o:
+
+mpas_ocn_tracer_hmix_del4.o:
+
+mpas_ocn_restoring.o:
+
+mpas_ocn_vmix.o: mpas_ocn_vmix_coefs_const.o mpas_ocn_vmix_coefs_rich.o mpas_ocn_vmix_coefs_tanh.o
+
+mpas_ocn_vmix_coefs_const.o:
+
+mpas_ocn_vmix_coefs_rich.o: mpas_ocn_equation_of_state.o
+
+mpas_ocn_vmix_coefs_tanh.o:
+
+mpas_ocn_equation_of_state.o: mpas_ocn_equation_of_state_jm.o mpas_ocn_equation_of_state_linear.o
+
+mpas_ocn_equation_of_state_jm.o:
+
+mpas_ocn_equation_of_state_linear.o:
+
+mpas_ocn_mpas_core.o: mpas_ocn_mpas_core.o \
+                                  mpas_ocn_test_cases.o \
+                                          mpas_ocn_advection.o \
+                                          mpas_ocn_thick_hadv.o \
+                                          mpas_ocn_thick_vadv.o \
+                                          mpas_ocn_vel_coriolis.o \
+                                          mpas_ocn_vel_vadv.o \
+                                          mpas_ocn_vel_hmix.o \
+                                          mpas_ocn_vel_hmix_del2.o \
+                                          mpas_ocn_vel_hmix_del4.o \
+                                          mpas_ocn_vel_forcing.o \
+                                          mpas_ocn_vel_forcing_windstress.o \
+                                          mpas_ocn_vel_forcing_bottomdrag.o \
+                                          mpas_ocn_vel_pressure_grad.o \
+                                          mpas_ocn_tracer_vadv.o \
+                                          mpas_ocn_tracer_vadv_spline.o \
+                                          mpas_ocn_tracer_vadv_spline2.o \
+                                          mpas_ocn_tracer_vadv_spline3.o \
+                                          mpas_ocn_tracer_vadv_stencil.o \
+                                          mpas_ocn_tracer_vadv_stencil2.o \
+                                          mpas_ocn_tracer_vadv_stencil3.o \
+                                          mpas_ocn_tracer_vadv_stencil4.o \
+                                          mpas_ocn_tracer_hadv.o \
+                                          mpas_ocn_tracer_hadv2.o \
+                                          mpas_ocn_tracer_hadv3.o \
+                                          mpas_ocn_tracer_hadv4.o \
+                                          mpas_ocn_tracer_hmix.o \
+                                          mpas_ocn_tracer_hmix_del2.o \
+                                          mpas_ocn_tracer_hmix_del4.o \
+                                          mpas_ocn_vmix.o \
+                                          mpas_ocn_vmix_coefs_const.o \
+                                          mpas_ocn_vmix_coefs_rich.o \
+                                          mpas_ocn_vmix_coefs_tanh.o \
+                                          mpas_ocn_restoring.o \
+                                          mpas_ocn_tendency.o \
+                                          mpas_ocn_time_integration.o \
+                                          mpas_ocn_time_integration_rk4.o \
+                                          mpas_ocn_time_integration_split.o \
+                                          mpas_ocn_equation_of_state.o \
+                                          mpas_ocn_equation_of_state_jm.o \
+                                          mpas_ocn_equation_of_state_linear.o \
+                                          mpas_ocn_global_diagnostics.o
+
 clean:
         $(RM) *.o *.mod *.f90 libdycore.a
 

Modified: trunk/mpas/src/core_ocean/Registry
===================================================================
--- trunk/mpas/src/core_ocean/Registry        2011-09-30 17:04:51 UTC (rev 1045)
+++ trunk/mpas/src/core_ocean/Registry        2011-09-30 18:04:47 UTC (rev 1046)
@@ -3,6 +3,7 @@
 #
 namelist integer   sw_model config_test_case           5
 namelist character sw_model config_time_integration    RK4
+namelist logical   sw_model config_rk_filter_btr_mode  false
 namelist real      sw_model config_dt                  172.8
 namelist integer   sw_model config_calendar_type       MPAS_360DAY
 namelist character sw_model config_start_time          0000-01-01_00:00:00
@@ -19,11 +20,31 @@
 namelist character restart  config_restart_interval    none
 namelist character grid     config_vert_grid_type      isopycnal
 namelist real      grid     config_rho0                1028
+namelist integer   split_explicit_ts config_n_ts_iter     2
+namelist integer   split_explicit_ts config_n_bcl_iter_beg   4
+namelist integer   split_explicit_ts config_n_bcl_iter_mid   4
+namelist integer   split_explicit_ts config_n_bcl_iter_end   4
+namelist integer   split_explicit_ts config_n_btr_subcycles  10
+namelist integer   split_explicit_ts config_n_btr_cor_iter  1
+namelist logical   split_explicit_ts config_compute_tr_midstage true
+namelist logical   split_explicit_ts config_u_correction true
+namelist logical   split_explicit_ts config_filter_btr_mode false
+namelist logical   split_explicit_ts config_btr_mom_decay         false 
+namelist real      split_explicit_ts config_btr_mom_decay_time    3600.0
+namelist real      split_explicit_ts config_btr_flux_coef         1.0
+namelist real      split_explicit_ts config_btr_mom_eddy_visc2    0.0
+namelist integer   split_explicit_ts config_btr_subcycle_loop_factor  2
+namelist character split_explicit_ts config_SSH_from  avg_flux
+namelist character split_explicit_ts config_new_btr_variables_from  btr_avg
+namelist logical   sw_model config_h_ScaleWithMesh     false
 namelist real      hmix     config_h_mom_eddy_visc2     0.0
 namelist real      hmix     config_h_mom_eddy_visc4     0.0
+namelist logical   hmix     config_visc_vorticity_term true
 namelist real      hmix     config_h_tracer_eddy_diff2  0.0
 namelist real      hmix     config_h_tracer_eddy_diff4  0.0
 namelist real      hmix     config_apvm_upwinding       0.5
+namelist logical   hmix     config_mom_decay            false 
+namelist real      hmix     config_mom_decay_time       3600.0
 namelist character vmix     config_vert_visc_type       const
 namelist character vmix     config_vert_diff_type       const
 namelist logical   vmix     config_implicit_vertical_mix  .true.
@@ -94,6 +115,10 @@
 var persistent real    zVertex ( nVertices ) 0 iro zVertex mesh - -
 var persistent integer indexToVertexID ( nVertices ) 0 iro indexToVertexID mesh - -
 
+var persistent real    meshDensity ( nCells ) 0 iro meshDensity mesh - -
+var persistent real    meshScalingDel2 ( nEdges ) 0 ro meshScalingDel2 mesh - -
+var persistent real    meshScalingDel4 ( nEdges ) 0 ro meshScalingDel4 mesh - -
+
 var persistent integer cellsOnEdge ( TWO nEdges ) 0 iro cellsOnEdge mesh - -
 var persistent integer nEdgesOnCell ( nCells ) 0 iro nEdgesOnCell mesh - -
 var persistent integer nEdgesOnEdge ( nEdges ) 0 iro nEdgesOnEdge mesh - -
@@ -152,30 +177,44 @@
 var persistent integer boundaryEdge ( nVertLevels nEdges ) 0 iro boundaryEdge mesh - -
 var persistent integer boundaryVertex ( nVertLevels nVertices ) 0 iro boundaryVertex mesh - -
 var persistent integer boundaryCell ( nVertLevels nCells ) 0 iro boundaryCell mesh - -
-var persistent real    u_src ( nVertLevels nEdges ) 0 iro u_src mesh - -
-var persistent real    temperatureRestore ( nCells ) 0 iro temperatureRestore mesh - -
-var persistent real    salinityRestore ( nCells ) 0 iro salinityRestore mesh - -
+var persistent real    u_src ( nVertLevels nEdges ) 0 ir u_src mesh - -
+var persistent real    temperatureRestore ( nCells ) 0 ir temperatureRestore mesh - -
+var persistent real    salinityRestore ( nCells ) 0 ir salinityRestore mesh - -
 
 # Prognostic variables: read from input, saved in restart, and written to output
-var persistent real    u ( nVertLevels nEdges Time ) 2 iro u state - -
-var persistent real    h ( nVertLevels nCells Time ) 2 iro h state - -
-var persistent real    rho ( nVertLevels nCells Time ) 2 iro rho state - -
+var persistent real    u ( nVertLevels nEdges Time ) 2 ir u state - -
+var persistent real    h ( nVertLevels nCells Time ) 2 ir h state - -
+var persistent real    rho ( nVertLevels nCells Time ) 2 ir rho state - -
 var persistent real    temperature ( nVertLevels nCells Time ) 2 iro temperature state tracers dynamics
-var persistent real    salinity ( nVertLevels nCells Time ) 2 iro salinity state tracers dynamics
-var persistent real    tracer1 ( nVertLevels nCells Time ) 2 iro tracer1 state tracers testing
-var persistent real    tracer2 ( nVertLevels nCells Time ) 2 iro tracer2 state tracers testing
+var persistent real    salinity ( nVertLevels nCells Time ) 2 ir salinity state tracers dynamics
+var persistent real    tracer1 ( nVertLevels nCells Time ) 2 ir tracer1 state tracers testing
+var persistent real    tracer2 ( nVertLevels nCells Time ) 2 ir tracer2 state tracers testing
 
 # Tendency variables: neither read nor written to any files
 var persistent real    tend_u ( nVertLevels nEdges Time ) 1 - u tend - -
 var persistent real    tend_h ( nVertLevels nCells Time ) 1 - h tend - -
+var persistent real    tend_ssh ( nCells Time ) 1 - ssh tend - -
 var persistent real    tend_temperature ( nVertLevels nCells Time ) 1 - temperature tend tracers dynamics
 var persistent real    tend_salinity ( nVertLevels nCells Time ) 1 - salinity tend tracers dynamics
 var persistent real    tend_tracer1 ( nVertLevels nCells Time ) 1 - tracer1 tend tracers testing
 var persistent real    tend_tracer2 ( nVertLevels nCells Time ) 1 - tracer2 tend tracers testing
 
+# state variables for Split Explicit timesplitting
+var persistent real   uBtr ( nEdges Time )         2 -  uBtr state - -
+var persistent real   ssh ( nCells Time )          2 o  ssh state - - 
+var persistent real   uBtrSubcycle ( nEdges Time ) 2 -  uBtrSubcycle state - -
+var persistent real   sshSubcycle ( nCells Time )  2 -  sshSubcycle state - - 
+var persistent real   FBtr ( nEdges Time )         1 -  FBtr state - - 
+var persistent real   GBtrForcing ( nEdges Time )  1 -  GBtrForcing state - -
+var persistent real   uBcl ( nVertLevels nEdges Time )  2 - uBcl state - - 
+var persistent real   circulationBtr ( nVertices Time ) 1 - circulationBtr state - -
+var persistent real   divergenceBtr ( nCells Time ) 1 - divergenceBtr state - -
+var persistent real   vorticityBtr ( nVertices Time ) 1 - vorticityBtr state - -
+var persistent real   u_diffusionBtr ( nEdges Time ) 1 - u_diffusionBtr state - -
+
 # Diagnostic fields: only written to output
 var persistent real    v ( nVertLevels nEdges Time ) 2 - v state - -
-var persistent real    divergence ( nVertLevels nCells Time ) 2 o divergence state - -
+var persistent real    divergence ( nVertLevels nCells Time ) 2 - divergence state - -
 var persistent real    vorticity ( nVertLevels nVertices Time ) 2 - vorticity state - -
 var persistent real    pv_edge ( nVertLevels nEdges Time ) 2 - pv_edge state - -
 var persistent real    h_edge ( nVertLevels nEdges Time ) 2 - h_edge state - -
@@ -183,16 +222,16 @@
 var persistent real    ke ( nVertLevels nCells Time ) 2 o ke state - -
 var persistent real    ke_edge ( nVertLevels nEdges Time ) 2 - ke_edge state - -
 var persistent real    pv_vertex ( nVertLevels nVertices Time ) 2 - pv_vertex state - -
-var persistent real    pv_cell ( nVertLevels nCells Time ) 2 o pv_cell state - -
-var persistent real    uReconstructX ( nVertLevels nCells Time ) 2 o uReconstructX state - -
-var persistent real    uReconstructY ( nVertLevels nCells Time ) 2 o uReconstructY state - -
-var persistent real    uReconstructZ ( nVertLevels nCells Time ) 2 o uReconstructZ state - -
-var persistent real    uReconstructZonal ( nVertLevels nCells Time ) 2 o uReconstructZonal state - -
-var persistent real    uReconstructMeridional ( nVertLevels nCells Time ) 2 o uReconstructMeridional state - -
-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 - -
+var persistent real    pv_cell ( nVertLevels nCells Time ) 2 - pv_cell state - -
+var persistent real    uReconstructX ( nVertLevels nCells Time ) 2 - uReconstructX state - -
+var persistent real    uReconstructY ( nVertLevels nCells Time ) 2 - uReconstructY state - -
+var persistent real    uReconstructZ ( nVertLevels nCells Time ) 2 - uReconstructZ state - -
+var persistent real    uReconstructZonal ( nVertLevels nCells Time ) 2 - uReconstructZonal state - -
+var persistent real    uReconstructMeridional ( nVertLevels nCells Time ) 2 - uReconstructMeridional state - -
+var persistent real    MontPot ( nVertLevels nCells Time ) 2 - MontPot state - -
+var persistent real    pressure ( nVertLevels nCells Time ) 2 - pressure state - -
+var persistent real    wTop ( nVertLevelsP1 nCells Time ) 2 - wTop state - -
+var persistent real    rhoDisplaced ( nVertLevels nCells Time ) 2 - rhoDisplaced state - -
 
 # Other diagnostic variables: neither read nor written to any files
 var persistent real    vh ( nVertLevels nEdges Time ) 2 - vh state - -
@@ -210,9 +249,7 @@
 var persistent real    CFLNumberGlobal ( Time ) 2 o CFLNumberGlobal state - -
 
 # Diagnostics fields, only one time level required
-var persistent real    RiTopOfCell ( nVertLevelsP1 nCells Time ) 1 o RiTopOfCell diagnostics - -
-var persistent real    RiTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 o RiTopOfEdge diagnostics - -
-var persistent real    vertViscTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 o vertViscTopOfEdge diagnostics - -
-var persistent real    vertDiffTopOfCell ( nVertLevelsP1 nCells Time ) 1 o vertDiffTopOfCell diagnostics - -
-
-
+var persistent real    RiTopOfCell ( nVertLevelsP1 nCells Time ) 1 - RiTopOfCell diagnostics - -
+var persistent real    RiTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 - RiTopOfEdge diagnostics - -
+var persistent real    vertViscTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 - vertViscTopOfEdge diagnostics - -
+var persistent real    vertDiffTopOfCell ( nVertLevelsP1 nCells Time ) 1 - vertDiffTopOfCell diagnostics - -

Copied: trunk/mpas/src/core_ocean/mpas_ocn_advection.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_advection.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_advection.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_advection.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,934 @@
+module advection
+
+   use grid_types
+   use configure
+   use constants
+
+
+   contains
+
+
+   subroutine initialize_advection_rk( grid )
+                                      
+!
+! compute the cell coefficients for the polynomial fit.
+! this is performed during setup for model integration.
+! WCS, 31 August 2009
+!
+      implicit none
+
+      type (mesh_type), intent(in) :: grid
+
+      real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
+      integer, dimension(:,:), pointer :: advCells
+
+!  local variables
+
+      real (kind=RKIND), dimension(2, grid % nEdges) :: thetae
+      real (kind=RKIND), dimension(grid % nEdges) :: xe, ye
+      real (kind=RKIND), dimension(grid % nCells) :: theta_abs
+
+      real (kind=RKIND), dimension(25) :: xc, yc, zc ! cell center coordinates
+      real (kind=RKIND), dimension(25) :: thetav, thetat, dl_sphere
+      real (kind=RKIND) :: xm, ym, zm, dl, xec, yec, zec
+      real (kind=RKIND) :: thetae_tmp, xe_tmp, ye_tmp
+      real (kind=RKIND) :: xv1, xv2, yv1, yv2, zv1, zv2
+      integer :: i, j, k, ip1, ip2, m, n, ip1a, ii
+      integer :: iCell, iEdge
+      real (kind=RKIND) :: pii
+      real (kind=RKIND) :: x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5
+      real (kind=RKIND) :: pdx1, pdx2, pdx3, pdy1, pdy2, pdy3, dx1, dx2, dy1, dy2
+      real (kind=RKIND) :: angv1, angv2, dl1, dl2
+      real (kind=RKIND), dimension(25) :: dxe, dye, x2v, y2v, xp, yp
+      
+      real (kind=RKIND) :: amatrix(25,25), bmatrix(25,25), wmatrix(25,25)
+      real (kind=RKIND) :: length_scale
+      integer :: ma,na, cell_add, mw, nn
+      integer, dimension(25) :: cell_list
+
+
+      integer :: cell1, cell2
+      integer, parameter :: polynomial_order = 2
+!      logical, parameter :: debug = .true.
+      logical, parameter :: debug = .false.
+!      logical, parameter :: least_squares = .false.
+      logical, parameter :: least_squares = .true.
+      logical :: add_the_cell, do_the_cell
+
+      logical, parameter :: reset_poly = .true.
+
+      real (kind=RKIND) :: rcell, cos2t, costsint, sin2t
+      real (kind=RKIND), dimension(grid%maxEdges) :: angle_2d
+
+!---
+
+      pii = 2.*asin(1.0)
+
+      advCells =&gt; grid % advCells % array
+      deriv_two =&gt; grid % deriv_two % array
+      deriv_two(:,:,:) = 0.
+
+      do iCell = 1, grid % nCells !  is this correct? - we need first halo cell also...
+
+         cell_list(1) = iCell
+         do i=2, grid % nEdgesOnCell % array(iCell)+1
+            cell_list(i) = grid % CellsOnCell % array(i-1,iCell)
+         end do
+         n = grid % nEdgesOnCell % array(iCell) + 1
+
+         if ( polynomial_order &gt; 2 ) then
+            do i=2,grid % nEdgesOnCell % array(iCell) + 1
+               do j=1,grid % nEdgesOnCell % array ( cell_list(i) )
+                  cell_add = grid % CellsOnCell % array (j,cell_list(i))
+                  add_the_cell = .true.
+                  do k=1,n
+                     if ( cell_add == cell_list(k) ) add_the_cell = .false.
+                  end do
+                  if (add_the_cell) then
+                     n = n+1
+                     cell_list(n) = cell_add
+                  end if
+               end do
+            end do
+         end if

+         advCells(1,iCell) = n
+
+!  check to see if we are reaching outside the halo
+
+         do_the_cell = .true.
+         do i=1,n
+            if (cell_list(i) &gt; grid % nCells) do_the_cell = .false.
+         end do
+
+
+         if ( .not. do_the_cell ) cycle
+
+
+!  compute poynomial fit for this cell if all needed neighbors exist
+         if ( grid % on_a_sphere ) then
+
+            do i=1,n
+               advCells(i+1,iCell) = cell_list(i)
+               xc(i) = grid % xCell % array(advCells(i+1,iCell))/a
+               yc(i) = grid % yCell % array(advCells(i+1,iCell))/a
+               zc(i) = grid % zCell % array(advCells(i+1,iCell))/a
+            end do
+
+            theta_abs(iCell) =  pii/2. - sphere_angle( xc(1), yc(1), zc(1),  &amp;
+                                                       xc(2), yc(2), zc(2),  &amp;
+                                                       0.,    0.,    1.      ) 
+
+! angles from cell center to neighbor centers (thetav)
+
+            do i=1,n-1
+   
+               ip2 = i+2
+               if (ip2 &gt; n) ip2 = 2
+    
+               thetav(i) = sphere_angle( xc(1),   yc(1),   zc(1),    &amp;
+                                         xc(i+1), yc(i+1), zc(i+1),  &amp;
+                                         xc(ip2), yc(ip2), zc(ip2)   )
+
+               dl_sphere(i) = a*arc_length( xc(1),   yc(1),   zc(1),  &amp;
+                                            xc(i+1), yc(i+1), zc(i+1) )
+            end do
+
+            length_scale = 1.
+            do i=1,n-1
+               dl_sphere(i) = dl_sphere(i)/length_scale
+            end do
+
+!            thetat(1) = 0.  !  this defines the x direction, cell center 1 -&gt; 
+            thetat(1) = theta_abs(iCell)  !  this defines the x direction, longitude line
+            do i=2,n-1
+               thetat(i) = thetat(i-1) + thetav(i-1)
+            end do
+   
+            do i=1,n-1
+               xp(i) = cos(thetat(i)) * dl_sphere(i)
+               yp(i) = sin(thetat(i)) * dl_sphere(i)
+            end do
+
+         else     ! On an x-y plane
+
+            do i=1,n-1
+
+               angle_2d(i) = grid%angleEdge%array(grid % EdgesOnCell % array(i,iCell))
+               iEdge = grid % EdgesOnCell % array(i,iCell)
+               if ( iCell .ne. grid % CellsOnEdge % array(1,iEdge)) &amp;
+                  angle_2d(i) = angle_2d(i) - pii
+
+!               xp(i) = grid % xCell % array(cell_list(i)) - grid % xCell % array(iCell)
+!               yp(i) = grid % yCell % array(cell_list(i)) - grid % yCell % array(iCell)
+
+               xp(i) = grid % dcEdge % array(grid % EdgesOnCell % array(i,iCell)) * cos(angle_2d(i))
+               yp(i) = grid % dcEdge % array(grid % EdgesOnCell % array(i,iCell)) * sin(angle_2d(i))
+
+            end do
+
+         end if
+
+
+         ma = n-1
+         mw = grid % nEdgesOnCell % array (iCell)
+
+         bmatrix = 0.
+         amatrix = 0.
+         wmatrix = 0.
+
+         if (polynomial_order == 2) then
+            na = 6
+            ma = ma+1
+  
+            amatrix(1,1) = 1.
+            wmatrix(1,1) = 1.
+            do i=2,ma
+               amatrix(i,1) = 1.
+               amatrix(i,2) = xp(i-1)
+               amatrix(i,3) = yp(i-1)
+               amatrix(i,4) = xp(i-1)**2
+               amatrix(i,5) = xp(i-1) * yp(i-1)
+               amatrix(i,6) = yp(i-1)**2
+   
+               wmatrix(i,i) = 1.
+            end do

+         else if (polynomial_order == 3) then
+            na = 10
+            ma = ma+1
+  
+            amatrix(1,1) = 1.
+            wmatrix(1,1) = 1.
+            do i=2,ma
+               amatrix(i,1) = 1.
+               amatrix(i,2) = xp(i-1)
+               amatrix(i,3) = yp(i-1)
+   
+               amatrix(i,4) = xp(i-1)**2
+               amatrix(i,5) = xp(i-1) * yp(i-1)
+               amatrix(i,6) = yp(i-1)**2
+   
+               amatrix(i,7) = xp(i-1)**3
+               amatrix(i,8) = yp(i-1) * (xp(i-1)**2)
+               amatrix(i,9) = xp(i-1) * (yp(i-1)**2)
+               amatrix(i,10) = yp(i-1)**3
+   
+               wmatrix(i,i) = 1.

+            end do
+
+         else
+            na = 15
+            ma = ma+1
+  
+            amatrix(1,1) = 1.
+            wmatrix(1,1) = 1.
+            do i=2,ma
+               amatrix(i,1) = 1.
+               amatrix(i,2) = xp(i-1)
+               amatrix(i,3) = yp(i-1)
+   
+               amatrix(i,4) = xp(i-1)**2
+               amatrix(i,5) = xp(i-1) * yp(i-1)
+               amatrix(i,6) = yp(i-1)**2
+   
+               amatrix(i,7) = xp(i-1)**3
+               amatrix(i,8) = yp(i-1) * (xp(i-1)**2)
+               amatrix(i,9) = xp(i-1) * (yp(i-1)**2)
+               amatrix(i,10) = yp(i-1)**3
+   
+               amatrix(i,11) = xp(i-1)**4
+               amatrix(i,12) = yp(i-1) * (xp(i-1)**3)
+               amatrix(i,13) = (xp(i-1)**2)*(yp(i-1)**2)
+               amatrix(i,14) = xp(i-1) * (yp(i-1)**3)
+               amatrix(i,15) = yp(i-1)**4
+   
+               wmatrix(i,i) = 1.
+  
+            end do

+            do i=1,mw
+               wmatrix(i,i) = 1.
+            end do

+         end if

+         call poly_fit_2( amatrix, bmatrix, wmatrix, ma, na, 25 )
+
+         do i=1,grid % nEdgesOnCell % array (iCell)
+            ip1 = i+1
+            if (ip1 &gt; n-1) ip1 = 1
+  
+            iEdge = grid % EdgesOnCell % array (i,iCell)
+            xv1 = grid % xVertex % array(grid % verticesOnEdge % array (1,iedge))/a
+            yv1 = grid % yVertex % array(grid % verticesOnEdge % array (1,iedge))/a
+            zv1 = grid % zVertex % array(grid % verticesOnEdge % array (1,iedge))/a
+            xv2 = grid % xVertex % array(grid % verticesOnEdge % array (2,iedge))/a
+            yv2 = grid % yVertex % array(grid % verticesOnEdge % array (2,iedge))/a
+            zv2 = grid % zVertex % array(grid % verticesOnEdge % array (2,iedge))/a
+  
+            if ( grid % on_a_sphere ) then
+               call arc_bisect( xv1, yv1, zv1,  &amp;
+                                xv2, yv2, zv2,  &amp;
+                                xec, yec, zec   )
+  
+               thetae_tmp = sphere_angle( xc(1),   yc(1),   zc(1),    &amp;
+                                          xc(i+1), yc(i+1), zc(i+1),  &amp;
+                                          xec,     yec,     zec       )
+               thetae_tmp = thetae_tmp + thetat(i)
+               if (iCell == grid % cellsOnEdge % array(1,iEdge)) then
+                  thetae(1,grid % EdgesOnCell % array (i,iCell)) = thetae_tmp
+               else
+                  thetae(2,grid % EdgesOnCell % array (i,iCell)) = thetae_tmp
+               end if
+!            else
+!
+!               xe(grid % EdgesOnCell % array (i,iCell)) = 0.5 * (xv1 + xv2)
+!               ye(grid % EdgesOnCell % array (i,iCell)) = 0.5 * (yv1 + yv2)
+
+            end if
+  
+         end do
+
+!  fill second derivative stencil for rk advection 
+
+         do i=1, grid % nEdgesOnCell % array (iCell)
+            iEdge = grid % EdgesOnCell % array (i,iCell)
+  
+  
+            if ( grid % on_a_sphere ) then
+               if (iCell == grid % cellsOnEdge % array(1,iEdge)) then
+  
+                  cos2t = cos(thetae(1,grid % EdgesOnCell % array (i,iCell)))
+                  sin2t = sin(thetae(1,grid % EdgesOnCell % array (i,iCell)))
+                  costsint = cos2t*sin2t
+                  cos2t = cos2t**2
+                  sin2t = sin2t**2
+   
+                  do j=1,n
+                     deriv_two(j,1,iEdge) =   2.*cos2t*bmatrix(4,j)  &amp;
+                                            + 2.*costsint*bmatrix(5,j)  &amp;
+                                            + 2.*sin2t*bmatrix(6,j)
+                  end do
+               else
+     
+                  cos2t = cos(thetae(2,grid % EdgesOnCell % array (i,iCell)))
+                  sin2t = sin(thetae(2,grid % EdgesOnCell % array (i,iCell)))
+                  costsint = cos2t*sin2t
+                  cos2t = cos2t**2
+                  sin2t = sin2t**2
+      
+                  do j=1,n
+                     deriv_two(j,2,iEdge) =   2.*cos2t*bmatrix(4,j)  &amp;
+                                            + 2.*costsint*bmatrix(5,j)  &amp;
+                                            + 2.*sin2t*bmatrix(6,j)
+                  end do
+               end if
+
+            else
+
+               cos2t = cos(angle_2d(i))
+               sin2t = sin(angle_2d(i))
+               costsint = cos2t*sin2t
+               cos2t = cos2t**2
+               sin2t = sin2t**2
+
+!               do j=1,n
+!
+!                  deriv_two(j,1,iEdge) =   2.*xe(iEdge)*xe(iEdge)*bmatrix(4,j)  &amp;
+!                                         + 2.*xe(iEdge)*ye(iEdge)*bmatrix(5,j)  &amp;
+!                                         + 2.*ye(iEdge)*ye(iEdge)*bmatrix(6,j)
+!               end do
+
+               if (iCell == grid % cellsOnEdge % array(1,iEdge)) then
+                  do j=1,n
+                     deriv_two(j,1,iEdge) =   2.*cos2t*bmatrix(4,j)  &amp;
+                                            + 2.*costsint*bmatrix(5,j)  &amp;
+                                            + 2.*sin2t*bmatrix(6,j)
+                  end do
+               else
+                  do j=1,n
+                     deriv_two(j,2,iEdge) =   2.*cos2t*bmatrix(4,j)  &amp;
+                                            + 2.*costsint*bmatrix(5,j)  &amp;
+                                            + 2.*sin2t*bmatrix(6,j)
+                  end do
+               end if
+
+            end if
+         end do

+      end do ! end of loop over cells
+
+      if (debug) stop
+
+
+!      write(0,*) ' check for deriv2 coefficients, iEdge 4 '
+!
+!      iEdge = 4
+!      j = 1
+!      iCell = grid % cellsOnEdge % array(1,iEdge)
+!      write(0,*) ' j, icell, coef ',j,iCell,deriv_two(j,1,iEdge)
+!      do j=2,7
+!         write(0,*) ' j, icell, coef ',j,grid % CellsOnCell % array(j-1,iCell),deriv_two(j,1,iEdge)
+!      end do
+!
+!      j = 1
+!      iCell = grid % cellsOnEdge % array(2,iEdge)
+!      write(0,*) ' j, icell, coef ',j,iCell,deriv_two(j,2,iEdge)
+!      do j=2,7
+!         write(0,*) ' j, icell, coef ',j,grid % CellsOnCell % array(j-1,iCell),deriv_two(j,2,iEdge)
+!      end do
+!      stop
+
+   end subroutine initialize_advection_rk
+
+
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! FUNCTION SPHERE_ANGLE
+   !
+   ! Computes the angle between arcs AB and AC, given points A, B, and C
+   ! Equation numbers w.r.t. http://mathworld.wolfram.com/SphericalTrigonometry.html
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   real function sphere_angle(ax, ay, az, bx, by, bz, cx, cy, cz)
+   
+      implicit none
+   
+      real (kind=RKIND), intent(in) :: ax, ay, az, bx, by, bz, cx, cy, cz
+   
+      real (kind=RKIND) :: a, b, c          ! Side lengths of spherical triangle ABC
+   
+      real (kind=RKIND) :: ABx, ABy, ABz    ! The components of the vector AB
+      real (kind=RKIND) :: mAB              ! The magnitude of AB
+      real (kind=RKIND) :: ACx, ACy, ACz    ! The components of the vector AC
+      real (kind=RKIND) :: mAC              ! The magnitude of AC
+   
+      real (kind=RKIND) :: Dx               ! The i-components of the cross product AB x AC
+      real (kind=RKIND) :: Dy               ! The j-components of the cross product AB x AC
+      real (kind=RKIND) :: Dz               ! The k-components of the cross product AB x AC
+   
+      real (kind=RKIND) :: s                ! Semiperimeter of the triangle
+      real (kind=RKIND) :: sin_angle
+   
+      a = acos(max(min(bx*cx + by*cy + bz*cz,1.0),-1.0))      ! Eqn. (3)
+      b = acos(max(min(ax*cx + ay*cy + az*cz,1.0),-1.0))      ! Eqn. (2)
+      c = acos(max(min(ax*bx + ay*by + az*bz,1.0),-1.0))      ! Eqn. (1)
+   
+      ABx = bx - ax
+      ABy = by - ay
+      ABz = bz - az
+   
+      ACx = cx - ax
+      ACy = cy - ay
+      ACz = cz - az
+   
+      Dx =   (ABy * ACz) - (ABz * ACy)
+      Dy = -((ABx * ACz) - (ABz * ACx))
+      Dz =   (ABx * ACy) - (ABy * ACx)
+   
+      s = 0.5*(a + b + c)
+!      sin_angle = sqrt((sin(s-b)*sin(s-c))/(sin(b)*sin(c)))   ! Eqn. (28)
+      sin_angle = sqrt(min(1.,max(0.,(sin(s-b)*sin(s-c))/(sin(b)*sin(c)))))   ! Eqn. (28)
+   
+      if ((Dx*ax + Dy*ay + Dz*az) &gt;= 0.0) then
+         sphere_angle =  2.0 * asin(max(min(sin_angle,1.0),-1.0))
+      else
+         sphere_angle = -2.0 * asin(max(min(sin_angle,1.0),-1.0))
+      end if
+   
+   end function sphere_angle
+   
+
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! FUNCTION PLANE_ANGLE
+   !
+   ! Computes the angle between vectors AB and AC, given points A, B, and C, and
+   !   a vector (u,v,w) normal to the plane.
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   real function plane_angle(ax, ay, az, bx, by, bz, cx, cy, cz, u, v, w)
+   
+      implicit none
+   
+      real (kind=RKIND), intent(in) :: ax, ay, az, bx, by, bz, cx, cy, cz, u, v, w
+   
+      real (kind=RKIND) :: ABx, ABy, ABz    ! The components of the vector AB
+      real (kind=RKIND) :: mAB              ! The magnitude of AB
+      real (kind=RKIND) :: ACx, ACy, ACz    ! The components of the vector AC
+      real (kind=RKIND) :: mAC              ! The magnitude of AC
+   
+      real (kind=RKIND) :: Dx               ! The i-components of the cross product AB x AC
+      real (kind=RKIND) :: Dy               ! The j-components of the cross product AB x AC
+      real (kind=RKIND) :: Dz               ! The k-components of the cross product AB x AC
+   
+      real (kind=RKIND) :: cos_angle
+   
+      ABx = bx - ax
+      ABy = by - ay
+      ABz = bz - az
+      mAB = sqrt(ABx**2.0 + ABy**2.0 + ABz**2.0)
+   
+      ACx = cx - ax
+      ACy = cy - ay
+      ACz = cz - az
+      mAC = sqrt(ACx**2.0 + ACy**2.0 + ACz**2.0)
+   
+   
+      Dx =   (ABy * ACz) - (ABz * ACy)
+      Dy = -((ABx * ACz) - (ABz * ACx))
+      Dz =   (ABx * ACy) - (ABy * ACx)
+   
+      cos_angle = (ABx*ACx + ABy*ACy + ABz*ACz) / (mAB * mAC)
+   
+      if ((Dx*u + Dy*v + Dz*w) &gt;= 0.0) then
+         plane_angle =  acos(max(min(cos_angle,1.0),-1.0))
+      else
+         plane_angle = -acos(max(min(cos_angle,1.0),-1.0))
+      end if
+   
+   end function plane_angle
+
+
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! FUNCTION ARC_LENGTH
+   !
+   ! Returns the length of the great circle arc from A=(ax, ay, az) to 
+   !    B=(bx, by, bz). It is assumed that both A and B lie on the surface of the
+   !    same sphere centered at the origin.
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   real function arc_length(ax, ay, az, bx, by, bz)
+   
+      implicit none
+   
+      real (kind=RKIND), intent(in) :: ax, ay, az, bx, by, bz
+   
+      real (kind=RKIND) :: r, c
+      real (kind=RKIND) :: cx, cy, cz
+   
+      cx = bx - ax
+      cy = by - ay
+      cz = bz - az
+
+!      r = ax*ax + ay*ay + az*az
+!      c = cx*cx + cy*cy + cz*cz
+!
+!      arc_length = sqrt(r) * acos(1.0 - c/(2.0*r))
+
+      r = sqrt(ax*ax + ay*ay + az*az)
+      c = sqrt(cx*cx + cy*cy + cz*cz)
+!      arc_length = sqrt(r) * 2.0 * asin(c/(2.0*r))
+      arc_length = r * 2.0 * asin(c/(2.0*r))
+
+   end function arc_length
+   
+   
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! SUBROUTINE ARC_BISECT
+   !
+   ! Returns the point C=(cx, cy, cz) that bisects the great circle arc from
+   !   A=(ax, ay, az) to B=(bx, by, bz). It is assumed that A and B lie on the
+   !   surface of a sphere centered at the origin.
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   subroutine arc_bisect(ax, ay, az, bx, by, bz, cx, cy, cz)
+   
+      implicit none
+   
+      real (kind=RKIND), intent(in) :: ax, ay, az, bx, by, bz
+      real (kind=RKIND), intent(out) :: cx, cy, cz
+   
+      real (kind=RKIND) :: r           ! Radius of the sphere
+      real (kind=RKIND) :: d           
+   
+      r = sqrt(ax*ax + ay*ay + az*az)
+   
+      cx = 0.5*(ax + bx)
+      cy = 0.5*(ay + by)
+      cz = 0.5*(az + bz)
+   
+      if (cx == 0. .and. cy == 0. .and. cz == 0.) then
+         write(0,*) 'Error: arc_bisect: A and B are diametrically opposite'
+      else
+         d = sqrt(cx*cx + cy*cy + cz*cz)
+         cx = r * cx / d
+         cy = r * cy / d
+         cz = r * cz / d
+      end if
+   
+   end subroutine arc_bisect
+
+
+   subroutine poly_fit_2(a_in,b_out,weights_in,m,n,ne)
+
+      implicit none
+
+      integer, intent(in) :: m,n,ne
+      real (kind=RKIND), dimension(ne,ne), intent(in) :: a_in, weights_in
+      real (kind=RKIND), dimension(ne,ne), intent(out) :: b_out
+   
+      ! local storage
+   
+      real (kind=RKIND), dimension(m,n)  :: a
+      real (kind=RKIND), dimension(n,m)  :: b
+      real (kind=RKIND), dimension(m,m)  :: w,wt,h
+      real (kind=RKIND), dimension(n,m)  :: at, ath
+      real (kind=RKIND), dimension(n,n)  :: ata, ata_inv, atha, atha_inv
+      integer, dimension(n) :: indx
+      integer :: i,j
+   
+      if ( (ne&lt;n) .or. (ne&lt;m) ) then
+         write(6,*) ' error in poly_fit_2 inversion ',m,n,ne
+         stop
+      end if
+   
+!      a(1:m,1:n) = a_in(1:n,1:m) 
+      a(1:m,1:n) = a_in(1:m,1:n)
+      w(1:m,1:m) = weights_in(1:m,1:m) 
+      b_out(:,:) = 0.   
+
+      wt = transpose(w)
+      h = matmul(wt,w)
+      at = transpose(a)
+      ath = matmul(at,h)
+      atha = matmul(ath,a)
+      
+      ata = matmul(at,a)
+
+!      if (m == n) then
+!         call migs(a,n,b,indx)
+!      else
+
+         call migs(atha,n,atha_inv,indx)
+
+         b = matmul(atha_inv,ath)
+
+!         call migs(ata,n,ata_inv,indx)
+!         b = matmul(ata_inv,at)
+!      end if
+      b_out(1:n,1:m) = b(1:n,1:m)
+
+!     do i=1,n
+!        write(6,*) ' i, indx ',i,indx(i)
+!     end do
+!
+!     write(6,*) ' '
+
+   end subroutine poly_fit_2
+
+
+! Updated 10/24/2001.
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!   Program 4.4   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!                                                                       !
+! Please Note:                                                          !
+!                                                                       !
+! (1) This computer program is written by Tao Pang in conjunction with  !
+!     his book, &quot;An Introduction to Computational Physics,&quot; published   !
+!     by Cambridge University Press in 1997.                            !
+!                                                                       !
+! (2) No warranties, express or implied, are made for this program.     !
+!                                                                       !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+SUBROUTINE MIGS (A,N,X,INDX)
+!
+! Subroutine to invert matrix A(N,N) with the inverse stored
+! in X(N,N) in the output.  Copyright (c) Tao Pang 2001.
+!
+  IMPLICIT NONE
+  INTEGER, INTENT (IN) :: N
+  INTEGER :: I,J,K
+  INTEGER, INTENT (OUT), DIMENSION (N) :: INDX
+  REAL (kind=RKIND), INTENT (INOUT), DIMENSION (N,N):: A
+  REAL (kind=RKIND), INTENT (OUT), DIMENSION (N,N):: X
+  REAL (kind=RKIND), DIMENSION (N,N) :: B
+!
+  DO I = 1, N
+    DO J = 1, N
+      B(I,J) = 0.0
+    END DO
+  END DO
+  DO I = 1, N
+    B(I,I) = 1.0
+  END DO
+!
+  CALL ELGS (A,N,INDX)
+!
+  DO I = 1, N-1
+    DO J = I+1, N
+      DO K = 1, N
+        B(INDX(J),K) = B(INDX(J),K)-A(INDX(J),I)*B(INDX(I),K)
+      END DO
+    END DO
+  END DO
+!
+  DO I = 1, N
+    X(N,I) = B(INDX(N),I)/A(INDX(N),N)
+    DO J = N-1, 1, -1
+      X(J,I) = B(INDX(J),I)
+      DO K = J+1, N
+        X(J,I) = X(J,I)-A(INDX(J),K)*X(K,I)
+      END DO
+      X(J,I) =  X(J,I)/A(INDX(J),J)
+    END DO
+  END DO
+END SUBROUTINE MIGS
+
+
+SUBROUTINE ELGS (A,N,INDX)
+!
+! Subroutine to perform the partial-pivoting Gaussian elimination.
+! A(N,N) is the original matrix in the input and transformed matrix
+! plus the pivoting element ratios below the diagonal in the output.
+! INDX(N) records the pivoting order.  Copyright (c) Tao Pang 2001.
+!
+  IMPLICIT NONE
+  INTEGER, INTENT (IN) :: N
+  INTEGER :: I,J,K,ITMP
+  INTEGER, INTENT (OUT), DIMENSION (N) :: INDX
+  REAL (kind=RKIND) :: C1,PI,PI1,PJ
+  REAL (kind=RKIND), INTENT (INOUT), DIMENSION (N,N) :: A
+  REAL (kind=RKIND), DIMENSION (N) :: C
+!
+! Initialize the index
+!
+  DO I = 1, N
+    INDX(I) = I
+  END DO
+!
+! Find the rescaling factors, one from each row
+!
+  DO I = 1, N
+    C1= 0.0
+    DO J = 1, N
+      C1 = MAX(C1,ABS(A(I,J)))
+    END DO
+    C(I) = C1
+  END DO
+!
+! Search the pivoting (largest) element from each column
+!
+  DO J = 1, N-1
+    PI1 = 0.0
+    DO I = J, N
+      PI = ABS(A(INDX(I),J))/C(INDX(I))
+      IF (PI.GT.PI1) THEN
+        PI1 = PI
+        K   = I
+      ENDIF
+    END DO
+!
+! Interchange the rows via INDX(N) to record pivoting order
+!
+    ITMP    = INDX(J)
+    INDX(J) = INDX(K)
+    INDX(K) = ITMP
+    DO I = J+1, N
+      PJ  = A(INDX(I),J)/A(INDX(J),J)
+!
+! Record pivoting ratios below the diagonal
+!
+      A(INDX(I),J) = PJ
+!
+! Modify other elements accordingly
+!
+      DO K = J+1, N
+        A(INDX(I),K) = A(INDX(I),K)-PJ*A(INDX(J),K)
+      END DO
+    END DO
+  END DO
+!
+END SUBROUTINE ELGS
+
+!-------------------------------------------------------------
+
+   subroutine initialize_deformation_weights( grid )
+                                      
+!
+! compute the cell coefficients for the deformation calculations
+! WCS, 13 July 2010
+!
+      implicit none
+
+      type (mesh_type), intent(in) :: grid
+!      type (grid_meta), intent(in) :: grid
+
+      real (kind=RKIND), dimension(:,:), pointer :: defc_a, defc_b
+      integer, dimension(:,:), pointer :: cellsOnEdge, edgesOnCell
+
+!  local variables
+
+      real (kind=RKIND), dimension(2, grid % nEdges) :: thetae
+      real (kind=RKIND), dimension(grid % nEdges) :: xe, ye
+      real (kind=RKIND), dimension(grid % nCells) :: theta_abs
+
+      real (kind=RKIND), dimension(25) :: xc, yc, zc ! cell center coordinates
+      real (kind=RKIND), dimension(25) :: thetav, thetat, dl_sphere
+      real (kind=RKIND) :: xm, ym, zm, dl, xec, yec, zec
+      real (kind=RKIND) :: thetae_tmp, xe_tmp, ye_tmp
+      real (kind=RKIND) :: xv1, xv2, yv1, yv2, zv1, zv2
+      integer :: i, j, k, ip1, ip2, m, n, ip1a, ii
+      integer :: iCell, iEdge
+      real (kind=RKIND) :: pii
+      real (kind=RKIND) :: x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5
+      real (kind=RKIND) :: pdx1, pdx2, pdx3, pdy1, pdy2, pdy3, dx1, dx2, dy1, dy2
+      real (kind=RKIND) :: angv1, angv2, dl1, dl2
+      real (kind=RKIND), dimension(25) :: dxe, dye, x2v, y2v, xp, yp, xpt, ypt
+      
+      real (kind=RKIND) :: length_scale
+      integer :: ma,na, cell_add, mw, nn
+      integer, dimension(25) :: cell_list
+
+      integer :: cell1, cell2, iv
+      logical :: do_the_cell
+      real (kind=RKIND) :: area_cell, sint2, cost2, sint_cost, sumw1, sumw2, xptt, area_cellt
+
+      logical, parameter :: debug = .false.
+
+      if (debug) write(0,*) ' in def weight calc '
+
+      defc_a =&gt; grid % defc_a % array
+      defc_b =&gt; grid % defc_b % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      edgesOnCell =&gt; grid % edgesOnCell % array
+
+      defc_a(:,:) = 0.
+      defc_b(:,:) = 0.
+
+      pii = 2.*asin(1.0)
+
+      if (debug) write(0,*) ' beginning cell loop '
+
+      do iCell = 1, grid % nCells
+
+         if (debug) write(0,*) ' cell loop ', iCell
+
+         cell_list(1) = iCell
+         do i=2, grid % nEdgesOnCell % array(iCell)+1
+            cell_list(i) = grid % CellsOnCell % array(i-1,iCell)
+         end do
+         n = grid % nEdgesOnCell % array(iCell) + 1
+
+!  check to see if we are reaching outside the halo
+
+         if (debug) write(0,*) ' points ', n
+
+         do_the_cell = .true.
+         do i=1,n
+            if (cell_list(i) &gt; grid % nCells) do_the_cell = .false.
+         end do
+
+
+         if (.not. do_the_cell) cycle
+
+
+!  compute poynomial fit for this cell if all needed neighbors exist
+         if (grid % on_a_sphere) then
+
+            xc(1) = grid % xCell % array(iCell)/a
+            yc(1) = grid % yCell % array(iCell)/a
+            zc(1) = grid % zCell % array(iCell)/a
+
+
+            do i=2,n
+               iv = grid % verticesOnCell % array(i-1,iCell)
+               xc(i) = grid % xVertex % array(iv)/a
+               yc(i) = grid % yVertex % array(iv)/a
+               zc(i) = grid % zVertex % array(iv)/a
+            end do
+
+            theta_abs(iCell) =  pii/2. - sphere_angle( xc(1), yc(1), zc(1),  &amp;
+                                                       xc(2), yc(2), zc(2),  &amp;
+                                                       0.,    0.,    1.      ) 
+
+! angles from cell center to neighbor centers (thetav)
+
+            do i=1,n-1
+   
+               ip2 = i+2
+               if (ip2 &gt; n) ip2 = 2
+    
+               thetav(i) = sphere_angle( xc(1),   yc(1),   zc(1),    &amp;
+                                         xc(i+1), yc(i+1), zc(i+1),  &amp;
+                                         xc(ip2), yc(ip2), zc(ip2)   )
+
+               dl_sphere(i) = a*arc_length( xc(1),   yc(1),   zc(1),  &amp;
+                                            xc(i+1), yc(i+1), zc(i+1) )
+            end do
+
+            length_scale = 1.
+            do i=1,n-1
+               dl_sphere(i) = dl_sphere(i)/length_scale
+            end do
+
+            thetat(1) = 0.  !  this defines the x direction, cell center 1 -&gt; 
+!            thetat(1) = theta_abs(iCell)  !  this defines the x direction, longitude line
+            do i=2,n-1
+               thetat(i) = thetat(i-1) + thetav(i-1)
+            end do
+   
+            do i=1,n-1
+               xp(i) = cos(thetat(i)) * dl_sphere(i)
+               yp(i) = sin(thetat(i)) * dl_sphere(i)
+            end do
+
+         else     ! On an x-y plane
+
+            xp(1) = grid % xCell % array(iCell)
+            yp(1) = grid % yCell % array(iCell)
+
+
+            do i=2,n
+               iv = grid % verticesOnCell % array(i-1,iCell)
+               xp(i) = grid % xVertex % array(iv)
+               yp(i) = grid % yVertex % array(iv)
+            end do
+
+         end if
+
+!         thetat(1) = 0.
+         thetat(1) = theta_abs(iCell)
+         do i=2,n-1
+            ip1 = i+1
+            if (ip1 == n) ip1 = 1
+            thetat(i) = plane_angle( 0.,0.,0.,  &amp;
+                                     xp(i)-xp(i-1), yp(i)-yp(i-1), 0.,  &amp;
+                                     xp(ip1)-xp(i), yp(ip1)-yp(i), 0.,  &amp;
+                                     0., 0., 1.)
+            thetat(i) = thetat(i) + thetat(i-1)
+         end do
+
+         area_cell = 0.
+         area_cellt = 0.
+         do i=1,n-1
+            ip1 = i+1
+            if (ip1 == n) ip1 = 1
+            dl = sqrt((xp(ip1)-xp(i))**2 + (yp(ip1)-yp(i))**2)
+            area_cell = area_cell + 0.25*(xp(i)+xp(ip1))*(yp(ip1)-yp(i)) - 0.25*(yp(i)+yp(ip1))*(xp(ip1)-xp(i))
+            area_cellt = area_cellt + (0.25*(xp(i)+xp(ip1))*cos(thetat(i)) + 0.25*(yp(i)+yp(ip1))*sin(thetat(i)))*dl
+         end do
+         if (debug) write(0,*) ' area_cell, area_cellt ',area_cell, area_cellt,area_cell-area_cellt
+
+         do i=1,n-1
+            ip1 = i+1
+            if (ip1 == n) ip1 = 1
+            dl = sqrt((xp(ip1)-xp(i))**2 + (yp(ip1)-yp(i))**2)
+            sint2 = (sin(thetat(i)))**2
+            cost2 = (cos(thetat(i)))**2
+            sint_cost = sin(thetat(i))*cos(thetat(i))
+            defc_a(i,iCell) = dl*(cost2 - sint2)/area_cell
+            defc_b(i,iCell) = dl*2.*sint_cost/area_cell
+            if (cellsOnEdge(1,EdgesOnCell(i,iCell)) /= iCell) then
+               defc_a(i,iCell) = - defc_a(i,iCell)
+               defc_b(i,iCell) = - defc_b(i,iCell)
+            end if

+         end do
+
+      end do
+
+      if (debug) write(0,*) ' exiting def weight calc '
+
+   end subroutine initialize_deformation_weights
+
+end module advection

Copied: trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_equation_of_state.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,185 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_equation_of_state
+!
+!&gt; \brief MPAS ocean equation of state driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   29 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for calling
+!&gt;  the equation of state.
+!
+!-----------------------------------------------------------------------
+
+module ocn_equation_of_state
+
+   use grid_types
+   use configure
+   use timer
+   use ocn_equation_of_state_linear
+   use ocn_equation_of_state_jm
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_equation_of_state_rho, &amp;
+             ocn_equation_of_state_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: eosON
+   logical :: linearEos, jmEos
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_state
+!
+!&gt; \brief   Calls equation of state
+!&gt; \author  Doug Jacobsen
+!&gt; \date    29 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine calls the equation of state to update the density
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_rho(s, grid, k_displaced, displacement_type, err)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !  This module contains routines necessary for computing the density
+   !  from model temperature and salinity using an equation of state.
+   !
+   ! Input: grid - grid metadata
+   !        s - state: tracers
+   !        k_displaced 
+   !  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
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      implicit none
+
+      type (state_type), intent(inout) :: s
+      type (mesh_type), intent(in) :: grid
+      integer, intent(out) :: err
+      integer :: k_displaced
+      character(len=8), intent(in) :: displacement_type
+
+      integer, dimension(:), pointer :: maxLevelCell
+      real (kind=RKIND), dimension(:,:), pointer :: rho
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+      integer :: nCells, iCell, k, indexT, indexS
+      type (dm_info) :: dminfo
+
+      err = 0
+
+      if(.not.eosOn) return
+
+      call timer_start(&quot;ocn_equation_of_state_rho&quot;)
+
+      tracers =&gt; s % tracers % array
+      indexT = s % index_temperature
+      indexS = s % index_salinity
+
+      if (linearEos) then
+         rho =&gt; s % rho % array
+
+         call ocn_equation_of_state_linear_rho(grid, indexT, indexS, tracers, rho, err)
+
+      elseif (jmEos) then
+
+         if(k_displaced == 0) then
+             rho =&gt; s % rho % array
+         else
+             rho =&gt; s % rhoDisplaced % array
+         endif
+
+         call ocn_equation_of_state_jm_rho(grid, k_displaced, displacement_type, indexT, indexS, tracers, rho, err)
+
+      endif
+
+      call timer_stop(&quot;ocn_equation_of_state_rho&quot;)
+
+   end subroutine ocn_equation_of_state_rho!}}}
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_stateInit
+!
+!&gt; \brief   Initializes ocean momentum horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    29 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err
+
+      err = 0
+      eosON = .false.
+      linearEos = .false.
+      jmEos = .false.
+
+      if(config_vert_grid_type.eq.'zlevel') then
+          eosON = .true.
+
+          if (config_eos_type.eq.'linear') then
+              linearEos = .true.
+          elseif (config_eos_type.eq.'jm') then
+              jmEos = .true.
+          else
+              print *,'Invalid choice for config_eos_type.'
+              print *,'  Choices are: linear, jm'
+              err = 1
+          endif
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_equation_of_state_init!}}}
+
+!***********************************************************************
+
+end module ocn_equation_of_state
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_jm.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_equation_of_state_jm.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_jm.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_jm.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,355 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_equation_of_state_jm
+!
+!&gt; \brief MPAS ocean equation of state driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   28 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for calling
+!&gt;  the equation of state.
+!
+!-----------------------------------------------------------------------
+
+module ocn_equation_of_state_jm
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_equation_of_state_jm_rho, &amp;
+             ocn_equation_of_state_jm_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_state_jm_rho
+!
+!&gt; \brief   Calls JM equation of state
+!&gt; \author  Doug Jacobsen
+!&gt; \date    28 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine uses a JM equation of state to update the density
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_jm_rho(grid, k_displaced, displacement_type, indexT, indexS, tracers, rho, err)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !  This module contains routines necessary for computing the density
+   !  from model temperature and salinity using an equation of state.
+   !
+   !  The UNESCO equation of state computed using the
+   !  potential-temperature-based bulk modulus from Jackett and
+   !  McDougall, JTECH, Vol.12, pp 381-389, April, 1995.
+   !
+   ! 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 
+   !  k_displaced.
+
+   !
+   ! Output: s - state: computed density
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (mesh_type), intent(in) :: grid
+      integer :: k_displaced, indexT, indexS
+      character(len=8), intent(in) :: displacement_type
+      integer, intent(out) :: err
+
+      type (dm_info) :: dminfo
+      integer :: iEdge, iCell, iVertex, k
+
+      integer :: nCells, nEdges, nVertices, nVertLevels
+
+
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        zMidZLevel, pRefEOS
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+        rho
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: tracers
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+   real (kind=RKIND) :: &amp;
+      TQ,SQ,             &amp;! adjusted T,S
+      BULK_MOD,          &amp;! Bulk modulus
+      RHO_S,             &amp;! density at the surface
+      DRDT0,             &amp;! d(density)/d(temperature), for surface
+      DRDS0,             &amp;! d(density)/d(salinity   ), for surface
+      DKDT,              &amp;! d(bulk modulus)/d(pot. temp.)
+      DKDS,              &amp;! d(bulk modulus)/d(salinity  )
+      SQR,DENOMK,        &amp;! work arrays
+      WORK1, WORK2, WORK3, WORK4, T2, depth
+
+   real (kind=RKIND) :: &amp; 
+      tmin, tmax,        &amp;! valid temperature range for level k
+      smin, smax          ! valid salinity    range for level k
+
+   real (kind=RKIND), dimension(:), allocatable :: &amp;
+      p, p2 ! temporary pressure scalars
+
+!-----------------------------------------------------------------------
+!
+!  UNESCO EOS constants and JMcD bulk modulus constants
+!
+!-----------------------------------------------------------------------
+
+   !*** for density of fresh water (standard UNESCO)
+
+   real (kind=RKIND), parameter ::              &amp;
+      unt0 =   999.842594,           &amp;
+      unt1 =  6.793952e-2,           &amp;
+      unt2 = -9.095290e-3,           &amp;
+      unt3 =  1.001685e-4,           &amp;
+      unt4 = -1.120083e-6,           &amp;
+      unt5 =  6.536332e-9
+
+   !*** for dependence of surface density on salinity (UNESCO)
+
+   real (kind=RKIND), parameter ::              &amp;
+      uns1t0 =  0.824493 ,           &amp;
+      uns1t1 = -4.0899e-3,           &amp;
+      uns1t2 =  7.6438e-5,           &amp;
+      uns1t3 = -8.2467e-7,           &amp;
+      uns1t4 =  5.3875e-9,           &amp;
+      unsqt0 = -5.72466e-3,          &amp;
+      unsqt1 =  1.0227e-4,           &amp;
+      unsqt2 = -1.6546e-6,           &amp;
+      uns2t0 =  4.8314e-4
+
+   !*** from Table A1 of Jackett and McDougall
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup0s0t0 =  1.965933e+4,       &amp;
+      bup0s0t1 =  1.444304e+2,       &amp;
+      bup0s0t2 = -1.706103   ,       &amp;
+      bup0s0t3 =  9.648704e-3,       &amp;
+      bup0s0t4 = -4.190253e-5
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup0s1t0 =  5.284855e+1,       &amp;
+      bup0s1t1 = -3.101089e-1,       &amp;
+      bup0s1t2 =  6.283263e-3,       &amp;
+      bup0s1t3 = -5.084188e-5
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup0sqt0 =  3.886640e-1,       &amp;
+      bup0sqt1 =  9.085835e-3,       &amp;
+      bup0sqt2 = -4.619924e-4
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup1s0t0 =  3.186519   ,       &amp;
+      bup1s0t1 =  2.212276e-2,       &amp;
+      bup1s0t2 = -2.984642e-4,       &amp;
+      bup1s0t3 =  1.956415e-6 
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup1s1t0 =  6.704388e-3,       &amp;
+      bup1s1t1 = -1.847318e-4,       &amp;
+      bup1s1t2 =  2.059331e-7,       &amp;
+      bup1sqt0 =  1.480266e-4 
+
+   real (kind=RKIND), parameter ::              &amp;
+      bup2s0t0 =  2.102898e-4,       &amp;
+      bup2s0t1 = -1.202016e-5,       &amp;
+      bup2s0t2 =  1.394680e-7,       &amp;
+      bup2s1t0 = -2.040237e-6,       &amp;
+      bup2s1t1 =  6.128773e-8,       &amp;
+      bup2s1t2 =  6.207323e-10
+
+   integer :: k_test, k_ref
+
+      err = 0
+
+      call timer_start(&quot;equation_of_state_jm&quot;)
+
+      nCells      = grid % nCells
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      nVertLevels = grid % nVertLevels
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+
+
+!  Jackett and McDougall
+      tmin = -2.0  ! valid pot. temp. range
+      tmax = 40.0 
+      smin =  0.0  ! valid salinity, in psu   
+      smax = 42.0 
+
+      ! This could be put in a startup routine.
+      ! Note I am using zMidZlevel, so pressure on top level does
+      ! not include SSH contribution.  I am not sure if that matters.
+
+!  This function computes pressure in bars from depth in meters
+!  using a mean density derived from depth-dependent global 
+!  average temperatures and salinities from Levitus 1994, and 
+!  integrating using hydrostatic balance.
+
+      allocate(pRefEOS(nVertLevels),p(nVertLevels),p2(nVertLevels))
+      do k = 1,nVertLevels
+        depth = -zMidZLevel(k)
+        pRefEOS(k) = 0.059808*(exp(-0.025*depth) - 1.0) &amp;
+            + 0.100766*depth + 2.28405e-7*depth**2
+      enddo
+
+   !  If k_displaced=0, in-situ density is returned (no displacement)
+   !  If k_displaced/=0, potential density is returned
+
+   !  if displacement_type = 'relative', potential density is calculated
+   !     referenced to level k + k_displaced
+   !  if displacement_type = 'absolute', potential density is calculated
+   !     referenced to level k_displaced for all k
+   !  NOTE: k_displaced = 0 or &gt; nVertLevels is incompatible with 'absolute'
+   !     so abort if necessary
+
+   if (displacement_type == 'absolute' .and.   &amp;
+       (k_displaced &lt;= 0 .or. k_displaced &gt; nVertLevels) ) then
+      write(0,*) 'Abort: In equation_of_state_jm', &amp;
+         ' k_displaced must be between 1 and nVertLevels for ', &amp;
+         'displacement_type = absolute'
+      call dmpar_abort(dminfo)
+   endif
+
+   if (k_displaced == 0) then
+      do k=1,nVertLevels
+         p(k)   = pRefEOS(k)
+         p2(k)  = p(k)*p(k)
+      enddo
+   else ! k_displaced /= 0
+      do k=1,nVertLevels
+         if (displacement_type == 'relative') then
+            k_test = min(k + k_displaced, nVertLevels)
+            k_ref  = max(k_test, 1)
+         else
+            k_test = min(k_displaced, nVertLevels)
+            k_ref  = max(k_test, 1)
+         endif
+         p(k)   = pRefEOS(k_ref)
+         p2(k)  = p(k)*p(k)
+      enddo
+   endif
+
+  do iCell=1,nCells
+    do k=1,maxLevelCell(iCell)
+
+      SQ  = max(min(tracers(indexS,k,iCell),smax),smin)
+      TQ  = max(min(tracers(indexT,k,iCell),tmax),tmin)
+
+      SQR = sqrt(SQ)
+      T2  = TQ*TQ
+
+      !***
+      !*** first calculate surface (p=0) values from UNESCO eqns.
+      !***
+
+      WORK1 = uns1t0 + uns1t1*TQ + &amp; 
+             (uns1t2 + uns1t3*TQ + uns1t4*T2)*T2
+      WORK2 = SQR*(unsqt0 + unsqt1*TQ + unsqt2*T2)
+
+      RHO_S = unt1*TQ + (unt2 + unt3*TQ + (unt4 + unt5*TQ)*T2)*T2 &amp;
+                      + (uns2t0*SQ + WORK1 + WORK2)*SQ
+
+      !***
+      !*** now calculate bulk modulus at pressure p from 
+      !*** Jackett and McDougall formula
+      !***
+
+      WORK3 = bup0s1t0 + bup0s1t1*TQ +                    &amp;
+             (bup0s1t2 + bup0s1t3*TQ)*T2 +                &amp;
+              p(k) *(bup1s1t0 + bup1s1t1*TQ + bup1s1t2*T2) + &amp;
+              p2(k)*(bup2s1t0 + bup2s1t1*TQ + bup2s1t2*T2)
+      WORK4 = SQR*(bup0sqt0 + bup0sqt1*TQ + bup0sqt2*T2 + &amp;
+                   bup1sqt0*p(k))
+
+      BULK_MOD  = bup0s0t0 + bup0s0t1*TQ +                    &amp;
+                  (bup0s0t2 + bup0s0t3*TQ + bup0s0t4*T2)*T2 + &amp;
+                  p(k) *(bup1s0t0 + bup1s0t1*TQ +                &amp;
+                     (bup1s0t2 + bup1s0t3*TQ)*T2) +           &amp;
+                  p2(k)*(bup2s0t0 + bup2s0t1*TQ + bup2s0t2*T2) + &amp;
+                  SQ*(WORK3 + WORK4)
+
+      DENOMK = 1.0/(BULK_MOD - p(k))
+
+      rho(k,iCell) = (unt0 + RHO_S)*BULK_MOD*DENOMK
+
+    end do
+  end do
+
+   deallocate(pRefEOS,p,p2)
+
+   call timer_stop(&quot;equation_of_state_jm&quot;)
+
+   end subroutine ocn_equation_of_state_jm_rho!}}}
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_state_jm_init
+!
+!&gt; \brief   Initializes ocean momentum horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    28 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_jm_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err
+
+      err = 0
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_equation_of_state_jm_init!}}}
+
+!***********************************************************************
+
+end module ocn_equation_of_state_jm
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_linear.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_equation_of_state_linear.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_linear.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_equation_of_state_linear.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,151 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_equation_of_state_linear
+!
+!&gt; \brief MPAS ocean equation of state driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   28 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for calling
+!&gt;  the equation of state.
+!
+!-----------------------------------------------------------------------
+
+module ocn_equation_of_state_linear
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_equation_of_state_linear_rho, &amp;
+             ocn_equation_of_state_linear_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_state_linear_rho
+!
+!&gt; \brief   Calls equation of state
+!&gt; \author  Doug Jacobsen
+!&gt; \date    28 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine uses a linear equation of state to update the density
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_linear_rho(grid, indexT, indexS, tracers, rho, err)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !  This module contains routines necessary for computing the density
+   !  from model temperature and salinity using an equation of state.
+   !
+   ! Input: grid - grid metadata
+   !        s - state: tracers
+   !        k_displaced 
+   !  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
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      implicit none
+
+      type (mesh_type), intent(in) :: grid
+      real (kind=RKIND), dimension(:,:), intent(inout) :: rho
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: tracers
+      integer, intent(in) :: indexT, indexS
+      integer, intent(out) :: err
+
+      integer, dimension(:), pointer :: maxLevelCell
+      integer :: nCells, iCell, k
+      type (dm_info) :: dminfo
+
+      call timer_start(&quot;ocn_equation_of_state_linear&quot;)
+
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      nCells      = grid % nCells
+
+      err = 0
+
+      do iCell=1,nCells
+         do k=1,maxLevelCell(iCell)
+            ! Linear equation of state
+            rho(k,iCell) = 1000.0*(  1.0 &amp;
+               - 2.5e-4*tracers(indexT,k,iCell) &amp;
+               + 7.6e-4*tracers(indexS,k,iCell))
+         end do
+      end do
+
+      call timer_stop(&quot;ocn_equation_of_state_linear&quot;)
+
+   end subroutine ocn_equation_of_state_linear_rho!}}}
+
+!***********************************************************************
+!
+!  routine ocn_equation_of_state_linear_init
+!
+!&gt; \brief   Initializes ocean momentum horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    28 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_equation_of_state_linear_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err
+
+      integer :: err1, err2
+
+      err = 0
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_equation_of_state_linear_init!}}}
+
+!***********************************************************************
+
+end module ocn_equation_of_state_linear
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_global_diagnostics.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_global_diagnostics.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_global_diagnostics.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_global_diagnostics.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,618 @@
+module global_diagnostics
+
+   use grid_types
+   use configure
+   use constants
+   use dmpar
+
+   implicit none
+   save
+   public
+
+   contains
+
+   subroutine computeGlobalDiagnostics(dminfo, state, grid, timeIndex, dt)
+
+      ! Note: this routine assumes that there is only one block per processor. No looping
+      ! is preformed over blocks.
+      ! dminfo is the domain info needed for global communication
+      ! state contains the state variables needed to compute global diagnostics
+      ! grid conains the meta data about the grid
+      ! timeIndex is the current time step counter
+      ! dt is the duration of each time step
+
+      ! Sums of variables at vertices are not weighted by thickness (since h is not known at
+      !    vertices as it is at cell centers and at edges).
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      type (state_type), intent(inout) :: state
+      type (mesh_type), intent(in) :: grid
+      integer, intent(in) :: timeIndex
+      real (kind=RKIND), intent(in) :: dt
+
+      integer :: nVertLevels, nCellsSolve, nEdgesSolve, nVerticesSolve, nCellsGlobal, nEdgesGlobal, nVerticesGlobal, iTracer
+
+      real (kind=RKIND) ::  areaCellGlobal, areaEdgeGlobal, areaTriangleGlobal
+      real (kind=RKIND), dimension(:), pointer ::  areaCell, dcEdge, dvEdge, areaTriangle, areaEdge
+      real (kind=RKIND), dimension(:,:), pointer :: h, u, v, h_edge, circulation, vorticity, ke, pv_edge, pv_vertex, &amp;
+         pv_cell, gradPVn, gradPVt, pressure, MontPot, wTop, rho, tracerTemp
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+
+      real (kind=RKIND) :: volumeCellGlobal, volumeEdgeGlobal, CFLNumberGlobal
+      real (kind=RKIND) ::  localCFL, localSum
+      integer :: elementIndex, variableIndex, nVariables, nSums, nMaxes, nMins
+      integer :: timeLevel,k,i, num_tracers
+
+      integer, parameter :: kMaxVariables = 1024 ! this must be a little more than double the number of variables to be reduced
+
+      real (kind=RKIND), dimension(kMaxVariables) :: sums, mins, maxes, averages, verticalSumMins, verticalSumMaxes, reductions
+
+      integer :: fileID
+
+      num_tracers = state % num_tracers
+
+      nVertLevels = grid % nVertLevels
+      nCellsSolve = grid % nCellsSolve
+      nEdgesSolve = grid % nEdgesSolve
+      nVerticesSolve = grid % nVerticesSolve
+
+      areaCell =&gt; grid % areaCell % array
+      dcEdge =&gt; grid % dcEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaTriangle =&gt; grid % areaTriangle % array
+      allocate(areaEdge(1:nEdgesSolve))
+      areaEdge = dcEdge(1:nEdgesSolve)*dvEdge(1:nEdgesSolve)
+
+      h =&gt; state % h % array
+      u =&gt; state % u % array
+      rho =&gt; state % rho % array
+      tracers =&gt; state % tracers % array
+      v =&gt; state % v % array
+      wTop =&gt; state % wTop % array
+      h_edge =&gt; state % h_edge % array
+      circulation =&gt; state % circulation % array
+      vorticity =&gt; state % vorticity % array
+      ke =&gt; state % ke % array
+      pv_edge =&gt; state % pv_edge % array
+      pv_vertex =&gt; state % pv_vertex % array
+      pv_cell =&gt; state % pv_cell % array
+      gradPVn =&gt; state % gradPVn % array
+      gradPVt =&gt; state % gradPVt % array
+      MontPot =&gt; state % MontPot % array
+      pressure =&gt; state % pressure % array
+
+      variableIndex = 0
+      ! h
+      variableIndex = variableIndex + 1
+      call computeFieldAreaWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), verticalSumMaxes(variableIndex))
+
+      ! u
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        u(:,1:nEdgesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! v
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        v(:,1:nEdgesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! h_edge
+      variableIndex = variableIndex + 1
+      call computeFieldAreaWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), verticalSumMaxes(variableIndex))
+
+      ! circulation
+      variableIndex = variableIndex + 1
+      call computeFieldLocalStats(dminfo, nVertLevels, nVerticesSolve, circulation(:,1:nVerticesSolve), &amp;
+        sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), verticalSumMaxes(variableIndex))
+
+      ! vorticity
+      variableIndex = variableIndex + 1
+      call computeFieldAreaWeightedLocalStats(dminfo, nVertLevels, nVerticesSolve, areaTriangle(1:nVerticesSolve), &amp;
+        vorticity(:,1:nVerticesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), &amp;
+        verticalSumMins(variableIndex), verticalSumMaxes(variableIndex))
+
+      ! ke
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        ke(:,1:nCellsSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! pv_edge
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        pv_edge(:,1:nEdgesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! pv_vertex
+      variableIndex = variableIndex + 1
+      call computeFieldAreaWeightedLocalStats(dminfo, nVertLevels, nVerticesSolve, areaTriangle(1:nVerticesSolve), &amp;
+        pv_vertex(:,1:nVerticesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), &amp;
+        verticalSumMins(variableIndex), verticalSumMaxes(variableIndex))
+
+      ! pv_cell
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        pv_cell(:,1:nCellsSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! gradPVn
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        gradPVn(:,1:nEdgesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! gradPVt
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nEdgesSolve, areaEdge(1:nEdgesSolve), h_edge(:,1:nEdgesSolve), &amp;
+        gradPVt(:,1:nEdgesSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! pressure
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        pressure(:,1:nCellsSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! MontPot
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        MontPot(:,1:nCellsSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! wTop vertical velocity
+      variableIndex = variableIndex + 1
+      call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels+1, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+        wTop(:,1:nCellsSolve), sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+        verticalSumMaxes(variableIndex))
+
+      ! Tracers
+      allocate(tracerTemp(nVertLevels,nCellsSolve))
+      do iTracer=1,num_tracers
+        variableIndex = variableIndex + 1
+        tracerTemp = Tracers(iTracer,:,1:nCellsSolve)
+        call computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nCellsSolve, areaCell(1:nCellsSolve), h(:,1:nCellsSolve), &amp;
+          tracerTemp, sums(variableIndex), mins(variableIndex), maxes(variableIndex), verticalSumMins(variableIndex), &amp;
+          verticalSumMaxes(variableIndex))
+      enddo
+      deallocate(tracerTemp)
+
+      nVariables = variableIndex
+      nSums = nVariables
+      nMins = nVariables
+      nMaxes = nVariables
+
+      nSums = nSums + 1
+      sums(nSums) = sum(areaCell(1:nCellsSolve))
+
+      nSums = nSums + 1
+      sums(nSums) = sum(dcEdge(1:nEdgesSolve)*dvEdge(1:nEdgesSolve))
+
+      nSums = nSums + 1
+      sums(nSums) = sum(areaTriangle(1:nVerticesSolve))
+
+      nSums = nSums + 1
+      sums(nSums) = nCellsSolve
+
+      nSums = nSums + 1
+      sums(nSums) = nEdgesSolve
+
+      nSums = nSums + 1
+      sums(nSums) = nVerticesSolve
+
+      localCFL = 0.0
+      do elementIndex = 1,nEdgesSolve
+         localCFL = max(localCFL, maxval(dt*u(:,elementIndex)/dcEdge(elementIndex)))
+      end do
+      nMaxes = nMaxes + 1
+      maxes(nMaxes) = localCFL
+
+      mins(nMins+1:nMins+nVariables) = verticalSumMins(1:nVariables)
+      nMins = nMins + nVariables
+      maxes(nMaxes+1:nMaxes+nVariables) = verticalSumMaxes(1:nVariables)
+      nMaxes = nMaxes + nVariables
+
+      ! global reduction of the 5 arrays (packed into 3 to minimize global communication)
+      call dmpar_sum_real_array(dminfo, nSums, sums(1:nSums), reductions(1:nSums))
+      sums(1:nVariables) = reductions(1:nVariables)
+      areaCellGlobal = reductions(nVariables+1)
+      areaEdgeGlobal = reductions(nVariables+2)
+      areaTriangleGlobal = reductions(nVariables+3)
+      nCellsGlobal = int(reductions(nVariables+4))
+      nEdgesGlobal = int(reductions(nVariables+5))
+      nVerticesGlobal = int(reductions(nVariables+6))
+
+      call dmpar_min_real_array(dminfo, nMins, mins(1:nMins), reductions(1:nMins))
+      mins(1:nVariables) = reductions(1:nVariables)
+      verticalSumMins(1:nVariables) = reductions(nMins-nVariables+1:nMins)
+
+      call dmpar_max_real_array(dminfo, nMaxes, maxes(1:nMaxes), reductions(1:nMaxes))
+      maxes(1:nVariables) = reductions(1:nVariables)
+      CFLNumberGlobal = reductions(nVariables+1)
+      verticalSumMaxes(1:nVariables) = reductions(nMaxes-nVariables+1:nMaxes)
+
+      volumeCellGlobal = sums(1)
+      volumeEdgeGlobal = sums(4)
+      ! compute the averages (slightly different depending on how the sum was computed)
+      variableIndex = 0
+      ! h
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/(areaCellGlobal*nVertLevels)
+
+      ! u
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeEdgeGlobal
+
+      ! v
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeEdgeGlobal
+
+      ! h_edge
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/(areaEdgeGlobal*nVertLevels)
+
+      ! circulation
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/(nVerticesGlobal*nVertLevels)
+
+      ! vorticity
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/(areaTriangleGlobal*nVertLevels)
+
+      ! ke
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+
+      ! pv_edge
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeEdgeGlobal
+
+      ! pv_vertex
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/(areaTriangleGlobal*nVertLevels)
+
+      ! pv_cell
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+
+      ! gradPVn
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeEdgeGlobal
+
+      ! gradPVt
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeEdgeGlobal
+
+      ! pressure
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+
+      ! MontPot
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+
+      ! wTop vertical velocity
+      variableIndex = variableIndex + 1
+      averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+
+      ! Tracers
+      do iTracer=1,num_tracers
+        variableIndex = variableIndex + 1
+        averages(variableIndex) = sums(variableIndex)/volumeCellGlobal
+      enddo
+
+      ! write out the data to files
+      if (dminfo % my_proc_id == IO_NODE) then
+         fileID = getFreeUnit()
+         open(fileID,file='stats_min.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') mins(1:nVariables)
+         close (fileID)
+         open(fileID,file='stats_max.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') maxes(1:nVariables)
+         close (fileID)
+         open(fileID,file='stats_sum.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') sums(1:nVariables)
+         close (fileID)
+         open(fileID,file='stats_avg.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') averages(1:nVariables)
+         close (fileID)
+         open(fileID,file='stats_time.txt',ACCESS='append')
+            write (fileID,'(i5,10x,a,100es24.16)') timeIndex, &amp;
+               state % xtime % scalar, dt, &amp;
+               CFLNumberGlobal
+         close (fileID)
+         open(fileID,file='stats_colmin.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') verticalSumMins(1:nVariables)
+         close (fileID)
+         open(fileID,file='stats_colmax.txt',ACCESS='append')
+            write (fileID,'(100es24.16)') verticalSumMaxes(1:nVariables)
+         close (fileID)
+      end if
+
+      state % areaCellGlobal % scalar = areaCellGlobal
+      state % areaEdgeGlobal % scalar = areaEdgeGlobal
+      state % areaTriangleGlobal % scalar = areaTriangleGlobal
+
+      state % volumeCellGlobal % scalar = volumeCellGlobal
+      state % volumeEdgeGlobal % scalar = volumeEdgeGlobal
+      state % CFLNumberGlobal % scalar = CFLNumberGlobal
+      deallocate(areaEdge)
+
+   end subroutine computeGlobalDiagnostics
+
+   integer function getFreeUnit()
+      implicit none
+
+      integer :: index
+      logical :: isOpened
+
+      getFreeUnit = 0
+      do index = 1,99
+         if((index /= 5) .and. (index /= 6)) then
+            inquire(unit = index, opened = isOpened)
+            if( .not. isOpened) then
+               getFreeUnit = index
+               return
+            end if
+         end if
+      end do
+   end function getFreeUnit
+
+   subroutine computeFieldLocalStats(dminfo, nVertLevels, nElements, field, localSum, localMin, localMax, localVertSumMin, &amp;
+      localVertSumMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: localSum, localMin, localMax, localVertSumMin, &amp;
+      localVertSumMax
+
+      localSum = sum(field)
+      localMin = minval(field)
+      localMax = maxval(field)
+      localVertSumMin = minval(sum(field,1))
+      localVertSumMax = maxval(sum(field,1))
+
+   end subroutine computeFieldLocalStats
+
+   subroutine computeFieldAreaWeightedLocalStats(dminfo, nVertLevels, nElements, areas, field, localSum, localMin, &amp;
+      localMax, localVertSumMin, localVertSumMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: localSum, localMin, localMax, localVertSumMin, &amp;
+      localVertSumMax
+
+      integer :: elementIndex
+
+      localSum = 0.0
+      do elementIndex = 1, nElements
+        localSum = localSum + areas(elementIndex) * sum(field(:,elementIndex))
+      end do
+
+      localMin = minval(field)
+      localMax = maxval(field)
+      localVertSumMin = minval(sum(field,1))
+      localVertSumMax = maxval(sum(field,1))
+
+   end subroutine computeFieldAreaWeightedLocalStats
+
+   subroutine computeFieldThicknessWeightedLocalStats(dminfo, nVertLevels, nElements, h, field, &amp;
+      localSum, localMin, localMax, localVertSumMin, localVertSumMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: localSum, localMin, localMax, localVertSumMin, &amp;
+      localVertSumMax
+
+      real (kind=RKIND), dimension(nVertLevels, nElements) :: hTimesField
+
+      integer :: elementIndex
+
+      localSum = sum(h*field)
+      localMin = minval(field)
+      localMax = maxval(field)
+      localVertSumMin = minval(sum(h*field,1))
+      localVertSumMax = maxval(sum(h*field,1))
+
+   end subroutine computeFieldThicknessWeightedLocalStats
+
+   subroutine computeFieldVolumeWeightedLocalStats(dminfo, nVertLevels, nElements, areas, h, field, &amp;
+      localSum, localMin, localMax, localVertSumMin, localVertSumMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: localSum, localMin, localMax, localVertSumMin, &amp;
+      localVertSumMax
+
+      real (kind=RKIND), dimension(nVertLevels, nElements) :: hTimesField
+
+      integer :: elementIndex
+
+      localSum = 0.0
+      do elementIndex = 1, nElements
+        localSum = localSum + areas(elementIndex) * sum(h(:,elementIndex)*field(:,elementIndex))
+      end do
+
+      localMin = minval(field)
+      localMax = maxval(field)
+      localVertSumMin = minval(sum(h*field,1))
+      localVertSumMax = maxval(sum(h*field,1))
+
+   end subroutine computeFieldVolumeWeightedLocalStats
+
+
+   subroutine computeGlobalSum(dminfo, nVertLevels, nElements, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+
+      real (kind=RKIND) :: localSum
+
+      localSum = sum(field)
+      call dmpar_sum_real(dminfo, localSum, globalSum)
+
+   end subroutine computeGlobalSum
+
+   subroutine computeAreaWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+      
+      integer :: elementIndex
+      real (kind=RKIND) :: localSum
+
+      localSum = 0.
+      do elementIndex = 1, nElements
+        localSum = localSum + areas(elementIndex) * sum(field(:,elementIndex))
+      end do
+   
+      call dmpar_sum_real(dminfo, localSum, globalSum)
+       
+   end subroutine computeAreaWeightedGlobalSum
+
+   subroutine computeVolumeWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, h, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+
+      real (kind=RKIND), dimension(nVertLevels, nElements) :: hTimesField
+
+      hTimesField = h*field
+
+      call computeAreaWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, hTimesField, globalSum)
+
+   end subroutine computeVolumeWeightedGlobalSum
+
+   subroutine computeGlobalMin(dminfo, nVertLevels, nElements, field, globalMin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMin
+
+      real (kind=RKIND) :: localMin
+
+      localMin = minval(field)
+      call dmpar_min_real(dminfo, localMin, globalMin)
+
+   end subroutine computeGlobalMin
+
+   subroutine computeGlobalMax(dminfo, nVertLevels, nElements, field, globalMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMax
+
+      real (kind=RKIND) :: localMax
+
+      localMax = maxval(field)
+      call dmpar_max_real(dminfo, localMax, globalMax)
+
+   end subroutine computeGlobalMax
+
+   subroutine computeGlobalVertSumHorizMin(dminfo, nVertLevels, nElements, field, globalMin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMin
+
+      real (kind=RKIND) :: localMin
+
+      localMin = minval(sum(field,1))
+      call dmpar_min_real(dminfo, localMin, globalMin)
+
+   end subroutine computeGlobalVertSumHorizMin
+
+   subroutine computeGlobalVertSumHorizMax(dminfo, nVertLevels, nElements, field, globalMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMax
+
+      real (kind=RKIND) :: localMax
+
+      localMax = maxval(sum(field,1))
+      call dmpar_max_real(dminfo, localMax, globalMax)
+
+   end subroutine computeGlobalVertSumHorizMax
+
+   subroutine computeGlobalVertThicknessWeightedSumHorizMin(dminfo, nVertLevels, nElements, h, field, globalMin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h, field
+      real (kind=RKIND), intent(out) :: globalMin
+
+      real (kind=RKIND) :: localMin
+
+      localMin = minval(sum(h*field,1))
+      call dmpar_min_real(dminfo, localMin, globalMin)
+
+   end subroutine computeGlobalVertThicknessWeightedSumHorizMin
+
+   subroutine computeGlobalVertThicknessWeightedSumHorizMax(dminfo, nVertLevels, nElements, h, field, globalMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h, field
+      real (kind=RKIND), intent(out) :: globalMax
+
+      real (kind=RKIND) :: localMax
+
+      localMax = maxval(sum(h*field,1))
+      call dmpar_max_real(dminfo, localMax, globalMax)
+
+   end subroutine computeGlobalVertThicknessWeightedSumHorizMax
+
+end module global_diagnostics

Copied: trunk/mpas/src/core_ocean/mpas_ocn_mpas_core.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_mpas_core.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_mpas_core.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_mpas_core.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,774 @@
+module mpas_core
+
+   use mpas_framework
+   use mpas_timekeeping
+   use dmpar
+   use test_cases
+
+   use ocn_time_integration
+
+   use ocn_tendency
+
+   use ocn_vel_pressure_grad
+   use ocn_vel_vadv
+   use ocn_vel_hmix
+   use ocn_vel_forcing
+
+   use ocn_tracer_hadv
+   use ocn_tracer_vadv
+   use ocn_tracer_hmix
+   use ocn_restoring
+
+   use ocn_equation_of_state
+
+   use ocn_vmix
+
+   type (io_output_object) :: restart_obj
+   integer :: restart_frame
+
+   integer :: current_outfile_frames
+
+   type (MPAS_Clock_type) :: clock
+
+   integer, parameter :: outputAlarmID = 1
+   integer, parameter :: restartAlarmID = 2
+   integer, parameter :: statsAlarmID = 3
+
+   contains
+
+   subroutine mpas_core_init(domain, startTimeStamp)!{{{
+
+      use configure
+      use grid_types
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain
+      character(len=*), intent(out) :: startTimeStamp
+
+      real (kind=RKIND) :: dt
+      type (block_type), pointer :: block
+      type (dm_info) :: dminfo
+
+      integer :: err
+
+      ! Initialize submodules before initializing blocks.
+      call ocn_timestep_init(err)
+
+      call ocn_vel_pressure_grad_init(err)
+      call ocn_vel_vadv_init(err)
+      call ocn_vel_hmix_init(err)
+      call ocn_vel_forcing_init(err)
+
+      call ocn_tracer_hadv_init(err)
+      call ocn_tracer_vadv_init(err)
+      call ocn_tracer_hmix_init(err)
+      call ocn_restoring_init(err)
+
+      call ocn_vmix_init(err)
+
+      call ocn_equation_of_state_init(err)
+
+      if (.not. config_do_restart) call setup_sw_test_case(domain)
+
+      call compute_maxLevel(domain)
+
+      if (config_vert_grid_type.eq.'isopycnal') then
+         print *, ' Using isopycnal coordinates'
+      elseif (config_vert_grid_type.eq.'zlevel') then
+         print *, ' Using z-level coordinates'
+         call init_ZLevel(domain)
+      else 
+         print *, ' Incorrect choice of config_vert_grid_type:',&amp;
+           config_vert_grid_type
+         call dmpar_abort(dminfo)
+      endif
+
+      if (trim(config_new_btr_variables_from) == 'btr_avg' &amp;
+           .and.trim(config_time_integration) == 'unsplit_explicit') then
+         print *, ' unsplit_explicit option must use',&amp;
+           ' config_new_btr_variables_from==last_subcycle'
+         call dmpar_abort(dminfo)
+      endif
+
+      !
+      ! Initialize core
+      !
+      dt = config_dt
+
+      call simulation_clock_init(domain, dt, startTimeStamp)
+
+      block =&gt; domain % blocklist
+      do while (associated(block))
+         call mpas_init_block(block, block % mesh, dt)
+         block % state % time_levs(1) % state % xtime % scalar = startTimeStamp 
+         block =&gt; block % next
+
+         !dwj 110919 This allows the restorings to grab the indices for
+         ! temperature and salinity tracers from state.
+      end do
+
+   ! mrp 100316 In order for this to work, we need to pass domain % dminfo as an 
+   ! input arguement into mpas_init.  Ask about that later.  For now, there will be
+   ! no initial statistics write.
+   
+   !   call timer_start(&quot;global diagnostics&quot;)
+   !   call computeGlobalDiagnostics(domain % dminfo, block % state % time_levs(1) % state, mesh, 0, dt)
+   !   call timer_stop(&quot;global diagnostics&quot;)
+   !   call output_state_init(output_obj, domain, &quot;OUTPUT&quot;)
+   !   call write_output_frame(output_obj, domain)
+
+      restart_frame = 1
+      current_outfile_frames = 0
+
+   end subroutine mpas_core_init!}}}
+
+   subroutine simulation_clock_init(domain, dt, startTimeStamp)!{{{
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain
+      real (kind=RKIND), intent(in) :: dt
+      character(len=*), intent(out) :: startTimeStamp
+
+      type (MPAS_Time_Type) :: startTime, stopTime, alarmStartTime
+      type (MPAS_TimeInterval_type) :: runDuration, timeStep, alarmTimeStep
+      integer :: ierr
+
+      call MPAS_setTime(curr_time=startTime, dateTimeString=config_start_time, ierr=ierr)
+      call MPAS_setTimeInterval(timeStep, dt=dt, ierr=ierr)
+
+      if (trim(config_run_duration) /= &quot;none&quot;) then
+         call MPAS_setTimeInterval(runDuration, timeString=config_run_duration, ierr=ierr)
+         call MPAS_createClock(clock, startTime=startTime, timeStep=timeStep, runDuration=runDuration, ierr=ierr)
+
+         if (trim(config_stop_time) /= &quot;none&quot;) then
+            call MPAS_setTime(curr_time=stopTime, dateTimeString=config_stop_time, ierr=ierr)
+            if(startTime + runduration /= stopTime) then
+               write(0,*) 'Warning: config_run_duration and config_stop_time are inconsitent: using config_run_duration.'
+            end if
+         end if
+      else if (trim(config_stop_time) /= &quot;none&quot;) then
+         call MPAS_setTime(curr_time=stopTime, dateTimeString=config_stop_time, ierr=ierr)
+         call MPAS_createClock(clock, startTime=startTime, timeStep=timeStep, stopTime=stopTime, ierr=ierr)
+      else
+          write(0,*) 'Error: Neither config_run_duration nor config_stop_time were specified.'
+          call dmpar_finalize(domain % dminfo)
+      end if
+
+      ! set output alarm
+      call MPAS_setTimeInterval(alarmTimeStep, timeString=config_output_interval, ierr=ierr)
+      alarmStartTime = startTime + alarmTimeStep
+      call MPAS_addClockAlarm(clock, outputAlarmID, alarmStartTime, alarmTimeStep, ierr=ierr)
+
+      ! set restart alarm, if necessary
+      if (trim(config_restart_interval) /= &quot;none&quot;) then
+         call MPAS_setTimeInterval(alarmTimeStep, timeString=config_restart_interval, ierr=ierr)
+         alarmStartTime = startTime + alarmTimeStep
+         call MPAS_addClockAlarm(clock, restartAlarmID, alarmStartTime, alarmTimeStep, ierr=ierr)
+      end if
+
+      !TODO: use this code if we desire to convert config_stats_interval to alarms 
+      !(must also change config_stats_interval type to character) 
+      ! set stats alarm, if necessary
+      !if (trim(config_stats_interval) /= &quot;none&quot;) then      
+      !   call MPAS_setTimeInterval(alarmTimeStep, timeString=config_stats_interval, ierr=ierr)
+      !   alarmStartTime = startTime + alarmTimeStep
+      !   call MPAS_addClockAlarm(clock, statsAlarmID, alarmStartTime, alarmTimeStep, ierr=ierr)
+      !end if
+
+      call MPAS_getTime(curr_time=startTime, dateTimeString=startTimeStamp, ierr=ierr)
+
+   end subroutine simulation_clock_init!}}}
+
+   subroutine mpas_init_block(block, mesh, dt)!{{{
+   
+      use grid_types
+      use RBF_interpolation
+      use vector_reconstruction
+   
+      implicit none
+   
+      type (block_type), intent(inout) :: block
+      type (mesh_type), intent(inout) :: mesh
+      real (kind=RKIND), intent(in) :: dt
+      integer :: i, iEdge, iCell, k
+   
+   
+      call ocn_diagnostic_solve(dt, block % state % time_levs(1) % state, mesh)
+
+      call compute_mesh_scaling(mesh)

+      call rbfInterp_initialize(mesh)
+      call init_reconstruct(mesh)
+      call reconstruct(block % state % time_levs(1) % state, mesh)
+
+      ! initialize velocities and tracers on land to be -1e34
+      ! The reconstructed velocity on land will have values not exactly
+      ! -1e34 due to the interpolation of reconstruction.
+
+      do iEdge=1,block % mesh % nEdges
+         ! mrp 101115 note: in order to include flux boundary conditions, the following
+         ! line will need to change.  Right now, set boundary edges between land and 
+         ! water to have zero velocity.
+         block % state % time_levs(1) % state % u % array( &amp;
+             block % mesh % maxLevelEdgeTop % array(iEdge)+1 &amp;
+            :block % mesh % maxLevelEdgeBot % array(iEdge), iEdge) = 0.0
+
+         block % state % time_levs(1) % state % u % array( &amp;
+             block % mesh % maxLevelEdgeBot % array(iEdge)+1: &amp;
+             block % mesh % nVertLevels,iEdge) = 0.0
+! mrp changed to 0
+!             block % mesh % nVertLevels,iEdge) = -1e34
+      end do
+      do iCell=1,block % mesh % nCells
+         block % state % time_levs(1) % state % tracers % array( &amp;
+            :, block % mesh % maxLevelCell % array(iCell)+1 &amp;
+              :block % mesh % nVertLevels,iCell) =  0.0
+! mrp changed to 0
+!              :block % mesh % nVertLevels,iCell) =  -1e34
+
+! mrp 110516 temp, added just to test for conservation of tracers
+         block % state % time_levs(1) % state % tracers % array(3,:,iCell) = 1.0
+
+      end do
+
+      if (.not. config_do_restart) then 
+
+! mrp 110808 add, so that variables are copied to * variables for split explicit
+          do i=2,nTimeLevs
+             call copy_state(block % state % time_levs(i) % state, &amp;
+                             block % state % time_levs(1) % state)
+          end do
+! mrp 110808 add end
+
+
+      else
+          do i=2,nTimeLevs
+             call copy_state(block % state % time_levs(i) % state, &amp;
+                             block % state % time_levs(1) % state)
+          end do
+      endif
+
+   end subroutine mpas_init_block!}}}
+   
+   subroutine mpas_core_run(domain, output_obj, output_frame)!{{{
+   
+      use grid_types
+      use io_output
+      use timer
+   
+      implicit none
+   
+      type (domain_type), intent(inout) :: domain
+      type (io_output_object), intent(inout) :: output_obj
+      integer, intent(inout) :: output_frame
+   
+      integer :: itimestep
+      real (kind=RKIND) :: dt
+      type (block_type), pointer :: block_ptr
+
+      type (MPAS_Time_Type) :: currTime
+      character(len=32) :: timeStamp
+      integer :: ierr
+   
+      ! Eventually, dt should be domain specific
+      dt = config_dt
+
+      currTime = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+      call MPAS_getTime(curr_time=currTime, dateTimeString=timeStamp, ierr=ierr)
+      write(0,*) 'Initial time ', timeStamp
+
+      call write_output_frame(output_obj, output_frame, domain)
+
+      ! During integration, time level 1 stores the model state at the beginning of the
+      !   time step, and time level 2 stores the state advanced dt in time by timestep(...)
+      itimestep = 0
+      do while (.not. MPAS_isClockStopTime(clock))
+
+         itimestep = itimestep + 1
+         call MPAS_advanceClock(clock)
+
+         currTime = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+         call MPAS_getTime(curr_time=currTime, dateTimeString=timeStamp, ierr=ierr)
+         write(0,*) 'Doing timestep ', timeStamp
+
+         call timer_start(&quot;time integration&quot;)
+         call mpas_timestep(domain, itimestep, dt, timeStamp)
+         call timer_stop(&quot;time integration&quot;)
+   
+         ! Move time level 2 fields back into time level 1 for next time step
+         call shift_time_levels_state(domain % blocklist % state)
+      
+         if (MPAS_isAlarmRinging(clock, outputAlarmID, ierr=ierr)) then
+            call MPAS_resetClockAlarm(clock, outputAlarmID, ierr=ierr)
+            if(output_frame == 1) call output_state_init(output_obj, domain, &quot;OUTPUT&quot;, trim(timeStamp)) ! output_frame will always be &gt; 1 here unless it is reset after the output file is finalized
+            call write_output_frame(output_obj, output_frame, domain)
+         end if
+
+         if (MPAS_isAlarmRinging(clock, restartAlarmID, ierr=ierr)) then
+            call MPAS_resetClockAlarm(clock, restartAlarmID, ierr=ierr)
+            if (restart_frame == 1) call output_state_init(restart_obj, domain, &quot;RESTART&quot;)
+            call output_state_for_domain(restart_obj, domain, restart_frame)
+            restart_frame = restart_frame + 1
+         end if
+
+      end do
+
+   end subroutine mpas_core_run!}}}
+   
+   subroutine write_output_frame(output_obj, output_frame, domain)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute diagnostic fields for a domain and write model state to output file
+   !
+   ! Input/Output: domain - contains model state; diagnostic field are computed
+   !                        before returning
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   
+      use grid_types
+      use io_output
+   
+      implicit none
+   
+      integer, intent(inout) :: output_frame
+      type (domain_type), intent(inout) :: domain
+      type (io_output_object), intent(inout) :: output_obj
+   
+      integer :: i, j, k
+      integer :: eoe
+      type (block_type), pointer :: block_ptr
+   
+      block_ptr =&gt; domain % blocklist
+      do while (associated(block_ptr))
+         call compute_output_diagnostics(block_ptr % state % time_levs(1) % state, block_ptr % mesh)
+         block_ptr =&gt; block_ptr % next
+      end do
+   
+      call output_state_for_domain(output_obj, domain, output_frame)
+      output_frame = output_frame + 1
+
+      ! if the maximum number of frames per outfile has been reached, finalize outfile and reset frame
+      if (config_frames_per_outfile &gt; 0) then
+         current_outfile_frames = current_outfile_frames + 1            
+         if(current_outfile_frames &gt;= config_frames_per_outfile) then
+            current_outfile_frames = 0
+            call output_state_finalize(output_obj, domain % dminfo)
+            output_frame = 1
+         end if
+      end if
+   
+   end subroutine write_output_frame!}}}
+   
+   subroutine compute_output_diagnostics(state, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute diagnostic fields for a domain
+   !
+   ! Input: state - contains model prognostic fields
+   !        grid  - contains grid metadata
+   !
+   ! Output: state - upon returning, diagnostic fields will have be computed
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   
+      use grid_types
+   
+      implicit none
+   
+      type (state_type), intent(inout) :: state
+      type (mesh_type), intent(in) :: grid
+   
+      integer :: i, eoe
+      integer :: iEdge, k
+   
+   end subroutine compute_output_diagnostics!}}}
+   
+   subroutine mpas_timestep(domain, itimestep, dt, timeStamp)!{{{
+   
+      use grid_types
+      use timer
+      use global_diagnostics
+   
+      implicit none
+   
+      type (domain_type), intent(inout) :: domain 
+      integer, intent(in) :: itimestep
+      real (kind=RKIND), intent(in) :: dt
+      character(len=*), intent(in) :: timeStamp
+
+      type (block_type), pointer :: block_ptr
+      integer :: ierr
+   
+      call ocn_timestep(domain, dt, timeStamp)
+
+      if (config_stats_interval &gt; 0) then
+          if (mod(itimestep, config_stats_interval) == 0) then
+              block_ptr =&gt; domain % blocklist
+              if (associated(block_ptr % next)) then
+                  write(0,*) 'Error: computeGlobalDiagnostics assumes ',&amp;
+                     'that there is only one block per processor.'
+              end if
+
+          call timer_start(&quot;global diagnostics&quot;)
+          call computeGlobalDiagnostics(domain % dminfo, &amp;
+             block_ptr % state % time_levs(2) % state, block_ptr % mesh, &amp;
+             itimestep, dt)
+          call timer_stop(&quot;global diagnostics&quot;)
+          end if
+      end if
+
+      !TODO: replace the above code block with this if we desire to convert config_stats_interval to use alarms
+      !if (MPAS_isAlarmRinging(clock, statsAlarmID, ierr=ierr)) then
+      !   call MPAS_resetClockAlarm(clock, statsAlarmID, ierr=ierr)
+
+      !   block_ptr =&gt; domain % blocklist
+      !   if (associated(block_ptr % next)) then
+      !      write(0,*) 'Error: computeGlobalDiagnostics assumes ',&amp;
+      !                 'that there is only one block per processor.'
+      !   end if
+   
+      !   call timer_start(&quot;global diagnostics&quot;)
+      !   call computeGlobalDiagnostics(domain % dminfo, &amp;
+      !            block_ptr % state % time_levs(2) % state, block_ptr % mesh, &amp;
+      !            timeStamp, dt)
+      !   call timer_stop(&quot;global diagnostics&quot;)
+      !end if
+
+   end subroutine mpas_timestep!}}}
+
+subroutine init_ZLevel(domain)!{{{
+! Initialize maxLevel and bouncary grid variables.
+
+   use grid_types
+   use configure
+
+   implicit none
+
+   type (domain_type), intent(inout) :: domain
+
+   integer :: i, iCell, iEdge, iVertex, k
+   type (block_type), pointer :: block
+
+   integer :: iTracer, cell, cell1, cell2
+   real (kind=RKIND) :: uhSum, hSum, sshEdge
+   real (kind=RKIND), dimension(:), pointer :: &amp;
+      hZLevel, zMidZLevel, zTopZLevel, &amp;
+      hMeanTopZLevel, hRatioZLevelK, hRatioZLevelKm1
+   real (kind=RKIND), dimension(:,:), pointer :: h
+   integer :: nVertLevels
+
+   ! Initialize z-level grid variables from h, read in from input file.
+   block =&gt; domain % blocklist
+   do while (associated(block))
+
+      h          =&gt; block % state % time_levs(1) % state % h % array
+      hZLevel    =&gt; block % mesh % hZLevel % array
+      zMidZLevel =&gt; block % mesh % zMidZLevel % array
+      zTopZLevel =&gt; block % mesh % zTopZLevel % array
+      nVertLevels = block % mesh % nVertLevels
+      hMeanTopZLevel    =&gt; block % mesh % hMeanTopZLevel % array
+      hRatioZLevelK    =&gt; block % mesh % hRatioZLevelK % array
+      hRatioZLevelKm1    =&gt; block % mesh % hRatioZLevelKm1 % array
+
+      ! These should eventually be in an input file.  For now
+      ! I just read them in from h(:,1).
+      ! Upon restart, the correct hZLevel should be in restart.nc
+      if (.not. config_do_restart) hZLevel = h(:,1)
+
+      ! hZLevel should be in the grid.nc and restart.nc file, 
+      ! and h for k=1 must be specified there as well.

+      zTopZLevel(1) = 0.0
+      do k = 1,nVertLevels
+         zMidZLevel(k) = zTopZLevel(k)-0.5*hZLevel(k)
+         zTopZLevel(k+1) = zTopZLevel(k)-  hZLevel(k)
+      end do
+
+      hMeanTopZLevel(1) = 0.0
+      hRatioZLevelK(1) = 0.0
+      hRatioZLevelKm1(1) = 0.0
+      do k = 2,nVertLevels
+         hMeanTopZLevel(k) = 0.5*(hZLevel(k-1) + hZLevel(k))
+         hRatioZLevelK(k) = 0.5*hZLevel(k)/hMeanTopZLevel(k)
+         hRatioZLevelKm1(k) = 0.5*hZLevel(k-1)/hMeanTopZLevel(k)
+      end do
+
+      ! mrp 110601 For now, h is the variable saved in the restart file
+      ! I am computing SSH here.  In the future, could make smaller 
+      ! restart files for z-Level runs by saving SSH only.
+      do iCell=1,block % mesh % nCells
+
+          block % state % time_levs(1) % state % ssh % array(iCell) &amp; 
+        = block % state % time_levs(1) % state % h % array(1,iCell) &amp; 
+        - block % mesh % hZLevel % array(1)
+      enddo
+
+         ! Compute barotropic velocity at first timestep
+         ! This is only done upon start-up.
+         if     (trim(config_time_integration) == 'unsplit_explicit') then
+            block % state % time_levs(1) % state % uBtr % array(:) = 0.0
+
+              block % state % time_levs(1) % state % uBcl % array(:,:) &amp;
+            = block % state % time_levs(1) % state % u % array(:,:) 
+
+         elseif (trim(config_time_integration) == 'split_explicit') then
+
+            if (config_filter_btr_mode) then
+               do iCell=1,block % mesh % nCells
+                  block % state % time_levs(1) % state % h % array(1,iCell) &amp; 
+                = block % mesh % hZLevel % array(1)

+                  block % state % time_levs(1) % state % ssh % array(iCell) = 0.0
+               enddo
+            endif 
+
+            do iEdge=1,block % mesh % nEdges
+               cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+               cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+               sshEdge = 0.5*( &amp;
+                   block % state % time_levs(1) % state % ssh % array(cell1) &amp; 
+                 + block % state % time_levs(1) % state % ssh % array(cell2) ) 
+
+               ! uBtr = sum(u)/sum(h) on each column
+               uhSum = (sshEdge + block % mesh % hZLevel % array(1)) &amp;
+                  * block % state % time_levs(1) % state % u % array(1,iEdge)
+               hSum = sshEdge + block % mesh % hZLevel % array(1)
+
+               do k=2,block % mesh % maxLevelEdgeTop % array(iEdge)
+                  uhSum = uhSum &amp;
+                     + block % mesh % hZLevel % array(k) &amp;
+                      *block % state % time_levs(1) % state % u % array(k,iEdge)
+                  hSum = hSum &amp;
+                     + block % mesh % hZLevel % array(k)
+               enddo
+               block % state % time_levs(1) % state % uBtr % array(iEdge) = uhSum/hsum
+
+               ! uBcl(k,iEdge) = u(k,iEdge) - uBtr(iEdge)
+               do k=1,block % mesh % maxLevelEdgeTop % array(iEdge)
+                 block % state % time_levs(1) % state % uBcl % array(k,iEdge) &amp;
+                 = block % state % time_levs(1) % state % u % array(k,iEdge) &amp;
+                 - block % state % time_levs(1) % state % uBtr % array(iEdge)
+               enddo
+
+               ! uBcl=0, u=0 on land cells
+               do k=block % mesh % maxLevelEdgeTop % array(iEdge)+1, block % mesh % nVertLevels
+                 block % state % time_levs(1) % state % uBcl % array(k,iEdge) = 0.0
+                 block % state % time_levs(1) % state % u % array(k,iEdge) = 0.0
+               enddo
+            enddo
+
+            if (config_filter_btr_mode) then
+               ! filter uBtr out of initial condition
+                block % state % time_levs(1) % state % u % array(:,:) &amp;
+              = block % state % time_levs(1) % state % uBcl % array(:,:)
+
+               block % state % time_levs(1) % state % uBtr % array(:) = 0.0
+            endif 
+
+         endif
+
+!print *, '11 u ',minval(domain % blocklist % state % time_levs(1) % state % u % array(:,1:domain % blocklist % mesh % nEdgesSolve)), &amp;
+!                maxval(domain % blocklist % state % time_levs(1) % state % u % array(:,1:domain % blocklist % mesh % nEdgesSolve))
+!print *, '11 uBtr ',minval(domain % blocklist % state % time_levs(1) % state % uBtr % array(1:domain % blocklist % mesh % nEdgesSolve)), &amp;
+!                    maxval(domain % blocklist % state % time_levs(1) % state % uBtr % array(1:domain % blocklist % mesh % nEdgesSolve))
+!print *, '11 uBcl ',minval(domain % blocklist % state % time_levs(1) % state % uBcl % array(:,1:domain % blocklist % mesh % nEdgesSolve)), &amp;
+!                    maxval(domain % blocklist % state % time_levs(1) % state % uBcl % array(:,1:domain % blocklist % mesh % nEdgesSolve))
+
+
+! mrp temp testing - is uBcl vert sum zero?
+!            do iEdge=1,block % mesh % nEdges
+!              uhSum = (sshEdge + block % mesh % hZLevel % array(1)) * block % state % time_levs(1) % state % uBcl % array(1,iEdge)
+!              hSum  =  sshEdge + block % mesh % hZLevel % array(1)
+
+!              do k=2,block % mesh % maxLevelEdgeTop % array(iEdge)
+!                 uhSum = uhSum + block % mesh % hZLevel % array(k) *  block % state % time_levs(1) % state % uBcl % array(k,iEdge)
+!                 hSum  =  hSum + block % mesh % hZLevel % array(k)
+!              enddo
+!              block % state % time_levs(1) % state % FBtr % array(iEdge) = uhSum/hSum
+
+!           enddo ! iEdge
+
+!print *, 'uBcl vert sum IC',minval(block % state % time_levs(1) % state % FBtr % array(1:block % mesh % nEdgesSolve)), &amp;
+!                            maxval(block % state % time_levs(1) % state % FBtr % array(1:block % mesh % nEdgesSolve))
+
+! mrp temp testing - is uBcl vert sum zero? end
+
+      block =&gt; block % next
+
+   end do
+
+end subroutine init_ZLevel!}}}
+
+subroutine compute_maxLevel(domain)!{{{
+! Initialize maxLevel and bouncary grid variables.
+
+   use grid_types
+   use configure
+   use constants
+
+   implicit none
+
+   type (domain_type), intent(inout) :: domain
+
+   integer :: i, iCell, iEdge, iVertex, k
+   type (block_type), pointer :: block
+
+   real (kind=RKIND), dimension(:,:), pointer :: h, u, u_src, rho
+   real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+   real (kind=RKIND) :: delta_rho, pi, latCenter, lonCenter, dist
+   real (kind=RKIND) :: centerx, centery
+   integer :: nCells, nEdges, nVertices, nVertLevels, vertexDegree
+
+   integer, dimension(:), pointer :: &amp;
+      maxLevelCell, maxLevelEdgeTop, maxLevelEdgeBot, &amp;
+      maxLevelVertexTop, maxLevelVertexBot
+   integer, dimension(:,:), pointer :: &amp;
+      cellsOnEdge, cellsOnVertex, boundaryEdge, boundaryCell, &amp;
+      boundaryVertex, verticesOnEdge
+
+   ! Initialize z-level grid variables from h, read in from input file.
+   block =&gt; domain % blocklist
+   do while (associated(block))
+
+      maxLevelCell =&gt; block % mesh % maxLevelCell % array
+      maxLevelEdgeTop =&gt; block % mesh % maxLevelEdgeTop % array
+      maxLevelEdgeBot =&gt; block % mesh % maxLevelEdgeBot % array
+      maxLevelVertexTop =&gt; block % mesh % maxLevelVertexTop % array
+      maxLevelVertexBot =&gt; block % mesh % maxLevelVertexBot % array
+      cellsOnEdge    =&gt; block % mesh % cellsOnEdge % array
+      cellsOnVertex  =&gt; block % mesh % cellsOnVertex % array
+      verticesOnEdge =&gt; block % mesh % verticesOnEdge % array
+      boundaryEdge   =&gt; block % mesh % boundaryEdge % array
+      boundaryCell   =&gt; block % mesh % boundaryCell % array
+      boundaryVertex =&gt; block % mesh % boundaryVertex % array
+
+      nCells      = block % mesh % nCells
+      nEdges      = block % mesh % nEdges
+      nVertices   = block % mesh % nVertices
+      nVertLevels = block % mesh % nVertLevels
+      vertexDegree = block % mesh % vertexDegree
+
+      ! for z-grids, maxLevelCell should be in input state
+      ! Isopycnal grid uses all vertical cells
+      if (config_vert_grid_type.eq.'isopycnal') then
+         maxLevelCell(1:nCells) = nVertLevels
+      endif
+      maxLevelCell(nCells+1) = 0
+
+      ! maxLevelEdgeTop is the minimum (shallowest) of the surrounding cells
+      do iEdge=1,nEdges
+         maxLevelEdgeTop(iEdge) = &amp;
+            min( maxLevelCell(cellsOnEdge(1,iEdge)), &amp;
+                 maxLevelCell(cellsOnEdge(2,iEdge)) )
+      end do 
+      maxLevelEdgeTop(nEdges+1) = 0
+
+      ! maxLevelEdgeBot is the maximum (deepest) of the surrounding cells
+      do iEdge=1,nEdges
+         maxLevelEdgeBot(iEdge) = &amp;
+            max( maxLevelCell(cellsOnEdge(1,iEdge)), &amp;
+                 maxLevelCell(cellsOnEdge(2,iEdge)) )
+      end do 
+      maxLevelEdgeBot(nEdges+1) = 0
+
+      ! maxLevelVertexBot is the maximum (deepest) of the surrounding cells
+      do iVertex = 1,nVertices
+         maxLevelVertexBot(iVertex) = maxLevelCell(cellsOnVertex(1,iVertex))
+         do i=2,vertexDegree
+            maxLevelVertexBot(iVertex) = &amp;
+               max( maxLevelVertexBot(iVertex), &amp;
+                    maxLevelCell(cellsOnVertex(i,iVertex)))
+         end do
+      end do 
+      maxLevelVertexBot(nVertices+1) = 0
+
+      ! maxLevelVertexTop is the minimum (shallowest) of the surrounding cells
+      do iVertex = 1,nVertices
+         maxLevelVertexTop(iVertex) = maxLevelCell(cellsOnVertex(1,iVertex))
+         do i=2,vertexDegree
+            maxLevelVertexTop(iVertex) = &amp;
+               min( maxLevelVertexTop(iVertex), &amp;
+                    maxLevelCell(cellsOnVertex(i,iVertex)))
+         end do
+      end do 
+      maxLevelVertexTop(nVertices+1) = 0
+
+      ! set boundary edge
+      boundaryEdge=1
+      do iEdge=1,nEdges
+         boundaryEdge(1:maxLevelEdgeTop(iEdge),iEdge)=0
+      end do 
+
+      !
+      ! Find cells and vertices that have an edge on the boundary
+      !
+      boundaryCell(:,:) = 0
+      do iEdge=1,nEdges
+         do k=1,nVertLevels
+            if (boundaryEdge(k,iEdge).eq.1) then
+               boundaryCell(k,cellsOnEdge(1,iEdge)) = 1
+               boundaryCell(k,cellsOnEdge(2,iEdge)) = 1
+               boundaryVertex(k,verticesOnEdge(1,iEdge)) = 1
+               boundaryVertex(k,verticesOnEdge(2,iEdge)) = 1
+            endif
+         end do
+      end do
+
+      block =&gt; block % next
+   end do
+
+   ! Note: We do not update halos on maxLevel* variables.  I want the
+   ! outside edge of a halo to be zero on each processor.
+
+end subroutine compute_maxLevel!}}}
+   
+   subroutine mpas_core_finalize(domain)!{{{
+   
+      use grid_types
+   
+      implicit none
+
+      integer :: ierr
+
+      type (domain_type), intent(inout) :: domain 
+
+      if (restart_frame &gt; 1) call output_state_finalize(restart_obj, domain % dminfo)
+
+      call MPAS_destroyClock(clock, ierr)
+
+   end subroutine mpas_core_finalize!}}}
+
+   subroutine compute_mesh_scaling(mesh)!{{{
+
+      use grid_types
+      use configure
+
+      implicit none
+
+      type (mesh_type), intent(inout) :: mesh
+
+      integer :: iEdge, cell1, cell2
+      real (kind=RKIND), dimension(:), pointer :: meshDensity, meshScalingDel2, meshScalingDel4
+
+      meshDensity =&gt; mesh % meshDensity % array
+      meshScalingDel2 =&gt; mesh % meshScalingDel2 % array
+      meshScalingDel4 =&gt; mesh % meshScalingDel4 % array
+
+      !
+      ! Compute the scaling factors to be used in the del2 and del4 dissipation
+      !
+      meshScalingDel2(:) = 1.0
+      meshScalingDel4(:) = 1.0
+      if (config_h_ScaleWithMesh) then
+         do iEdge=1,mesh%nEdges
+            cell1 = mesh % cellsOnEdge % array(1,iEdge)
+            cell2 = mesh % cellsOnEdge % array(2,iEdge)
+            meshScalingDel2(iEdge) = 1.0 / ( (meshDensity(cell1) + meshDensity(cell2) )/2.0)**(5.0/12.0)
+            meshScalingDel4(iEdge) = 1.0 / ( (meshDensity(cell1) + meshDensity(cell2) )/2.0)**(5.0/6.0)
+         end do
+      end if
+
+   end subroutine compute_mesh_scaling!}}}
+
+end module mpas_core
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_restoring.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_restoring.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_restoring.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_restoring.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,182 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_restoring
+!
+!&gt; \brief MPAS ocean restoring
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  tendencies for restoring.
+!
+!-----------------------------------------------------------------------
+
+module ocn_restoring
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_restoring_tend, &amp;
+             ocn_restoring_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: restoringOn !&lt; Flag to turn on/off resotring
+
+   real (kind=RKIND) :: temperatureTimeScale, salinityTimeScale !&lt; restoring timescales
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_restoring_tend
+!
+!&gt; \brief   Computes tendency term for restoring
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the restoring tendency for tracers
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_restoring_tend(grid, h, indexT, indexS, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h    !&lt; Input: thickness
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers !&lt; Input: tracer quantities
+
+      integer, intent(in) :: indexT !&lt; Input: index for temperature
+      integer, intent(in) :: indexS !&lt; Input: index for salinity
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCellsSolve, k
+
+      real (kind=RKIND), dimension(:), pointer :: temperatureRestore, salinityRestore
+
+      err = 0
+
+      if(.not.restoringOn) return
+
+      nCellsSolve = grid % nCellsSolve
+
+      temperatureRestore =&gt; grid % temperatureRestore % array
+      salinityRestore =&gt; grid % salinityRestore % array
+
+      k = 1  ! restoring only in top layer
+      do iCell=1,nCellsSolve
+
+        tend(indexT, k, iCell) = tend(indexT, k, iCell)  &amp;
+             - h(k,iCell)*(tracers(indexT, k, iCell) - temperatureRestore(iCell)) &amp;
+             / (temperatureTimeScale * 86400.0)
+
+        tend(indexS, k, iCell) = tend(indexS, k, iCell)  &amp;
+             - h(k,iCell)*(tracers(indexS, k, iCell) - salinityRestore(iCell)) &amp;
+             / (salinityTimeScale * 86400.0)
+
+!       write(6,10) iCell, tracers(indexT, k, iCell), &amp;
+!              temperatureRestore(iCell), tracers(indexT, k, iCell), &amp;
+!             (tracers(indexT, k, iCell) - temperatureRestore(iCell)) &amp;
+!             / (config_restoreT_timescale * 86400.0)
+
+      enddo
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_restoring_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_restoring_init
+!
+!&gt; \brief   Initializes ocean tracer restoring
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  restoring in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_restoring_init(err)!{{{
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      restoringOn = .false.
+
+      if(config_restoreTS) then
+          restoringOn = .true.
+          temperatureTimeScale = config_restoreT_timescale
+          salinityTimeScale = config_restoreS_timescale
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_restoring_init!}}}
+
+!***********************************************************************
+
+end module ocn_restoring
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tendency.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tendency.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tendency.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tendency.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,1317 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tendency
+!
+!&gt; \brief MPAS ocean tendency driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   23 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routines for computing
+!&gt;  various tendencies for the ocean. As well as routines
+!&gt;  for computing diagnostic variables, and other quantities
+!&gt;  such as wTop.
+!
+!-----------------------------------------------------------------------
+
+module ocn_tendency
+
+   use grid_types
+   use configure
+   use constants
+   use timer
+
+   use ocn_thick_hadv
+   use ocn_thick_vadv
+
+   use ocn_vel_coriolis
+   use ocn_vel_pressure_grad
+   use ocn_vel_vadv
+   use ocn_vel_hmix
+   use ocn_vel_forcing
+
+   use ocn_tracer_hadv
+   use ocn_tracer_vadv
+   use ocn_tracer_hmix
+   use ocn_restoring
+
+   use ocn_equation_of_state
+   use ocn_vmix
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tend_h, &amp;
+             ocn_tend_u, &amp;
+             ocn_tend_scalar, &amp;
+             ocn_diagnostic_solve, &amp;
+             ocn_wtop, &amp;
+             ocn_fuperp
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tend_h
+!
+!&gt; \brief   Computes thickness tendency
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the thickness tendency for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tend_h(tend, s, d, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute height and normal wind tendencies, as well as diagnostic variables
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      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;
+        vertex1, vertex2, eoe, i, j, err
+
+! mrp 110512 I just split compute_tend into compute_tend_u and ocn_tend_h.
+!  Most of these variables can be removed, but at a later time.
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: flux, vorticity_abs, h_vertex, workpv, q, &amp;
+        upstream_bias, wTopEdge, rho0Inv, r
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel 
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_h, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+      call timer_start(&quot;ocn_tend_h&quot;)
+
+      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
+      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
+      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
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      tend_h      =&gt; tend % h % array
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      !
+      ! height tendency: start accumulating tendency terms
+      !
+      tend_h = 0.0
+
+      !
+      ! height tendency: horizontal advection term -</font>
<font color="blue">abla\cdot ( hu)
+      !
+      ! See Ringler et al. (2010) jcp paper, eqn 19, 21, and fig. 3. 
+      ! for explanation of divergence operator.
+      !
+      ! for z-level, only compute height tendency for top layer.
+
+      call timer_start(&quot;ocn_tend_h-horiz adv&quot;)
+
+      call ocn_thick_hadv_tend(grid, u, h_edge, tend_h, err)
+
+      call timer_stop(&quot;ocn_tend_h-horiz adv&quot;)
+
+      !
+      ! height tendency: vertical advection term -d/dz(hw)
+      !
+      ! Vertical advection computed for top layer of a z grid only.
+      call timer_start(&quot;ocn_tend_h-vert adv&quot;)
+
+      call ocn_thick_vadv_tend(grid, wtop, tend_h, err)
+
+      call timer_stop(&quot;ocn_tend_h-vert adv&quot;)
+      call timer_stop(&quot;ocn_tend_h&quot;)
+   
+   end subroutine ocn_tend_h!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tend_u
+!
+!&gt; \brief   Computes velocity tendency
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the velocity tendency for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tend_u(tend, s, d, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute height and normal wind tendencies, as well as diagnostic variables
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (tend_type), intent(inout) :: tend
+      type (state_type), intent(in) :: s
+      type (diagnostics_type), intent(in) :: d
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into ocn_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve, err
+      real (kind=RKIND) :: flux, vorticity_abs, h_vertex, workpv, q, &amp;
+        upstream_bias, wTopEdge, rho0Inv, r, visc_vorticity_coef
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel, meshScalingDel2, meshScalingDel4
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;ocn_tend_u&quot;)
+
+      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
+      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
+      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
+! mrp 110516 cleanup fvertex fedge not used in this subroutine
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      tend_u      =&gt; tend % u % array
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      u_src =&gt; grid % u_src % array
+
+      meshScalingDel2 =&gt; grid % meshScalingDel2 % array
+      meshScalingDel4 =&gt; grid % meshScalingDel4 % array
+
+      !
+      ! velocity tendency: start accumulating tendency terms
+      !
+      ! mrp 110516 efficiency: could remove next line and have first tend_u operation not be additive
+      tend_u(:,:) = 0.0
+
+      !
+      ! velocity tendency: nonlinear Coriolis term and grad of kinetic energy
+      !
+
+      call timer_start(&quot;ocn_tend_u-coriolis&quot;)
+
+      call ocn_vel_coriolis_tend(grid, pv_edge, h_edge, u, ke, tend_u, err)
+
+      call timer_stop(&quot;ocn_tend_u-coriolis&quot;)
+
+      !
+      ! velocity tendency: vertical advection term -w du/dz
+      !
+      call timer_start(&quot;ocn_tend_u-vert adv&quot;)
+
+      call ocn_vel_vadv_tend(grid, u, wtop, tend_u, err)
+
+      call timer_stop(&quot;ocn_tend_u-vert adv&quot;)
+
+      !
+      ! velocity tendency: pressure gradient
+      !
+      call timer_start(&quot;ocn_tend_u-pressure grad&quot;)
+
+      if (config_vert_grid_type.eq.'isopycnal') then
+          call ocn_vel_pressure_grad_tend(grid, MontPot, tend_u, err)
+      elseif (config_vert_grid_type.eq.'zlevel') then
+          call ocn_vel_pressure_grad_tend(grid, pressure, tend_u, err)
+      end if
+
+      call timer_stop(&quot;ocn_tend_u-pressure grad&quot;)
+
+      !
+      ! velocity tendency: del2 dissipation, </font>
<font color="black">u_2 </font>
<font color="blue">abla^2 u
+      !   computed as </font>
<font color="black">u( </font>
<font color="black">abla divergence + k \times </font>
<font color="blue">abla vorticity )
+      !   strictly only valid for config_h_mom_eddy_visc2 == constant
+      !
+      call timer_start(&quot;ocn_tend_u-horiz mix&quot;)
+
+      call ocn_vel_hmix_tend(grid, divergence, vorticity, tend_u, err)
+
+      call timer_stop(&quot;ocn_tend_u-horiz mix&quot;)
+
+      !
+      ! velocity tendency: forcing and bottom drag
+      !
+      ! mrp 101115 note: in order to include flux boundary conditions, we will need to 
+      ! know the bottom edge with nonzero velocity and place the drag there.
+
+      call timer_start(&quot;ocn_tend_u-forcings&quot;)
+
+      call ocn_vel_forcing_tend(grid, u, u_src, ke_edge, h_edge, tend_u, err)
+
+      call timer_stop(&quot;ocn_tend_u-forcings&quot;)
+
+      !
+      ! velocity tendency: vertical mixing d/dz( nu_v du/dz))
+      !
+      if (.not.config_implicit_vertical_mix) then
+          call timer_start(&quot;ocn_tend_u-explicit vert mix&quot;)
+
+          call ocn_vel_vmix_tend_explicit(grid, u, h_edge, vertvisctopofedge, tend_u, err)
+
+          call timer_stop(&quot;ocn_tend_u-explicit vert mix&quot;)
+      endif
+      call timer_stop(&quot;ocn_tend_u&quot;)
+
+   end subroutine ocn_tend_u!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tendSalar
+!
+!&gt; \brief   Computes scalar tendency
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the scalar (tracer) tendency for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tend_scalar(tend, s, d, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !        note: the variable s % tracers really contains the tracers, 
+   !              not tracers*h
+   !
+   ! Output: tend - computed scalar tendencies
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      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;
+        nEdges, nCells, nCellsSolve, nVertLevels, num_tracers, err
+      real (kind=RKIND) :: invAreaCell1, invAreaCell2, tracer_turb_flux
+      real (kind=RKIND) :: flux, tracer_edge, r
+      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, vertDiffTopOfCell
+      real (kind=RKIND), dimension(:,:,:), pointer :: &amp;
+        tracers, tend_tr
+      integer, dimension(:,:), pointer :: boundaryEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: cellsOnEdge, boundaryCell
+      real (kind=RKIND), dimension(:), pointer :: zTopZLevel,zMidZLevel, &amp;
+         hRatioZLevelK, hRatioZLevelKm1, meshScalingDel2, meshScalingDel4
+      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
+
+
+      real (kind=RKIND) :: d2fdx2_cell1, d2fdx2_cell2
+      real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
+      real (kind=RKIND) :: coef_3rd_order, flux3Coef, cSignWTop
+
+      integer :: index_temperature, index_salinity, rrr
+      real (kind=RKIND), dimension(:), pointer :: temperatureRestore, salinityRestore
+
+      call timer_start(&quot;ocn_tend_scalar&quot;)
+
+      u           =&gt; s % u % array
+      h           =&gt; s % h % array
+      boundaryCell=&gt; grid % boundaryCell % array
+      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
+                  
+      areaCell          =&gt; grid % areaCell % array
+      cellsOnEdge       =&gt; grid % cellsOnEdge % array
+      dvEdge            =&gt; grid % dvEdge % array
+      dcEdge            =&gt; grid % dcEdge % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      hRatioZLevelK    =&gt; grid % hRatioZLevelK % array
+      hRatioZLevelKm1    =&gt; grid % hRatioZLevelKm1 % array
+      boundaryEdge      =&gt; grid % boundaryEdge % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      nEdges      = grid % nEdges
+      nCells      = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      nVertLevels = grid % nVertLevels
+      num_tracers = s % num_tracers
+
+      meshScalingDel2 =&gt; grid % meshScalingDel2 % array
+      meshScalingDel4 =&gt; grid % meshScalingDel4 % array
+
+
+      deriv_two   =&gt; grid % deriv_two % array
+
+      !
+      ! initialize tracer tendency (RHS of tracer equation) to zero.
+      !
+      tend_tr(:,:,:) = 0.0
+
+      !
+      ! tracer tendency: horizontal advection term -div( h \phi u)
+      !
+      ! mrp 101115 note: in order to include flux boundary conditions, we will need to 
+      ! assign h_edge for maxLevelEdgeTop:maxLevelEdgeBot in the compute_solve_diagnostics
+      ! and then change maxLevelEdgeTop to maxLevelEdgeBot in the following section.
+      ! tracer_edge at the boundary will also need to be defined for flux boundaries.
+
+      call timer_start(&quot;ocn_tend_scalar-horiz adv&quot;)
+
+      call ocn_tracer_hadv_tend(grid, u, h_edge, tracers, tend_tr, err)
+
+      call timer_stop(&quot;ocn_tend_scalar-horiz adv&quot;)
+
+
+      !
+      ! tracer tendency: vertical advection term -d/dz( h \phi w)
+      !
+
+      call timer_start(&quot;ocn_tend_scalar-vert adv&quot;)
+
+      call ocn_tracer_vadv_tend(grid, wtop, tracers, tend_tr, err)
+
+      call timer_stop(&quot;ocn_tend_scalar-vert adv&quot;)
+
+      !
+      ! tracer tendency: del2 horizontal tracer diffusion, div(h \kappa_2 </font>
<font color="gray">abla \phi)
+      !
+      call timer_start(&quot;ocn_tend_scalar-horiz diff&quot;)
+
+      call ocn_tracer_hmix_tend(grid, h_edge, tracers, tend_tr, err)
+
+      call timer_stop(&quot;ocn_tend_scalar-horiz diff&quot;)
+
+! mrp 110516 printing
+!print *, 'tend_tr 1',minval(tend_tr(3,1,1:nCells)),&amp;
+!                   maxval(tend_tr(3,1,1:nCells))
+!print *, 'tracer  1',minval(tracers(3,1,1:nCells)),&amp;
+!                   maxval(tracers(3,1,1:nCells))
+! mrp 110516 printing end
+
+      !
+      ! tracer tendency: vertical diffusion h d/dz( \kappa_v d\phi/dz)
+      !
+      if (.not.config_implicit_vertical_mix) then
+         call timer_start(&quot;ocn_tend_scalar-explicit vert diff&quot;)
+
+         call ocn_tracer_vmix_tend_explicit(grid, h, vertdifftopofcell, tracers, tend_tr, err)
+
+         call timer_stop(&quot;ocn_tend_scalar-explicit vert diff&quot;)
+      endif
+
+! mrp 110516 printing
+!print *, 'tend_tr 2',minval(tend_tr(3,1,1:nCells)),&amp;
+!                   maxval(tend_tr(3,1,1:nCells))
+! mrp 110516 printing end
+
+      !
+      ! add restoring to T and S in top model layer
+      !
+      call timer_start(&quot;ocn_tend_scalar-restoring&quot;)
+
+      call ocn_restoring_tend(grid, h, s%index_temperature, s%index_salinity, tracers, tend_tr, err)
+
+      call timer_stop(&quot;ocn_tend_scalar-restoring&quot;)
+
+ 10   format(2i8,10e20.10)
+      call timer_stop(&quot;ocn_tend_scalar&quot;)
+
+   end subroutine ocn_tend_scalar!}}}
+
+!***********************************************************************
+!
+!  routine ocn_diagnostic_solve
+!
+!&gt; \brief   Computes diagnostic variables
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the diagnostic variables for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_diagnostic_solve(dt, s, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute diagnostic fields used in the tendency computations
+   !
+   ! Input: grid - grid metadata
+   !
+   ! Output: s - computed diagnostics
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      real (kind=RKIND), intent(in) :: dt
+      type (state_type), intent(inout) :: s
+      type (mesh_type), intent(in) :: grid
+
+
+      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, fCoef, err
+
+
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        hZLevel
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, w, pressure,&amp;
+        circulation, vorticity, ke, ke_edge, MontPot, wTop, &amp;
+        pv_edge, pv_vertex, pv_cell, gradPVn, gradPVt, divergence, &amp;
+        rho, 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
+
+      call timer_start(&quot;ocn_diagnostic_solve&quot;)
+
+      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
+      rho         =&gt; s % rho % array
+      tracers     =&gt; s % tracers % array
+      MontPot     =&gt; s % MontPot % array
+      pressure    =&gt; s % pressure % array
+
+      weightsOnEdge     =&gt; grid % weightsOnEdge % 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 height on cell edges at velocity locations
+      !   Namelist options control the order of accuracy of the reconstructed h_edge value
+      !
+      ! mrp 101115 note: in order to include flux boundary conditions, we will need to 
+      ! assign h_edge for maxLevelEdgeTop:maxLevelEdgeBot in the following section
+
+      ! mrp 110516 efficiency note: For z-level, only do this on level 1.  h_edge for all
+      ! lower levels is defined by hZlevel.
+
+      call timer_start(&quot;ocn_diagnostic_solve-hEdge&quot;)
+
+      coef_3rd_order = 0.
+      if (config_thickness_adv_order == 3) coef_3rd_order = 1.0
+      if (config_thickness_adv_order == 3 .and. config_monotonic) coef_3rd_order = 0.25
+
+      if (config_thickness_adv_order == 2) then
+          call timer_start(&quot;ocn_diagnostic_solve-hEdge 2&quot;)
+
+         do iEdge=1,nEdges
+            cell1 = cellsOnEdge(1,iEdge)
+            cell2 = cellsOnEdge(2,iEdge)
+            do k=1,maxLevelEdgeTop(iEdge)
+               h_edge(k,iEdge) = 0.5 * (h(k,cell1) + h(k,cell2))
+            end do
+         end do
+          call timer_stop(&quot;ocn_diagnostic_solve-hEdge 2&quot;)
+
+      else if (config_thickness_adv_order == 3) then
+          call timer_start(&quot;ocn_diagnostic_solve-hEdge 3&quot;)
+
+         do iEdge=1,nEdges
+            cell1 = cellsOnEdge(1,iEdge)
+            cell2 = cellsOnEdge(2,iEdge)
+
+            do k=1,maxLevelEdgeTop(iEdge)
+
+               d2fdx2_cell1 = 0.0
+               d2fdx2_cell2 = 0.0
+
+               !-- if not a boundary cell
+               if(boundaryCell(k,cell1).eq.0.and.boundaryCell(k,cell2).eq.0) then
+
+                  d2fdx2_cell1 = deriv_two(1,1,iEdge) * h(k,cell1)
+                  d2fdx2_cell2 = deriv_two(1,2,iEdge) * h(k,cell2)
+
+                  !-- all edges of cell 1
+                  do i=1, grid % nEdgesOnCell % array (cell1)
+                          d2fdx2_cell1 = d2fdx2_cell1 + &amp;
+                          deriv_two(i+1,1,iEdge) * h(k,grid % CellsOnCell % array (i,cell1))
+                  end do
+
+                  !-- all edges of cell 2
+                  do i=1, grid % nEdgesOnCell % array (cell2)
+                          d2fdx2_cell2 = d2fdx2_cell2 + &amp;
+                          deriv_two(i+1,2,iEdge) * h(k,grid % CellsOnCell % array (i,cell2))
+                  end do
+
+               endif
+
+               !-- if u &gt; 0:
+               if (u(k,iEdge) &gt; 0) then
+                  h_edge(k,iEdge) =     &amp;
+                       0.5*(h(k,cell1) + h(k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12.          &amp;
+                       -(dcEdge(iEdge) **2) * coef_3rd_order*(d2fdx2_cell1 - d2fdx2_cell2) / 12.
+               !-- else u &lt;= 0:
+               else
+                  h_edge(k,iEdge) =     &amp;
+                       0.5*(h(k,cell1) + h(k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12.          &amp;
+                       +(dcEdge(iEdge) **2) * coef_3rd_order*(d2fdx2_cell1 - d2fdx2_cell2) / 12.
+               end if
+
+            end do   ! do k
+         end do         ! do iEdge
+
+          call timer_stop(&quot;ocn_diagnostic_solve-hEdge 3&quot;)
+      else  if (config_thickness_adv_order == 4) then
+          call timer_start(&quot;ocn_diagnostic_solve-hEdge 4&quot;)
+
+         do iEdge=1,nEdges
+            cell1 = cellsOnEdge(1,iEdge)
+            cell2 = cellsOnEdge(2,iEdge)
+
+            do k=1,maxLevelEdgeTop(iEdge)
+
+               d2fdx2_cell1 = 0.0
+               d2fdx2_cell2 = 0.0
+
+               !-- if not a boundary cell
+               if(boundaryCell(k,cell1).eq.0.and.boundaryCell(k,cell2).eq.0) then
+
+                  d2fdx2_cell1 = deriv_two(1,1,iEdge) * h(k,cell1)
+                  d2fdx2_cell2 = deriv_two(1,2,iEdge) * h(k,cell2)
+
+                  !-- all edges of cell 1
+                  do i=1, grid % nEdgesOnCell % array (cell1)
+                          d2fdx2_cell1 = d2fdx2_cell1 + &amp;
+                          deriv_two(i+1,1,iEdge) * h(k,grid % CellsOnCell % array (i,cell1))
+                  end do
+
+                  !-- all edges of cell 2
+                  do i=1, grid % nEdgesOnCell % array (cell2)
+                          d2fdx2_cell2 = d2fdx2_cell2 + &amp;
+                          deriv_two(i+1,2,iEdge) * h(k,grid % CellsOnCell % array (i,cell2))
+                  end do
+
+               endif
+
+               h_edge(k,iEdge) =   &amp;
+                    0.5*(h(k,cell1) + h(k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12.
+
+            end do   ! do k
+         end do         ! do iEdge
+
+         call timer_stop(&quot;ocn_diagnostic_solve-hEdge 4&quot;)
+      endif   ! if(config_thickness_adv_order == 2)
+      call timer_stop(&quot;ocn_diagnostic_solve-hEdge&quot;)
+
+      !
+      ! set the velocity and height at dummy address
+      !    used -1e34 so error clearly occurs if these values are used.
+      !
+!mrp 110516 change to zero, change back later:
+      u(:,nEdges+1) = -1e34
+      h(:,nCells+1) = -1e34
+      tracers(s % index_temperature,:,nCells+1) = -1e34
+      tracers(s % index_salinity,:,nCells+1) = -1e34
+
+      !
+      ! Compute circulation and relative vorticity at each vertex
+      !
+      circulation(:,:) = 0.0
+      do iEdge=1,nEdges
+         vertex1 = verticesOnEdge(1,iEdge)
+         vertex2 = verticesOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeBot(iEdge)
+            circulation(k,vertex1) = circulation(k,vertex1) - dcEdge(iEdge) * u(k,iEdge)
+            circulation(k,vertex2) = circulation(k,vertex2) + dcEdge(iEdge) * u(k,iEdge)
+         end do
+      end do
+      do iVertex=1,nVertices
+         do k=1,maxLevelVertexBot(iVertex)
+            vorticity(k,iVertex) = circulation(k,iVertex) / areaTriangle(iVertex)
+         end do
+      end do
+
+      !
+      ! Compute the divergence at each cell center
+      !
+      divergence(:,:) = 0.0
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeBot(iEdge)
+             divergence(k,cell1) = divergence(k,cell1) + u(k,iEdge)*dvEdge(iEdge)
+             divergence(k,cell2) = divergence(k,cell2) - u(k,iEdge)*dvEdge(iEdge)
+         enddo
+      end do
+      do iCell = 1,nCells
+         r = 1.0 / areaCell(iCell)
+         do k = 1,maxLevelCell(iCell)
+            divergence(k,iCell) = divergence(k,iCell) * r
+         enddo
+      enddo
+
+      !
+      ! Compute kinetic energy in each cell
+      !
+      ke(:,:) = 0.0
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeBot(iEdge)
+              ke(k,cell1) = ke(k,cell1) + 0.25 * dcEdge(iEdge) * dvEdge(iEdge) * u(k,iEdge)**2.0
+              ke(k,cell2) = ke(k,cell2) + 0.25 * dcEdge(iEdge) * dvEdge(iEdge) * u(k,iEdge)**2.0
+         enddo
+      end do
+      do iCell = 1,nCells
+         do k = 1,maxLevelCell(iCell)
+            ke(k,iCell) = ke(k,iCell) / areaCell(iCell)
+         enddo
+      enddo
+
+      !
+      ! Compute v (tangential) velocities
+      !
+      v(:,:) = 0.0
+      do iEdge = 1,nEdges
+         do i=1,nEdgesOnEdge(iEdge)
+            eoe = edgesOnEdge(i,iEdge)
+            ! mrp 101115 note: in order to include flux boundary conditions,
+            ! the following loop may need to change to maxLevelEdgeBot
+            do k = 1,maxLevelEdgeTop(iEdge) 
+               v(k,iEdge) = v(k,iEdge) + weightsOnEdge(i,iEdge) * u(k, eoe)
+            end do
+         end do
+      end do
+
+      !
+      ! Compute ke on cell edges at velocity locations for quadratic bottom drag. 
+      !
+      ! mrp 101025 efficiency note: we could get rid of ke_edge completely by 
+      ! using sqrt(u(k,iEdge)**2 + v(k,iEdge)**2) in its place elsewhere.
+      ke_edge = 0.0  !mrp remove 0 for efficiency
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeTop(iEdge)
+            ke_edge(k,iEdge) = 0.5 * (ke(k,cell1) + ke(k,cell2))
+         end do
+      end do
+
+      !
+      ! Compute height at vertices, pv at vertices, and average pv to edge locations
+      !  ( this computes pv_vertex at all vertices bounding real cells and distance-1 ghost cells )
+      !
+      if (trim(config_time_integration) == 'RK4') then
+         ! for RK4, PV is really PV = (eta+f)/h
+         fCoef = 1
+      elseif (trim(config_time_integration) == 'split_explicit' &amp;
+          .or.trim(config_time_integration) == 'unsplit_explicit') then
+         ! for split explicit, PV is eta/h because f is added separately to the momentum forcing.
+! mrp temp, new should be:
+         fCoef = 0
+! old, for testing:
+!         fCoef = 1
+      end if
+
+      do iVertex = 1,nVertices
+         do k=1,maxLevelVertexBot(iVertex)
+            h_vertex = 0.0
+            do i=1,vertexDegree
+               h_vertex = h_vertex + h(k,cellsOnVertex(i,iVertex)) * kiteAreasOnVertex(i,iVertex)
+            end do
+            h_vertex = h_vertex / areaTriangle(iVertex)
+
+            pv_vertex(k,iVertex) = (fCoef*fVertex(iVertex) + vorticity(k,iVertex)) / h_vertex
+         end do
+      end do
+
+      !
+      ! Compute pv at cell centers
+      !    ( this computes pv_cell for all real cells and distance-1 ghost cells )
+      !
+      pv_cell(:,:) = 0.0
+      do iVertex = 1,nVertices
+         do i=1,vertexDegree
+            iCell = cellsOnVertex(i,iVertex)
+            do k = 1,maxLevelCell(iCell)
+               pv_cell(k,iCell) = pv_cell(k,iCell)  &amp;
+                  + kiteAreasOnVertex(i, iVertex) * pv_vertex(k, iVertex) &amp;
+                    / areaCell(iCell)
+            enddo
+         enddo
+      enddo
+
+      !
+      ! Compute pv at the edges
+      !   ( this computes pv_edge at all edges bounding real cells )
+      !
+      pv_edge(:,:) = 0.0
+      do iVertex = 1,nVertices
+         do i=1,vertexDegree
+            iEdge = edgesOnVertex(i,iVertex)
+            do k=1,maxLevelEdgeBot(iEdge)
+               pv_edge(k,iEdge) =  pv_edge(k,iEdge) + 0.5 * pv_vertex(k,iVertex)
+            enddo
+        end do
+      end do
+
+      !
+      ! Compute gradient of PV in normal direction
+      !   ( this computes gradPVn for all edges bounding real cells )
+      !
+      gradPVn(:,:) = 0.0
+      do iEdge = 1,nEdges
+         do k=1,maxLevelEdgeTop(iEdge)
+            gradPVn(k,iEdge) = (  pv_cell(k,cellsOnEdge(2,iEdge)) &amp;
+                                - pv_cell(k,cellsOnEdge(1,iEdge))) &amp;
+                               / dcEdge(iEdge)
+         enddo
+      enddo
+
+      !
+      ! Compute gradient of PV in the tangent direction
+      !   ( this computes gradPVt at all edges bounding real cells and distance-1 ghost cells )
+      !
+      do iEdge = 1,nEdges
+         do k = 1,maxLevelEdgeBot(iEdge)
+           gradPVt(k,iEdge) = (  pv_vertex(k,verticesOnEdge(2,iEdge)) &amp;
+                               - pv_vertex(k,verticesOnEdge(1,iEdge))) &amp;
+                                 /dvEdge(iEdge)
+         enddo
+      enddo
+
+      !
+      ! Modify PV edge with upstream bias.
+      !
+      do iEdge = 1,nEdges
+         do k = 1,maxLevelEdgeBot(iEdge)
+           pv_edge(k,iEdge) = pv_edge(k,iEdge) &amp;
+             - 0.5 * dt* (  u(k,iEdge) * gradPVn(k,iEdge) &amp;
+                          + v(k,iEdge) * gradPVt(k,iEdge) )
+         enddo
+      enddo
+
+      !
+      ! equation of state
+      !
+      ! For an isopycnal model, density should remain constant.
+      ! For zlevel, calculate in-situ density
+      if (config_vert_grid_type.eq.'zlevel') then
+         call ocn_equation_of_state_rho(s, grid, 0, 'relative', err)
+      ! mrp 110324 In order to visualize rhoDisplaced, include the following
+         call ocn_equation_of_state_rho(s, grid, 1, 'relative', err)
+      endif
+
+      !
+      ! Pressure
+      ! This section must be after computing rho
+      !
+      if (config_vert_grid_type.eq.'isopycnal') then
+
+        ! For Isopycnal model.
+        ! Compute pressure at top of each layer, and then
+        ! Montgomery Potential.
+        allocate(pTop(nVertLevels))
+        do iCell=1,nCells
+
+           ! assume atmospheric pressure at the surface is zero for now.
+           pTop(1) = 0.0
+           ! For isopycnal mode, p is the Montgomery Potential.
+           ! At top layer it is g*SSH, where SSH may be off by a 
+           ! constant (ie, h_s can be relative to top or bottom)
+           MontPot(1,iCell) = gravity &amp;
+              * (h_s(iCell) + sum(h(1:nVertLevels,iCell)))
+
+           do k=2,nVertLevels
+              pTop(k) = pTop(k-1) + rho(k-1,iCell)*gravity* h(k-1,iCell)
+
+              ! from delta M = p delta / rho
+              MontPot(k,iCell) = MontPot(k-1,iCell) &amp;
+                 + pTop(k)*(1.0/rho(k,iCell) - 1.0/rho(k-1,iCell)) 
+           end do
+
+        end do
+        deallocate(pTop)
+
+      elseif (config_vert_grid_type.eq.'zlevel') then
+
+        ! For z-level model.
+        ! Compute pressure at middle of each level.  
+        ! At k=1, where p is pressure at a depth of hZLevel(1)/2, not
+        ! pressure at middle of layer including SSH.
+
+        do iCell=1,nCells
+           ! compute pressure for z-level coordinates
+           ! assume atmospheric pressure at the surface is zero for now.
+
+           pressure(1,iCell) = rho(1,iCell)*gravity &amp;
+              * (h(1,iCell)-0.5*hZLevel(1)) 
+
+           do k=2,maxLevelCell(iCell)
+              pressure(k,iCell) = pressure(k-1,iCell)  &amp;
+                + 0.5*gravity*(  rho(k-1,iCell)*hZLevel(k-1) &amp;
+                               + rho(k  ,iCell)*hZLevel(k  ))
+           end do
+
+        end do
+
+      endif
+
+      call ocn_wtop(s,grid)
+
+      call timer_stop(&quot;ocn_diagnostic_solve&quot;)
+
+   end subroutine ocn_diagnostic_solve!}}}
+
+!***********************************************************************
+!
+!  routine ocn_wtop
+!
+!&gt; \brief   Computes vertical velocity
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical velocity in the top layer for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_wtop(s, 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 (mesh_type), intent(in) :: grid
+
+      ! mrp 110512 could clean this out, remove pointers?
+      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(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        hZLevel
+      real (kind=RKIND), dimension(:,:), pointer :: u,wTop
+      real (kind=RKIND), dimension(:,:), allocatable:: div_u
+
+      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
+
+        call timer_start(&quot;wTop&quot;)
+
+      u           =&gt; s % u % array
+      wTop        =&gt; s % wTop % array
+
+      areaCell          =&gt; grid % areaCell % array
+      cellsOnEdge       =&gt; grid % cellsOnEdge % array
+      hZLevel           =&gt; grid % hZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeBot   =&gt; grid % maxLevelEdgeBot % array
+      dvEdge            =&gt; grid % dvEdge % array
+
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nVertLevels = grid % nVertLevels
+
+      !
+      ! vertical velocity through layer interface
+      !
+      if (config_vert_grid_type.eq.'isopycnal') then
+        ! set vertical velocity to zero in isopycnal case
+        wTop=0.0  
+
+      elseif (config_vert_grid_type.eq.'zlevel') then
+
+        !
+        ! Compute div(u) for each cell
+        ! See Ringler et al. (2010) jcp paper, eqn 19, 21, and fig. 3.
+        !
+        allocate(div_u(nVertLevels,nCells+1))
+        div_u(:,:) = 0.0
+        do iEdge=1,nEdges
+           cell1 = cellsOnEdge(1,iEdge)
+           cell2 = cellsOnEdge(2,iEdge)
+           do k=2,maxLevelEdgeBot(iEdge)
+              flux = u(k,iEdge) * dvEdge(iEdge) 
+              div_u(k,cell1) = div_u(k,cell1) + flux
+              div_u(k,cell2) = div_u(k,cell2) - flux
+           end do 
+        end do 
+
+        do iCell=1,nCells
+           ! Vertical velocity through layer interface at top and 
+           ! bottom is zero.
+           wTop(1,iCell) = 0.0
+           wTop(maxLevelCell(iCell)+1,iCell) = 0.0
+           do k=maxLevelCell(iCell),2,-1
+              wTop(k,iCell) = wTop(k+1,iCell) &amp;
+                 - div_u(k,iCell)/areaCell(iCell)*hZLevel(k)
+           end do
+        end do
+        deallocate(div_u)
+
+      endif
+
+      call timer_stop(&quot;wTop&quot;)
+
+   end subroutine ocn_wtop!}}}
+
+!***********************************************************************
+!
+!  routine ocn_fuperp
+!
+!&gt; \brief   Computes f u_perp
+!&gt; \author  Doug Jacobsen
+!&gt; \date    23 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes f u_perp for the ocean
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_fuperp(s, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Put f*uBcl^{perp} in u as a work variable
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (state_type), intent(inout) :: s
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into compute_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: flux, vorticity_abs, h_vertex, workpv, q, &amp;
+        upstream_bias, wTopEdge, rho0Inv, r
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel 
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, uBcl, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;ocn_fuperp&quot;)
+
+      h           =&gt; s % h % array
+      u           =&gt; s % u % array
+      uBcl        =&gt; s % uBcl % 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
+      MontPot     =&gt; s % MontPot % array
+      pressure    =&gt; s % pressure % array
+
+      weightsOnEdge     =&gt; grid % weightsOnEdge % 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
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      !
+      ! Put f*uBcl^{perp} in u as a work variable
+      !
+      do iEdge=1,grid % nEdgesSolve
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            u(k,iEdge) = 0.0
+            do j = 1,nEdgesOnEdge(iEdge)
+               eoe = edgesOnEdge(j,iEdge)
+               u(k,iEdge) = u(k,iEdge) + weightsOnEdge(j,iEdge) * uBcl(k,eoe) * fEdge(eoe) 
+            end do
+         end do
+      end do
+
+      call timer_stop(&quot;ocn_fuperp&quot;)
+
+   end subroutine ocn_fuperp!}}}
+
+!***********************************************************************
+
+end module ocn_tendency
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_test_cases.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_test_cases.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_test_cases.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_test_cases.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,526 @@
+ module test_cases
+
+   use grid_types
+   use configure
+   use constants
+
+
+   contains
+
+
+   subroutine setup_sw_test_case(domain)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Configure grid metadata and model state for the shallow water test case 
+   !   specified in the namelist
+   !
+   ! Output: block - a subset (not necessarily proper) of the model domain to be
+   !                 initialized
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain
+
+      integer :: i, iCell, iEdge, iVtx, iLevel
+      type (block_type), pointer :: block_ptr
+      type (dm_info) :: dminfo
+
+      if (config_test_case == 0) then
+         write(0,*) 'Using initial conditions supplied in input file'
+
+      else if (config_test_case == 1) then
+         write(0,*) ' Setting up shallow water test case 1:'
+         write(0,*) ' Advection of Cosine Bell over the Pole'
+
+         block_ptr =&gt; domain % blocklist
+         do while (associated(block_ptr))
+            call sw_test_case_1(block_ptr % mesh, block_ptr % state % time_levs(1) % state)
+            block_ptr =&gt; block_ptr % next
+         end do
+
+      else if (config_test_case == 2) then
+         write(0,*) ' Setup shallow water test case 2: '// &amp;
+           'Global Steady State Nonlinear Zonal Geostrophic Flow'
+
+         block_ptr =&gt; domain % blocklist
+         do while (associated(block_ptr))
+            call sw_test_case_2(block_ptr % mesh, block_ptr % state % time_levs(1) % state)
+            block_ptr =&gt; block_ptr % next
+         end do
+
+      else if (config_test_case == 5) then
+         write(0,*) ' Setup shallow water test case 5:'// &amp;
+           ' Zonal Flow over an Isolated Mountain'
+
+         block_ptr =&gt; domain % blocklist
+         do while (associated(block_ptr))
+            call sw_test_case_5(block_ptr % mesh, block_ptr % state % time_levs(1) % state)
+            block_ptr =&gt; block_ptr % next
+         end do
+
+      else if (config_test_case == 6) then
+         write(0,*) ' Set up shallow water test case 6:'
+         write(0,*) ' Rossby-Haurwitz Wave'
+
+         block_ptr =&gt; domain % blocklist
+         do while (associated(block_ptr))
+            call sw_test_case_6(block_ptr % mesh, block_ptr % state % time_levs(1) % state)
+            block_ptr =&gt; block_ptr % next
+         end do
+
+      else
+         write(0,*) 'Abort: config_test_case=',config_test_case
+         write(0,*) 'Only test case 1, 2, 5, and 6 ', &amp;
+           'are currently supported.  '
+           call dmpar_abort(dminfo)
+      end if
+
+      block_ptr =&gt; domain % blocklist
+      do while (associated(block_ptr))
+
+        do i=2,nTimeLevs
+           call copy_state(block_ptr % state % time_levs(i) % state, &amp;
+                           block_ptr % state % time_levs(1) % state)
+        end do
+
+        block_ptr =&gt; block_ptr % next
+      end do
+
+   end subroutine setup_sw_test_case
+
+
+   subroutine sw_test_case_1(grid, state)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Setup shallow water test case 1: Advection of Cosine Bell over the Pole
+   !
+   ! Reference: Williamson, D.L., et al., &quot;A Standard Test Set for Numerical 
+   !            Approximations to the Shallow Water Equations in Spherical 
+   !            Geometry&quot; J. of Comp. Phys., 102, pp. 211--224
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (mesh_type), intent(inout) :: grid
+      type (state_type), intent(inout) :: state
+
+      real (kind=RKIND), parameter :: u0 = 2.0 * pii * a / (12.0 * 86400.0)
+      real (kind=RKIND), parameter :: h0 = 1000.0
+      real (kind=RKIND), parameter :: theta_c = 0.0
+      real (kind=RKIND), parameter :: lambda_c = 3.0*pii/2.0
+      real (kind=RKIND), parameter :: alpha = pii/4.0
+
+      integer :: iCell, iEdge, iVtx
+      real (kind=RKIND) :: r, u, v
+      real (kind=RKIND), allocatable, dimension(:) :: psiVertex
+
+      !
+      ! Scale all distances and areas from a unit sphere to one with radius a
+      !
+      grid % xCell % array = grid % xCell % array * a
+      grid % yCell % array = grid % yCell % array * a
+      grid % zCell % array = grid % zCell % array * a
+      grid % xVertex % array = grid % xVertex % array * a
+      grid % yVertex % array = grid % yVertex % array * a
+      grid % zVertex % array = grid % zVertex % array * a
+      grid % xEdge % array = grid % xEdge % array * a
+      grid % yEdge % array = grid % yEdge % array * a
+      grid % zEdge % array = grid % zEdge % array * a
+      grid % dvEdge % array = grid % dvEdge % array * a
+      grid % dcEdge % array = grid % dcEdge % array * a
+      grid % areaCell % array = grid % areaCell % array * a**2.0
+      grid % areaTriangle % array = grid % areaTriangle % array * a**2.0
+      grid % kiteAreasOnVertex % array = grid % kiteAreasOnVertex % array * a**2.0
+
+      !
+      ! Initialize wind field
+      !
+      allocate(psiVertex(grid % nVertices))
+      do iVtx=1,grid % nVertices
+         psiVertex(iVtx) = -a * u0 * ( &amp;
+                                       sin(grid%latVertex%array(iVtx)) * cos(alpha) - &amp;
+                                       cos(grid%lonVertex%array(iVtx)) * cos(grid%latVertex%array(iVtx)) * sin(alpha) &amp;
+                                     )
+      end do
+      do iEdge=1,grid % nEdges
+         state % u % array(1,iEdge) = -1.0 * ( &amp;
+                                               psiVertex(grid%verticesOnEdge%array(2,iEdge)) - &amp;
+                                               psiVertex(grid%verticesOnEdge%array(1,iEdge)) &amp;
+                                             ) / grid%dvEdge%array(iEdge)
+      end do
+      deallocate(psiVertex)
+
+      !
+      ! Initialize cosine bell at (theta_c, lambda_c)
+      !
+      do iCell=1,grid % nCells
+         r = sphere_distance(theta_c, lambda_c, grid % latCell % array(iCell), grid % lonCell % array(iCell), a) 
+         if (r &lt; a/3.0) then
+            state % h % array(1,iCell) = (h0 / 2.0) * (1.0 + cos(pii*r*3.0/a))
+         else
+            state % h % array(1,iCell) = 0.0
+         end if
+      end do
+
+   end subroutine sw_test_case_1
+
+
+   subroutine sw_test_case_2(grid, state)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Setup shallow water test case 2: Global Steady State Nonlinear Zonal 
+   !                                  Geostrophic Flow
+   !
+   ! Reference: Williamson, D.L., et al., &quot;A Standard Test Set for Numerical 
+   !            Approximations to the Shallow Water Equations in Spherical 
+   !            Geometry&quot; J. of Comp. Phys., 102, pp. 211--224
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (mesh_type), intent(inout) :: grid
+      type (state_type), intent(inout) :: state
+
+      real (kind=RKIND), parameter :: u0 = 2.0 * pii * a / (12.0 * 86400.0)
+      real (kind=RKIND), parameter :: gh0 = 29400.0
+      real (kind=RKIND), parameter :: alpha = 0.0
+
+      integer :: iCell, iEdge, iVtx
+      real (kind=RKIND) :: u, v
+      real (kind=RKIND), allocatable, dimension(:) :: psiVertex
+
+
+      !
+      ! Scale all distances and areas from a unit sphere to one with radius a
+      !
+      grid % xCell % array = grid % xCell % array * a
+      grid % yCell % array = grid % yCell % array * a
+      grid % zCell % array = grid % zCell % array * a
+      grid % xVertex % array = grid % xVertex % array * a
+      grid % yVertex % array = grid % yVertex % array * a
+      grid % zVertex % array = grid % zVertex % array * a
+      grid % xEdge % array = grid % xEdge % array * a
+      grid % yEdge % array = grid % yEdge % array * a
+      grid % zEdge % array = grid % zEdge % array * a
+      grid % dvEdge % array = grid % dvEdge % array * a
+      grid % dcEdge % array = grid % dcEdge % array * a
+      grid % areaCell % array = grid % areaCell % array * a**2.0
+      grid % areaTriangle % array = grid % areaTriangle % array * a**2.0
+      grid % kiteAreasOnVertex % array = grid % kiteAreasOnVertex % array * a**2.0
+      
+
+      !
+      ! Initialize wind field
+      !
+      allocate(psiVertex(grid % nVertices))
+      do iVtx=1,grid % nVertices
+         psiVertex(iVtx) = -a * u0 * ( &amp;
+                                       sin(grid%latVertex%array(iVtx)) * cos(alpha) - &amp;
+                                       cos(grid%lonVertex%array(iVtx)) * cos(grid%latVertex%array(iVtx)) * sin(alpha) &amp;
+                                     )
+      end do
+      do iEdge=1,grid % nEdges
+         state % u % array(1,iEdge) = -1.0 * ( &amp;
+                                               psiVertex(grid%verticesOnEdge%array(2,iEdge)) - &amp;
+                                               psiVertex(grid%verticesOnEdge%array(1,iEdge)) &amp;
+                                             ) / grid%dvEdge%array(iEdge)
+      end do
+      deallocate(psiVertex)
+
+      !
+      ! Generate rotated Coriolis field
+      !
+      do iEdge=1,grid % nEdges
+         grid % fEdge % array(iEdge) = 2.0 * omega * &amp;
+                                       ( -cos(grid%lonEdge%array(iEdge)) * cos(grid%latEdge%array(iEdge)) * sin(alpha) + &amp;
+                                         sin(grid%latEdge%array(iEdge)) * cos(alpha) &amp;
+                                       )
+      end do
+      do iVtx=1,grid % nVertices
+         grid % fVertex % array(iVtx) = 2.0 * omega * &amp;
+                                         (-cos(grid%lonVertex%array(iVtx)) * cos(grid%latVertex%array(iVtx)) * sin(alpha) + &amp;
+                                          sin(grid%latVertex%array(iVtx)) * cos(alpha) &amp;
+                                         )
+      end do
+
+      !
+      ! Initialize height field (actually, fluid thickness field)
+      !
+      do iCell=1,grid % nCells
+         state % h % array(1,iCell) = (gh0 - (a * omega * u0 + 0.5 * u0**2.0) * &amp;
+                                             (-cos(grid%lonCell%array(iCell)) * cos(grid%latCell%array(iCell)) * sin(alpha) + &amp;
+                                              sin(grid%latCell%array(iCell)) * cos(alpha) &amp;
+                                             )**2.0 &amp;
+                                      ) / &amp;
+                                      gravity
+      end do
+
+   end subroutine sw_test_case_2
+
+
+   subroutine sw_test_case_5(grid, state)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Setup shallow water test case 5: Zonal Flow over an Isolated Mountain
+   !
+   ! Reference: Williamson, D.L., et al., &quot;A Standard Test Set for Numerical 
+   !            Approximations to the Shallow Water Equations in Spherical 
+   !            Geometry&quot; J. of Comp. Phys., 102, pp. 211--224
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (mesh_type), intent(inout) :: grid
+      type (state_type), intent(inout) :: state
+
+      real (kind=RKIND), parameter :: u0 = 20.
+      real (kind=RKIND), parameter :: gh0 = 5960.0*gravity
+!      real (kind=RKIND), parameter :: hs0 = 2000. original
+      real (kind=RKIND), parameter :: hs0 = 250.  !mrp 100204
+      real (kind=RKIND), parameter :: theta_c = pii/6.0
+      real (kind=RKIND), parameter :: lambda_c = 3.0*pii/2.0
+      real (kind=RKIND), parameter :: rr = pii/9.0
+      real (kind=RKIND), parameter :: alpha = 0.0
+
+      integer :: iCell, iEdge, iVtx
+      real (kind=RKIND) :: r, u, v
+      real (kind=RKIND), allocatable, dimension(:) :: psiVertex
+
+
+      !
+      ! Scale all distances and areas from a unit sphere to one with radius a
+      !
+      grid % xCell % array = grid % xCell % array * a
+      grid % yCell % array = grid % yCell % array * a
+      grid % zCell % array = grid % zCell % array * a
+      grid % xVertex % array = grid % xVertex % array * a
+      grid % yVertex % array = grid % yVertex % array * a
+      grid % zVertex % array = grid % zVertex % array * a
+      grid % xEdge % array = grid % xEdge % array * a
+      grid % yEdge % array = grid % yEdge % array * a
+      grid % zEdge % array = grid % zEdge % array * a
+      grid % dvEdge % array = grid % dvEdge % array * a
+      grid % dcEdge % array = grid % dcEdge % array * a
+      grid % areaCell % array = grid % areaCell % array * a**2.0
+      grid % areaTriangle % array = grid % areaTriangle % array * a**2.0
+      grid % kiteAreasOnVertex % array = grid % kiteAreasOnVertex % array * a**2.0
+
+      !
+      ! Initialize wind field
+      !
+      allocate(psiVertex(grid % nVertices))
+      do iVtx=1,grid % nVertices
+         psiVertex(iVtx) = -a * u0 * ( &amp;
+                                       sin(grid%latVertex%array(iVtx)) * cos(alpha) - &amp;
+                                       cos(grid%lonVertex%array(iVtx)) * cos(grid%latVertex%array(iVtx)) * sin(alpha) &amp;
+                                     )
+      end do
+      do iEdge=1,grid % nEdges
+         state % u % array(1,iEdge) = -1.0 * ( &amp;
+                                               psiVertex(grid%verticesOnEdge%array(2,iEdge)) - &amp;
+                                               psiVertex(grid%verticesOnEdge%array(1,iEdge)) &amp;
+                                             ) / grid%dvEdge%array(iEdge)
+      end do
+      deallocate(psiVertex)
+
+      !
+      ! Generate rotated Coriolis field
+      !
+      do iEdge=1,grid % nEdges
+         grid % fEdge % array(iEdge) = 2.0 * omega * &amp;
+                                        (-cos(grid%lonEdge%array(iEdge)) * cos(grid%latEdge%array(iEdge)) * sin(alpha) + &amp;
+                                         sin(grid%latEdge%array(iEdge)) * cos(alpha) &amp;
+                                        )
+      end do
+      do iVtx=1,grid % nVertices
+         grid % fVertex % array(iVtx) = 2.0 * omega * &amp;
+                                         (-cos(grid%lonVertex%array(iVtx)) * cos(grid%latVertex%array(iVtx)) * sin(alpha) + &amp;
+                                          sin(grid%latVertex%array(iVtx)) * cos(alpha) &amp;
+                                         )
+      end do
+
+      !
+      ! Initialize mountain
+      !
+      do iCell=1,grid % nCells
+         if (grid % lonCell % array(iCell) &lt; 0.0) grid % lonCell % array(iCell) = grid % lonCell % array(iCell) + 2.0 * pii
+         r = sqrt(min(rr**2.0, (grid % lonCell % array(iCell) - lambda_c)**2.0 + (grid % latCell % array(iCell) - theta_c)**2.0))
+         grid % h_s % array(iCell) = hs0 * (1.0 - r/rr)
+      end do
+! output about mountain
+print *, 'h_s',minval(grid % h_s % array),sum(grid % h_s % array)/grid % nCells, maxval(grid % h_s % array)
+
+      !
+      ! Initialize tracer fields
+      !
+      do iCell=1,grid % nCells
+         r = sqrt(min(rr**2.0, (grid % lonCell % array(iCell) - lambda_c)**2.0 + (grid % latCell % array(iCell) - theta_c)**2.0))
+         state % tracers % array(1,1,iCell) = 1.0 - r/rr
+      end do
+      do iCell=1,grid % nCells
+         r = sqrt(min(rr**2.0, (grid % lonCell % array(iCell) - lambda_c)**2.0 + &amp;
+                      (grid % latCell % array(iCell) - theta_c - pii/6.0)**2.0 &amp;
+                     ) &amp;
+                 )
+         state % tracers % array(2,1,iCell) = 1.0 - r/rr
+      end do
+
+      !
+      ! Initialize height field (actually, fluid thickness field)
+      !
+      do iCell=1,grid % nCells
+         state % h % array(1,iCell) = (gh0 - (a * omega * u0 + 0.5 * u0**2.0) * &amp;
+                                         (-cos(grid%lonCell%array(iCell)) * cos(grid%latCell%array(iCell)) * sin(alpha) + &amp;
+                                          sin(grid%latCell%array(iCell)) * cos(alpha) &amp;
+                                         )**2.0 &amp;
+                                      ) / &amp;
+                                      gravity
+         state % h % array(1,iCell) = state % h % array(1,iCell) - grid % h_s % array(iCell)
+      end do
+
+   end subroutine sw_test_case_5
+
+
+   subroutine sw_test_case_6(grid, state)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Setup shallow water test case 6: Rossby-Haurwitz Wave
+   !
+   ! Reference: Williamson, D.L., et al., &quot;A Standard Test Set for Numerical 
+   !            Approximations to the Shallow Water Equations in Spherical 
+   !            Geometry&quot; J. of Comp. Phys., 102, pp. 211--224
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (mesh_type), intent(inout) :: grid
+      type (state_type), intent(inout) :: state
+
+      real (kind=RKIND), parameter :: h0 = 8000.0
+      real (kind=RKIND), parameter :: w = 7.848e-6
+      real (kind=RKIND), parameter :: K = 7.848e-6
+      real (kind=RKIND), parameter :: R = 4.0
+
+      integer :: iCell, iEdge, iVtx
+      real (kind=RKIND) :: u, v
+      real (kind=RKIND), allocatable, dimension(:) :: psiVertex
+
+
+      !
+      ! Scale all distances and areas from a unit sphere to one with radius a
+      !
+      grid % xCell % array = grid % xCell % array * a
+      grid % yCell % array = grid % yCell % array * a
+      grid % zCell % array = grid % zCell % array * a
+      grid % xVertex % array = grid % xVertex % array * a
+      grid % yVertex % array = grid % yVertex % array * a
+      grid % zVertex % array = grid % zVertex % array * a
+      grid % xEdge % array = grid % xEdge % array * a
+      grid % yEdge % array = grid % yEdge % array * a
+      grid % zEdge % array = grid % zEdge % array * a
+      grid % dvEdge % array = grid % dvEdge % array * a
+      grid % dcEdge % array = grid % dcEdge % array * a
+      grid % areaCell % array = grid % areaCell % array * a**2.0
+      grid % areaTriangle % array = grid % areaTriangle % array * a**2.0
+      grid % kiteAreasOnVertex % array = grid % kiteAreasOnVertex % array * a**2.0
+
+      !
+      ! Initialize wind field
+      !
+      allocate(psiVertex(grid % nVertices))
+      do iVtx=1,grid % nVertices
+         psiVertex(iVtx) = -a * a * w * sin(grid%latVertex%array(iVtx)) + &amp;
+                            a *a * K * (cos(grid%latVertex%array(iVtx))**R) * &amp;
+                            sin(grid%latVertex%array(iVtx)) * cos(R * grid%lonVertex%array(iVtx))
+      end do
+      do iEdge=1,grid % nEdges
+         state % u % array(1,iEdge) = -1.0 * ( &amp;
+                                               psiVertex(grid%verticesOnEdge%array(2,iEdge)) - &amp;
+                                               psiVertex(grid%verticesOnEdge%array(1,iEdge)) &amp;
+                                             ) / grid%dvEdge%array(iEdge)
+      end do
+      deallocate(psiVertex)
+
+      !
+      ! Initialize height field (actually, fluid thickness field)
+      !
+      do iCell=1,grid % nCells
+         state % h % array(1,iCell) = (gravity * h0 + a*a*AA(grid%latCell%array(iCell)) + &amp;
+                                                      a*a*BB(grid%latCell%array(iCell)) * cos(R*grid%lonCell%array(iCell)) + &amp;
+                                                      a*a*CC(grid%latCell%array(iCell)) * cos(2.0*R*grid%lonCell%array(iCell)) &amp;
+                                      ) / gravity
+      end do
+
+   end subroutine sw_test_case_6
+
+
+   real function sphere_distance(lat1, lon1, lat2, lon2, radius)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Compute the great-circle distance between (lat1, lon1) and (lat2, lon2) on a
+   !   sphere with given radius.
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      real (kind=RKIND), intent(in) :: lat1, lon1, lat2, lon2, radius
+
+      real (kind=RKIND) :: arg1
+
+      arg1 = sqrt( sin(0.5*(lat2-lat1))**2 +  &amp;
+                   cos(lat1)*cos(lat2)*sin(0.5*(lon2-lon1))**2 )
+      sphere_distance = 2.*radius*asin(arg1)
+
+   end function sphere_distance
+
+
+   real function AA(theta)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! A, used in height field computation for Rossby-Haurwitz wave
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      real (kind=RKIND), parameter :: w = 7.848e-6
+      real (kind=RKIND), parameter :: K = 7.848e-6
+      real (kind=RKIND), parameter :: R = 4.0
+
+      real (kind=RKIND), intent(in) :: theta
+
+      AA = 0.5 * w * (2.0 * omega + w) * cos(theta)**2.0 + &amp;
+          0.25 * K**2.0 * cos(theta)**(2.0*R) * ((R+1.0)*cos(theta)**2.0 + 2.0*R**2.0 - R - 2.0 - 2.0*R**2*cos(theta)**-2.0)
+
+   end function AA
+
+   
+   real function BB(theta)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! B, used in height field computation for Rossby-Haurwitz wave
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      real (kind=RKIND), parameter :: w = 7.848e-6
+      real (kind=RKIND), parameter :: K = 7.848e-6
+      real (kind=RKIND), parameter :: R = 4.0
+
+      real (kind=RKIND), intent(in) :: theta
+
+      BB = (2.0*(omega + w)*K / ((R+1.0)*(R+2.0))) * cos(theta)**R * ((R**2.0 + 2.0*R + 2.0) - ((R+1.0)*cos(theta))**2.0)
+
+   end function BB
+
+
+   real function CC(theta)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! C, used in height field computation for Rossby-Haurwitz wave
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      real (kind=RKIND), parameter :: w = 7.848e-6
+      real (kind=RKIND), parameter :: K = 7.848e-6
+      real (kind=RKIND), parameter :: R = 4.0
+
+      real (kind=RKIND), intent(in) :: theta
+
+      CC = 0.25 * K**2.0 * cos(theta)**(2.0*R) * ((R+1.0)*cos(theta)**2.0 - R - 2.0)
+
+   end function CC
+
+end module test_cases

Copied: trunk/mpas/src/core_ocean/mpas_ocn_thick_hadv.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_thick_hadv.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_thick_hadv.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_thick_hadv.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,209 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_thick_hadv
+!
+!&gt; \brief MPAS ocean horizontal advection for thickness
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies for thickness from horizontal advection
+!
+!-----------------------------------------------------------------------
+
+module ocn_thick_hadv
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_thick_hadv_tend, &amp;
+             ocn_thick_hadv_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_thick_hadv_tend
+!
+!&gt; \brief   Computes tendency term from horizontal advection of thickness
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal advection tendency for
+!&gt;  thicknes based on current state and user choices of forcings.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_thick_hadv_tend(grid, u, h_edge, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: velocity
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, cell1, cell2, nVertLevels, k
+      integer :: iCell, nCells
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real (kind=RKIND) :: flux
+      real (kind=RKIND), dimension(:), pointer :: dvEdge, areaCell
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      nEdges = grid % nEdges
+      nCells = grid % nCells
+      nVertLevels = grid % nVertLevels
+
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaCell =&gt; grid % areaCell % array
+
+      if (config_vert_grid_type.eq.'isopycnal') then

+         do iEdge=1,nEdges
+            cell1 = cellsOnEdge(1,iEdge)
+            cell2 = cellsOnEdge(2,iEdge)
+            do k=1,nVertLevels
+               flux = u(k,iEdge) * dvEdge(iEdge) * h_edge(k,iEdge)
+               tend(k,cell1) = tend(k,cell1) - flux
+               tend(k,cell2) = tend(k,cell2) + flux
+            end do
+         end do
+         do iCell=1,nCells
+            do k=1,nVertLevels
+               tend(k,iCell) = tend(k,iCell) / areaCell(iCell)
+            end do
+         end do
+
+      elseif (config_vert_grid_type.eq.'zlevel') then
+
+         do iEdge=1,nEdges
+            cell1 = cellsOnEdge(1,iEdge)
+            cell2 = cellsOnEdge(2,iEdge)
+            do k=1,min(1,maxLevelEdgeTop(iEdge))
+               flux = u(k,iEdge) * dvEdge(iEdge) * h_edge(k,iEdge)
+               tend(k,cell1) = tend(k,cell1) - flux
+               tend(k,cell2) = tend(k,cell2) + flux
+            end do
+         end do
+         do iCell=1,nCells
+           tend(1,iCell) = tend(1,iCell) / areaCell(iCell)
+         end do
+
+      endif ! config_vert_grid_type
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_thick_hadv_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_thick_hadv_init
+!
+!&gt; \brief   Initializes ocean horizontal thickness advection
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes quantities related to horizontal thickness 
+!&gt;  advection in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_thick_hadv_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_thick_hadv_init!}}}
+
+!***********************************************************************
+
+end module ocn_thick_hadv
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_thick_vadv.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_thick_vadv.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_thick_vadv.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_thick_vadv.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,163 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_thick_vadv
+!
+!&gt; \brief MPAS ocean vertical advection for thickness
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies for thickness from vertical advection
+!
+!-----------------------------------------------------------------------
+
+module ocn_thick_vadv
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_thick_vadv_tend, &amp;
+             ocn_thick_vadv_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_thick_vadv_tend
+!
+!&gt; \brief   Computes tendency term from vertical advection of thickness
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for
+!&gt;  thicknes based on current state and user choices of forcings.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_thick_vadv_tend(grid, wTop, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop     !&lt; Input: vertical velocity on top layer
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCells
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      nCells = grid % nCells
+
+      if (config_vert_grid_type.eq.'zlevel') then
+        do iCell=1,nCells
+           tend(1,iCell) =   tend(1,iCell) + wTop(2,iCell)
+        end do
+      endif ! coordinate type
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_thick_vadv_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_thick_vadv_init
+!
+!&gt; \brief   Initializes ocean thickness vertical advection
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes quantities related to vertical advection of 
+!&gt;  thickness in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_thick_vadv_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+      
+      err = 0
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_thick_vadv_init!}}}
+
+!***********************************************************************
+
+end module ocn_thick_vadv
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_time_integration.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_time_integration.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_time_integration.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_time_integration.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,134 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_time_integration
+!
+!&gt; \brief MPAS ocean time integration driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for calling
+!&gt;  the time integration scheme
+!
+!-----------------------------------------------------------------------
+
+module ocn_time_integration
+
+   use grid_types
+   use configure
+   use constants
+   use dmpar
+   use vector_reconstruction
+   use spline_interpolation
+   use timer
+
+   use ocn_time_integration_rk4
+   use ocn_time_integration_split
+
+   implicit none
+   private
+   save
+
+   public :: ocn_timestep, &amp;
+             ocn_timestep_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+    logical :: rk4On, splitOn
+
+   contains
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_timestep
+!
+!&gt; \brief MPAS ocean time integration driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This routine handles a single timestep for the ocean. It determines
+!&gt;  the time integrator that will be used for the run, and calls the
+!&gt;  appropriate one.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_timestep(domain, dt, timeStamp)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Advance model state forward in time by the specified time step
+   !
+   ! Input: domain - current model state in time level 1 (e.g., time_levs(1)state%h(:,:)) 
+   !                 plus grid meta-data
+   ! Output: domain - upon exit, time level 2 (e.g., time_levs(2)%state%h(:,:)) contains 
+   !                  model state advanced forward in time by dt seconds
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain
+      real (kind=RKIND), intent(in) :: dt
+      character(len=*), intent(in) :: timeStamp
+
+      type (dm_info) :: dminfo
+      type (block_type), pointer :: block
+
+      if (rk4On) then
+         call ocn_time_integrator_rk4(domain, dt)
+      elseif (splitOn) then
+         call ocn_time_integrator_split(domain, dt)
+     endif
+
+     block =&gt; domain % blocklist
+     do while (associated(block))
+        block % state % time_levs(2) % state % xtime % scalar = timeStamp
+
+        if (isNaN(sum(block % state % time_levs(2) % state % u % array))) then
+           write(0,*) 'Abort: NaN detected'
+           call dmpar_abort(dminfo)
+        endif
+
+        block =&gt; block % next
+     end do
+
+   end subroutine ocn_timestep!}}}
+
+   subroutine ocn_timestep_init(err)!{{{
+
+      integer, intent(out) :: err
+
+      rk4On = .false.
+      splitOn = .false.
+
+      if (trim(config_time_integration) == 'RK4') then
+          rk4On = .true.
+      elseif (trim(config_time_integration) == 'split_explicit' &amp;
+          .or.trim(config_time_integration) == 'unsplit_explicit') then
+          splitOn = .true.
+      else
+          err = 1
+          write(*,*) 'Incorrect choice for config_time_integration:', trim(config_time_integration)
+          write(*,*) '   choices are: RK4, split_explicit, unsplit_explicit'
+      endif
+
+
+   end subroutine ocn_timestep_init!}}}
+
+end module ocn_time_integration
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_time_integration_rk4.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_time_integration_rk4.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_time_integration_rk4.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_time_integration_rk4.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,651 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_time_integration_rk4
+!
+!&gt; \brief MPAS ocean RK4 Time integration scheme
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the RK4 time integration routine.
+!
+!-----------------------------------------------------------------------
+
+module ocn_time_integration_rk4
+
+   use grid_types
+   use configure
+   use constants
+   use dmpar
+   use vector_reconstruction
+   use spline_interpolation
+   use timer
+
+   use ocn_tendency
+
+   use ocn_equation_of_state
+   use ocn_Vmix
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_time_integrator_rk4
+
+   contains
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_time_integrator_rk4
+!
+!&gt; \brief MPAS ocean RK4 Time integration scheme
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This routine integrates one timestep (dt) using an RK4 time integrator.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_time_integrator_rk4(domain, dt)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Advance model state forward in time by the specified time step using 
+   !   4th order Runge-Kutta
+   !
+   ! Input: domain - current model state in time level 1 (e.g., time_levs(1)state%h(:,:)) 
+   !                 plus grid meta-data
+   ! Output: domain - upon exit, time level 2 (e.g., time_levs(2)%state%h(:,:)) contains 
+   !                  model state advanced forward in time by dt seconds
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain !&lt; Input/Output: domain information
+      real (kind=RKIND), intent(in) :: dt !&lt; Input: timestep
+
+      integer :: iCell, k, i, err
+      type (block_type), pointer :: block
+      type (state_type) :: provis
+
+      integer :: rk_step, iEdge, cell1, cell2
+
+      real (kind=RKIND), dimension(4) :: rk_weights, rk_substep_weights
+
+      integer :: nCells, nEdges, nVertLevels, num_tracers
+      real (kind=RKIND) :: coef
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        u, h, h_edge, vertViscTopOfEdge, vertDiffTopOfCell, ke_edge
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+      integer, dimension(:), pointer :: &amp; 
+        maxLevelCell, maxLevelEdgeTop
+      real (kind=RKIND), dimension(:), allocatable:: A,C,uTemp
+      real (kind=RKIND), dimension(:,:), allocatable:: tracersTemp
+
+
+      block =&gt; domain % blocklist
+      call allocate_state(provis, &amp;
+                          block % mesh % nCells, block % mesh % nEdges, block % mesh % maxEdges, block % mesh % maxEdges2, &amp;
+                          block % mesh % nVertices, block % mesh % vertexDegree, block % mesh % nVertLevels )
+
+      !
+      ! Initialize time_levs(2) with state at current time
+      ! Initialize first RK state
+      ! Couple tracers time_levs(2) with h in time-levels
+      ! Initialize RK weights
+      !
+      block =&gt; domain % blocklist
+      do while (associated(block))
+
+         block % state % time_levs(2) % state % u % array(:,:) = block % state % time_levs(1) % state % u % array(:,:)
+         block % state % time_levs(2) % state % h % array(:,:) = block % state % time_levs(1) % state % h % array(:,:)
+         do iCell=1,block % mesh % nCells  ! couple tracers to h
+           do k=1,block % mesh % maxLevelCell % array(iCell)
+             block % state % time_levs(2) % state % tracers % array(:,k,iCell) = block % state % time_levs(1) % state % tracers % array(:,k,iCell) &amp;
+                                                                       * block % state % time_levs(1) % state % h % array(k,iCell)
+            end do
+         end do
+
+         call copy_state(provis, block % state % time_levs(1) % state)
+
+         block =&gt; block % next
+      end do
+
+      rk_weights(1) = dt/6.
+      rk_weights(2) = dt/3.
+      rk_weights(3) = dt/3.
+      rk_weights(4) = dt/6.
+
+      rk_substep_weights(1) = dt/2.
+      rk_substep_weights(2) = dt/2.
+      rk_substep_weights(3) = dt
+      rk_substep_weights(4) = 0.
+
+
+      call timer_start(&quot;RK4-main loop&quot;)
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! BEGIN RK loop 
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      do rk_step = 1, 4
+! ---  update halos for diagnostic variables
+
+        call timer_start(&quot;RK4-diagnostic halo update&quot;)
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           call dmpar_exch_halo_field2dReal(domain % dminfo, provis % pv_edge % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nEdges, &amp;
+                                            block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+           if (config_h_mom_eddy_visc4 &gt; 0.0) then
+              call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % divergence % array(:,:), &amp;
+                                               block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                               block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+              call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % vorticity % array(:,:), &amp;
+                                               block % mesh % nVertLevels, block % mesh % nVertices, &amp;
+                                               block % parinfo % verticesToSend, block % parinfo % verticesToRecv)
+           end if
+
+           block =&gt; block % next
+        end do
+        call timer_stop(&quot;RK4-diagnostic halo update&quot;)
+
+! ---  compute tendencies
+
+        call timer_start(&quot;RK4-tendency computations&quot;)
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           if (.not.config_implicit_vertical_mix) then
+              call ocn_vmix_coefs(block % mesh, provis, block % diagnostics, err)
+           end if
+           call ocn_tend_h(block % tend, provis, block % diagnostics, block % mesh)
+           call ocn_tend_u(block % tend, provis, block % diagnostics, block % mesh)
+
+           ! mrp 110718 filter btr mode out of u_tend
+           ! still got h perturbations with just this alone.  Try to set uBtr=0 after full u computation
+           if (config_rk_filter_btr_mode) then
+               call filter_btr_mode_tend_u(block % tend, provis, block % diagnostics, block % mesh)
+           endif
+
+           call ocn_tend_scalar(block % tend, provis, block % diagnostics, block % mesh)
+           call enforce_boundaryEdge(block % tend, block % mesh)
+           block =&gt; block % next
+        end do
+        call timer_stop(&quot;RK4-tendency computations&quot;)
+
+! ---  update halos for prognostic variables
+
+        call timer_start(&quot;RK4-pronostic halo update&quot;)
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           call dmpar_exch_halo_field2dReal(domain % dminfo, block % tend % u % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nEdges, &amp;
+                                            block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+           call dmpar_exch_halo_field2dReal(domain % dminfo, block % tend % h % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                            block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+           call dmpar_exch_halo_field3dReal(domain % dminfo, block % tend % tracers % array(:,:,:), &amp;
+                                            block % tend % num_tracers, block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                            block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+           block =&gt; block % next
+        end do
+        call timer_stop(&quot;RK4-pronostic halo update&quot;)
+
+! ---  compute next substep state
+
+        call timer_start(&quot;RK4-update diagnostic variables&quot;)
+        if (rk_step &lt; 4) then
+           block =&gt; domain % blocklist
+           do while (associated(block))
+
+              provis % u % array(:,:)       = block % state % time_levs(1) % state % u % array(:,:)  &amp;
+                                         + rk_substep_weights(rk_step) * block % tend % u % array(:,:)
+
+              provis % h % array(:,:)       = block % state % time_levs(1) % state % h % array(:,:)  &amp;
+                                         + rk_substep_weights(rk_step) * block % tend % h % array(:,:)
+              do iCell=1,block % mesh % nCells
+                 do k=1,block % mesh % maxLevelCell % array(iCell)
+                    provis % tracers % array(:,k,iCell) = ( &amp;
+                                                                      block % state % time_levs(1) % state % h % array(k,iCell) * &amp;
+                                                                      block % state % time_levs(1) % state % tracers % array(:,k,iCell)  &amp;
+                                      + rk_substep_weights(rk_step) * block % tend % tracers % array(:,k,iCell) &amp;
+                                                                     ) / provis % h % array(k,iCell)
+                 end do
+
+              end do
+              if (config_test_case == 1) then    ! For case 1, wind field should be fixed
+                 provis % u % array(:,:) = block % state % time_levs(1) % state % u % array(:,:)
+              end if
+
+              call ocn_diagnostic_solve(dt, provis, block % mesh)
+
+              block =&gt; block % next
+           end do
+        end if
+        call timer_stop(&quot;RK4-update diagnostic variables&quot;)
+
+
+
+!--- accumulate update (for RK4)
+
+        call timer_start(&quot;RK4-RK4 accumulate update&quot;)
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           block % state % time_levs(2) % state % u % array(:,:) = block % state % time_levs(2) % state % u % array(:,:) &amp;
+                                   + rk_weights(rk_step) * block % tend % u % array(:,:) 
+
+           block % state % time_levs(2) % state % h % array(:,:) = block % state % time_levs(2) % state % h % array(:,:) &amp;
+                                   + rk_weights(rk_step) * block % tend % h % array(:,:) 
+
+           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;
+                                               + rk_weights(rk_step) * block % tend % tracers % array(:,k,iCell)
+              end do
+           end do
+
+           block =&gt; block % next
+        end do
+        call timer_stop(&quot;RK4-RK4 accumulate update&quot;)
+
+      end do
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! END RK loop 
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      call timer_stop(&quot;RK4-main loop&quot;)
+
+      !
+      !  A little clean up at the end: decouple new scalar fields and compute diagnostics for new state
+      !
+      call timer_start(&quot;RK4-cleaup phase&quot;)
+      block =&gt; domain % blocklist
+      do while (associated(block))
+
+         u           =&gt; block % state % time_levs(2) % state % u % array
+         tracers     =&gt; block % state % time_levs(2) % state % tracers % array
+         h           =&gt; block % state % time_levs(2) % state % h % array
+         h_edge      =&gt; block % state % time_levs(2) % state % h_edge % array
+         ke_edge     =&gt; block % state % time_levs(2) % state % ke_edge % array
+         num_tracers = block % state % time_levs(2) % state % num_tracers
+         vertViscTopOfEdge =&gt; block % diagnostics % vertViscTopOfEdge % array
+         vertDiffTopOfCell =&gt; block % diagnostics % vertDiffTopOfCell % array
+         maxLevelCell    =&gt; block % mesh % maxLevelCell % array
+         maxLevelEdgeTop =&gt; block % mesh % maxLevelEdgeTop % array
+                  
+         nCells      = block % mesh % nCells
+         nEdges      = block % mesh % nEdges
+         nVertLevels = block % mesh % nVertLevels
+
+         do iCell=1,nCells
+            do k=1,maxLevelCell(iCell)
+               tracers(:,k,iCell) = tracers(:,k,iCell) / h(k,iCell)
+            end do
+         end do
+
+         if (config_implicit_vertical_mix) then
+            call timer_start(&quot;RK4-implicit vert mix&quot;)
+            allocate(A(nVertLevels),C(nVertLevels),uTemp(nVertLevels), &amp;
+               tracersTemp(num_tracers,nVertLevels))
+
+            call ocn_vmix_coefs(block % mesh, block % state % time_levs(2) % state, block % diagnostics, err)
+
+            !
+            !  Implicit vertical solve for momentum
+            !
+            call ocn_vel_vmix_tend_implicit(block % mesh, dt, ke_edge, vertvisctopofedge, h, h_edge, u, err)
+
+          !  mrp 110718 filter btr mode out of u
+           if (config_rk_filter_btr_mode) then
+               call filter_btr_mode_u(block % state % time_levs(2) % state, block % mesh)
+               !block % tend % h % array(:,:) = 0.0 ! I should not need this
+           endif
+
+            !
+            !  Implicit vertical solve for tracers
+            !
+
+            call ocn_tracer_vmix_tend_implicit(block % mesh, dt, vertdifftopofcell, h, tracers, err)
+         end if
+
+         ! mrp 110725 momentum decay term
+         if (config_mom_decay) then
+             call timer_start(&quot;RK4-momentum decay&quot;)
+
+            !
+            !  Implicit solve for momentum decay
+            !
+            !  Add term to RHS of momentum equation: -1/gamma u
+            !
+            !  This changes the solve to:
+            !  u^{n+1} = u_provis^{n+1}/(1+dt/gamma)
+            !
+            coef = 1.0/(1.0 + dt/config_mom_decay_time)
+            do iEdge=1,block % mesh % nEdges
+               do k=1,maxLevelEdgeTop(iEdge)
+                  u(k,iEdge) = coef*u(k,iEdge) 
+               end do
+            end do
+
+            call timer_stop(&quot;RK4-momentum decay&quot;)
+         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(:,:)
+         end if
+
+         call ocn_diagnostic_solve(dt, block % state % time_levs(2) % state, block % mesh)
+
+         call reconstruct(block % state % time_levs(2) % state, block % mesh)
+
+         block =&gt; block % next
+      end do
+      call timer_stop(&quot;RK4-cleaup phase&quot;)
+
+      call deallocate_state(provis)
+
+   end subroutine ocn_time_integrator_rk4!}}}
+
+   subroutine filter_btr_mode_tend_u(tend, s, d, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Filter and remove barotropic mode from the tendencies
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (tend_type), intent(inout) :: tend
+      type (state_type), intent(in) :: s
+      type (diagnostics_type), intent(in) :: d
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into compute_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: vertSum, uhSum, hSum, sshEdge
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel, meshScalingDel2, meshScalingDel4
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;filter_btr_mode_tend_u&quot;)
+
+      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
+      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
+      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
+! mrp 110516 cleanup fvertex fedge not used in this subroutine
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      tend_u      =&gt; tend % u % array
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      u_src =&gt; grid % u_src % array
+
+           do iEdge=1,grid % nEdges
+
+              ! I am using hZLevel here.  This assumes that SSH is zero everywhere already,
+              ! which should be the case if the barotropic mode is filtered.
+              ! The more general case is to use sshEdge or h_edge.
+              uhSum = (grid % hZLevel % array(1)) * tend_u(1,iEdge)
+              hSum  =  grid % hZLevel % array(1)
+
+              do k=2,grid % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + grid % hZLevel % array(k) * tend_u(k,iEdge)
+                 hSum  =  hSum + grid % hZLevel % array(k)
+              enddo
+
+              vertSum = uhSum/hSum
+
+              do k=1,grid % maxLevelEdgeTop % array(iEdge)
+                 tend_u(k,iEdge) = tend_u(k,iEdge) - vertSum
+              enddo
+
+           enddo ! iEdge
+
+      call timer_stop(&quot;filter_btr_mode_tend_u&quot;)
+
+   end subroutine filter_btr_mode_tend_u!}}}
+
+   subroutine filter_btr_mode_u(s, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Filter and remove barotropic mode.
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (state_type), intent(inout) :: s
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into compute_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: vertSum, uhSum, hSum, sshEdge
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel, meshScalingDel2, meshScalingDel4
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;filter_btr_mode_u&quot;)
+
+      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
+      MontPot     =&gt; s % MontPot % array
+      pressure    =&gt; s % pressure % array
+
+      weightsOnEdge     =&gt; grid % weightsOnEdge % 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
+! mrp 110516 cleanup fvertex fedge not used in this subroutine
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      u_src =&gt; grid % u_src % array
+
+           do iEdge=1,grid % nEdges
+
+              ! I am using hZLevel here.  This assumes that SSH is zero everywhere already,
+              ! which should be the case if the barotropic mode is filtered.
+              ! The more general case is to use sshedge or h_edge.
+              uhSum = (grid % hZLevel % array(1)) * u(1,iEdge)
+              hSum  =  grid % hZLevel % array(1)
+
+              do k=2,grid % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + grid % hZLevel % array(k) * u(k,iEdge)
+                 hSum  =  hSum + grid % hZLevel % array(k)
+              enddo
+
+              vertSum = uhSum/hSum
+              do k=1,grid % maxLevelEdgeTop % array(iEdge)
+                 u(k,iEdge) = u(k,iEdge) - vertSum
+              enddo
+
+           enddo ! iEdge
+
+      call timer_stop(&quot;filter_btr_mode_u&quot;)
+
+   end subroutine filter_btr_mode_u!}}}
+
+   subroutine enforce_boundaryEdge(tend, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Enforce any boundary conditions on the normal velocity at each edge
+   !
+   ! Input: grid - grid metadata
+   !
+   ! Output: tend_u set to zero at boundaryEdge == 1 locations
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+      implicit none
+
+      type (tend_type), intent(inout) :: tend
+      type (mesh_type), intent(in) :: grid
+
+      integer, dimension(:,:), pointer :: boundaryEdge
+      real (kind=RKIND), dimension(:,:), pointer :: tend_u
+      integer :: nCells, nEdges, nVertices, nVertLevels
+      integer :: iEdge, k
+
+      call timer_start(&quot;enforce_boundaryEdge&quot;)
+
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      boundaryEdge         =&gt; grid % boundaryEdge % array
+      tend_u      =&gt; tend % u % array
+
+      if(maxval(boundaryEdge).le.0) return
+
+      do iEdge = 1,nEdges
+        do k = 1,nVertLevels
+
+          if(boundaryEdge(k,iEdge).eq.1) then
+             tend_u(k,iEdge) = 0.0
+          endif
+
+        enddo
+       enddo
+      call timer_stop(&quot;enforce_boundaryEdge&quot;)
+
+   end subroutine enforce_boundaryEdge!}}}
+
+end module ocn_time_integration_rk4
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_time_integration_split.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_time_integration_split.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_time_integration_split.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_time_integration_split.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,1439 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_time_integration_split
+!
+!&gt; \brief MPAS ocean split explicit time integration scheme
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for the split explicit
+!&gt;  time integration scheme
+!
+!-----------------------------------------------------------------------
+
+
+module ocn_time_integration_split
+
+   use grid_types
+   use configure
+   use constants
+   use dmpar
+   use vector_reconstruction
+   use spline_interpolation
+   use timer
+
+   use ocn_tendency
+
+   use ocn_equation_of_state
+   use ocn_vmix
+
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_time_integrator_split
+
+   contains
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_time_integration_split
+!
+!&gt; \brief MPAS ocean split explicit time integration scheme
+!&gt; \author Doug Jacobsen
+!&gt; \date   26 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This routine integrates a single time step (dt) using a
+!&gt;  split explicit time integrator.
+!
+!-----------------------------------------------------------------------
+
+subroutine ocn_time_integrator_split(domain, dt)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Advance model state forward in time by the specified time step using 
+   !   Split_Explicit timestepping scheme
+   !
+   ! Input: domain - current model state in time level 1 (e.g., time_levs(1)state%h(:,:)) 
+   !                 plus grid meta-data
+   ! Output: domain - upon exit, time level 2 (e.g., time_levs(2)%state%h(:,:)) contains 
+   !                  model state advanced forward in time by dt seconds
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (domain_type), intent(inout) :: domain
+      real (kind=RKIND), intent(in) :: dt
+
+      type (dm_info) :: dminfo
+      integer :: iCell, i,k,j, iEdge, cell1, cell2, split_explicit_step, split, &amp;
+        eoe, oldBtrSubcycleTime, newBtrSubcycleTime, uPerpTime, BtrCorIter, &amp;
+        n_bcl_iter(config_n_ts_iter), &amp;
+        vertex1, vertex2, iVertex
+
+      type (block_type), pointer :: block
+      real (kind=RKIND) :: uhSum, hSum, sshEdge, flux, &amp;
+         uPerp, uCorr, tracerTemp, coef
+      real (kind=RKIND), dimension(:), pointer :: sshNew
+
+      integer :: num_tracers, ucorr_coef, err
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        u, h, h_edge, ke_edge, vertViscTopOfEdge, vertDiffTopOfCell
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+      integer, dimension(:), pointer :: &amp; 
+        maxLevelCell, maxLevelEdgeTop
+      real (kind=RKIND), dimension(:), allocatable:: A,C,uTemp, hNew
+      real (kind=RKIND), dimension(:,:), allocatable:: tracersTemp
+
+      call timer_start(&quot;split_explicit_timestep&quot;)
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      !
+      !  Prep variables before first iteration
+      !
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      block =&gt; domain % blocklist
+      do while (associated(block))
+
+         do iEdge=1,block % mesh % nEdges
+
+            ! The baroclinic velocity needs be recomputed at the beginning of a 
+            ! timestep because the implicit vertical mixing is conducted on the
+            ! total u.  We keep uBtr from the previous timestep.
+              block % state % time_levs(1) % state % uBcl % array(:,iEdge) &amp;
+            = block % state % time_levs(1) % state % u % array(:,iEdge) &amp;
+            - block % state % time_levs(1) % state % uBtr % array(iEdge)
+
+              block % state % time_levs(2) % state % u % array(:,iEdge) &amp;
+            = block % state % time_levs(1) % state % u % array(:,iEdge)
+
+              block % state % time_levs(2) % state % uBcl % array(:,iEdge) &amp;
+            = block % state % time_levs(1) % state % uBcl % array(:,iEdge)
+
+         enddo ! iEdge
+
+         ! Initialize * variables that are used compute baroclinic tendencies below.
+           block % state % time_levs(2) % state % ssh % array(:) &amp;
+         = block % state % time_levs(1) % state % ssh % array(:)
+
+           block % state % time_levs(2) % state % h_edge % array(:,:) &amp;
+         = block % state % time_levs(1) % state % h_edge % array(:,:)
+
+         do iCell=1,block % mesh % nCells  ! couple tracers to h
+           ! change to maxLevelCell % array(iCell) ?
+           do k=1,block % mesh % nVertLevels
+
+                block % state % time_levs(2) % state % tracers % array(:,k,iCell) &amp; 
+              = block % state % time_levs(1) % state % tracers % array(:,k,iCell) 
+            end do
+
+         end do
+
+         block =&gt; block % next
+      end do
+
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! BEGIN large iteration loop 
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      n_bcl_iter = config_n_bcl_iter_mid
+      n_bcl_iter(1) = config_n_bcl_iter_beg
+      n_bcl_iter(config_n_ts_iter) = config_n_bcl_iter_end
+
+      do split_explicit_step = 1, config_n_ts_iter
+! ---  update halos for diagnostic variables
+
+        block =&gt; domain % blocklist
+        do while (associated(block))
+! mrp 110512 not sure if I need the following three.  Leave be, assume I need it.
+           call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % pv_edge % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nEdges, &amp;
+                                            block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+           if (config_h_mom_eddy_visc4 &gt; 0.0) then
+              call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % divergence % array(:,:), &amp;
+                                               block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                               block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+              call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % vorticity % array(:,:), &amp;
+                                               block % mesh % nVertLevels, block % mesh % nVertices, &amp;
+                                               block % parinfo % verticesToSend, block % parinfo % verticesToRecv)
+           end if
+
+           block =&gt; block % next
+        end do
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      !
+      !  Stage 1: Baroclinic velocity (3D) prediction, explicit with long timestep
+      !
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      ! compute velocity tendencies, T(u*,w*,p*)
+
+      block =&gt; domain % blocklist
+      do while (associated(block))
+         if (.not.config_implicit_vertical_mix) then
+            call ocn_vmix_coefs(block % mesh, block % state % time_levs(2) % state, block % diagnostics, err)
+         end if
+         call ocn_tend_u(block % tend, block % state % time_levs(2) % state , block % diagnostics, block % mesh)
+         call enforce_boundaryEdge(block % tend, block % mesh)
+         block =&gt; block % next
+      end do
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! BEGIN baroclinic iterations on linear Coriolis term
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      do j=1,n_bcl_iter(split_explicit_step)
+
+         ! Use this G coefficient to avoid an if statement within the iEdge loop.
+         if     (trim(config_time_integration) == 'unsplit_explicit') then
+            split = 0
+         elseif (trim(config_time_integration) == 'split_explicit') then
+            split = 1
+         endif
+
+         block =&gt; domain % blocklist
+         do while (associated(block))
+           allocate(uTemp(block % mesh % nVertLevels))
+
+           ! Put f*uBcl^{perp} in uNew as a work variable
+           call ocn_fuperp(block % state % time_levs(2) % state , block % mesh)
+
+           do iEdge=1,block % mesh % nEdges
+              cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+              cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+              uTemp = 0.0  ! could put this after with uTemp(maxleveledgetop+1:nvertlevels)=0
+              do k=1,block % mesh % maxLevelEdgeTop % array(iEdge)
+
+                 ! uBclNew = uBclOld + dt*(-f*uBclPerp + T(u*,w*,p*) + g*grad(SSH*) )
+                 ! Here uNew is a work variable containing -fEdge(iEdge)*uBclPerp(k,iEdge)
+                 uTemp(k) &amp;
+                 = block % state % time_levs(1) % state % uBcl % array(k,iEdge) &amp;
+                 + dt * (block % tend % u % array (k,iEdge) &amp;
+                      + block % state % time_levs(2) % state % u % array (k,iEdge) &amp;  ! this is f*uBcl^{perp}
+                      + split*gravity &amp;
+                        *(  block % state % time_levs(2) % state % ssh % array(cell2) &amp;
+                          - block % state % time_levs(2) % state % ssh % array(cell1) ) &amp;
+                          /block % mesh % dcEdge % array(iEdge) )
+              enddo
+
+              ! Compute GBtrForcing, the vertically averaged forcing
+              sshEdge = 0.5*( &amp;
+                  block % state % time_levs(1) % state % ssh % array(cell1) &amp; 
+                + block % state % time_levs(1) % state % ssh % array(cell2) ) 
+
+              uhSum = (sshEdge + block % mesh % hZLevel % array(1)) * uTemp(1)
+              hSum  =  sshEdge + block % mesh % hZLevel % array(1)
+
+              do k=2,block % mesh % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + block % mesh % hZLevel % array(k) * uTemp(k)
+                 hSum  =  hSum + block % mesh % hZLevel % array(k)
+              enddo
+              block % state % time_levs(1) % state % GBtrForcing % array(iEdge) = split*uhSum/hSum/dt
+
+
+              do k=1,block % mesh % maxLevelEdgeTop % array(iEdge)
+                 ! These two steps are together here:
+                 !{\bf u}'_{k,n+1} = {\bf u}'_{k,n} - \Delta t {\overline {\bf G}}
+                 !{\bf u}'_{k,n+1/2} = \frac{1}{2}\left({\bf u}^{'}_{k,n} +{\bf u}'_{k,n+1}\right) 
+                 ! so that uBclNew is at time n+1/2
+                block % state % time_levs(2) % state % uBcl % array(k,iEdge) &amp;
+                  = 0.5*( &amp;
+                  block % state % time_levs(1) % state % uBcl % array(k,iEdge) &amp;
+                  + uTemp(k) - dt * block % state % time_levs(1) % state % GBtrForcing % array(iEdge))
+              enddo
+
+           enddo ! iEdge
+
+           deallocate(uTemp)
+
+           block =&gt; block % next
+         end do
+
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           call dmpar_exch_halo_field2dReal(domain % dminfo, block % state % time_levs(2) % state % uBcl % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nEdges, &amp;
+                                            block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+           block =&gt; block % next
+        end do
+
+      enddo  ! do j=1,config_n_bcl_iter
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! END baroclinic iterations on linear Coriolis term
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      !
+      !  Stage 2: Barotropic velocity (2D) prediction, explicitly subcycled
+      !
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      oldBtrSubcycleTime = 1
+      newBtrSubcycleTime = 2
+
+      if (trim(config_time_integration) == 'unsplit_explicit') then
+
+         block =&gt; domain % blocklist
+         do while (associated(block))
+
+            ! For Split_Explicit unsplit, simply set uBtrNew=0, uBtrSubcycle=0, and uNew=uBclNew
+            block % state % time_levs(2) % state % uBtr % array(:) = 0.0
+
+            block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(:) = 0.0
+
+               block % state % time_levs(2) % state % u    % array(:,:) &amp;
+             = block % state % time_levs(2) % state % uBcl % array(:,:) 
+
+            block =&gt; block % next
+         end do  ! block
+
+      elseif (trim(config_time_integration) == 'split_explicit') then
+
+         ! Initialize variables for barotropic subcycling
+         block =&gt; domain % blocklist
+         do while (associated(block))
+
+        if (config_filter_btr_mode) then
+          block % state % time_levs(1) % state % GBtrForcing % array(:) = 0.0
+        endif
+
+            do iCell=1,block % mesh % nCells
+              ! sshSubcycleOld = sshOld  
+                block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(iCell) &amp; 
+              = block % state % time_levs(1) % state % ssh % array(iCell)  
+
+              ! sshNew = sshOld  This is the first for the summation
+                block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+              = block % state % time_levs(1) % state % ssh % array(iCell)  
+            enddo
+
+           do iEdge=1,block % mesh % nEdges
+
+              ! uBtrSubcycleOld = uBtrOld 
+                block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              = block % state % time_levs(1) % state % uBtr % array(iEdge) 
+
+              ! uBtrNew = BtrOld  This is the first for the summation
+                block % state % time_levs(2) % state % uBtr % array(iEdge) &amp;
+              = block % state % time_levs(1) % state % uBtr % array(iEdge) 
+
+              ! FBtr = 0  
+              block % state % time_levs(1) % state % FBtr % array(iEdge) = 0.0
+            enddo
+
+            block =&gt; block % next
+         end do  ! block
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! BEGIN Barotropic subcycle loop
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+         do j=1,config_n_btr_subcycles*config_btr_subcycle_loop_factor
+
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            ! Barotropic subcycle: initial solve for velecity
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            uPerpTime = oldBtrSubcycleTime
+
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+         do iEdge=1,block % mesh % nEdges
+
+               cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+               cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+            ! Compute -f*uPerp
+            uPerp = 0.0
+            do i = 1,block % mesh % nEdgesOnEdge % array(iEdge)
+               eoe = block % mesh % edgesOnEdge % array(i,iEdge)
+               uPerp = uPerp + block % mesh % weightsOnEdge % array(i,iEdge) &amp;
+                  * block % state % time_levs(uPerpTime) % state % uBtrSubcycle % array(eoe) &amp;
+                  * block % mesh % fEdge  % array(eoe)
+            end do
+
+          ! mrp 110606 efficiency note: could make this a 1D integer factor instead of an if statement.
+          if (block % mesh % boundaryEdge % array(1,iEdge).eq.1) then
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) = 0.0
+          else
+
+             ! uBtrNew = uBtrOld + dt*(-f*uBtroldPerp - g*grad(SSH) + G)
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              = block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              + dt/config_n_btr_subcycles *( &amp;
+                        uPerp &amp;
+                      - gravity &amp;
+                        *(  block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(cell2) &amp;
+                          - block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(cell1) ) &amp;
+                          /block % mesh % dcEdge % array(iEdge) &amp;
+                      + block % state % time_levs(1) % state % GBtrForcing % array(iEdge) )
+
+          endif
+
+         end do
+
+         !  Implicit solve for barotropic momentum decay
+         if ( config_btr_mom_decay) then
+            !
+            !  Add term to RHS of momentum equation: -1/gamma u
+            !
+            !  This changes the solve to:
+            !  u^{n+1} = u_provis^{n+1}/(1+dt/gamma)
+            !
+            coef = 1.0/(1.0 + dt/config_n_btr_subcycles/config_btr_mom_decay_time)
+            do iEdge=1,block % mesh % nEdges
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              = block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              * coef
+            end do
+
+          endif
+
+
+               block =&gt; block % next
+            end do  ! block
+
+
+            !   boundary update on uBtrNew
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+           call dmpar_exch_halo_field1dReal(domain % dminfo, &amp;
+              block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(:), &amp;
+              block % mesh % nEdges, &amp;
+              block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+               block =&gt; block % next
+            end do  ! block
+
+
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            ! Barotropic subcycle: Compute thickness flux and new SSH
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+           block % tend % ssh % array(:) = 0.0
+
+           ! config_btr_flux_coef sets the forward weighting of velocity in the SSH computation
+           ! config_btr_flux_coef=  1     flux = uBtrNew*H
+           ! config_btr_flux_coef=0.5     flux = 1/2*(uBtrNew+uBtrOld)*H
+           ! config_btr_flux_coef=  0     flux = uBtrOld*H
+           do iEdge=1,block % mesh % nEdges
+              cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+              cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+              sshEdge = 0.5 &amp;
+                 *(  block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(cell1) &amp;
+                   + block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(cell2) )
+              hSum = sum(block % mesh % hZLevel % array (1:block % mesh % maxLevelEdgeTop % array(iEdge)))
+
+              flux = ((1.0-config_btr_flux_coef) &amp; 
+                        * block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+                       + config_btr_flux_coef &amp;
+                        * block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge)) &amp;
+                    * block % mesh % dvEdge % array(iEdge) &amp;
+                    * (sshEdge + hSum)
+
+               block % tend % ssh % array(cell1) = block % tend % ssh % array(cell1) - flux
+               block % tend % ssh % array(cell2) = block % tend % ssh % array(cell2) + flux
+
+               block % state % time_levs(1) % state % FBtr % array(iEdge) &amp;
+             = block % state % time_levs(1) % state % FBtr % array(iEdge) &amp;
+             + flux
+         end do

+         ! SSHnew = SSHold + dt/J*(-div(Flux))
+         do iCell=1,block % mesh % nCells 
+
+                block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(iCell) &amp; 
+              = block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(iCell) &amp; 
+              + dt/config_n_btr_subcycles &amp;
+                * block % tend % ssh % array(iCell) / block % mesh % areaCell % array (iCell)
+
+         end do
+
+               block =&gt; block % next
+            end do  ! block
+
+            !   boundary update on SSNnew
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+!              block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(:), &amp;
+
+           call dmpar_exch_halo_field1dReal(domain % dminfo, &amp;
+              block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(:), &amp;
+              block % mesh % nCells, &amp;
+              block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+
+               block =&gt; block % next
+            end do  ! block
+
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+         do iCell=1,block % mesh % nCells 
+
+         ! Accumulate SSH in running sum over the subcycles.
+                block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+              = block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+              + block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(iCell)  
+
+         end do
+
+               block =&gt; block % next
+            end do  ! block
+
+! mrp 110801 begin
+! This whole section, bounded by 'mrp 110801', may be deleted later if it is found
+! that barotropic del2 is not useful.
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            ! Barotropic subcycle: compute btr_divergence and btr_vorticity for del2(u_btr) 
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            block =&gt; domain % blocklist
+            do while (associated(block))
+      block % state % time_levs(1) % state % u_diffusionBtr % array(:) = 0.0
+      if ( config_btr_mom_eddy_visc2 &gt; 0.0 ) then
+      !
+      ! Compute circulation and relative vorticity at each vertex
+      !
+      block % state % time_levs(1) % state % circulationBtr % array(:) = 0.0
+      do iEdge=1,block % mesh % nEdges
+         vertex1 = block % mesh % verticesOnEdge % array(1,iEdge)
+         vertex2 = block % mesh % verticesOnEdge % array(2,iEdge)
+             block % state % time_levs(1) % state % circulationBtr % array(vertex1) &amp;
+           = block % state % time_levs(1) % state % circulationBtr % array(vertex1) &amp;
+           - block % mesh % dcEdge % array (iEdge) &amp;
+            *block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge)
+
+             block % state % time_levs(1) % state % circulationBtr % array(vertex2) &amp;
+           = block % state % time_levs(1) % state % circulationBtr % array(vertex2) &amp;
+           + block % mesh % dcEdge % array (iEdge) &amp;
+            *block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge)
+      end do 
+      do iVertex=1,block % mesh % nVertices
+            block % state % time_levs(1) % state % vorticityBtr % array(iVertex) &amp;
+          = block % state % time_levs(1) % state % circulationBtr % array(iVertex) / block % mesh % areaTriangle % array (iVertex)
+      end do
+
+      !
+      ! Compute the divergence at each cell center
+      !
+      block % state % time_levs(1) % state % divergenceBtr % array(:) = 0.0
+      do iEdge=1,block % mesh % nEdges
+         cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+         cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+             block % state % time_levs(1) % state % divergenceBtr % array (cell1) &amp;
+           = block % state % time_levs(1) % state % divergenceBtr % array (cell1) &amp;
+           + block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+            *block % mesh % dvEdge % array(iEdge)
+
+             block % state % time_levs(1) % state % divergenceBtr % array (cell2) &amp;
+           = block % state % time_levs(1) % state % divergenceBtr % array (cell2) &amp;
+           - block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+            *block % mesh % dvEdge % array(iEdge)
+      end do
+      do iCell = 1,block % mesh % nCells
+         block % state % time_levs(1) % state % divergenceBtr % array(iCell) &amp;
+       = block % state % time_levs(1) % state % divergenceBtr % array(iCell) &amp;
+        /block % mesh % areaCell % array(iCell)
+      enddo
+
+      !
+      ! Compute Btr diffusion
+      !
+         do iEdge=1,block % mesh % nEdgesSolve
+            cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+            cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+            vertex1 = block % mesh % verticesOnEdge % array(1,iEdge)
+            vertex2 = block % mesh % verticesOnEdge % array(2,iEdge)
+
+               ! Here -( vorticityBtr(vertex2) - vorticityBtr(vertex1) ) / dvEdge % array (iEdge)
+               ! is - </font>
<font color="blue">abla vorticity pointing from vertex 2 to vertex 1, or equivalently 
+               !    + k \times </font>
<font color="gray">abla vorticity pointing from cell1 to cell2.
+
+               block % state % time_levs(1) % state % u_diffusionBtr % array(iEdge) = block % mesh % meshScalingDel2 % array (iEdge) * config_btr_mom_eddy_visc2 * &amp;
+                   (( block % state % time_levs(1) % state % divergenceBtr % array(cell2)  - block % state % time_levs(1) % state % divergenceBtr % array(cell1) ) / block % mesh % dcEdge % array (iEdge)  &amp;
+                  -( block % state % time_levs(1) % state % vorticityBtr % array(vertex2) - block % state % time_levs(1) % state % vorticityBtr % array(vertex1) ) / block % mesh % dvEdge % array (iEdge))
+
+         end do
+      end if
+               block =&gt; block % next
+            end do  ! block
+! mrp 110801 end
+
+
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            ! Barotropic subcycle: Final solve for velocity.  Iterate for Coriolis term.
+            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+       do BtrCorIter=1,config_n_btr_cor_iter
+
+          uPerpTime = newBtrSubcycleTime
+
+          block =&gt; domain % blocklist
+          do while (associated(block))
+
+         do iEdge=1,block % mesh % nEdges 
+
+               cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+               cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+            ! Compute -f*uPerp
+            uPerp = 0.0
+            do i = 1,block % mesh % nEdgesOnEdge % array(iEdge)
+               eoe = block % mesh % edgesOnEdge % array(i,iEdge)
+               uPerp = uPerp + block % mesh % weightsOnEdge % array(i,iEdge) &amp;
+                  * block % state % time_levs(uPerpTime) % state % uBtrSubcycle % array(eoe) &amp;
+                  * block % mesh % fEdge  % array(eoe) 
+            end do
+
+          ! mrp 110606 efficiency note: could make this a 1D integer factor instead of an if statement.
+          if (block % mesh % boundaryEdge % array(1,iEdge).eq.1) then
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) = 0.0
+          else
+
+             ! uBtrNew = uBtrOld + dt*(-f*uBtroldPerp - g*grad(SSH) + G)
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp; 
+              = block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp; 
+              + dt/config_n_btr_subcycles *( &amp;
+                        uPerp &amp;
+                      - gravity &amp;
+                        *(  block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(cell2) &amp;
+                          - block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(cell1) ) &amp;
+                          /block % mesh % dcEdge % array(iEdge) &amp;
+                      + block % state % time_levs(1) % state % GBtrForcing % array(iEdge) &amp;
+                      + block % state % time_levs(1) % state % u_diffusionBtr % array(iEdge))
+                      ! added del2 diffusion to btr solve
+
+          endif
+
+         end do
+
+            !  Implicit solve for barotropic momentum decay
+         if ( config_btr_mom_decay) then
+            !  Add term to RHS of momentum equation: -1/gamma u
+            !
+            !  This changes the solve to:
+            !  u^{n+1} = u_provis^{n+1}/(1+dt/gamma)
+            !
+            coef = 1.0/(1.0 + dt/config_n_btr_subcycles/config_btr_mom_decay_time)
+            do iEdge=1,block % mesh % nEdges 
+                block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp; 
+              = block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge) &amp;
+              * coef
+            end do
+
+         endif
+
+               block =&gt; block % next
+            end do  ! block
+
+
+            !   boundary update on uBtrNew
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+               call dmpar_exch_halo_field1dReal(domain % dminfo, &amp;
+                  block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(:), &amp;
+                  block % mesh % nEdges, &amp;
+                  block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+               block =&gt; block % next
+            end do  ! block
+
+       end do !do BtrCorIter=1,config_n_btr_cor_iter
+
+
+            ! uBtrNew = uBtrNew + uBtrSubcycleNEW
+            ! This accumulates the sum.
+            ! If the Barotropic Coriolis iteration is limited to one, this could 
+            ! be merged with the above code.
+            block =&gt; domain % blocklist
+            do while (associated(block))
+         do iEdge=1,block % mesh % nEdges 
+
+                block % state % time_levs(2) % state % uBtr % array(iEdge) &amp; 
+              = block % state % time_levs(2) % state % uBtr % array(iEdge) &amp; 
+              + block % state % time_levs(newBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge)  
+
+            end do  ! iEdge
+               block =&gt; block % next
+         end do  ! block
+
+            ! advance time pointers
+            oldBtrSubcycleTime = mod(oldBtrSubcycleTime,2)+1
+            newBtrSubcycleTime = mod(newBtrSubcycleTime,2)+1
+
+         end do ! j=1,config_n_btr_subcycles
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! END Barotropic subcycle loop
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+            ! Normalize Barotropic subcycle sums: ssh, uBtr, and F
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+         do iEdge=1,block % mesh % nEdges
+               block % state % time_levs(1) % state % FBtr % array(iEdge) &amp;
+             = block % state % time_levs(1) % state % FBtr % array(iEdge) &amp;
+             / (config_n_btr_subcycles*config_btr_subcycle_loop_factor)
+
+                block % state % time_levs(2) % state % uBtr % array(iEdge) &amp; 
+              = block % state % time_levs(2) % state % uBtr % array(iEdge) &amp; 
+             / (config_n_btr_subcycles*config_btr_subcycle_loop_factor + 1)
+         end do
+
+        if (config_SSH_from=='avg_of_SSH_subcycles') then
+         do iCell=1,block % mesh % nCells 
+                block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+              = block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+             / (config_n_btr_subcycles*config_btr_subcycle_loop_factor + 1)
+         end do
+        elseif (config_SSH_from=='avg_flux') then
+           ! see below
+        else
+         write(0,*) 'Abort: Unknown config_SSH_from option: '&amp;
+           //trim(config_SSH_from)
+         call dmpar_abort(dminfo)
+        endif
+
+               block =&gt; block % next
+            end do  ! block
+
+
+            ! boundary update on F
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+           call dmpar_exch_halo_field1dReal(domain % dminfo, &amp;
+              block % state % time_levs(1) % state % FBtr % array(:), &amp;
+              block % mesh % nEdges, &amp;
+              block % parinfo % edgesToSend, block % parinfo % edgesToRecv)
+
+               block =&gt; block % next
+            end do  ! block
+
+
+            ! Check that you can compute SSH using the total sum or the individual increments
+            ! over the barotropic subcycles.
+            ! efficiency: This next block of code is really a check for debugging, and can 
+            ! be removed later.
+            block =&gt; domain % blocklist
+            do while (associated(block))
+
+               allocate(uTemp(block % mesh % nVertLevels))
+
+        if (config_SSH_from=='avg_flux') then
+           ! Accumulate fluxes in the tend % ssh variable
+           block % tend % ssh % array(:) = 0.0
+           do iEdge=1,block % mesh % nEdges
+              cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+              cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+                 block % tend % ssh % array(cell1) &amp;
+               = block % tend % ssh % array(cell1) &amp;
+               - block % state % time_levs(1) % state % FBtr % array(iEdge)
+
+                 block % tend % ssh % array(cell2) &amp;
+               = block % tend % ssh % array(cell2) &amp;
+               + block % state % time_levs(1) % state % FBtr % array(iEdge)
+
+          end do
+
+         do iCell=1,block % mesh % nCells 

+             ! SSHnew = SSHold + dt*(-div(Flux))
+                block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+              = block % state % time_levs(1) % state % ssh % array(iCell) &amp; 
+              + dt &amp;
+                * block % tend % ssh % array(iCell) / block % mesh % areaCell % array (iCell)
+         end do
+       endif
+         ! Now can compare sshSubcycleNEW (big step using summed fluxes) with
+         ! sshSubcycleOLD (individual steps to get there)
+!print *, 'ssh, by substeps',minval(block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(1:block % mesh % nCellsSolve)), &amp;
+!                            maxval(block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(1:block % mesh % nCellsSolve))
+!print *, 'ssh, by 1 step  ',minval(block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(1:block % mesh % nCellsSolve)), &amp;
+!                            maxval(block % state % time_levs(newBtrSubcycleTime) % state % sshSubcycle % array(1:block % mesh % nCellsSolve))
+
+         ! Correction velocity    uCorr = (Flux - Sum(h u*))/H
+         ! or, for the full latex version:
+         !u^{corr} = \left( {\overline {\bf F}} 
+         !  - \sum_{k=1}^{N^{edge}} \left(\zeta_{k,n}^{*\;edge}+\Delta z_k\right)  u_k^* \right)
+         !\left/ \sum_{k=1}^{N^{edge}} \left(\zeta_{k,n}^{*\;edge}+\Delta z_k\right)   \right. 
+
+          if (config_u_correction) then
+             ucorr_coef = 1
+          else
+             ucorr_coef = 0
+          endif
+
+           do iEdge=1,block % mesh % nEdges
+              cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+              cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+
+              sshEdge = 0.5 &amp;
+                 *(  block % state % time_levs(2) % state % ssh % array(cell1) &amp;
+                   + block % state % time_levs(2) % state % ssh % array(cell2) )
+
+             ! This is u*
+               uTemp(:) &amp;
+             = block % state % time_levs(2) % state % uBtr % array(iEdge) &amp;
+             + block % state % time_levs(2) % state % uBcl % array(:,iEdge) 
+
+              uhSum = (sshEdge + block % mesh % hZLevel % array(1)) * uTemp(1)
+              hSum  =  sshEdge + block % mesh % hZLevel % array(1)
+
+              do k=2,block % mesh % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + block % mesh % hZLevel % array(k) * uTemp(k)
+                 hSum  =  hSum + block % mesh % hZLevel % array(k)
+              enddo
+
+            uCorr =   ucorr_coef*(( block % state % time_levs(1) % state % FBtr % array(iEdge) &amp;
+                       /block % mesh % dvEdge % array(iEdge) &amp;
+                      - uhSum)/hSum)
+
+              ! put u^{tr}, the velocity for tracer transport, in uNew
+          ! mrp 060611 not sure if boundary enforcement is needed here.  
+          if (block % mesh % boundaryEdge % array(1,iEdge).eq.1) then
+              block % state % time_levs(2) % state % u % array(:,iEdge) = 0.0
+          else
+              block % state % time_levs(2) % state % u % array(:,iEdge) = uTemp(:) + uCorr
+          endif
+
+         ! Put new sshEdge values in h_edge array, for the OcnTendScalar call below.
+             block % state % time_levs(2) % state % h_edge % array(1,iEdge) &amp;
+           = sshEdge + block % mesh % hZLevel % array(1)
+
+           do k=2,block % mesh % nVertLevels
+             block % state % time_levs(2) % state % h_edge % array(k,iEdge) &amp;
+           = block % mesh % hZLevel % array(k)
+           enddo
+
+          end do ! iEdge
+
+         ! Put new SSH values in h array, for the OcnTendScalar call below.
+         do iCell=1,block % mesh % nCells 
+             block % state % time_levs(2) % state % h % array(1,iCell) &amp;
+           = block % state % time_levs(2) % state % ssh % array(iCell) &amp;
+           + block % mesh % hZLevel % array(1)
+
+           ! mrp 110601 efficiency note: Since h just moves back and forth between pointers,
+           ! this is not necessary once initialized.
+           do k=2,block % mesh % nVertLevels
+             block % state % time_levs(2) % state % h % array(k,iCell) &amp;
+           = block % mesh % hZLevel % array(k)
+           enddo
+         enddo ! iCell
+
+           deallocate(uTemp)
+
+               block =&gt; block % next
+            end do  ! block
+
+
+      endif ! split_explicit
+
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      !
+      !  Stage 3: Tracer, density, pressure, vertical velocity prediction
+      !
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+         block =&gt; domain % blocklist
+         do while (associated(block))
+
+           call ocn_wtop(block % state % time_levs(2) % state, block % mesh)
+
+      if (trim(config_time_integration) == 'unsplit_explicit') then
+           call ocn_tend_h(block % tend, block % state % time_levs(2) % state , block % diagnostics, block % mesh)
+      endif
+
+           call ocn_tend_scalar(block % tend, block % state % time_levs(2) % state , block % diagnostics, block % mesh)
+
+           block =&gt; block % next
+         end do
+
+        ! ---  update halos for prognostic variables
+
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           call dmpar_exch_halo_field2dReal(domain % dminfo, block % tend % h % array(:,:), &amp;
+                                            block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                            block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+           call dmpar_exch_halo_field3dReal(domain % dminfo, block % tend % tracers % array(:,:,:), &amp;
+                                            block % tend % num_tracers, block % mesh % nVertLevels, block % mesh % nCells, &amp;
+                                            block % parinfo % cellsToSend, block % parinfo % cellsToRecv)
+           block =&gt; block % next
+        end do
+
+
+        block =&gt; domain % blocklist
+        do while (associated(block))
+           allocate(hNew(block % mesh % nVertLevels))
+
+        if (trim(config_new_btr_variables_from) == 'last_subcycle') then
+           ! This points to the last barotropic SSH subcycle
+           sshNew =&gt; block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array
+        elseif (trim(config_new_btr_variables_from) == 'btr_avg') then
+           ! This points to the tendency variable SSH*
+           sshNew =&gt; block % state % time_levs(2) % state % ssh % array
+        endif
+
+      if (trim(config_time_integration) == 'unsplit_explicit') then
+
+         do iCell=1,block % mesh % nCells
+           ! this is h_{n+1}
+             block % state % time_levs(2) % state % h % array(:,iCell) &amp;
+           = block % state % time_levs(1) % state % h % array(:,iCell) &amp;
+           + dt* block % tend % h % array(:,iCell) 
+
+            ! this is only for the hNew computation below, so there is the correct
+            ! value in the ssh variable for unsplit_explicit case.
+            block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(iCell) &amp;
+          = block % state % time_levs(2) % state % h % array(1,iCell) &amp;
+          - block % mesh % hZLevel % array(1)
+           end do ! iCell
+
+      endif ! unsplit_explicit
+
+           ! Only need T &amp; S for earlier iterations,
+           ! then all the tracers needed the last time through.
+         if (split_explicit_step &lt; config_n_ts_iter) then
+
+           hNew(:) = block % mesh % hZLevel % array(:)
+           do iCell=1,block % mesh % nCells
+              ! sshNew is a pointer, defined above.
+              hNew(1) =  sshNew(iCell) + block % mesh % hZLevel % array(1)
+              do k=1,block % mesh % maxLevelCell % array(iCell)
+                 do i=1,2
+                ! This is Phi at n+1
+                tracerTemp &amp;
+                = (  block % state % time_levs(1) % state % tracers % array(i,k,iCell) &amp;
+                   * block % state % time_levs(1) % state % h % array(k,iCell) &amp;
+                 + dt * block % tend % tracers % array(i,k,iCell) &amp;
+                  ) / hNew(k)
+
+                ! This is Phi at n+1/2
+                   block % state % time_levs(2) % state % tracers % array(i,k,iCell)  &amp;
+                 = 0.5*( &amp;
+                   block % state % time_levs(1) % state % tracers % array(i,k,iCell) &amp;
+                 + tracerTemp )
+                 enddo
+              end do
+           end do ! iCell
+
+
+          if (trim(config_time_integration) == 'unsplit_explicit') then
+
+            ! compute h*, which is h at n+1/2 and put into array hNew
+            ! on last iteration, hNew remains at n+1
+           do iCell=1,block % mesh % nCells
+                 block % state % time_levs(2) % state % h % array(1,iCell) &amp;
+                 = 0.5*( &amp;
+                 block % state % time_levs(2) % state % h % array(1,iCell) &amp;
+               + block % state % time_levs(1) % state % h % array(1,iCell) )
+
+           end do ! iCell
+          endif ! unsplit_explicit
+
+          ! compute u*, the velocity for tendency terms.  Put in uNew.
+          ! uBclNew is at time n+1/2 here.
+          ! This overwrites u^{tr}, the tracer transport velocity, which was in uNew.
+          ! The following must occur after  call OcnTendScalar
+           do iEdge=1,block % mesh % nEdges
+               block % state % time_levs(2) % state % u    % array(:,iEdge) &amp;
+             = block % state % time_levs(2) % state % uBtr % array(iEdge) &amp;
+             + block % state % time_levs(2) % state % uBcl % array(:,iEdge) 
+           end do ! iEdge
+
+         ! mrp 110512  I really only need this to compute h_edge, density, pressure.
+         ! I can par this down later.
+         call ocn_diagnostic_solve(dt, block % state % time_levs(2) % state, block % mesh)

+
+         elseif (split_explicit_step == config_n_ts_iter) then
+
+           hNew(:) = block % mesh % hZLevel % array(:)
+           do iCell=1,block % mesh % nCells
+              ! sshNew is a pointer, defined above.
+              hNew(1) =  sshNew(iCell) + block % mesh % hZLevel % array(1)
+              do k=1,block % mesh % maxLevelCell % array(iCell)
+                 do i=1,block % state % time_levs(1) % state % num_tracers
+                ! This is Phi at n+1
+                   block % state % time_levs(2) % state % tracers % array(i,k,iCell)  &amp;
+                = (  block % state % time_levs(1) % state % tracers % array(i,k,iCell) &amp;
+                   * block % state % time_levs(1) % state % h % array(k,iCell) &amp;
+                 + dt * block % tend % tracers % array(i,k,iCell) &amp;
+                  ) / hNew(k)
+
+                 enddo
+              end do
+           end do
+
+         endif ! split_explicit_step
+           deallocate(hNew)
+
+         block =&gt; block % next
+       end do
+
+      end do  ! split_explicit_step = 1, config_n_ts_iter
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! END large iteration loop 
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      !
+      !  A little clean up at the end: decouple new scalar fields and compute diagnostics for new state
+      !
+      block =&gt; domain % blocklist
+      do while (associated(block))
+
+        if (trim(config_new_btr_variables_from) == 'last_subcycle') then
+         do iEdge=1,block % mesh % nEdges
+               ! uBtrNew = uBtrSubcycleNew  (old here is because counter already flipped)
+               ! This line is not needed if u is resplit at the beginning of the timestep.
+                block % state % time_levs(2) % state % uBtr % array(iEdge) &amp; 
+              = block % state % time_levs(oldBtrSubcycleTime) % state % uBtrSubcycle % array(iEdge)  
+         enddo ! iEdges
+        elseif (trim(config_new_btr_variables_from) == 'btr_avg') then
+               ! uBtrNew from u*.  this is done above, so u* is already in
+               ! block % state % time_levs(2) % state % uBtr % array(iEdge) 
+        else
+         write(0,*) 'Abort: Unknown config_new_btr_variables_from: '&amp;
+           //trim(config_time_integration)
+         call dmpar_abort(dminfo)
+       endif
+
+         ! Recompute final u to go on to next step.
+         ! u_{n+1} = uBtr_{n+1} + uBcl_{n+1} 
+         ! Right now uBclNew is at time n+1/2, so back compute to get uBcl at time n+1
+         !   using uBcl_{n+1/2} = 1/2*(uBcl_n + u_Bcl_{n+1})
+         ! so the following lines are
+         ! u_{n+1} = uBtr_{n+1} + 2*uBcl_{n+1/2} - uBcl_n
+         ! note that uBcl is recomputed at the beginning of the next timestep due to Imp Vert mixing,
+         ! so uBcl does not have to be recomputed here.
+
+         do iEdge=1,block % mesh % nEdges
+            do k=1,block % mesh % maxLevelEdgeTop % array(iEdge)
+
+               block % state % time_levs(2) % state % u % array(k,iEdge) &amp; 
+            =  block % state % time_levs(2) % state % uBtr % array(iEdge) &amp;
+            +2*block % state % time_levs(2) % state % uBcl % array(k,iEdge) &amp;
+            -  block % state % time_levs(1) % state % uBcl % array(k,iEdge)
+            enddo
+            ! mrp 110607 zero out velocity below land edges. efficiency: this may not be required.
+            do k=block % mesh % maxLevelEdgeTop % array(iEdge) + 1, block % mesh % nVertLevels
+               block % state % time_levs(2) % state % u % array(k,iEdge) = 0.0
+            enddo
+
+         enddo ! iEdges
+
+        if (trim(config_time_integration) == 'split_explicit') then
+
+        if (trim(config_new_btr_variables_from) == 'last_subcycle') then
+         do iCell=1,block % mesh % nCells
+         ! SSH for the next step is from the end of the barotropic subcycle.
+               block % state % time_levs(2) % state % ssh % array(iCell) &amp; 
+            =  block % state % time_levs(oldBtrSubcycleTime) % state % sshSubcycle % array(iCell) 
+         end do ! iCell
+        elseif (trim(config_new_btr_variables_from) == 'btr_avg') then
+               ! sshNew from ssh*.  This is done above, so ssh* is already in
+               ! block % state % time_levs(2) % state % ssh % array(iCell) 
+        endif
+
+         do iCell=1,block % mesh % nCells
+         ! Put new SSH values in h array, for the OcnTendScalar call below.
+             block % state % time_levs(2) % state % h % array(1,iCell) &amp;
+           = block % state % time_levs(2) % state % ssh % array(iCell) &amp;
+           + block % mesh % hZLevel % array(1)
+
+           ! mrp 110601 efficiency note: Since h just moves back and forth between pointers,
+           ! this is not necessary once initialized.
+           do k=2,block % mesh % nVertLevels
+             block % state % time_levs(2) % state % h % array(k,iCell) &amp;
+           = block % mesh % hZLevel % array(k)
+           end do
+         end do ! iCell
+       end if ! split_explicit

+       !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+       !
+       !  Implicit vertical mixing, done after timestep is complete
+       !
+       !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+         u           =&gt; block % state % time_levs(2) % state % u % array
+         tracers     =&gt; block % state % time_levs(2) % state % tracers % array
+         h           =&gt; block % state % time_levs(2) % state % h % array
+         h_edge      =&gt; block % state % time_levs(2) % state % h_edge % array
+         ke_edge     =&gt; block % state % time_levs(2) % state % ke_edge % array
+         num_tracers = block % state % time_levs(2) % state % num_tracers
+         vertViscTopOfEdge =&gt; block % diagnostics % vertViscTopOfEdge % array
+         vertDiffTopOfCell =&gt; block % diagnostics % vertDiffTopOfCell % array
+         maxLevelCell    =&gt; block % mesh % maxLevelCell % array
+         maxLevelEdgeTop =&gt; block % mesh % maxLevelEdgeTop % array
+
+         if (config_implicit_vertical_mix) then
+            allocate(A(block % mesh % nVertLevels),C(block % mesh % nVertLevels),uTemp(block % mesh % nVertLevels), &amp;
+               tracersTemp(num_tracers,block % mesh % nVertLevels))
+
+            call ocn_vmix_coefs(block % mesh, block % state % time_levs(2) % state, block % diagnostics, err)
+
+            !
+            !  Implicit vertical solve for momentum
+            !
+
+            call ocn_vel_vmix_tend_implicit(block % mesh, dt, ke_edge, vertvisctopofedge, h, h_edge, u, err)
+
+            !
+            !  Implicit vertical solve for tracers
+            !
+            call ocn_tracer_vmix_tend_implicit(block % mesh, dt, vertdifftopofcell, h, tracers, err)
+         end if
+
+         ! mrp 110725 adding momentum decay term
+         if (config_mom_decay) then
+
+            !
+            !  Implicit solve for momentum decay
+            !
+            !  Add term to RHS of momentum equation: -1/gamma u
+            !
+            !  This changes the solve to:
+            !  u^{n+1} = u_provis^{n+1}/(1+dt/gamma)
+            !
+            coef = 1.0/(1.0 + dt/config_mom_decay_time)
+            do iEdge=1,block % mesh % nEdges
+               do k=1,maxLevelEdgeTop(iEdge)
+                  u(k,iEdge) = coef*u(k,iEdge) 
+               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(:,:)
+         end if
+
+         call ocn_diagnostic_solve(dt, block % state % time_levs(2) % state, block % mesh)
+
+         call reconstruct(block % state % time_levs(2) % state, block % mesh)
+
+         block =&gt; block % next
+      end do
+      call timer_stop(&quot;split_explicit_timestep&quot;)
+
+   end subroutine ocn_time_integrator_split!}}}
+
+   subroutine filter_btr_mode_tend_u(tend, s, d, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Filter and remove barotropic mode from the tendencies
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (tend_type), intent(inout) :: tend
+      type (state_type), intent(in) :: s
+      type (diagnostics_type), intent(in) :: d
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into compute_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: vertSum, uhSum, hSum, sshEdge
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel, meshScalingDel2, meshScalingDel4
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;filter_btr_mode_tend_u&quot;)
+
+      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
+      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
+      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
+! mrp 110516 cleanup fvertex fedge not used in this subroutine
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      tend_u      =&gt; tend % u % array
+                  
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      u_src =&gt; grid % u_src % array
+
+           do iEdge=1,grid % nEdges
+
+              ! I am using hZLevel here.  This assumes that SSH is zero everywhere already,
+              ! which should be the case if the barotropic mode is filtered.
+              ! The more general case is to use sshEdge or h_edge.
+              uhSum = (grid % hZLevel % array(1)) * tend_u(1,iEdge)
+              hSum  =  grid % hZLevel % array(1)
+
+              do k=2,grid % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + grid % hZLevel % array(k) * tend_u(k,iEdge)
+                 hSum  =  hSum + grid % hZLevel % array(k)
+              enddo
+
+              vertSum = uhSum/hSum
+
+              do k=1,grid % maxLevelEdgeTop % array(iEdge)
+                 tend_u(k,iEdge) = tend_u(k,iEdge) - vertSum
+              enddo
+
+           enddo ! iEdge
+
+      call timer_stop(&quot;filter_btr_mode_tend_u&quot;)
+
+   end subroutine filter_btr_mode_tend_u!}}}
+
+   subroutine filter_btr_mode_u(s, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Filter and remove barotropic mode.
+   !
+   ! Input: s - current model state
+   !        grid - grid metadata
+   !
+   ! Output: tend - computed tendencies for prognostic variables
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (state_type), intent(inout) :: s
+      type (mesh_type), intent(in) :: grid
+
+! mrp 110512 I just split compute_tend into compute_tend_u and compute_tend_h.
+!  Some of these variables can be removed, but at a later time.
+      integer :: iEdge, iCell, iVertex, k, cell1, cell2, &amp;
+        vertex1, vertex2, eoe, i, j
+
+      integer :: nCells, nEdges, nVertices, nVertLevels, nEdgesSolve
+      real (kind=RKIND) :: vertSum, uhSum, hSum, sshEdge
+      real (kind=RKIND), dimension(:), pointer :: &amp;
+        h_s, fVertex, fEdge, dvEdge, dcEdge, areaCell, areaTriangle, &amp;
+        zMidZLevel, zTopZLevel, meshScalingDel2, meshScalingDel4
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        weightsOnEdge, kiteAreasOnVertex, h_edge, h, u, v, pressure, &amp;
+        tend_u, circulation, vorticity, ke, ke_edge, pv_edge, &amp;
+        MontPot, wTop, divergence, vertViscTopOfEdge
+      type (dm_info) :: dminfo
+
+      integer, dimension(:), pointer :: nEdgesOnCell, nEdgesOnEdge, &amp;
+        maxLevelCell, maxLevelEdgeTop, maxLevelVertexBot
+      integer, dimension(:,:), pointer :: &amp;
+        cellsOnEdge, cellsOnVertex, verticesOnEdge, edgesOnCell, &amp;
+        edgesOnEdge, edgesOnVertex
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), allocatable:: fluxVertTop,w_dudzTopEdge
+
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_divergence
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_u
+      real (kind=RKIND), allocatable, dimension(:,:) :: delsq_circulation, delsq_vorticity
+
+
+      real (kind=RKIND), dimension(:,:), pointer :: u_src
+      real (kind=RKIND), parameter :: rho_ref = 1000.0
+
+      call timer_start(&quot;filter_btr_mode_u&quot;)
+
+      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
+      MontPot     =&gt; s % MontPot % array
+      pressure    =&gt; s % pressure % array
+
+      weightsOnEdge     =&gt; grid % weightsOnEdge % 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
+! mrp 110516 cleanup fvertex fedge not used in this subroutine
+      fVertex           =&gt; grid % fVertex % array
+      fEdge             =&gt; grid % fEdge % array
+      zMidZLevel        =&gt; grid % zMidZLevel % array
+      zTopZLevel        =&gt; grid % zTopZLevel % array
+      maxLevelCell      =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop      =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot    =&gt; grid % maxLevelVertexBot % array
+
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nEdgesSolve = grid % nEdgesSolve
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      u_src =&gt; grid % u_src % array
+
+           do iEdge=1,grid % nEdges
+
+              ! I am using hZLevel here.  This assumes that SSH is zero everywhere already,
+              ! which should be the case if the barotropic mode is filtered.
+              ! The more general case is to use sshedge or h_edge.
+              uhSum = (grid % hZLevel % array(1)) * u(1,iEdge)
+              hSum  =  grid % hZLevel % array(1)
+
+              do k=2,grid % maxLevelEdgeTop % array(iEdge)
+                 uhSum = uhSum + grid % hZLevel % array(k) * u(k,iEdge)
+                 hSum  =  hSum + grid % hZLevel % array(k)
+              enddo
+
+              vertSum = uhSum/hSum
+              do k=1,grid % maxLevelEdgeTop % array(iEdge)
+                 u(k,iEdge) = u(k,iEdge) - vertSum
+              enddo
+
+           enddo ! iEdge
+
+      call timer_stop(&quot;filter_btr_mode_u&quot;)
+
+   end subroutine filter_btr_mode_u!}}}
+
+   subroutine enforce_boundaryEdge(tend, grid)!{{{
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   ! Enforce any boundary conditions on the normal velocity at each edge
+   !
+   ! Input: grid - grid metadata
+   !
+   ! Output: tend_u set to zero at boundaryEdge == 1 locations
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+      implicit none
+
+      type (tend_type), intent(inout) :: tend
+      type (mesh_type), intent(in) :: grid
+
+      integer, dimension(:,:), pointer :: boundaryEdge
+      real (kind=RKIND), dimension(:,:), pointer :: tend_u
+      integer :: nCells, nEdges, nVertices, nVertLevels
+      integer :: iEdge, k
+
+      call timer_start(&quot;enforce_boundaryEdge&quot;)
+
+      nCells      = grid % nCells
+      nEdges      = grid % nEdges
+      nVertices   = grid % nVertices
+      nVertLevels = grid % nVertLevels
+
+      boundaryEdge         =&gt; grid % boundaryEdge % array
+      tend_u      =&gt; tend % u % array
+
+      if(maxval(boundaryEdge).le.0) return
+
+      do iEdge = 1,nEdges
+        do k = 1,nVertLevels
+
+          if(boundaryEdge(k,iEdge).eq.1) then
+             tend_u(k,iEdge) = 0.0
+          endif
+
+        enddo
+       enddo
+      call timer_stop(&quot;enforce_boundaryEdge&quot;)
+
+   end subroutine enforce_boundaryEdge!}}}
+
+end module ocn_time_integration_split
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hadv.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,180 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hadv
+!
+!&gt; \brief MPAS ocean horizontal tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hadv
+
+   use grid_types
+   use configure
+
+   use ocn_tracer_hadv2
+   use ocn_tracer_hadv3
+   use ocn_tracer_hadv4
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hadv_tend, &amp;
+             ocn_tracer_hadv_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv_tend
+!
+!&gt; \brief   Computes tendency term for horizontal tracer advection
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal advection tendency for tracer
+!&gt;  based on current state and user choices of advection parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv_tend(grid, u, h_edge, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: velocity
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2, err3
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      call ocn_tracer_hadv2_tend(grid, u, h_edge, tracers, tend, err1)
+      call ocn_tracer_hadv3_tend(grid, u, h_edge, tracers, tend, err2)
+      call ocn_tracer_hadv4_tend(grid, u, h_edge, tracers, tend, err3)
+
+      err = err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity advection in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      integer :: err1, err2, err3
+
+      call ocn_tracer_hadv2_init(err1)
+      call ocn_tracer_hadv3_init(err2)
+      call ocn_tracer_hadv4_init(err3)
+
+      err = err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hadv
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmetho=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv2.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hadv2.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv2.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv2.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,200 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hadv2
+!
+!&gt; \brief MPAS ocean horizontal tracer advection 2nd order
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hadv2
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hadv2_tend, &amp;
+             ocn_tracer_hadv2_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: hadv2On !&lt; Flag to turn on/off 2nd order hadv
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv2_tend
+!
+!&gt; \brief   Computes tendency term for horizontal tracer advection 2nd order
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal advection tendency for tracer
+!&gt;  based on current state using a 2nd order formulation.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv2_tend(grid, u, h_edge, tracers , tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: tracer
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, cell1, cell2, iTracer, num_tracers, k
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real (kind=RKIND) :: flux, tracer_edge
+
+      real (kind=RKIND), dimension(:), pointer :: dvEdge, areaCell
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.hadv2On) return
+
+      call timer_start(&quot;compute_scalar_tend-horiz adv 2&quot;)
+
+      nEdges = grid % nEdges
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaCell =&gt; grid % areaCell % array
+      num_tracers = size(tracers, 1)
+
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeTop(iEdge)
+            do iTracer=1,num_tracers
+               tracer_edge = 0.5 * (tracers(iTracer,k,cell1) + tracers(iTracer,k,cell2))
+               flux = u(k,iEdge) * dvEdge(iEdge) * h_edge(k,iEdge) * tracer_edge
+               tend(iTracer,k,cell1) = tend(iTracer,k,cell1) - flux/areaCell(cell1)
+               tend(iTracer,k,cell2) = tend(iTracer,k,cell2) + flux/areaCell(cell2)
+            end do
+         end do
+      end do
+
+      call timer_stop(&quot;compute_scalar_tend-horiz adv 2&quot;)
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv2_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv2_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  2nd order horizontal tracer advection in the ocean.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv2_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      err = 0
+      hadv2On = .false.
+
+      if (config_tracer_adv_order == 2) then
+          hadv2On = .true.
+      end if
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv2_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hadv2
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv3.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hadv3.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv3.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv3.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,248 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hadv3
+!
+!&gt; \brief MPAS ocean horizontal tracer advection 3rd order
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hadv3
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hadv3_tend, &amp;
+             ocn_tracer_hadv3_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: hadv3On !&lt; Flag to turn on/off 3rd order hadv
+   real (kind=RKIND) :: coef_3rd_order !&lt; Coefficient for 3rd order hadv
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv3_tend
+!
+!&gt; \brief   Computes tendency term for horizontal tracer advection 3rd order
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal advection tendency for tracer
+!&gt;  based on current state using a 3rd order formulation.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv3_tend(grid, u, h_edge, tracers , tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: tracer
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, cell1, cell2, iTracer, num_tracers, i, k
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop, nEdgesOnCell
+      integer, dimension(:,:), pointer :: cellsOnEdge, cellsOnCell, &amp;
+                                          boundaryCell
+
+      real (kind=RKIND) :: flux, tracer_edge, d2fdx2_cell1, d2fdx2_cell2
+
+      real (kind=RKIND), dimension(:), pointer :: dvEdge, dcEdge, areaCell
+      real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.hadv3On) return
+
+      nEdges = grid % nEdges
+      num_tracers = size(tracers, dim=1)
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      nEdgesOnCell =&gt; grid % nEdgesOnCell % array
+      boundaryCell =&gt; grid % boundaryCell % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      cellsOnCell =&gt; grid % cellsOnCell % array
+      dvEdge =&gt; grid % dvEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+      areaCell =&gt; grid % areaCell % array
+      deriv_two =&gt; grid % deriv_two % array
+
+      call timer_start(&quot;compute_scalar_tend-horiz adv 3&quot;)
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            d2fdx2_cell1 = 0.0
+            d2fdx2_cell2 = 0.0
+
+            do iTracer=1,num_tracers
+
+               !-- if not a boundary cell
+               if(boundaryCell(k,cell1).eq.0.and.boundaryCell(k,cell2).eq.0) then
+
+                  d2fdx2_cell1 = deriv_two(1,1,iEdge) * tracers(iTracer,k,cell1)
+                  d2fdx2_cell2 = deriv_two(1,2,iEdge) * tracers(iTracer,k,cell2)
+
+                  !-- all edges of cell 1
+                  do i=1,nEdgesOnCell(cell1)
+                     d2fdx2_cell1 = d2fdx2_cell1 + &amp;
+                     deriv_two(i+1,1,iEdge) * tracers(iTracer,k,cellsOnCell(i,cell1))
+                  end do
+
+                  !-- all edges of cell 2
+                  do i=1,nEdgesOnCell(cell2)
+                     d2fdx2_cell2 = d2fdx2_cell2 + &amp;
+                     deriv_two(i+1,2,iEdge) * tracers(iTracer,k,cellsOnCell(i,cell2))
+                  end do
+
+               endif
+
+               !-- if u &gt; 0:
+               if (u(k,iEdge) &gt; 0) then
+                  flux = dvEdge(iEdge) * u(k,iEdge) * h_edge(k,iEdge) * (          &amp;
+                       0.5*(tracers(iTracer,k,cell1) + tracers(iTracer,k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12.          &amp;
+                       -(dcEdge(iEdge) **2) * coef_3rd_order*(d2fdx2_cell1 - d2fdx2_cell2) / 12. )
+               !-- else u &lt;= 0:
+               else
+                  flux = dvEdge(iEdge) *  u(k,iEdge) * h_edge(k,iEdge) * (          &amp;
+                       0.5*(tracers(iTracer,k,cell1) + tracers(iTracer,k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12.          &amp;
+                       +(dcEdge(iEdge) **2) * coef_3rd_order*(d2fdx2_cell1 - d2fdx2_cell2) / 12. )
+               end if
+
+               !-- update tendency
+               tend(iTracer,k,cell1) = tend(iTracer,k,cell1) - flux/areaCell(cell1)
+               tend(iTracer,k,cell2) = tend(iTracer,k,cell2) + flux/areaCell(cell2)
+            enddo
+         end do
+      end do
+      call timer_stop(&quot;compute_scalar_tend-horiz adv 3&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv3_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv3_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  3rd order horizontal tracer advection in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv3_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      hadv3On = .false.
+
+      if (config_tracer_adv_order == 3) then
+          hadv3On = .true.
+
+          coef_3rd_order = 1.0
+          if (config_monotonic) coef_3rd_order = 0.25
+      end if
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv3_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hadv3
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv4.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hadv4.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv4.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hadv4.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,233 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hadv4
+!
+!&gt; \brief MPAS ocean horizontal tracer advection 4th order
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hadv4
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hadv4_tend, &amp;
+             ocn_tracer_hadv4_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: hadv4On !&lt; Flag to turning on/off 4th order hadv
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv4_tend
+!
+!&gt; \brief   Computes tendency term for horizontal tracer advection 4th order
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal advection tendency for tracer
+!&gt;  based on current state using a 4th order formulation.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv4_tend(grid, u, h_edge, tracers , tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: tracer
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, cell1, cell2, iTracer, num_tracers, i, k
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge, cellsOnCell, boundaryCell
+
+      real (kind=RKIND) :: flux, tracer_edge, d2fdx2_cell1, d2fdx2_cell2
+
+      real (kind=RKIND), dimension(:), pointer :: dvEdge, dcEdge, areaCell
+      real (kind=RKIND), dimension(:,:,:), pointer :: deriv_two
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.hadv4On) return
+
+      nEdges = grid % nEdges
+      num_tracers = size(tracers, dim=1)
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      boundaryCell =&gt; grid % boundaryCell % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      cellsOnCell =&gt; grid % cellsOnCell % array
+      dvEdge =&gt; grid % dvEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+      areaCell =&gt; grid % areaCell % array
+      deriv_two =&gt; grid % deriv_two % array
+
+      call timer_start(&quot;compute_scalar_tend-horiz adv 4&quot;)
+
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            d2fdx2_cell1 = 0.0
+            d2fdx2_cell2 = 0.0
+
+            do iTracer=1,num_tracers
+
+               !-- if not a boundary cell
+               if(boundaryCell(k,cell1).eq.0.and.boundaryCell(k,cell2).eq.0) then
+
+                  d2fdx2_cell1 = deriv_two(1,1,iEdge) * tracers(iTracer,k,cell1)
+                  d2fdx2_cell2 = deriv_two(1,2,iEdge) * tracers(iTracer,k,cell2)
+
+                  !-- all edges of cell 1
+                  do i=1, grid % nEdgesOnCell % array (cell1)
+                     d2fdx2_cell1 = d2fdx2_cell1 + &amp;
+                     deriv_two(i+1,1,iEdge) * tracers(iTracer,k,cellsOnCell(i,cell1))
+                  end do
+
+                  !-- all edges of cell 2
+                  do i=1, grid % nEdgesOnCell % array (cell2)
+                      d2fdx2_cell2 = d2fdx2_cell2 + &amp;
+                      deriv_two(i+1,2,iEdge) * tracers(iTracer,k,cellsOnCell(i,cell2))
+                  end do
+
+               endif
+
+               flux = dvEdge(iEdge) *  u(k,iEdge) * h_edge(k,iEdge) * (          &amp;
+                    0.5*(tracers(iTracer,k,cell1) + tracers(iTracer,k,cell2))      &amp;
+                       -(dcEdge(iEdge) **2) * (d2fdx2_cell1 + d2fdx2_cell2) / 12. )
+
+               !-- update tendency
+               tend(iTracer,k,cell1) = tend(iTracer,k,cell1) - flux/areaCell(cell1)
+               tend(iTracer,k,cell2) = tend(iTracer,k,cell2) + flux/areaCell(cell2)
+            enddo
+         end do
+      end do
+      call timer_stop(&quot;compute_scalar_tend-horiz adv 4&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv4_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hadv4_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes the 4th order formulation for 
+!&gt;  horizontal tracer advection in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hadv4_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      err = 0
+      hadv4On = .false.
+
+      if (config_tracer_adv_order == 4) then
+          hadv4On = .true.
+      end if
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hadv4_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hadv4
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hmix.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,174 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hmix
+!
+!&gt; \brief MPAS ocean horizontal tracer mixing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal mixing tendencies.  
+!&gt;
+!&gt;  It provides an init and a tend function. Each are described below.
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hmix
+
+   use grid_types
+   use configure
+   use ocn_tracer_hmix_del2
+   use ocn_tracer_hmix_del4
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hmix_tend, &amp;
+             ocn_tracer_hmix_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_tend
+!
+!&gt; \brief   Computes tendency term for horizontal tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for tracer
+!&gt;  based on current state and user choices of mixing parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_tend(grid, h_edge, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge    !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers !&lt; Input: tracer quantities
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      call ocn_tracer_hmix_del2_tend(grid, h_edge, tracers, tend, err1)
+      call ocn_tracer_hmix_del4_tend(grid, h_edge, tracers, tend, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2
+
+      call ocn_tracer_hmix_del2_init(err1)
+      call ocn_tracer_hmix_del4_init(err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hmix
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del2.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hmix_del2.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del2.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del2.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,232 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hmix_del2
+!
+!&gt; \brief MPAS ocean horizontal tracer mixing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal mixing tendencies.  
+!&gt;
+!&gt;  It provides an init and a tend function. Each are described below.
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hmix_del2
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hmix_del2_tend, &amp;
+             ocn_tracer_hmix_del2_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: del2On
+
+   real (kind=RKIND) :: eddyDiff2
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_del2_tend
+!
+!&gt; \brief   Computes laplacian tendency term for horizontal tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for tracers
+!&gt;  based on current state using a laplacian parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_del2_tend(grid, h_edge, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge    !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers !&lt; Input: tracer quantities
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, nVertLevels, cell1, cell2
+      integer :: k, iTracer, num_tracers
+
+      integer, dimension(:,:), allocatable :: boundaryMask
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge, boundaryEdge
+
+      real (kind=RKIND) :: invAreaCell1, invAreaCell2
+      real (kind=RKIND) :: tracer_turb_flux, flux
+
+      real (kind=RKIND), dimension(:), pointer :: areaCell, dvEdge, dcEdge
+      real (kind=RKIND), dimension(:), pointer :: meshScalingDel2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if (.not.del2On) return
+
+      call timer_start(&quot;compute_scalar_tend-horiz diff 2&quot;)
+
+      nEdges = grid % nEdges
+      nVertLevels = grid % nVertLevels
+      num_tracers = size(tracers, dim=1)
+
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      boundaryEdge =&gt; grid % boundaryEdge % array
+      areaCell =&gt; grid % areaCell % array
+      dvEdge =&gt; grid % dvEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+      meshScalingDel2 =&gt; grid % meshScalingDel2 % array
+
+      !
+      ! compute a boundary mask to enforce insulating boundary conditions in the horizontal
+      !
+      allocate(boundaryMask(nVertLevels, nEdges+1))
+      boundaryMask = 1.0
+      where(boundaryEdge.eq.1) boundaryMask=0.0
+
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         invAreaCell1 = 1.0/areaCell(cell1)
+         invAreaCell2 = 1.0/areaCell(cell2)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+           do iTracer=1,num_tracers
+              ! \kappa_2 </font>
<font color="blue">abla \phi on edge
+              tracer_turb_flux = meshScalingDel2(iEdge) * eddyDiff2 &amp;
+                 *(  tracers(iTracer,k,cell2) &amp;
+                   - tracers(iTracer,k,cell1))/dcEdge(iEdge)
+
+              ! div(h \kappa_2 </font>
<font color="gray">abla \phi) at cell center
+              flux = dvEdge (iEdge) * h_edge(k,iEdge) &amp;
+                 * tracer_turb_flux * boundaryMask(k, iEdge)
+              tend(iTracer,k,cell1) = tend(iTracer,k,cell1) + flux * invAreaCell1
+              tend(iTracer,k,cell2) = tend(iTracer,k,cell2) - flux * invAreaCell2
+           end do
+         end do
+
+      end do
+
+      deallocate(boundaryMask)
+      call timer_stop(&quot;compute_scalar_tend-horiz diff 2&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_del2_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_del2_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  laplacian horizontal velocity mixing in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_del2_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      del2on = .false.
+
+      if ( config_h_tracer_eddy_diff2 &gt; 0.0 ) then
+          del2On = .true.
+          eddyDiff2 = config_h_tracer_eddy_diff2
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_del2_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hmix_del2
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del4.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_hmix_del4.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del4.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_hmix_del4.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,263 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_hmix_del4
+!
+!&gt; \brief MPAS ocean horizontal tracer mixing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal mixing tendencies.  
+!&gt;
+!&gt;  It provides an init and a tend function. Each are described below.
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_hmix_del4
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_hmix_del4_tend, &amp;
+             ocn_tracer_hmix_del4_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: Del4On
+
+   real (kind=RKIND) :: eddyDiff4
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_del4_tend
+!
+!&gt; \brief   Computes biharmonic tendency term for horizontal tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for tracers
+!&gt;  based on current state using a biharmonic parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_del4_tend(grid, h_edge, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge    !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+        tracers !&lt; Input: tracer quantities
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, num_tracers, nVertLevels, nCells
+      integer :: iTracer, k, iCell, cell1, cell2
+
+      integer, dimension(:,:), allocatable :: boundaryMask
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop, maxLevelCell
+      integer, dimension(:,:), pointer :: boundaryEdge, cellsOnEdge
+
+      real (kind=RKIND) :: invAreaCell1, invAreaCell2, r, tracer_turb_flux, flux
+
+      real (kind=RKIND), dimension(:,:,:), allocatable :: delsq_tracer
+
+      real (kind=RKIND), dimension(:), pointer :: dcEdge, dvEdge, areaCell, meshScalingDel4
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if (.not.Del4On) return
+
+      call timer_start(&quot;compute_scalar_tend-horiz diff 4&quot;)
+
+      nEdges = grid % nEdges
+      nCells = grid % nCells
+      num_tracers = size(tracers, dim=1)
+      nVertLevels = grid % nVertLevels
+
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      maxLevelCell =&gt; grid % maxLevelCell % array
+      boundaryEdge =&gt; grid % boundaryEdge % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+
+      dcEdge =&gt; grid % dcEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaCell =&gt; grid % areaCell % array
+      meshScalingDel4 =&gt; grid % meshScalingDel4 % array
+
+      allocate(boundaryMask(nVertLevels, nEdges+1))
+      boundaryMask = 1.0
+      where(boundaryEdge.eq.1) boundaryMask=0.0
+
+      allocate(delsq_tracer(num_tracers,nVertLevels, nCells+1))
+
+      delsq_tracer(:,:,:) = 0.
+
+      ! first del2: div(h </font>
<font color="blue">abla \phi) at cell center
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+           do iTracer=1,num_tracers
+              delsq_tracer(iTracer,k,cell1) = delsq_tracer(iTracer,k,cell1) &amp;
+                 + dvEdge(iEdge)*h_edge(k,iEdge) &amp;
+                   *(tracers(iTracer,k,cell2) - tracers(iTracer,k,cell1)) &amp;
+                   /dcEdge(iEdge) * boundaryMask(k,iEdge)
+              delsq_tracer(iTracer,k,cell2) = delsq_tracer(iTracer,k,cell2) &amp;
+                 - dvEdge(iEdge)*h_edge(k,iEdge) &amp;
+                 *(tracers(iTracer,k,cell2) - tracers(iTracer,k,cell1)) &amp;
+                 /dcEdge(iEdge) * boundaryMask(k,iEdge)
+           end do
+         end do
+      end do
+
+      do iCell = 1,nCells
+         r = 1.0 / areaCell(iCell)
+         do k=1,maxLevelCell(iCell)
+            do iTracer=1,num_tracers
+               delsq_tracer(iTracer,k,iCell) = delsq_tracer(iTracer,k,iCell) * r
+            end do
+         end do
+      end do
+
+      ! second del2: div(h </font>
<font color="gray">abla [delsq_tracer]) at cell center
+      do iEdge=1,grid % nEdges
+         cell1 = grid % cellsOnEdge % array(1,iEdge)
+         cell2 = grid % cellsOnEdge % array(2,iEdge)
+         invAreaCell1 = 1.0 / areaCell(cell1)
+         invAreaCell2 = 1.0 / areaCell(cell2)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+            do iTracer=1,num_tracers
+               tracer_turb_flux = meshScalingDel4(iEdge) * eddyDiff4 &amp;
+                  *(  delsq_tracer(iTracer,k,cell2)  &amp;
+                    - delsq_tracer(iTracer,k,cell1))/dcEdge(iEdge)
+               flux = dvEdge (iEdge) * tracer_turb_flux
+
+               tend(iTracer,k,cell1) = tend(iTracer,k,cell1) &amp; 
+                  - flux * invAreaCell1 * boundaryMask(k,iEdge)
+               tend(iTracer,k,cell2) = tend(iTracer,k,cell2) &amp;
+                  + flux * invAreaCell2 * boundaryMask(k,iEdge)
+
+            enddo
+         enddo
+      end do
+
+      deallocate(delsq_tracer)
+      call timer_stop(&quot;compute_scalar_tend-horiz diff 4&quot;)
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_del4_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_hmix_del4_init
+!
+!&gt; \brief   Initializes ocean tracer horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  biharmonic horizontal velocity mixing in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_hmix_del4_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      Del4on = .false.
+
+      if ( config_h_tracer_eddy_diff4 &gt; 0.0 ) then
+          Del4On = .true.
+          eddyDiff4 = config_h_tracer_eddy_diff4
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_hmix_del4_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_hmix_del4
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,185 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv
+
+   use grid_types
+   use configure
+
+   use ocn_tracer_vadv_stencil
+   use ocn_tracer_vadv_spline
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_tend, &amp;
+             ocn_tracer_vadv_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: vadvOn
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state and user choices of advection parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.vadvOn) return
+
+      call ocn_tracer_vadv_stencil_tend(grid, wTop, tracers, tend, err1)
+      call ocn_tracer_vadv_spline_tend(grid, wTop, tracers, tend, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical tracer advection in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2
+
+      vadvOn = .false.
+
+      if (config_vert_grid_type.eq.'zlevel') then
+          vadvOn = .true.
+          call ocn_tracer_vadv_stencil_init(err1)
+          call ocn_tracer_vadv_spline_init(err2)
+
+          err = err1 .or. err2
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_spline.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,186 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_spline
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_spline
+
+   use grid_types
+   use configure
+
+   use ocn_tracer_vadv_spline2
+   use ocn_tracer_vadv_spline3
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_spline_tend, &amp;
+             ocn_tracer_vadv_spline_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: splineOn
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state and user choices of advection parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.splineOn) return
+
+      call ocn_tracer_vadv_spline2_tend(grid, wTop, tracers, tend, err1)
+      call ocn_tracer_vadv_spline3_tend(grid, wTop, tracers, tend, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical tracer advection in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2
+
+      splineOn = .false.
+
+      if(config_vert_tracer_adv.eq.'spline') then
+         splineOn = .true.
+
+         call ocn_tracer_vadv_spline2_init(err2)
+         call ocn_tracer_vadv_spline3_init(err2)
+
+         err = err1 .or. err2
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_spline
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline2.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_spline2.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline2.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline2.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,214 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_spline2
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_spline2
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_spline2_tend, &amp;
+             ocn_tracer_vadv_spline2_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: spline2On
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline2_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection 2nd order spline
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state using a 2nd order spline.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline2_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCells, nCellsSolve, k, iTracer, num_tracers, nVertLevels
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND), dimension(:), pointer :: hRatioZLevelK, hRatioZLevelKm1
+
+      real (kind=RKIND), dimension(:,:,:), allocatable :: tracerTop
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.spline2On) return
+      ! Compute tracerTop using linear interpolation.
+
+      call timer_start(&quot;compute_scalar_tend-vert adv spline 2&quot;)
+
+      nCells = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      nVertLevels = grid % nVertLevels
+      num_tracers = size(tracers, 1)
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      hRatioZLevelK =&gt; grid % hRatioZLevelK % array
+      hRatioZLevelKm1 =&gt; grid % hRatioZLevelKm1 % array
+
+      allocate(tracerTop(num_tracers,nVertLevels+1,nCells))
+
+      do iCell=1,nCellsSolve 
+         do k=2,maxLevelCell(iCell)
+            do iTracer=1,num_tracers
+               ! Note hRatio on the k side is multiplied by tracer at k-1
+               ! and hRatio on the Km1 (k-1) side is mult. by tracer at k.
+               tracerTop(iTracer,k,iCell) = &amp;
+                    hRatioZLevelK(k)  *tracers(iTracer,k-1,iCell) &amp;
+                  + hRatioZLevelKm1(k)*tracers(iTracer,k  ,iCell)
+            end do
+         end do
+      end do
+
+      do iCell=1,nCellsSolve 
+         do k=1,maxLevelCell(iCell)  
+            do iTracer=1,num_tracers
+               tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+                  - (   wTop(k  ,iCell)*tracerTop(iTracer,k  ,iCell) &amp;
+                      - wTop(k+1,iCell)*tracerTop(iTracer,k+1,iCell))
+            end do
+         end do
+      end do
+
+      deallocate(tracerTop)
+
+      call timer_stop(&quot;compute_scalar_tend-vert adv spline 2&quot;)
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline2_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline2_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  2nd order spline based vertical tracer advection in the ocean.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline2_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      spline2On = .false.
+
+      if(config_vert_tracer_adv_order.eq.2) then
+        spline2On = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline2_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_spline2
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline3.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_spline3.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline3.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_spline3.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,243 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_spline3
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_spline3
+
+   use grid_types
+   use configure
+   use timer
+   use spline_interpolation
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_spline3_tend, &amp;
+             ocn_tracer_vadv_spline3_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: spline3On
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline3_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection 3rd order spline
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state using a 3rd order spline.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline3_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCells, nCellsSolve, k, iTracer, num_tracers, nVertLevels
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND), dimension(:), pointer :: hRatioZLevelK, &amp;
+            hRatioZLevelKm1, zTopZLevel, zMidZLevel
+
+      real (kind=RKIND), dimension(:), allocatable :: tracer2ndDer,  &amp;
+            tracersIn, tracersOut, posZMidZLevel, posZTopZLevel
+      real (kind=RKIND), dimension(:,:,:), allocatable :: tracerTop
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.spline3On) return
+      ! Compute tracerTop using linear interpolation.
+
+      call timer_start(&quot;compute_scalar_tend-vert adv spline 3&quot;)
+
+      nCells = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      nVertLevels = grid % nVertLevels
+      num_tracers = size(tracers, 1)
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      hRatioZLevelK =&gt; grid % hRatioZLevelK % array
+      hRatioZLevelKm1 =&gt; grid % hRatioZLevelKm1 % array
+      zMidZLevel =&gt; grid % zMidZLevel % array
+      zTopZLevel =&gt; grid % zTopZLevel % array
+
+      allocate(tracerTop(num_tracers,nVertLevels+1,nCells))
+
+      ! Compute tracerTop using cubic spline interpolation.
+
+      allocate(tracer2ndDer(nVertLevels))
+      allocate(tracersIn(nVertLevels),tracersOut(nVertLevels), &amp;
+            posZMidZLevel(nVertLevels), posZTopZLevel(nVertLevels-1))
+
+      ! For the ocean, zlevel coordinates are negative and decreasing, 
+      ! but spline functions assume increasing, so flip to positive.
+
+      posZMidZLevel = -zMidZLevel(1:nVertLevels)
+      posZTopZLevel = -zTopZLevel(2:nVertLevels)
+
+      do iCell=1,nCellsSolve 
+         ! mrp 110201 efficiency note: push tracer loop down
+         ! into spline subroutines to improve efficiency
+         do iTracer=1,num_tracers
+
+            ! Place data in arrays to avoid creating new temporary arrays for every 
+            ! subroutine call.  
+            tracersIn(1:maxLevelCell(iCell))=tracers(iTracer,1:maxLevelCell(iCell),iCell)
+
+            call CubicSplineCoefficients(posZMidZLevel, &amp;
+               tracersIn, maxLevelCell(iCell), tracer2ndDer)
+
+            call InterpolateCubicSpline( &amp;
+               posZMidZLevel, tracersIn, tracer2ndDer, maxLevelCell(iCell), &amp;
+               posZTopZLevel, tracersOut, maxLevelCell(iCell)-1 )
+
+            tracerTop(iTracer,2:maxLevelCell(iCell),iCell) = tracersOut(1:maxLevelCell(iCell)-1)
+
+         end do
+      end do
+
+      do iCell=1,nCellsSolve 
+         do k=1,maxLevelCell(iCell)  
+            do iTracer=1,num_tracers
+               tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+                  - (   wTop(k  ,iCell)*tracerTop(iTracer,k  ,iCell) &amp;
+                      - wTop(k+1,iCell)*tracerTop(iTracer,k+1,iCell))
+            end do
+         end do
+      end do
+
+      deallocate(tracer2ndDer)
+      deallocate(tracersIn,tracersOut, posZMidZLevel, posZTopZLevel)
+      deallocate(tracerTop)
+
+      call timer_stop(&quot;compute_scalar_tend-vert adv spline 3&quot;)
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline3_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_spline3_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  3rd order spline based vertical tracer advection in the ocean.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_spline3_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      spline3On = .false.
+
+      if(config_vert_tracer_adv_order.eq.3) then
+        spline3On = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_spline3_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_spline3
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_stencil.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,191 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_stencil
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_stencil
+
+   use grid_types
+   use configure
+
+   use ocn_tracer_vadv_stencil2
+   use ocn_tracer_vadv_stencil3
+   use ocn_tracer_vadv_stencil4
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_stencil_tend, &amp;
+             ocn_tracer_vadv_stencil_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: stencilOn
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracers
+!&gt;  based on current state and user choices of stencil based advection parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2, err3
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not. stencilOn) return
+
+      call ocn_tracer_vadv_stencil2_tend(grid, wTop, tracers, tend, err1)
+      call ocn_tracer_vadv_stencil3_tend(grid, wTop, tracers, tend, err1)
+      call ocn_tracer_vadv_stencil4_tend(grid, wTop, tracers, tend, err1)
+
+      err = err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  stencil based vertical tracer advection in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2, err3
+
+      err = 0
+
+      stencilOn = .false.
+
+      if (config_vert_tracer_adv.eq.'stencil') then
+         stencilOn = .true.
+
+         call ocn_tracer_vadv_stencil2_init(err1)
+         call ocn_tracer_vadv_stencil3_init(err2)
+         call ocn_tracer_vadv_stencil4_init(err3)
+
+         err = err1 .or. err2 .or. err3
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_stencil
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil2.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_stencil2.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil2.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil2.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,212 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_stencil2
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_stencil2
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_stencil2_tend, &amp;
+             ocn_tracer_vadv_stencil2_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: stencil2On
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil2_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection 2nd order stencil
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state using a 2nd order stencil.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil2_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: nCellsSolve, iCell, k, iTracer, num_tracers, nVertLevels
+      integer :: nCells
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND), dimension(:,:,:), allocatable :: tracerTop
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not. stencil2On) return
+
+
+      call timer_start(&quot;compute_scalar_tend-vert adv stencil 2&quot;)
+
+      nCells = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      num_tracers = size(tracers, 1)
+      nVertLevels = grid % nVertLevels
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      allocate(tracerTop(num_tracers,nVertLevels+1,nCells))
+
+      ! Compute tracerTop using centered stencil, a simple average.
+
+      do iCell=1,nCellsSolve 
+         do k=2,maxLevelCell(iCell)
+            do iTracer=1,num_tracers
+               tracerTop(iTracer,k,iCell) = &amp;
+                  ( tracers(iTracer,k-1,iCell) &amp;
+                   +tracers(iTracer,k  ,iCell))/2.0
+            end do
+         end do
+      end do
+
+      do iCell=1,nCellsSolve 
+         do k=1,maxLevelCell(iCell)  
+            do iTracer=1,num_tracers
+               tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+                  - (   wTop(k  ,iCell)*tracerTop(iTracer,k  ,iCell) &amp;
+                      - wTop(k+1,iCell)*tracerTop(iTracer,k+1,iCell))
+            end do
+         end do
+      end do
+
+      deallocate(tracerTop)
+      call timer_stop(&quot;compute_scalar_tend-vert adv stencil 2&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil2_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil2_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  a 2nd order stencil based vertical tracer advection in the ocean.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil2_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2, err3
+
+      err = 0
+      stencil2On = .false.
+
+      if(config_vert_tracer_adv_order.eq.2) then
+          stencil2On = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil2_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_stencil2
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil3.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_stencil3.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil3.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil3.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,233 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_stencil3
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_stencil3
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_stencil3_tend, &amp;
+             ocn_tracer_vadv_stencil3_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: stencil3On
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil3_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection 3rd order stencil
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state using a 3rd order stencil.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil3_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: nCellsSolve, iCell, k, iTracer, num_tracers, nVertLevels
+      integer :: nCells
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND) :: cSignWTop, flux3Coef
+      real (kind=RKIND), dimension(:), pointer :: hRatioZLevelK, hRatioZLevelKm1
+      real (kind=RKIND), dimension(:,:,:), allocatable :: tracerTop
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not. stencil3On) return
+
+      nCells = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      num_tracers = size(tracers, 1)
+      nVertLevels = grid % nVertLevels
+      maxLevelCell =&gt; grid % maxLevelCell % array
+      hRatioZLevelK =&gt; grid % hRatioZLevelK % array
+      hRatioZLevelKm1 =&gt; grid % hRatioZLevelKm1 % array
+
+      call timer_start(&quot;compute_scalar_tend-vert adv stencil 3&quot;)
+
+      allocate(tracerTop(num_tracers,nVertLevels+1,nCells))
+
+      ! Compute tracerTop using 3rd order stencil.  This is the same
+      ! as 4th order, but includes upwinding.
+
+      ! Hardwire flux3Coeff at 1.0 for now.  Could add this to the 
+      ! namelist, if desired.
+      flux3Coef = 1.0
+      do iCell=1,nCellsSolve 
+         k=2
+         do iTracer=1,num_tracers
+           tracerTop(iTracer,k,iCell) = &amp;
+                hRatioZLevelK(k)  *tracers(iTracer,k-1,iCell) &amp;
+              + hRatioZLevelKm1(k)*tracers(iTracer,k  ,iCell)
+         end do
+         do k=3,maxLevelCell(iCell)-1
+            cSignWTop = sign(flux3Coef,wTop(k,iCell))
+            do iTracer=1,num_tracers
+               tracerTop(iTracer,k,iCell) = &amp;
+                  ( (-1.+   cSignWTop)*tracers(iTracer,k-2,iCell) &amp;
+                   +( 7.-3.*cSignWTop)*tracers(iTracer,k-1,iCell) &amp;
+                   +( 7.+3.*cSignWTop)*tracers(iTracer,k  ,iCell) &amp;
+                   +(-1.-   cSignWTop)*tracers(iTracer,k+1,iCell) &amp;
+                  )/12.
+            end do
+         end do
+         k=maxLevelCell(iCell)
+            do iTracer=1,num_tracers
+              tracerTop(iTracer,k,iCell) = &amp;
+                   hRatioZLevelK(k)  *tracers(iTracer,k-1,iCell) &amp;
+                 + hRatioZLevelKm1(k)*tracers(iTracer,k  ,iCell)
+            end do
+      end do
+
+      do iCell=1,nCellsSolve 
+         do k=1,maxLevelCell(iCell)  
+            do iTracer=1,num_tracers
+               tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+                  - (   wTop(k  ,iCell)*tracerTop(iTracer,k  ,iCell) &amp;
+                      - wTop(k+1,iCell)*tracerTop(iTracer,k+1,iCell))
+            end do
+         end do
+      end do
+
+      deallocate(tracerTop)
+      call timer_stop(&quot;compute_scalar_tend-vert adv stencil 3&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil3_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil3_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  3rd order stencil based vertical tracer advection in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil3_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      stencil3On = .false.
+
+      if(config_vert_tracer_adv_order.eq.3) then
+          stencil3On = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil3_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_stencil3
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil4.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_tracer_vadv_stencil4.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil4.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_tracer_vadv_stencil4.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,228 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_tracer_vadv_stencil4
+!
+!&gt; \brief MPAS ocean vertical tracer advection driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  vertical advection tendencies.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_tracer_vadv_stencil4
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_tracer_vadv_stencil4_tend, &amp;
+             ocn_tracer_vadv_stencil4_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: stencil4On
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil4_tend
+!
+!&gt; \brief   Computes tendency term for vertical tracer advection 4th order stencil
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for tracer
+!&gt;  based on current state using a 4th order stencil.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil4_tend(grid, wTop, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop    !&lt; Input: vertical tracer in top layer
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers     !&lt; Input: tracers
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tracer tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: nCellsSolve, iCell, k, iTracer, num_tracers, nVertLevels
+      integer :: nCells
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND) :: cSingWTop, flux3Coef
+      real (kind=RKIND), dimension(:), pointer :: hRatioZLevelK, hRatioZLevelKm1
+      real (kind=RKIND), dimension(:,:,:), allocatable :: tracerTop
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not. Stencil4On) return
+
+      call timer_start(&quot;compute_scalar_tend-vert adv stencil 4&quot;)
+
+      nCells = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      num_tracers = size(tracers, 1)
+      nVertLevels = grid % nVertLevels
+      maxLevelCell =&gt; grid % maxLevelCell % array
+      hRatioZLevelK =&gt; grid % hRatioZLevelK % array
+      hRatioZLevelKm1 =&gt; grid % hRatioZLevelKm1 % array
+
+      allocate(tracerTop(num_tracers,nVertLevels+1,nCells))
+
+      ! Compute tracerTop using 4rd order stencil [-1 7 7 -1]
+
+      do iCell=1,nCellsSolve 
+         k=2
+            do iTracer=1,num_tracers
+              tracerTop(iTracer,k,iCell) = &amp;
+                   hRatioZLevelK(k)  *tracers(iTracer,k-1,iCell) &amp;
+                 + hRatioZLevelKm1(k)*tracers(iTracer,k  ,iCell)
+            end do
+         do k=3,maxLevelCell(iCell)-1
+            do iTracer=1,num_tracers
+               tracerTop(iTracer,k,iCell) = &amp;
+                  (-   tracers(iTracer,k-2,iCell) &amp;
+                   +7.*tracers(iTracer,k-1,iCell) &amp;
+                   +7.*tracers(iTracer,k  ,iCell) &amp;
+                   -   tracers(iTracer,k+1,iCell) &amp;
+                  )/12.
+            end do
+         end do
+         k=maxLevelCell(iCell)
+            do iTracer=1,num_tracers
+              tracerTop(iTracer,k,iCell) = &amp;
+                   hRatioZLevelK(k)  *tracers(iTracer,k-1,iCell) &amp;
+                 + hRatioZLevelKm1(k)*tracers(iTracer,k  ,iCell)
+            end do
+      end do
+
+      do iCell=1,nCellsSolve 
+         do k=1,maxLevelCell(iCell)  
+            do iTracer=1,num_tracers
+               tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+                      - (   wTop(k  ,iCell)*tracerTop(iTracer,k  ,iCell) &amp;
+                      - wTop(k+1,iCell)*tracerTop(iTracer,k+1,iCell))
+            end do
+         end do
+      end do
+
+      deallocate(tracerTop)
+      call timer_stop(&quot;compute_scalar_tend-vert adv stencil 4&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil4_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vadv_stencil4_init
+!
+!&gt; \brief   Initializes ocean tracer vertical advection quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  4th order stencil based vertical tracer advection in the ocean.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vadv_stencil4_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      stencil4On = .false.
+
+      if(config_vert_tracer_adv_order.eq.4) then
+          stencil4On = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vadv_stencil4_init!}}}
+
+!***********************************************************************
+
+end module ocn_tracer_vadv_stencil4
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_coriolis.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_coriolis.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_coriolis.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_coriolis.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,191 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_coriolis
+!
+!&gt; \brief MPAS ocean horizontal momentum mixing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies from the coriolis force.  
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_coriolis
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_coriolis_tend, &amp;
+             ocn_vel_coriolis_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_coriolis_tend
+!
+!&gt; \brief   Computes tendency term for coriolis force
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the coriolis tendency for momentum
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_coriolis_tend(grid, pv_edge, h_edge, u, ke, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         pv_edge  !&lt; Input: Potential vorticity on edge
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge  !&lt; Input: Thickness on edge
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u  !&lt; Input: Horizontal velocity
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         ke  !&lt; Input: Kinetic Energy
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop, nEdgesOnEdge
+      integer, dimension(:,:), pointer :: cellsOnEdge, edgesOnEdge
+      real (kind=RKIND), dimension(:,:), pointer :: weightsOnEdge
+      real (kind=RKIND), dimension(:), pointer :: dcEdge
+
+      integer :: j, k
+      integer :: cell1, cell2, nEdgesSolve, iEdge, eoe
+      real (kind=RKIND) :: workpv, q
+
+      err = 0
+
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      nEdgesOnEdge =&gt; grid % nEdgesOnEdge % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      edgesOnEdge =&gt; grid % edgesOnEdge % array
+      weightsOnEdge =&gt; grid % weightsOnEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+
+      nEdgesSolve = grid % nEdgesSolve
+
+      do iEdge=1,grid % nEdgesSolve
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            q = 0.0
+            do j = 1,nEdgesOnEdge(iEdge)
+               eoe = edgesOnEdge(j,iEdge)
+               workpv = 0.5 * (pv_edge(k,iEdge) + pv_edge(k,eoe))
+               q = q + weightsOnEdge(j,iEdge) * u(k,eoe) * workpv * h_edge(k,eoe) 
+            end do
+
+           tend(k,iEdge) = tend(k,iEdge)     &amp;
+                  + q     &amp;
+                  - (   ke(k,cell2) - ke(k,cell1) ) / dcEdge(iEdge)
+
+         end do
+      end do
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_coriolis_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_coriolis_init
+!
+!&gt; \brief   Initializes ocean momentum horizontal mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_coriolis_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! Output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_coriolis_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_coriolis
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_forcing.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,180 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_forcing
+!
+!&gt; \brief MPAS ocean forcing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  tendencies from forcings.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_forcing
+
+   use grid_types
+   use configure
+
+   use ocn_vel_forcing_windstress
+   use ocn_vel_forcing_bottomdrag
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_forcing_tend, &amp;
+             ocn_vel_forcing_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_tend
+!
+!&gt; \brief   Computes tendency term from forcings
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the forcing tendency for momentum
+!&gt;  based on current state and user choices of forcings.
+!&gt;  Multiple forcings may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen forcing, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_tend(grid, u, u_src, ke_edge, h_edge, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: velocity
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u_src     !&lt; Input: wind stress
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         ke_edge     !&lt; Input: kinetic energy at edge
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      call ocn_vel_forcing_windstress_tend(grid, u_src, h_edge, tend, err1)
+      call ocn_vel_forcing_bottomdrag_tend(grid, u, ke_edge, h_edge, tend, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_init
+!
+!&gt; \brief   Initializes ocean forcings
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes quantities related to forcings 
+!&gt;  in the ocean. Since a multiple forcings are available, 
+!&gt;  this routine primarily calls the
+!&gt;  individual init routines for each forcing. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2
+
+      call ocn_vel_forcing_windstress_init(err1)
+      call ocn_vel_forcing_bottomdrag_init(err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_forcing
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_bottomdrag.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_forcing_bottomdrag.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_bottomdrag.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_bottomdrag.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,201 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_forcing_bottomdrag
+!
+!&gt; \brief MPAS ocean bottom drag
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies from bottom drag.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_forcing_bottomdrag
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_forcing_bottomdrag_tend, &amp;
+             ocn_vel_forcing_bottomdrag_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: bottomDragOn
+   real (kind=RKIND) :: bottomDragCoef
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_bottomdrag_tend
+!
+!&gt; \brief   Computes tendency term from bottom drag
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the bottom drag tendency for momentum
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_bottomdrag_tend(grid, u, ke_edge, h_edge, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u    !&lt; Input: velocity 
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         ke_edge     !&lt; Input: kinetic energy at edge
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdgesSolve, k
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.bottomDragOn) return
+
+      nEdgesSolve = grid % nEdgesSolve
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+
+      do iEdge=1,grid % nEdgesSolve
+
+        k = maxLevelEdgeTop(iEdge)
+
+        ! efficiency note: it would be nice to avoid this
+        ! if within a do.  This could be done with
+        ! k =  max(maxLevelEdgeTop(iEdge),1)
+        ! and then tend_u(1,iEdge) is just not used for land cells.
+
+        if (k&gt;0) then
+           ! bottom drag is the same as POP:
+           ! -c |u| u  where c is unitless and 1.0e-3.
+           ! see POP Reference guide, section 3.4.4.
+
+           tend(k,iEdge) = tend(k,iEdge)  &amp;
+               -bottomDragCoef*u(k,iEdge) &amp;
+               *sqrt(2.0*ke_edge(k,iEdge))/h_edge(k,iEdge)
+
+        endif
+
+      enddo
+
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_bottomdrag_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_bottomdrag_init
+!
+!&gt; \brief   Initializes ocean bottom drag
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes quantities related to bottom drag 
+!&gt;  in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_bottomdrag_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+
+      err = 0
+
+      bottomDragOn = .false.
+
+      if (.not.config_implicit_vertical_mix) then
+          bottomDragOn = .true.
+          bottomDragCoef = config_bottom_drag_coeff
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_bottomdrag_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_forcing_bottomdrag
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_windstress.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_forcing_windstress.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_windstress.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_forcing_windstress.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,190 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_forcing_windstress
+!
+!&gt; \brief MPAS ocean wind stress
+!&gt; \author Doug Jacobsen
+!&gt; \date   16 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies from wind stress.  
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_forcing_windstress
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_forcing_windstress_tend, &amp;
+             ocn_vel_forcing_windstress_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: windStressOn
+   real (kind=RKIND) :: rho_ref
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_windstress_tend
+!
+!&gt; \brief   Computes tendency term from wind stress
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the wind stress tendency for momentum
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_windstress_tend(grid, u_src, h_edge, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u_src    !&lt; Input: wind stress
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge     !&lt; Input: thickness at edge
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdgesSolve, k
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.windStressOn) return
+
+      nEdgesSolve = grid % nEdgesSolve
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+
+      do iEdge=1,nEdgesSolve
+
+        k = maxLevelEdgeTop(iEdge)
+
+        ! efficiency note: it would be nice to avoid this
+        ! if within a do.  This could be done with
+        ! k =  max(maxLevelEdgeTop(iEdge),1)
+        ! and then tend_u(1,iEdge) is just not used for land cells.
+
+        if (k&gt;0) then
+           ! forcing in top layer only
+           tend(1,iEdge) =  tend(1,iEdge) &amp;
+              + u_src(1,iEdge)/rho_ref/h_edge(1,iEdge)
+        endif
+
+      enddo
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_windstress_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_forcing_windstress_init
+!
+!&gt; \brief   Initializes ocean wind stress forcing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    16 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes quantities related to wind stress 
+!&gt;  in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_forcing_windstress_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+
+      windStressOn = .true.
+      rho_ref = 1000.0
+
+      err = 0
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_forcing_windstress_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_forcing_windstress
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_hmix.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,175 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_hmix
+!
+!&gt; \brief MPAS ocean horizontal momentum mixing driver
+!&gt; \author Phil Jones, Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the main driver routine for computing 
+!&gt;  horizontal mixing tendencies.  
+!&gt;
+!&gt;  It provides an init and a tend function. Each are described below.
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_hmix
+
+   use grid_types
+   use configure
+   use ocn_vel_hmix_del2
+   use ocn_vel_hmix_del4
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_hmix_tend, &amp;
+             ocn_vel_hmix_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_tend
+!
+!&gt; \brief   Computes tendency term for horizontal momentum mixing
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for momentum
+!&gt;  based on current state and user choices of mixing parameterization.
+!&gt;  Multiple parameterizations may be chosen and added together.  These
+!&gt;  tendencies are generally computed by calling the specific routine
+!&gt;  for the chosen parameterization, so this routine is primarily a
+!&gt;  driver for managing these choices.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_tend(grid, divergence, vorticity, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         divergence    !&lt; Input: velocity divergence
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vorticity     !&lt; Input: vorticity
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      call ocn_vel_hmix_del2_tend(grid, divergence, vorticity, tend, err1)
+      call ocn_vel_hmix_del4_tend(grid, divergence, vorticity, tend, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_init
+!
+!&gt; \brief   Initializes ocean momentum horizontal mixing quantities
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  horizontal velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2
+
+      call ocn_vel_hmix_del2_init(err1)
+      call ocn_vel_hmix_del4_init(err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_hmix
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del2.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_hmix_del2.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del2.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del2.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,225 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_hmix_del2
+!
+!&gt; \brief Ocean horizontal mixing - Laplacian parameterization 
+!&gt; \author Phil Jones, Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains routines for computing horizontal mixing 
+!&gt;  tendencies using a Laplacian formulation.
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_hmix_del2
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_hmix_del2_tend, &amp;
+             ocn_vel_hmix_del2_init
+
+   !-------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: &amp;
+      hmixDel2On         !&lt; local flag to determine whether del2 chosen
+
+   real (kind=RKIND) :: &amp;
+      eddyVisc2,        &amp;!&lt; base eddy diffusivity for Laplacian
+      viscVortCoef
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_del2_tend
+!
+!&gt; \brief   Computes tendency term for Laplacian horizontal momentum mixing
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    22 August 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for momentum
+!&gt;  based on a Laplacian form for the mixing, \f$</font>
<font color="black">u_2 </font>
<font color="blue">abla^2 u\f$
+!&gt;  This tendency takes the
+!&gt;  form \f$</font>
<font color="black">u( </font>
<font color="black">abla divergence + k \times </font>
<font color="blue">abla vorticity )\f$,
+!&gt;  where \f$</font>
<font color="blue">u\f$ is a viscosity and \f$k\f$ is the vertical unit vector.
+!&gt;  This form is strictly only valid for constant \f$</font>
<font color="blue">u\f$ .
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_del2_tend(grid, divergence, vorticity, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         divergence      !&lt; Input: velocity divergence
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vorticity       !&lt; Input: vorticity
+
+      type (mesh_type), intent(in) :: &amp;
+         grid            !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend             !&lt; Input/Output: velocity tendency
+
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdgesSolve, cell1, cell2, vertex1, vertex2
+      integer :: k
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge, verticesOnEdge
+
+      real (kind=RKIND) :: u_diffusion
+      real (kind=RKIND), dimension(:), pointer :: meshScalingDel2, &amp;
+              dcEdge, dvEdge
+
+      !-----------------------------------------------------------------
+      !
+      ! exit if this mixing is not selected
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.hmixDel2On) return
+
+      call timer_start(&quot;compute_tend_u-horiz mix-del2&quot;)
+      
+      nEdgesSolve = grid % nEdgesSolve
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      verticesOnEdge =&gt; grid % verticesOnEdge % array
+      meshScalingDel2 =&gt; grid % meshScalingDel2 % array
+      dcEdge =&gt; grid % dcEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+
+      do iEdge=1,nEdgesSolve
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         vertex1 = verticesOnEdge(1,iEdge)
+         vertex2 = verticesOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            ! Here -( vorticity(k,vertex2) - vorticity(k,vertex1) ) / dvEdge(iEdge)
+            ! is - </font>
<font color="blue">abla vorticity pointing from vertex 2 to vertex 1, or equivalently 
+            !    + k \times </font>
<font color="gray">abla vorticity pointing from cell1 to cell2.
+
+            u_diffusion = ( divergence(k,cell2)  - divergence(k,cell1) ) / dcEdge(iEdge)  &amp;
+                          -viscVortCoef &amp;
+                          *( vorticity(k,vertex2) - vorticity(k,vertex1) ) / dvEdge(iEdge)
+
+            u_diffusion = meshScalingDel2(iEdge) * eddyVisc2 * u_diffusion
+
+            tend(k,iEdge) = tend(k,iEdge) + u_diffusion
+
+         end do
+      end do
+
+      call timer_stop(&quot;compute_tend_u-horiz mix-del2&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_del2_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_del2_init
+!
+!&gt; \brief   Initializes ocean momentum Laplacian horizontal mixing
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  Laplacian horizontal momentum mixing in the ocean.  
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_del2_init(err)!{{{
+
+
+   integer, intent(out) :: err !&lt; Output: error flag
+
+   !--------------------------------------------------------------------
+   !
+   ! set some local module variables based on input config choices
+   !
+   !--------------------------------------------------------------------
+
+   err = 0
+
+   hmixDel2On = .false.
+
+   if ( config_h_mom_eddy_visc2 &gt; 0.0 ) then
+      hmixDel2On = .true.
+      eddyVisc2 = config_h_mom_eddy_visc2
+
+
+      if (config_visc_vorticity_term) then
+         viscVortCoef = 1.0
+      else
+         viscVortCoef = 0.0
+      endif
+   endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_del2_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_hmix_del2
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del4.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_hmix_del4.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del4.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_hmix_del4.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,300 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_hmix_del4
+!
+!&gt; \brief Ocean horizontal mixing - biharmonic parameterization
+!&gt; \author Phil Jones, Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains routines and variables for computing 
+!&gt;  horizontal mixing tendencies using a biharmonic formulation. 
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_hmix_del4
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_hmix_del4_tend, &amp;
+             ocn_vel_hmix_del4_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: &amp;
+      hmixDel4On       !&lt; local flag to determine whether del4 chosen
+
+   real (kind=RKIND) :: &amp;
+      eddyVisc4,        &amp;!&lt; base eddy diffusivity for biharmonic
+      viscVortCoef
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_del4_tend
+!
+!&gt; \brief   Computes tendency term for biharmonic horizontal momentum mixing
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the horizontal mixing tendency for momentum
+!&gt;  based on a biharmonic form for the mixing.  This mixing tendency
+!&gt;  takes the form  \f$-</font>
<font color="black">u_4 </font>
<font color="blue">abla^4 u\f$
+!&gt;  but is computed as 
+!&gt;  \f$</font>
<font color="black">abla^2 u = </font>
<font color="black">abla divergence + k \times </font>
<font color="blue">abla vorticity\f$
+!&gt;  applied recursively.
+!&gt;  This formulation is only valid for constant \f$</font>
<font color="blue">u_4\f$ .
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_del4_tend(grid, divergence, vorticity, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         divergence      !&lt; Input: velocity divergence
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vorticity       !&lt; Input: vorticity
+
+      type (mesh_type), intent(in) :: &amp;
+         grid           !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend       !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+    
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, cell1, cell2, vertex1, vertex2, k
+      integer :: iCell, iVertex
+      integer :: nVertices, nVertLevels, nCells
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop, maxLevelVertexBot, &amp;
+            maxLevelCell
+      integer, dimension(:,:), pointer :: cellsOnEdge, verticesOnEdge
+
+
+      real (kind=RKIND) :: u_diffusion, r
+      real (kind=RKIND), dimension(:), pointer :: dcEdge, dvEdge, areaTriangle, &amp;
+            meshScalingDel4, areaCell
+
+      real (kind=RKIND), dimension(:,:), allocatable :: delsq_divergence, &amp;
+            delsq_u, delsq_circulation, delsq_vorticity
+
+      err = 0
+
+      if(.not.hmixDel4On) return
+
+      call timer_start(&quot;compute_tend-horiz mix-del4&quot;)
+
+      nCells = grid % nCells
+      nEdges = grid % nEdges
+      nVertices = grid % nVertices
+      nVertLevels = grid % nVertLevels
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      maxLevelVertexBot =&gt; grid % maxLevelVertexBot % array
+      maxLevelCell =&gt; grid % maxLevelCell % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      verticesOnEdge =&gt; grid % verticesOnEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaTriangle =&gt; grid % areaTriangle % array
+      areaCell =&gt; grid % areaCell % array
+      meshScalingDel4 =&gt; grid % meshScalingDel4 % array
+
+      allocate(delsq_divergence(nVertLevels, nCells+1))
+      allocate(delsq_u(nVertLevels, nEdges+1))
+      allocate(delsq_circulation(nVertLevels, nVertices+1))
+      allocate(delsq_vorticity(nVertLevels, nVertices+1))
+
+      delsq_u(:,:) = 0.0
+
+      ! Compute </font>
<font color="black">abla^2 u = </font>
<font color="black">abla divergence + k \times </font>
<font color="blue">abla vorticity
+      do iEdge=1,grid % nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         vertex1 = verticesOnEdge(1,iEdge)
+         vertex2 = verticesOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+
+            delsq_u(k,iEdge) = &amp; 
+               ( divergence(k,cell2)  - divergence(k,cell1) ) / dcEdge(iEdge)  &amp;
+               -viscVortCoef &amp;
+               *( vorticity(k,vertex2) - vorticity(k,vertex1)) / dvEdge(iEdge)
+
+         end do
+      end do
+
+      ! vorticity using </font>
<font color="blue">abla^2 u
+      delsq_circulation(:,:) = 0.0
+      do iEdge=1,nEdges
+         vertex1 = verticesOnEdge(1,iEdge)
+         vertex2 = verticesOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeTop(iEdge)
+            delsq_circulation(k,vertex1) = delsq_circulation(k,vertex1) &amp;
+               - dcEdge(iEdge) * delsq_u(k,iEdge)
+            delsq_circulation(k,vertex2) = delsq_circulation(k,vertex2) &amp;
+               + dcEdge(iEdge) * delsq_u(k,iEdge)
+         end do
+      end do
+      do iVertex=1,nVertices
+         r = 1.0 / areaTriangle(iVertex)
+         do k=1,maxLevelVertexBot(iVertex)
+            delsq_vorticity(k,iVertex) = delsq_circulation(k,iVertex) * r
+         end do
+      end do
+
+      ! Divergence using </font>
<font color="blue">abla^2 u
+      delsq_divergence(:,:) = 0.0
+      do iEdge=1,nEdges
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeTop(iEdge)
+           delsq_divergence(k,cell1) = delsq_divergence(k,cell1) &amp;
+             + delsq_u(k,iEdge)*dvEdge(iEdge)
+           delsq_divergence(k,cell2) = delsq_divergence(k,cell2) &amp;
+             - delsq_u(k,iEdge)*dvEdge(iEdge)
+         end do
+      end do
+      do iCell = 1,nCells
+         r = 1.0 / areaCell(iCell)
+         do k = 1,maxLevelCell(iCell)
+            delsq_divergence(k,iCell) = delsq_divergence(k,iCell) * r
+         end do
+      end do
+
+      ! Compute - \kappa </font>
<font color="blue">abla^4 u 
+      ! as  </font>
<font color="black">abla div(</font>
<font color="black">abla^2 u) + k \times </font>
<font color="black">abla ( k \cross curl(</font>
<font color="gray">abla^2 u) )
+      do iEdge=1,grid % nEdgesSolve
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         vertex1 = verticesOnEdge(1,iEdge)
+         vertex2 = verticesOnEdge(2,iEdge)
+
+         do k=1,maxLevelEdgeTop(iEdge)
+            delsq_u(k,iEdge) = &amp; 
+               ( divergence(k,cell2)  - divergence(k,cell1) ) / dcEdge(iEdge)  &amp;
+              -( vorticity(k,vertex2) - vorticity(k,vertex1)) / dvEdge(iEdge)
+
+            u_diffusion = (  delsq_divergence(k,cell2) &amp;
+                           - delsq_divergence(k,cell1) ) / dcEdge(iEdge)  &amp;
+                         -viscVortCoef &amp;
+                         *(  delsq_vorticity(k,vertex2) &amp;
+                           - delsq_vorticity(k,vertex1) ) / dvEdge(iEdge)
+
+            u_diffusion = meshScalingDel4(iEdge) * eddyVisc4 * u_diffusion
+
+            tend(k,iEdge) = tend(k,iEdge) - u_diffusion
+         end do
+      end do
+
+      deallocate(delsq_divergence)
+      deallocate(delsq_u)
+      deallocate(delsq_circulation)
+      deallocate(delsq_vorticity)
+
+      call timer_stop(&quot;compute_tend-horiz mix-del4&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_del4_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_hmix_del4_init
+!
+!&gt; \brief   Initializes ocean momentum biharmonic horizontal mixing
+!&gt; \author  Phil Jones, Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  biharmonic horizontal tracer mixing in the ocean.  
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_hmix_del4_init(err)!{{{
+
+   integer, intent(out) :: err !&lt; Output: error flag
+
+   !--------------------------------------------------------------------
+   !
+   ! set some local module variables based on input config choices
+   !
+   !--------------------------------------------------------------------
+
+   err = 0
+
+   hmixDel4On = .false.
+
+   if ( config_h_mom_eddy_visc4 &gt; 0.0 ) then
+      hmixDel4On = .true.
+      eddyVisc4 = config_h_mom_eddy_visc4
+      if (config_visc_vorticity_term) then
+         viscVortCoef = 1.0
+      else
+         viscVortCoef = 0.0
+      endif
+
+   endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_hmix_del4_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_hmix_del4
+
+!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_pressure_grad.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_pressure_grad.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_pressure_grad.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_pressure_grad.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,195 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_pressure_grad
+!
+!&gt; \brief MPAS ocean pressure gradient module
+!&gt; \author Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencie from the horizontal pressure gradient.
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_pressure_grad
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_pressure_grad_tend, &amp;
+             ocn_vel_pressure_grad_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   real (kind=RKIND) :: rho0Inv
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_pressure_grad_tend
+!
+!&gt; \brief   Computes tendency term for horizontal pressure gradient
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the pressure gradient tendency for momentum
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_pressure_grad_tend(grid, pressure, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         pressure !&lt; Input: Pressure field or Mongomery potential
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: nEdgesSolve, iEdge, k, cell1, cell2
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real (kind=RKIND), dimension(:), pointer :: dcEdge
+
+      err = 0
+
+      nEdgesSolve = grid % nEdgesSolve
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+
+      if (config_vert_grid_type.eq.'isopycnal') then
+        do iEdge=1,nEdgesSolve
+          cell1 = cellsOnEdge(1,iEdge)
+          cell2 = cellsOnEdge(2,iEdge)
+          do k=1,maxLevelEdgeTop(iEdge)
+             tend(k,iEdge) = tend(k,iEdge)     &amp;
+               - (pressure(k,cell2) - pressure(k,cell1))/dcEdge(iEdge)
+           end do
+        enddo
+      elseif (config_vert_grid_type.eq.'zlevel') then
+        do iEdge=1,nEdgesSolve
+          cell1 = cellsOnEdge(1,iEdge)
+          cell2 = cellsOnEdge(2,iEdge)
+          do k=1,maxLevelEdgeTop(iEdge)
+
+            tend(k,iEdge) = tend(k,iEdge)     &amp;
+              - rho0Inv*(  pressure(k,cell2) &amp;
+                         - pressure(k,cell1) )/dcEdge(iEdge)
+          end do
+
+        enddo
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_pressure_grad_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_pressure_grad_init
+!
+!&gt; \brief   Initializes ocean momentum horizontal pressure gradient
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes parameters required for the computation of the
+!&gt;  horizontal pressure gradient.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_pressure_grad_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+
+      !-----------------------------------------------------------------
+      !
+      ! Output Variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if (config_vert_grid_type.eq.'isopycnal') then
+        rho0Inv = 1.0
+      elseif (config_vert_grid_type.eq.'zlevel') then
+        rho0Inv = 1.0/config_rho0
+      end if
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_pressure_grad_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_pressure_grad
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vel_vadv.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vel_vadv.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vel_vadv.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vel_vadv.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,195 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vel_vadv
+!
+!&gt; \brief MPAS ocean vertical advection 
+!&gt; \author Doug Jacobsen
+!&gt; \date   15 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routine for computing 
+!&gt;  tendencies for vertical advection.
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_vadv
+
+   use grid_types
+   use configure
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vel_vadv_tend, &amp;
+             ocn_vel_vadv_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: velVadvOn
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vel_vadv_tend
+!
+!&gt; \brief   Computes tendency term for vertical advection
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical advection tendency for momentum
+!&gt;  based on current state.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vadv_tend(grid, u, wTop, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u     !&lt; Input: Horizontal velocity
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         wTop  !&lt; Input: Vertical velocity on top layer
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: velocity tendency
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdgesSolve, cell1, cell2, k
+      integer :: nVertLevels
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real :: wTopEdge
+      real, dimension(:), allocatable :: w_dudzTopEdge
+      real, dimension(:), pointer :: zMidZLevel
+
+      if(.not.velVadvOn) return
+
+      err = 0
+
+      nVertLevels = grid % nVertLevels
+      nEdgesSolve = grid % nEdgesSolve
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      zMidZLevel =&gt; grid % zMidZLevel % array
+
+      allocate(w_dudzTopEdge(nVertLevels+1))
+      w_dudzTopEdge(1) = 0.0
+      do iEdge=1,nEdgesSolve
+        cell1 = cellsOnEdge(1,iEdge)
+        cell2 = cellsOnEdge(2,iEdge)
+
+        do k=2,maxLevelEdgeTop(iEdge)
+          ! Average w from cell center to edge
+          wTopEdge = 0.5*(wTop(k,cell1)+wTop(k,cell2))
+
+          ! compute dudz at vertical interface with first order derivative.
+          w_dudzTopEdge(k) = wTopEdge * (u(k-1,iEdge)-u(k,iEdge)) &amp;
+                       / (zMidZLevel(k-1) - zMidZLevel(k))
+        end do
+        w_dudzTopEdge(maxLevelEdgeTop(iEdge)+1) = 0.0
+        ! Average w*du/dz from vertical interface to vertical middle of cell
+        do k=1,maxLevelEdgeTop(iEdge)
+
+          tend(k,iEdge) = tend(k,iEdge) &amp;
+             - 0.5 * (w_dudzTopEdge(k) + w_dudzTopEdge(k+1))
+        enddo
+      enddo
+      deallocate(w_dudzTopEdge)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vadv_tend!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vadv_init
+!
+!&gt; \brief   Initializes ocean momentum vertical advection
+!&gt; \author  Doug Jacobsen
+!&gt; \date    15 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical velocity advection in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vadv_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! Output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+      velVadvOn = .false.
+
+      if (config_vert_grid_type.eq.'zlevel') then
+          velVadvOn = .true.
+      end if
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vadv_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_vadv
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vmix.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vmix.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vmix.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vmix.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,724 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vmix
+!
+!&gt; \brief MPAS ocean vertical mixing driver
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module is the main driver for 
+!&gt;  vertical mixing in the ocean. 
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vmix
+
+   use grid_types
+   use configure
+   use timer
+
+   use ocn_vmix_coefs_const
+   use ocn_vmix_coefs_tanh
+   use ocn_vmix_coefs_rich
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   private :: tridiagonal_solve, &amp;
+              tridiagonal_solve_mult
+
+   public :: ocn_vmix_coefs, &amp;
+             ocn_vel_vmix_tend_explicit, &amp;
+             ocn_tracer_vmix_tend_explicit, &amp;
+             ocn_vel_vmix_tend_implicit, &amp;
+             ocn_tracer_vmix_tend_implicit, &amp;
+             ocn_vmix_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: explicitOn, implicitOn
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs
+!
+!&gt; \brief   Computes coefficients for vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical mixing coefficients for momentum
+!&gt;  and tracers based user choices of mixing parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vmix_coefs(grid, s, d, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (state_type), intent(inout) :: &amp;
+         s             !&lt; Input/Output: state information
+
+      type (diagnostics_type), intent(inout) :: &amp;
+         d             !&lt; Input/Output: diagnostic information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2, err3
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing coefficients
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      call ocn_vmix_coefs_const_build(grid, s, d, err1)
+      call ocn_vmix_coefs_tanh_build(grid, s, d, err2)
+      call ocn_vmix_coefs_rich_build(grid, s, d, err3)
+
+      err = err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vmix_tendExplict
+!
+!&gt; \brief   Computes tendencies for explict momentum vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tendencies for explicit vertical mixing for momentum
+!&gt;  using computed coefficients.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vmix_tend_explicit(grid, u, h_edge, vertViscTopOfEdge, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         u             !&lt; Input: velocity
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge        !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vertViscTopOfEdge !&lt; Input: vertical mixing coefficients
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tendency information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdgesSolve, k, nVertLevels
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+
+      real (kind=RKIND), dimension(:), allocatable :: fluxVertTop
+
+      err = 0
+
+      if(implicitOn) return
+
+      call timer_start(&quot;compute_tend_u-explicit vert mix&quot;)
+
+      nEdgessolve = grid % nEdgesSolve
+      nVertLevels = grid % nVertLevels
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+
+      allocate(fluxVertTop(nVertLevels+1))
+      fluxVertTop(1) = 0.0
+      do iEdge=1,nEdgesSolve
+         do k=2,maxLevelEdgeTop(iEdge)
+           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
+         fluxVertTop(maxLevelEdgeTop(iEdge)+1) = 0.0
+
+         do k=1,maxLevelEdgeTop(iEdge)
+           tend(k,iEdge) = tend(k,iEdge) &amp;
+             + (fluxVertTop(k) - fluxVertTop(k+1)) &amp;
+             / h_edge(k,iEdge)
+         enddo
+
+      end do
+      deallocate(fluxVertTop)
+
+      call timer_stop(&quot;compute_tend_u-explicit vert mix&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vmix_tend_explicit!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vmix_tend_implicit
+!
+!&gt; \brief   Computes tendencies for implicit momentum vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tendencies for implicit vertical mixing for momentum
+!&gt;  using computed coefficients.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vmix_tend_implicit(grid, dt, ke_edge, vertViscTopOfEdge, h, h_edge, u, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         ke_edge        !&lt; Input: kinetic energy at edge
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vertViscTopOfEdge !&lt; Input: vertical mixing coefficients
+
+      real (kind=RKIND), intent(in) :: &amp;
+         dt            !&lt; Input: time step
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h             !&lt; Input: thickness at cell center
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         u             !&lt; Input: velocity
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: &amp;
+         h_edge        !&lt; Input: thickness at edge
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, k, cell1, cell2, nVertLevels
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real (kind=RKIND), dimension(:), allocatable :: A, C, uTemp
+
+      err = 0
+
+      if(explicitOn) return
+
+      nEdges = grid % nEdges
+      nVertLevels = grid % nVertLevels
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+
+      allocate(A(nVertLevels),C(nVertLevels),uTemp(nVertLevels)) 
+
+      do iEdge=1,nEdges
+        if (maxLevelEdgeTop(iEdge).gt.0) then
+
+         ! Compute A(k), C(k) for momentum
+         ! mrp 110315 efficiency note: for z-level, could precompute
+         ! -2.0*dt/(h(k)_h(k+1))/h(k) in setup
+         ! h_edge is computed in compute_solve_diag, and is not available yet.
+         ! This could be removed if hZLevel used instead.
+         cell1 = cellsOnEdge(1,iEdge)
+         cell2 = cellsOnEdge(2,iEdge)
+         do k=1,maxLevelEdgeTop(iEdge)
+            h_edge(k,iEdge) = 0.5 * (h(k,cell1) + h(k,cell2))
+         end do
+
+         do k=1,maxLevelEdgeTop(iEdge)-1
+            A(k) = -2.0*dt*vertViscTopOfEdge(k+1,iEdge) &amp;
+               / (h_edge(k,iEdge) + h_edge(k+1,iEdge)) &amp;
+               / h_edge(k,iEdge)
+         enddo
+         A(maxLevelEdgeTop(iEdge)) = -dt*config_bottom_drag_coeff  &amp;
+            *sqrt(2.0*ke_edge(k,iEdge))/h_edge(k,iEdge)
+
+         C(1) = 1 - A(1)
+         do k=2,maxLevelEdgeTop(iEdge)
+            C(k) = 1 - A(k) - A(k-1)
+         enddo
+
+         call tridiagonal_solve(A,C,A,u(:,iEdge),uTemp,maxLevelEdgeTop(iEdge))
+
+         u(1:maxLevelEdgeTop(iEdge),iEdge) = uTemp(1:maxLevelEdgeTop(iEdge))
+         u(maxLevelEdgeTop(iEdge)+1:nVertLevels,iEdge) = 0.0
+
+        end if
+      end do
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vmix_tend_implicit!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vmix_tendExplict
+!
+!&gt; \brief   Computes tendencies for explict tracer vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tendencies for explicit vertical mixing for
+!&gt;  tracers using computed coefficients.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vmix_tend_explicit(grid, h, vertDiffTopOfCell, tracers, tend, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h        !&lt; Input: thickness at cell center
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vertDiffTopOfCell !&lt; Input: vertical mixing coefficients
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: &amp;
+         tracers             !&lt; Input: tracers
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tend          !&lt; Input/Output: tendency information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCellsSolve, k, iTracer, num_tracers, nVertLevels
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND), dimension(:,:), allocatable :: fluxVertTop
+
+      err = 0
+
+      if(implicitOn) return
+
+      call timer_start(&quot;compute_scalar_tend-explicit vert diff&quot;)
+
+      nCellsSolve = grid % nCellsSolve
+      nVertLevels = grid % nVertLevels
+      num_tracers = size(tracers, dim=1)
+
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      allocate(fluxVertTop(num_tracers,nVertLevels+1))
+      fluxVertTop(:,1) = 0.0
+      do iCell=1,nCellsSolve 
+
+         do k=2,maxLevelCell(iCell)
+           do iTracer=1,num_tracers
+             ! compute \kappa_v d\phi/dz
+             fluxVertTop(iTracer,k) = vertDiffTopOfCell(k,iCell) &amp;
+                * (   tracers(iTracer,k-1,iCell)    &amp;
+                    - tracers(iTracer,k  ,iCell) )  &amp;
+                * 2 / (h(k-1,iCell) + h(k,iCell))
+
+           enddo
+         enddo
+         fluxVertTop(:,maxLevelCell(iCell)+1) = 0.0
+
+         do k=1,maxLevelCell(iCell)
+           do iTracer=1,num_tracers
+             ! This is h d/dz( fluxVertTop) but h and dz cancel, so 
+             ! reduces to delta( fluxVertTop)
+             tend(iTracer,k,iCell) = tend(iTracer,k,iCell) &amp;
+               + fluxVertTop(iTracer,k) - fluxVertTop(iTracer,k+1)
+           enddo
+         enddo
+!print '(a,50e12.2)', 'fluxVertTop',fluxVertTop(3,1:maxLevelCell(iCell)+1)
+!print '(a,50e12.2)', 'tend_tr    ',tend_tr(3,1,1:maxLevelCell(iCell))
+      enddo ! iCell loop
+      deallocate(fluxVertTop)
+
+      call timer_stop(&quot;compute_scalar_tend-explicit vert diff&quot;)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vmix_tend_explicit!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vmix_tend_implicit
+!
+!&gt; \brief   Computes tendencies for implicit tracer vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tendencies for implicit vertical mixing for
+!&gt;  tracers using computed coefficients.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vmix_tend_implicit(grid, dt, vertDiffTopOfCell, h, tracers, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         vertDiffTopOfCell !&lt; Input: vertical mixing coefficients
+
+      real (kind=RKIND), intent(in) :: &amp;
+         dt            !&lt; Input: time step
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h             !&lt; Input: thickness at cell center
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:,:), intent(inout) :: &amp;
+         tracers        !&lt; Input: tracers
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCells, k, nVertLevels, num_tracers
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND), dimension(:), allocatable :: A, C
+      real (kind=RKIND), dimension(:,:), allocatable :: tracersTemp
+
+      err = 0
+
+      if(explicitOn) return
+
+      nCells = grid % nCells
+      nVertLevels = grid % nVertLevels
+      num_tracers = size(tracers, dim=1)
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      allocate(A(nVertLevels),C(nVertLevels), tracersTemp(num_tracers,nVertLevels))
+
+      do iCell=1,nCells
+         ! Compute A(k), C(k) for tracers
+         ! mrp 110315 efficiency note: for z-level, could precompute
+         ! -2.0*dt/(h(k)_h(k+1))/h(k) in setup
+         do k=1,maxLevelCell(iCell)-1
+            A(k) = -2.0*dt*vertDiffTopOfCell(k+1,iCell) &amp;
+                 / (h(k,iCell) + h(k+1,iCell)) / h(k,iCell)
+         enddo
+
+         A(maxLevelCell(iCell)) = 0.0
+
+         C(1) = 1 - A(1)
+         do k=2,maxLevelCell(iCell)
+            C(k) = 1 - A(k) - A(k-1)
+         enddo
+
+         call tridiagonal_solve_mult(A,C,A,tracers(:,:,iCell), &amp;
+              tracersTemp, maxLevelCell(iCell), nVertLevels,num_tracers)
+
+         tracers(:,1:maxLevelCell(iCell),iCell) = tracersTemp(:,1:maxLevelCell(iCell))
+         tracers(:,maxLevelCell(iCell)+1:nVertLevels,iCell) = -1e34
+      end do
+      deallocate(A,C,tracersTemp)
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vmix_tend_implicit!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vmix_init
+!
+!&gt; \brief   Initializes ocean vertical mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical mixing in the ocean. This primarily determines if
+!&gt;  explicit or implicit vertical mixing is to be used.
+!
+!-----------------------------------------------------------------------
+
+
+   subroutine ocn_vmix_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      integer :: err1, err2, err3
+
+      err = 0
+
+      explicitOn = .true.
+      implicitOn = .false.
+
+      if(config_implicit_vertical_mix) then
+          explicitOn = .false.
+          implicitOn =.true.
+      end if
+
+      call ocn_vmix_coefs_const_init(err1)
+      call ocn_vmix_coefs_tanh_init(err2)
+      call ocn_vmix_coefs_rich_init(err3)
+
+      err = err .or. err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_init!}}}
+
+subroutine tridiagonal_solve(a,b,c,r,x,n)!{{{
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Solve the matrix equation Ax=r for x, where A is tridiagonal.
+! A is an nxn matrix, with:
+!   a sub-diagonal, filled from 1:n-1 (a(1) appears on row 2)
+!   b diagonal, filled from 1:n
+!   c sup-diagonal, filled from 1:n-1  (c(1) apears on row 1)
+!
+! Input: a,b,c,r,n
+!
+! Output: x
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

+   implicit none
+
+   integer,intent(in) :: n
+   real (KIND=RKIND), dimension(n), intent(in) :: a,b,c,r
+   real (KIND=RKIND), dimension(n), intent(out) :: x
+   real (KIND=RKIND), dimension(n) :: bTemp,rTemp
+   real (KIND=RKIND) :: m
+   integer i
+
+   call timer_start(&quot;tridiagonal_solve&quot;)

+   ! Use work variables for b and r
+   bTemp(1) = b(1)
+   rTemp(1) = r(1)

+   ! First pass: set the coefficients
+   do i = 2,n
+      m = a(i-1)/bTemp(i-1)
+      bTemp(i) = b(i) - m*c(i-1)
+      rTemp(i) = r(i) - m*rTemp(i-1)
+   end do 

+   x(n) = rTemp(n)/bTemp(n)
+   ! Second pass: back-substition
+   do i = n-1, 1, -1
+      x(i) = (rTemp(i) - c(i)*x(i+1))/bTemp(i)
+   end do
+
+   call timer_stop(&quot;tridiagonal_solve&quot;)

+end subroutine tridiagonal_solve!}}}
+
+subroutine tridiagonal_solve_mult(a,b,c,r,x,n,nDim,nSystems)!{{{
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Solve the matrix equation Ax=r for x, where A is tridiagonal.
+! A is an nxn matrix, with:
+!   a sub-diagonal, filled from 1:n-1 (a(1) appears on row 2)
+!   b diagonal, filled from 1:n
+!   c sup-diagonal, filled from 1:n-1  (c(1) apears on row 1)
+!
+! Input: a,b,c,r,n
+!
+! Output: x
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

+   implicit none
+
+   integer,intent(in) :: n, nDim, nSystems
+   real (KIND=RKIND), dimension(n), intent(in) :: a,b,c
+   real (KIND=RKIND), dimension(nSystems,nDim), intent(in) :: r
+   real (KIND=RKIND), dimension(nSystems,nDim), intent(out) :: x
+   real (KIND=RKIND), dimension(n) :: bTemp
+   real (KIND=RKIND), dimension(nSystems,n) :: rTemp
+   real (KIND=RKIND) :: m
+   integer i,j
+
+   call timer_start(&quot;tridiagonal_solve_mult&quot;)

+   ! Use work variables for b and r
+   bTemp(1) = b(1)
+   do j = 1,nSystems
+      rTemp(j,1) = r(j,1)
+   end do

+   ! First pass: set the coefficients
+   do i = 2,n
+      m = a(i-1)/bTemp(i-1)
+      bTemp(i) = b(i) - m*c(i-1)
+      do j = 1,nSystems
+         rTemp(j,i) = r(j,i) - m*rTemp(j,i-1)
+      end do 
+   end do 

+   do j = 1,nSystems
+      x(j,n) = rTemp(j,n)/bTemp(n)
+   end do
+   ! Second pass: back-substition
+   do i = n-1, 1, -1
+      do j = 1,nSystems
+         x(j,i) = (rTemp(j,i) - c(i)*x(j,i+1))/bTemp(i)
+      end do
+   end do

+   call timer_stop(&quot;tridiagonal_solve_mult&quot;)
+
+end subroutine tridiagonal_solve_mult!}}}
+
+!***********************************************************************
+
+end module ocn_vmix
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_const.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vmix_coefs_const.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_const.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_const.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,306 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vmix_coefs_const
+!
+!&gt; \brief MPAS ocean vertical mixing coefficients
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routines for computing 
+!&gt;  constant vertical mixing coefficients.  
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vmix_coefs_const
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   private :: ocn_vel_vmix_coefs_const, &amp;
+              ocn_tracer_vmix_coefs_const
+
+   public :: ocn_vmix_coefs_const_build, &amp;
+             ocn_vmix_coefs_const_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: constViscOn, constDiffOn
+
+   real (kind=RKIND) :: constVisc, constDiff
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_const_build
+!
+!&gt; \brief   Computes coefficients for vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical mixing coefficients for momentum
+!&gt;  and tracers based user choices of mixing parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vmix_coefs_const_build(grid, s, d, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (state_type), intent(inout) :: &amp;
+         s             !&lt; Input/Output: state information
+
+      type (diagnostics_type), intent(inout) :: &amp;
+         d             !&lt; Input/Output: diagnostic information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        vertViscTopOfEdge, vertDiffTopOfCell
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+      if((.not.constViscOn) .and. (.not.constDiffOn)) return
+
+      vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
+      vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
+
+      call ocn_vel_vmix_coefs_const(grid, vertViscTopOfEdge, err1)
+      call ocn_tracer_vmix_coefs_const(grid, vertDiffTopOfCell, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_const_build!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vmix_coefs_const
+!
+!&gt; \brief   Computes coefficients for vertical momentum mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the constant vertical mixing coefficients for momentum
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vmix_coefs_const(grid, vertViscTopOfEdge, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertViscTopOfEdge !&lt; Output: vertical viscosity
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.constViscOn) return
+
+      vertViscTopOfEdge = constVisc
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vmix_coefs_const!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vmix_coefs_const
+!
+!&gt; \brief   Computes coefficients for vertical tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the constant vertical mixing coefficients for tracers
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vmix_coefs_const(grid, vertDiffTopOfCell, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertDiffTopOfCell !&lt; Output: Vertical diffusion
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+
+      if(.not.constDiffOn) return
+
+      vertDiffTopOfCell = constDiff
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vmix_coefs_const!}}}
+
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_const_init
+!
+!&gt; \brief   Initializes ocean momentum vertical mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+
+   subroutine ocn_vmix_coefs_const_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      constViscOn = .false.
+      constDiffOn = .false.
+
+      if (config_vert_visc_type.eq.'const') then
+          constViscOn = .true.
+          constVisc = config_vert_visc
+      endif
+
+      if (config_vert_diff_type.eq.'const') then
+          constDiffOn = .true.
+          constDiff = config_vert_diff
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_const_init!}}}
+
+!***********************************************************************
+
+end module ocn_vmix_coefs_const
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_rich.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vmix_coefs_rich.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_rich.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_rich.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,601 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vmix_coefs_rich
+!
+!&gt; \brief MPAS ocean vertical mixing coefficients
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routines for computing 
+!&gt;  richardson vertical mixing coefficients.  
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vmix_coefs_rich
+
+   use grid_types
+   use configure
+   use constants
+   use timer
+
+   use ocn_equation_of_state
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vmix_coefs_rich_build, &amp;
+             ocn_vmix_coefs_rich_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: richViscOn, richDiffOn
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_rich_build
+!
+!&gt; \brief   Computes coefficients for vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical mixing coefficients for momentum
+!&gt;  and tracers based user choices of mixing parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vmix_coefs_rich_build(grid, s, d, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (state_type), intent(inout) :: &amp;
+         s             !&lt; Input/Output: state information
+
+      type (diagnostics_type), intent(inout) :: &amp;
+         d             !&lt; Input/Output: diagnostic information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2, err3, indexT, indexS
+
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        vertViscTopOfEdge, vertDiffTopOfCell, u, h, h_edge, rho, rhoDisplaced
+
+      real (kind=RKIND), dimension(:,:), pointer :: RiTopOfEdge, RiTopOfCell
+
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+      if((.not.richViscOn) .and. (.not.richDiffOn)) return
+
+      indexT = s%index_temperature
+      indexS = s%index_salinity
+
+      vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
+      vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
+      RiTopOfEdge =&gt; d % RiTopOfEdge % array
+      RiTopOfCell =&gt; d % RiTopOfCell % array
+
+      u =&gt; s % u % array
+      h =&gt; s % h % array
+      h_edge =&gt; s % h_edge % array
+      rho =&gt; s % rho % array
+      rhoDisplaced =&gt; s % rhoDisplaced % array
+      tracers =&gt; s % tracers % array
+
+      call ocn_equation_of_state_rho(s, grid, 0, 'relative', err)
+      call ocn_equation_of_state_rho(s, grid, 1, 'relative', err)
+
+      call ocn_vmix_get_rich_numbers(grid, indexT, indexS, u, h, h_edge, &amp; 
+                                  rho, rhoDisplaced, tracers, RiTopOfEdge, RiTopOfCell, err1)
+
+      call ocn_vel_vmix_coefs_rich(grid, RiTopOfEdge, h_edge, vertViscTopOfEdge, err2)
+      call ocn_tracer_vmix_coefs_rich(grid, RiTopOfCell, h, vertDiffTopOfCell, err3)
+
+      err = err1 .or. err2 .or. err3
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_rich_build!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vmix_coefs_rich
+!
+!&gt; \brief   Computes coefficients for vertical momentum mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the richardson vertical mixing coefficients for momentum
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vmix_coefs_rich(grid, RiTopOfEdge, h_edge, vertViscTopOfEdge, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h_edge        !&lt; Input: thickness at edge
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         RiTopOfEdge   !&lt; Richardson number at top of edge
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertViscTopOfEdge !&lt; Output: vertical viscosity
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iEdge, nEdges, k
+
+      integer, dimension(:), pointer :: maxLevelEdgeTop
+
+      err = 0
+
+      if(.not.richViscOn) return
+
+      nEdges = grid % nEdges
+
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+
+      vertViscTopOfEdge = 0.0
+      do iEdge = 1,nEdges
+         do k = 2,maxLevelEdgeTop(iEdge)
+            ! mrp 110324 efficiency note: this if is inside iEdge and k loops.
+            ! Perhaps there is a more efficient way to do this.
+            if (RiTopOfEdge(k,iEdge)&gt;0.0) then
+               vertViscTopOfEdge(k,iEdge) = config_bkrd_vert_visc &amp;
+                  + config_rich_mix / (1.0 + 5.0*RiTopOfEdge(k,iEdge))**2
+            ! maltrud do limiting of coefficient--should not be necessary
+            ! also probably better logic could be found
+               if (vertViscTopOfEdge(k,iEdge) &gt; config_convective_visc) then
+                   if( config_implicit_vertical_mix) then
+                      vertViscTopOfEdge(k,iEdge) = config_convective_visc
+                   else
+                      vertViscTopOfEdge(k,iEdge) = &amp;
+                      ((h_edge(k-1,iEdge)+h_edge(k,iEdge))/2.0)**2/config_dt/4.0
+                   end if
+               end if
+            else
+               ! mrp 110324 efficiency note: this if is inside iCell and k loops.
+               if (config_implicit_vertical_mix) then
+                  ! for Ri&lt;0 and implicit mix, use convective diffusion
+                  vertViscTopOfEdge(k,iEdge) = config_convective_visc
+               else
+                  ! for Ri&lt;0 and explicit vertical mix, 
+                  ! use maximum diffusion allowed by CFL criterion
+                  ! mrp 110324 efficiency note: for z-level, could use fixed
+                  ! grid array hMeanTopZLevel and compute maxdiff on startup.
+                  vertViscTopOfEdge(k,iEdge) = &amp;
+                      ((h_edge(k-1,iEdge)+h_edge(k,iEdge))/2.0)**2/config_dt/4.0
+               end if
+            end if
+         end do
+      end do
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vmix_coefs_rich!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vmix_coefs_rich
+!
+!&gt; \brief   Computes coefficients for vertical tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the richardson vertical mixing coefficients for tracers
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vmix_coefs_rich(grid, RiTopOfCell, h, vertDiffTopOfCell, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         h             !&lt; Input: thickness at cell center
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: &amp;
+         RiTopOfCell   !&lt; Input: Richardson number at top of cell
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertDiffTopOfCell !&lt; Output: vertical diffusions
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: iCell, nCells, k
+
+      integer, dimension(:), pointer :: maxLevelCell
+
+      real (kind=RKIND) :: coef
+
+      err = 0
+
+      if(.not.richDiffOn) return
+
+      nCells = grid % nCells
+
+      maxLevelCell =&gt; grid % maxLevelCell % array
+
+      vertDiffTopOfCell = 0.0
+      coef = -gravity/1000.0/2.0
+      do iCell = 1,nCells
+         do k = 2,maxLevelCell(iCell)
+            ! mrp 110324 efficiency note: this if is inside iCell and k loops.
+            ! Perhaps there is a more efficient way to do this.
+            if (RiTopOfCell(k,iCell)&gt;0.0) then
+               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))
+            ! maltrud do limiting of coefficient--should not be necessary
+            ! also probably better logic could be found
+               if (vertDiffTopOfCell(k,iCell) &gt; config_convective_diff) then
+                  if (config_implicit_vertical_mix) then
+                     vertDiffTopOfCell(k,iCell) = config_convective_diff
+                  else
+                     vertDiffTopOfCell(k,iCell) = &amp;
+                        ((h(k-1,iCell)+h(k,iCell))/2.0)**2/config_dt/4.0
+                  end if
+               end if
+             else
+               ! mrp 110324 efficiency note: this if is inside iCell and k loops.
+               if (config_implicit_vertical_mix) then
+                  ! for Ri&lt;0 and implicit mix, use convective diffusion
+                  vertDiffTopOfCell(k,iCell) = config_convective_diff
+               else
+                  ! for Ri&lt;0 and explicit vertical mix, 
+                  ! use maximum diffusion allowed by CFL criterion
+                  ! mrp 110324 efficiency note: for z-level, could use fixed
+                  ! grid array hMeanTopZLevel and compute maxdiff on startup.
+                  vertDiffTopOfCell(k,iCell) = &amp;
+                     ((h(k-1,iCell)+h(k,iCell))/2.0)**2/config_dt/4.0
+               end if
+            end if
+         end do
+      end do
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vmix_coefs_rich!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vmix_get_rich_numbers
+!
+!&gt; \brief   Build richardson numbers for vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine builds the arrays needed for richardson number vertical
+!&gt;  mixing coefficients.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vmix_get_rich_numbers(grid, indexT, indexS, u, h, h_edge, &amp; !{{{
+                                 rho, rhoDisplaced, tracers, RiTopOfEdge, RiTopOfCell, err)
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      integer, intent(in) :: indexT !&lt; Input: index for temperature
+      integer, intent(in) :: indexS !&lt; Input: index for salinity
+
+      real (kind=RKIND), dimension(:,:), intent(in) :: u       !&lt; Input: horizontal velocity
+      real (kind=RKIND), dimension(:,:), intent(in) :: h       !&lt; Input: thickness
+      real (kind=RKIND), dimension(:,:), intent(in) :: h_edge  !&lt; Input: thickness at edge 
+
+      real (kind=RKIND), dimension(:,:,:), intent(in) :: tracers !&lt; Input: tracers
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(inout) :: rho    !&lt; Input/output: density
+      real (kind=RKIND), dimension(:,:), intent(inout) :: rhoDisplaced    !&lt; Input/output: displaced density
+      real (kind=RKIND), dimension(:,:), intent(inout) :: RiTopOfEdge     !&lt; Input/output: Richardson number top of cell
+      real (kind=RKIND), dimension(:,:), intent(inout) :: RiTopOfCell     !&lt; Input/output: Richardson number top of cell
+
+      integer, intent(inout) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: nVertLevels, nCells, nEdges, iCell, iEdge, k
+      integer :: cell1, cell2
+
+      integer, dimension(:), pointer :: maxLevelCell, maxLevelEdgeTop, maxLevelEdgeBot
+      integer, dimension(:,:), pointer :: cellsOnEdge
+
+      real (kind=RKIND) :: coef
+      real (kind=RKIND), dimension(:), pointer :: dcEdge, dvEdge, areaCell
+      real (kind=RKIND), dimension(:,:), allocatable :: drhoTopOfCell, du2TopOfCell, &amp;
+                                                        drhoTopOfEdge, du2TopOfEdge
+
+      err = 0
+
+      if(.not.richViscOn .and. .not.richDiffOn) return
+
+      nVertLevels = grid % nVertLevels
+      nCells = grid % nCells
+      nEdges = grid % nEdges
+
+      maxLevelCell =&gt; grid % maxLevelCell % array
+      maxLevelEdgeTop =&gt; grid % maxLevelEdgeTop % array
+      maxLevelEdgeBot =&gt; grid % maxLevelEdgeBot % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      dcEdge =&gt; grid % dcEdge % array
+      areaCell =&gt; grid % areaCell % array
+
+      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 next deeper z-level,
+      ! in state % rhoDisplaced
+!maltrud make sure rho is current--check this for redundancy
+!     call OcnEquationOfStateRho(grid, 'relative', 0, indexT, indexS, &amp;
+!              tracers, rho, err) 
+      ! mrp 110324 In order to visualize rhoDisplaced, include the following
+!     call OcnEquationOfStateRho(grid, 'relative', 1, indexT, indexS, &amp;
+!              tracers, rhoDisplaced, err) 
+
+
+      ! drhoTopOfCell(k) = $\rho^*_{k-1}-\rho^*_k$
+      drhoTopOfCell = 0.0
+      do iCell=1,nCells
+         do k=2,maxLevelCell(iCell)
+            drhoTopOfCell(k,iCell) = rho(k-1,iCell) - rhoDisplaced(k-1,iCell)
+          end do
+      end do
+
+      ! interpolate drhoTopOfCell to drhoTopOfEdge
+      drhoTopOfEdge = 0.0
+      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
+
+      ! 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
+
+      deallocate(drhoTopOfCell, drhoTopOfEdge, &amp;
+        du2TopOfCell, du2TopOfEdge)
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_get_rich_numbers!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_rich_init
+!
+!&gt; \brief   Initializes ocean momentum vertical mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  vertical velocity mixing in the ocean. Since a variety of 
+!&gt;  parameterizations are available, this routine primarily calls the
+!&gt;  individual init routines for each parameterization. 
+!
+!-----------------------------------------------------------------------
+
+
+   subroutine ocn_vmix_coefs_rich_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      richViscOn = .false.
+      richDiffOn = .false.
+
+      if (config_vert_visc_type.eq.'rich') then
+          richViscOn = .true.
+      endif
+
+      if (config_vert_diff_type.eq.'rich') then
+          richDiffOn = .true.
+      endif
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_rich_init!}}}
+
+!***********************************************************************
+
+end module ocn_vmix_coefs_rich
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

Copied: trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_tanh.F (from rev 1045, branches/ocean_projects/performance/src/core_ocean/mpas_ocn_vmix_coefs_tanh.F)
===================================================================
--- trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_tanh.F                                (rev 0)
+++ trunk/mpas/src/core_ocean/mpas_ocn_vmix_coefs_tanh.F        2011-09-30 18:04:47 UTC (rev 1046)
@@ -0,0 +1,329 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_vmix_coefs_tanh
+!
+!&gt; \brief MPAS ocean vertical mixing coefficients
+!&gt; \author Doug Jacobsen
+!&gt; \date   19 September 2011
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains the routines for computing 
+!&gt;  tanhant vertical mixing coefficients.  
+!&gt;
+!
+!-----------------------------------------------------------------------
+
+module ocn_vmix_coefs_tanh
+
+   use grid_types
+   use configure
+   use timer
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: ocn_vmix_coefs_tanh_build, &amp;
+             ocn_vmix_coefs_tanh_init
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+   logical :: tanhViscOn, tanhDiffOn
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_tanh_build
+!
+!&gt; \brief   Computes coefficients for vertical mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the vertical mixing coefficients for momentum
+!&gt;  and tracers based user choices of mixing parameterization.
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vmix_coefs_tanh_build(grid, s, d, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (state_type), intent(inout) :: &amp;
+         s             !&lt; Input/Output: state information
+
+      type (diagnostics_type), intent(inout) :: &amp;
+         d             !&lt; Input/Output: diagnostic information
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: err1, err2
+
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        vertViscTopOfEdge, vertDiffTopOfCell
+
+      !-----------------------------------------------------------------
+      !
+      ! call relevant routines for computing tendencies
+      ! note that the user can choose multiple options and the 
+      !   tendencies will be added together
+      !
+      !-----------------------------------------------------------------
+
+      err = 0
+      if((.not.tanhViscOn) .and. (.not.tanhDiffOn)) return
+
+      vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
+      vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
+
+      call ocn_vel_vmix_coefs_tanh(grid, vertViscTopOfEdge, err1)
+      call ocn_tracer_vmix_coefs_tanh(grid, vertDiffTopOfCell, err2)
+
+      err = err1 .or. err2
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_tanh_build!}}}
+
+!***********************************************************************
+!
+!  routine ocn_vel_vmix_coefs_tanh
+!
+!&gt; \brief   Computes coefficients for vertical momentum mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tanh vertical mixing coefficients for momentum
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_vel_vmix_coefs_tanh(grid, vertViscTopOfEdge, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertViscTopOfEdge !&lt; Output: Vertical viscosity
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: k, nVertLevels
+
+      real (kind=RKIND), dimension(:), pointer :: zTopZLevel
+
+      err = 0
+
+      if(.not.tanhViscOn) return
+
+      nVertLevels = grid % nVertLevels
+      zTopZLevel =&gt; grid % zTopZLevel % array
+
+      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
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vel_vmix_coefs_tanh!}}}
+
+!***********************************************************************
+!
+!  routine ocn_tracer_vmix_coefs_tanh
+!
+!&gt; \brief   Computes coefficients for vertical tracer mixing
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the tanh vertical mixing coefficients for tracers
+!
+!-----------------------------------------------------------------------
+
+   subroutine ocn_tracer_vmix_coefs_tanh(grid, vertDiffTopOfCell, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(in) :: &amp;
+         grid          !&lt; Input: grid information
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:), intent(out) :: vertDiffTopOfCell !&lt; Output: Vertical diffusion
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+
+      integer :: k, nVertLevels
+
+      real (kind=RKIND), dimension(:), pointer :: zTopZLevel
+
+      err = 0
+
+      if(.not.tanhDiffOn) return
+
+      nVertLevels = grid % nVertLevels
+      zTopZLevel =&gt; grid % zTopZLevel % array
+
+      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
+
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_tracer_vmix_coefs_tanh!}}}
+
+
+!***********************************************************************
+!
+!  routine ocn_vmix_coefs_tanh_init
+!
+!&gt; \brief   Initializes ocean vertical mixing quantities
+!&gt; \author  Doug Jacobsen
+!&gt; \date    19 September 2011
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine initializes a variety of quantities related to 
+!&gt;  tanh vertical mixing in the ocean. 
+!
+!-----------------------------------------------------------------------
+
+
+   subroutine ocn_vmix_coefs_tanh_init(err)!{{{
+
+   !--------------------------------------------------------------------
+
+      !-----------------------------------------------------------------
+      !
+      ! call individual init routines for each parameterization
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: error flag
+
+      err = 0
+
+      tanhViscOn = .false.
+      tanhDiffOn = .false.
+
+      if (config_vert_visc_type.eq.'tanh') then
+          tanhViscOn = .true.
+      endif
+
+      if (config_vert_diff_type.eq.'tanh') then
+          tanhDiffOn = .true.
+      endif
+
+      if(tanhViscOn .or. tanhDiffOn) 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'
+            err = 1
+         endif
+      endif
+
+   !--------------------------------------------------------------------
+
+   end subroutine ocn_vmix_coefs_tanh_init!}}}
+
+!***********************************************************************
+
+end module ocn_vmix_coefs_tanh
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+! vim: foldmethod=marker

</font>
</pre>