MOM6
mom_dynamics_unsplit Module Reference

Detailed Description

Time steps the ocean dynamics with an unsplit quasi 3rd order scheme.

Data Types

type  mom_dyn_unsplit_cs
 MOM_dynamics_unsplit module control structure. More...
 

Functions/Subroutines

subroutine, public step_mom_dyn_unsplit (u, v, h, tv, visc, Time_local, dt, forces, p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, US, CS, VarMix, MEKE, Waves)
 Step the MOM6 dynamics using an unsplit mixed 2nd order (for continuity) and 3rd order (for the inviscid momentum equations) order scheme. More...
 
subroutine, public register_restarts_dyn_unsplit (HI, GV, param_file, CS, restart_CS)
 Allocate the control structure for this module, allocates memory in it, and registers any auxiliary restart variables that are specific to the unsplit time stepping scheme. More...
 
subroutine, public initialize_dyn_unsplit (u, v, h, Time, G, GV, US, param_file, diag, CS, restart_CS, Accel_diag, Cont_diag, MIS, MEKE, OBC, update_OBC_CSp, ALE_CSp, setVisc_CSp, visc, dirs, ntrunc, cont_stencil)
 Initialize parameters and allocate memory associated with the unsplit dynamics module. More...
 
subroutine, public end_dyn_unsplit (CS)
 Clean up and deallocate memory associated with the unsplit dynamics module. More...
 

Variables

integer id_clock_cor
 CPU time clock IDs.
 
integer id_clock_pres
 CPU time clock IDs.
 
integer id_clock_vertvisc
 CPU time clock IDs.
 
integer id_clock_continuity
 CPU time clock IDs.
 
integer id_clock_horvisc
 CPU time clock IDs.
 
integer id_clock_mom_update
 CPU time clock IDs.
 
integer id_clock_pass
 CPU time clock IDs.
 
integer id_clock_pass_init
 CPU time clock IDs.
 

Function/Subroutine Documentation

◆ end_dyn_unsplit()

subroutine, public mom_dynamics_unsplit::end_dyn_unsplit ( type(mom_dyn_unsplit_cs), pointer  CS)

Clean up and deallocate memory associated with the unsplit dynamics module.

Parameters
csunsplit dynamics control structure that will be deallocated in this subroutine.

Definition at line 708 of file MOM_dynamics_unsplit.F90.

709  type(MOM_dyn_unsplit_CS), pointer :: CS !< unsplit dynamics control structure that
710  !! will be deallocated in this subroutine.
711 
712  dealloc_(cs%diffu) ; dealloc_(cs%diffv)
713  dealloc_(cs%CAu) ; dealloc_(cs%CAv)
714  dealloc_(cs%PFu) ; dealloc_(cs%PFv)
715 
716  deallocate(cs)

◆ initialize_dyn_unsplit()

subroutine, public mom_dynamics_unsplit::initialize_dyn_unsplit ( real, dimension( g %isdb: g %iedb, g %jsd: g %jed, g %ke), intent(inout)  u,
real, dimension( g %isd: g %ied, g %jsdb: g %jedb, g %ke), intent(inout)  v,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(inout)  h,
type(time_type), intent(in), target  Time,
type(ocean_grid_type), intent(inout)  G,
type(verticalgrid_type), intent(in)  GV,
type(unit_scale_type), intent(in)  US,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout), target  diag,
type(mom_dyn_unsplit_cs), pointer  CS,
type(mom_restart_cs), pointer  restart_CS,
type(accel_diag_ptrs), intent(inout), target  Accel_diag,
type(cont_diag_ptrs), intent(inout), target  Cont_diag,
type(ocean_internal_state), intent(inout)  MIS,
type(meke_type), pointer  MEKE,
type(ocean_obc_type), pointer  OBC,
type(update_obc_cs), pointer  update_OBC_CSp,
type(ale_cs), pointer  ALE_CSp,
type(set_visc_cs), pointer  setVisc_CSp,
type(vertvisc_type), intent(inout)  visc,
type(directories), intent(in)  dirs,
integer, intent(inout), target  ntrunc,
integer, intent(out), optional  cont_stencil 
)

Initialize parameters and allocate memory associated with the unsplit dynamics module.

Parameters
[in,out]gThe ocean's grid structure.
[in]gvThe ocean's vertical grid structure.
[in]usA dimensional unit scaling type
[in,out]uThe zonal velocity [L T-1 ~> m s-1].
[in,out]vThe meridional velocity [L T-1 ~> m s-1].
[in,out]hLayer thicknesses [H ~> m or kg m-2]
[in]timeThe current model time.
[in]param_fileA structure to parse for run-time parameters.
[in,out]diagA structure that is used to regulate diagnostic output.
csThe control structure set up by initialize_dyn_unsplit.
restart_csA pointer to the restart control structure.
[in,out]accel_diagA set of pointers to the various accelerations in the momentum equations, which can be used for later derived diagnostics, like energy budgets.
[in,out]cont_diagA structure with pointers to various terms in the continuity equations.
[in,out]misThe "MOM6 Internal State" structure, used to pass around pointers to various arrays for diagnostic purposes.
mekeMEKE data
obcIf open boundary conditions are used, this points to the ocean_OBC_type that was set up in MOM_initialization.
update_obc_cspIf open boundary condition updates are used, this points to the appropriate control structure.
ale_cspThis points to the ALE control structure.
setvisc_cspThis points to the set_visc control structure.
[in,out]viscA structure containing vertical viscosities, bottom drag viscosities, and related fields.
[in]dirsA structure containing several relevant directory paths.
[in,out]ntruncA target for the variable that records the number of times the velocity is truncated (this should be 0).
[out]cont_stencilThe stencil for thickness from the continuity solver.

Definition at line 556 of file MOM_dynamics_unsplit.F90.

560  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
561  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
562  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
563  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
564  intent(inout) :: u !< The zonal velocity [L T-1 ~> m s-1].
565  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
566  intent(inout) :: v !< The meridional velocity [L T-1 ~> m s-1].
567  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) , &
568  intent(inout) :: h !< Layer thicknesses [H ~> m or kg m-2]
569  type(time_type), target, intent(in) :: Time !< The current model time.
570  type(param_file_type), intent(in) :: param_file !< A structure to parse
571  !! for run-time parameters.
572  type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to
573  !! regulate diagnostic output.
574  type(MOM_dyn_unsplit_CS), pointer :: CS !< The control structure set up
575  !! by initialize_dyn_unsplit.
576  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control
577  !!structure.
578  type(accel_diag_ptrs), target, intent(inout) :: Accel_diag !< A set of pointers to the various
579  !! accelerations in the momentum equations, which can be used
580  !! for later derived diagnostics, like energy budgets.
581  type(cont_diag_ptrs), target, intent(inout) :: Cont_diag !< A structure with pointers to
582  !! various terms in the continuity
583  !! equations.
584  type(ocean_internal_state), intent(inout) :: MIS !< The "MOM6 Internal State"
585  !! structure, used to pass around pointers
586  !! to various arrays for diagnostic purposes.
587  type(MEKE_type), pointer :: MEKE !< MEKE data
588  type(ocean_OBC_type), pointer :: OBC !< If open boundary conditions are
589  !! used, this points to the ocean_OBC_type
590  !! that was set up in MOM_initialization.
591  type(update_OBC_CS), pointer :: update_OBC_CSp !< If open boundary condition
592  !! updates are used, this points to
593  !! the appropriate control structure.
594  type(ALE_CS), pointer :: ALE_CSp !< This points to the ALE control
595  !! structure.
596  type(set_visc_CS), pointer :: setVisc_CSp !< This points to the set_visc
597  !! control structure.
598  type(vertvisc_type), intent(inout) :: visc !< A structure containing vertical
599  !! viscosities, bottom drag
600  !! viscosities, and related fields.
601  type(directories), intent(in) :: dirs !< A structure containing several
602  !! relevant directory paths.
603  integer, target, intent(inout) :: ntrunc !< A target for the variable that
604  !! records the number of times the velocity
605  !! is truncated (this should be 0).
606  integer, optional, intent(out) :: cont_stencil !< The stencil for thickness
607  !! from the continuity solver.
608 
609  ! This subroutine initializes all of the variables that are used by this
610  ! dynamic core, including diagnostics and the cpu clocks.
611 
612  ! Local variables
613  character(len=40) :: mdl = "MOM_dynamics_unsplit" ! This module's name.
614  character(len=48) :: thickness_units, flux_units
615  ! This include declares and sets the variable "version".
616 # include "version_variable.h"
617  real :: H_convert
618  logical :: use_tides
619  integer :: isd, ied, jsd, jed, nz, IsdB, IedB, JsdB, JedB
620  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
621  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
622 
623  if (.not.associated(cs)) call mom_error(fatal, &
624  "initialize_dyn_unsplit called with an unassociated control structure.")
625  if (cs%module_is_initialized) then
626  call mom_error(warning, "initialize_dyn_unsplit called with a control "// &
627  "structure that has already been initialized.")
628  return
629  endif
630  cs%module_is_initialized = .true.
631 
632  cs%diag => diag
633 
634  call log_version(param_file, mdl, version, "")
635  call get_param(param_file, mdl, "FIX_UNSPLIT_DT_VISC_BUG", cs%use_correct_dt_visc, &
636  "If true, use the correct timestep in the viscous terms applied in the first "//&
637  "predictor step with the unsplit time stepping scheme, and in the calculation "//&
638  "of the turbulent mixed layer properties for viscosity with unsplit or "//&
639  "unsplit_RK2.", default=.true.)
640  call get_param(param_file, mdl, "DEBUG", cs%debug, &
641  "If true, write out verbose debugging data.", &
642  default=.false., debuggingparam=.true.)
643  call get_param(param_file, mdl, "TIDES", use_tides, &
644  "If true, apply tidal momentum forcing.", default=.false.)
645 
646  allocate(cs%taux_bot(isdb:iedb,jsd:jed)) ; cs%taux_bot(:,:) = 0.0
647  allocate(cs%tauy_bot(isd:ied,jsdb:jedb)) ; cs%tauy_bot(:,:) = 0.0
648 
649  mis%diffu => cs%diffu ; mis%diffv => cs%diffv
650  mis%PFu => cs%PFu ; mis%PFv => cs%PFv
651  mis%CAu => cs%CAu ; mis%CAv => cs%CAv
652 
653  cs%ADp => accel_diag ; cs%CDp => cont_diag
654  accel_diag%diffu => cs%diffu ; accel_diag%diffv => cs%diffv
655  accel_diag%PFu => cs%PFu ; accel_diag%PFv => cs%PFv
656  accel_diag%CAu => cs%CAu ; accel_diag%CAv => cs%CAv
657 
658  call continuity_init(time, g, gv, us, param_file, diag, cs%continuity_CSp)
659  if (present(cont_stencil)) cont_stencil = continuity_stencil(cs%continuity_CSp)
660  call coriolisadv_init(time, g, gv, us, param_file, diag, cs%ADp, cs%CoriolisAdv_CSp)
661  if (use_tides) call tidal_forcing_init(time, g, param_file, cs%tides_CSp)
662  call pressureforce_init(time, g, gv, us, param_file, diag, cs%PressureForce_CSp, &
663  cs%tides_CSp)
664  call hor_visc_init(time, g, us, param_file, diag, cs%hor_visc_CSp, meke)
665  call vertvisc_init(mis, time, g, gv, us, param_file, diag, cs%ADp, dirs, &
666  ntrunc, cs%vertvisc_CSp)
667  if (.not.associated(setvisc_csp)) call mom_error(fatal, &
668  "initialize_dyn_unsplit called with setVisc_CSp unassociated.")
669  cs%set_visc_CSp => setvisc_csp
670 
671  if (associated(ale_csp)) cs%ALE_CSp => ale_csp
672  if (associated(obc)) cs%OBC => obc
673  if (associated(update_obc_csp)) cs%update_OBC_CSp => update_obc_csp
674 
675  flux_units = get_flux_units(gv)
676  h_convert = gv%H_to_m ; if (.not.gv%Boussinesq) h_convert = gv%H_to_kg_m2
677  cs%id_uh = register_diag_field('ocean_model', 'uh', diag%axesCuL, time, &
678  'Zonal Thickness Flux', flux_units, y_cell_method='sum', v_extensive=.true., &
679  conversion=h_convert*us%L_to_m**2*us%s_to_T)
680  cs%id_vh = register_diag_field('ocean_model', 'vh', diag%axesCvL, time, &
681  'Meridional Thickness Flux', flux_units, x_cell_method='sum', v_extensive=.true., &
682  conversion=h_convert*us%L_to_m**2*us%s_to_T)
683  cs%id_CAu = register_diag_field('ocean_model', 'CAu', diag%axesCuL, time, &
684  'Zonal Coriolis and Advective Acceleration', 'm s-2', &
685  conversion=us%L_T2_to_m_s2)
686  cs%id_CAv = register_diag_field('ocean_model', 'CAv', diag%axesCvL, time, &
687  'Meridional Coriolis and Advective Acceleration', 'm s-2', &
688  conversion=us%L_T2_to_m_s2)
689  cs%id_PFu = register_diag_field('ocean_model', 'PFu', diag%axesCuL, time, &
690  'Zonal Pressure Force Acceleration', 'm s-2', &
691  conversion=us%L_T2_to_m_s2)
692  cs%id_PFv = register_diag_field('ocean_model', 'PFv', diag%axesCvL, time, &
693  'Meridional Pressure Force Acceleration', 'm s-2', &
694  conversion=us%L_T2_to_m_s2)
695 
696  id_clock_cor = cpu_clock_id('(Ocean Coriolis & mom advection)', grain=clock_module)
697  id_clock_continuity = cpu_clock_id('(Ocean continuity equation)', grain=clock_module)
698  id_clock_pres = cpu_clock_id('(Ocean pressure force)', grain=clock_module)
699  id_clock_vertvisc = cpu_clock_id('(Ocean vertical viscosity)', grain=clock_module)
700  id_clock_horvisc = cpu_clock_id('(Ocean horizontal viscosity)', grain=clock_module)
701  id_clock_mom_update = cpu_clock_id('(Ocean momentum increments)', grain=clock_module)
702  id_clock_pass = cpu_clock_id('(Ocean message passing)', grain=clock_module)
703  id_clock_pass_init = cpu_clock_id('(Ocean init message passing)', grain=clock_routine)
704 

◆ register_restarts_dyn_unsplit()

subroutine, public mom_dynamics_unsplit::register_restarts_dyn_unsplit ( type(hor_index_type), intent(in)  HI,
type(verticalgrid_type), intent(in)  GV,
type(param_file_type), intent(in)  param_file,
type(mom_dyn_unsplit_cs), pointer  CS,
type(mom_restart_cs), pointer  restart_CS 
)

Allocate the control structure for this module, allocates memory in it, and registers any auxiliary restart variables that are specific to the unsplit time stepping scheme.

All variables registered here should have the ability to be recreated if they are not present in a restart file.

Parameters
[in]hiA horizontal index type structure.
[in]gvThe ocean's vertical grid structure.
[in]param_fileA structure to parse for run-time parameters.
csThe control structure set up by initialize_dyn_unsplit.
restart_csA pointer to the restart control structure.

Definition at line 517 of file MOM_dynamics_unsplit.F90.

518  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure.
519  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
520  type(param_file_type), intent(in) :: param_file !< A structure to parse for
521  !! run-time parameters.
522  type(MOM_dyn_unsplit_CS), pointer :: CS !< The control structure set up by
523  !! initialize_dyn_unsplit.
524  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control structure.
525 
526  ! Local arguments
527  character(len=40) :: mdl = "MOM_dynamics_unsplit" ! This module's name.
528  character(len=48) :: thickness_units, flux_units
529  integer :: isd, ied, jsd, jed, nz, IsdB, IedB, JsdB, JedB
530  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
531  isdb = hi%IsdB ; iedb = hi%IedB ; jsdb = hi%JsdB ; jedb = hi%JedB
532 
533  ! This is where a control structure that is specific to this module is allocated.
534  if (associated(cs)) then
535  call mom_error(warning, "register_restarts_dyn_unsplit called with an associated "// &
536  "control structure.")
537  return
538  endif
539  allocate(cs)
540 
541  alloc_(cs%diffu(isdb:iedb,jsd:jed,nz)) ; cs%diffu(:,:,:) = 0.0
542  alloc_(cs%diffv(isd:ied,jsdb:jedb,nz)) ; cs%diffv(:,:,:) = 0.0
543  alloc_(cs%CAu(isdb:iedb,jsd:jed,nz)) ; cs%CAu(:,:,:) = 0.0
544  alloc_(cs%CAv(isd:ied,jsdb:jedb,nz)) ; cs%CAv(:,:,:) = 0.0
545  alloc_(cs%PFu(isdb:iedb,jsd:jed,nz)) ; cs%PFu(:,:,:) = 0.0
546  alloc_(cs%PFv(isd:ied,jsdb:jedb,nz)) ; cs%PFv(:,:,:) = 0.0
547 
548  thickness_units = get_thickness_units(gv)
549  flux_units = get_flux_units(gv)
550 
551 ! No extra restart fields are needed with this time stepping scheme.
552 

◆ step_mom_dyn_unsplit()

subroutine, public mom_dynamics_unsplit::step_mom_dyn_unsplit ( real, dimension(szib_(g),szj_(g),szk_(g)), intent(inout)  u,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(inout)  v,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(inout)  h,
type(thermo_var_ptrs), intent(in)  tv,
type(vertvisc_type), intent(inout)  visc,
type(time_type), intent(in)  Time_local,
real, intent(in)  dt,
type(mech_forcing), intent(in)  forces,
real, dimension(:,:), pointer  p_surf_begin,
real, dimension(:,:), pointer  p_surf_end,
real, dimension(szib_(g),szj_(g),szk_(g)), intent(inout)  uh,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(inout)  vh,
real, dimension(szib_(g),szj_(g),szk_(g)), intent(inout)  uhtr,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(inout)  vhtr,
real, dimension(szi_(g),szj_(g)), intent(out)  eta_av,
type(ocean_grid_type), intent(inout)  G,
type(verticalgrid_type), intent(in)  GV,
type(unit_scale_type), intent(in)  US,
type(mom_dyn_unsplit_cs), pointer  CS,
type(varmix_cs), pointer  VarMix,
type(meke_type), pointer  MEKE,
type(wave_parameters_cs), optional, pointer  Waves 
)

Step the MOM6 dynamics using an unsplit mixed 2nd order (for continuity) and 3rd order (for the inviscid momentum equations) order scheme.

Parameters
[in,out]gThe ocean's grid structure.
[in]gvThe ocean's vertical grid structure.
[in]usA dimensional unit scaling type
[in,out]uThe zonal velocity [L T-1 ~> m s-1].
[in,out]vThe meridional velocity [L T-1 ~> m s-1].
[in,out]hLayer thicknesses [H ~> m or kg m-2].
[in]tvA structure pointing to various thermodynamic variables.
[in,out]viscA structure containing vertical viscosities, bottom drag viscosities, and related fields.
[in]time_localThe model time at the end of the time step.
[in]dtThe dynamics time step [T ~> s].
[in]forcesA structure with the driving mechanical forces
p_surf_beginA pointer (perhaps NULL) to the surface pressure at the start of this dynamic step [R L2 T-2 ~> Pa].
p_surf_endA pointer (perhaps NULL) to the surface pressure at the end of this dynamic step [R L2 T-2 ~> Pa].
[in,out]uhThe zonal volume or mass transport [H L2 T-1 ~> m3 s-1 or kg s-1].
[in,out]vhThe meridional volume or mass transport [H L2 T-1 ~> m3 s-1 or kg s-1].
[in,out]uhtrThe accumulated zonal volume or mass transport since the last tracer advection [H L2 ~> m3 or kg].
[in,out]vhtrThe accumulated meridional volume or mass transport since the last tracer advection [H L2 ~> m3 or kg].
[out]eta_avThe time-mean free surface height or column mass [H ~> m or kg m-2].
csThe control structure set up by initialize_dyn_unsplit.
varmixA pointer to a structure with fields that specify the spatially variable viscosities.
mekeA pointer to a structure containing fields related to the Mesoscale Eddy Kinetic Energy.
wavesA pointer to a structure containing fields related to the surface wave conditions

Definition at line 189 of file MOM_dynamics_unsplit.F90.

192  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
193  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
194  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
195  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: u !< The zonal velocity [L T-1 ~> m s-1].
196  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: v !< The meridional velocity [L T-1 ~> m s-1].
197  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thicknesses [H ~> m or kg m-2].
198  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
199  !! thermodynamic variables.
200  type(vertvisc_type), intent(inout) :: visc !< A structure containing vertical
201  !! viscosities, bottom drag viscosities, and related fields.
202  type(time_type), intent(in) :: Time_local !< The model time at the end
203  !! of the time step.
204  real, intent(in) :: dt !< The dynamics time step [T ~> s].
205  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
206  real, dimension(:,:), pointer :: p_surf_begin !< A pointer (perhaps NULL) to the surface
207  !! pressure at the start of this dynamic step [R L2 T-2 ~> Pa].
208  real, dimension(:,:), pointer :: p_surf_end !< A pointer (perhaps NULL) to the surface
209  !! pressure at the end of this dynamic step [R L2 T-2 ~> Pa].
210  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uh !< The zonal volume or mass transport
211  !! [H L2 T-1 ~> m3 s-1 or kg s-1].
212  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vh !< The meridional volume or mass
213  !! transport [H L2 T-1 ~> m3 s-1 or kg s-1].
214  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uhtr !< The accumulated zonal volume or mass
215  !! transport since the last tracer advection [H L2 ~> m3 or kg].
216  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vhtr !< The accumulated meridional volume or mass
217  !! transport since the last tracer advection [H L2 ~> m3 or kg].
218  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: eta_av !< The time-mean free surface height or
219  !! column mass [H ~> m or kg m-2].
220  type(MOM_dyn_unsplit_CS), pointer :: CS !< The control structure set up by
221  !! initialize_dyn_unsplit.
222  type(VarMix_CS), pointer :: VarMix !< A pointer to a structure with fields
223  !! that specify the spatially variable viscosities.
224  type(MEKE_type), pointer :: MEKE !< A pointer to a structure containing
225  !! fields related to the Mesoscale Eddy Kinetic Energy.
226  type(wave_parameters_CS), optional, pointer :: Waves !< A pointer to a structure containing
227  !! fields related to the surface wave conditions
228 
229  ! Local variables
230  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_av, hp ! Prediced or averaged layer thicknesses [H ~> m or kg m-2]
231  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: up, upp ! Predicted zonal velocities [L T-1 ~> m s-1]
232  real, dimension(SZI_(G),SZJB_(G),SZK_(G)) :: vp, vpp ! Predicted meridional velocities [L T-1 ~> m s-1]
233  real, dimension(:,:), pointer :: p_surf => null()
234  real :: dt_pred ! The time step for the predictor part of the baroclinic time stepping [T ~> s].
235  real :: dt_visc ! The time step for a part of the update due to viscosity [T ~> s].
236  logical :: dyn_p_surf
237  integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
238  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
239  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
240  dt_pred = dt / 3.0
241 
242  h_av(:,:,:) = 0; hp(:,:,:) = 0
243  up(:,:,:) = 0; upp(:,:,:) = 0
244  vp(:,:,:) = 0; vpp(:,:,:) = 0
245 
246  dyn_p_surf = associated(p_surf_begin) .and. associated(p_surf_end)
247  if (dyn_p_surf) then
248  call safe_alloc_ptr(p_surf,g%isd,g%ied,g%jsd,g%jed) ; p_surf(:,:) = 0.0
249  else
250  p_surf => forces%p_surf
251  endif
252 
253 ! Matsuno's third order accurate three step scheme is used to step
254 ! all of the fields except h. h is stepped separately.
255 
256  if (cs%debug) then
257  call mom_state_chksum("Start First Predictor ", u, v, h, uh, vh, g, gv, us)
258  endif
259 
260 ! diffu = horizontal viscosity terms (u,h)
261  call enable_averages(dt, time_local, cs%diag)
262  call cpu_clock_begin(id_clock_horvisc)
263  call horizontal_viscosity(u, v, h, cs%diffu, cs%diffv, meke, varmix, g, gv, us, cs%hor_visc_CSp)
264  call cpu_clock_end(id_clock_horvisc)
265  call disable_averaging(cs%diag)
266 
267 ! uh = u*h
268 ! hp = h + dt/2 div . uh
269  call cpu_clock_begin(id_clock_continuity)
270  call continuity(u, v, h, hp, uh, vh, dt*0.5, g, gv, us, cs%continuity_CSp, obc=cs%OBC)
271  call cpu_clock_end(id_clock_continuity)
272  call pass_var(hp, g%Domain, clock=id_clock_pass)
273  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
274 
275  call enable_averages(0.5*dt, time_local-real_to_time(0.5*us%T_to_s*dt), cs%diag)
276 ! Here the first half of the thickness fluxes are offered for averaging.
277  if (cs%id_uh > 0) call post_data(cs%id_uh, uh, cs%diag)
278  if (cs%id_vh > 0) call post_data(cs%id_vh, vh, cs%diag)
279  call disable_averaging(cs%diag)
280 
281 ! h_av = (h + hp)/2
282 ! u = u + dt diffu
283  call cpu_clock_begin(id_clock_mom_update)
284  do k=1,nz
285  do j=js-2,je+2 ; do i=is-2,ie+2
286  h_av(i,j,k) = (h(i,j,k) + hp(i,j,k)) * 0.5
287  enddo ; enddo
288  do j=js,je ; do i=isq,ieq
289  u(i,j,k) = u(i,j,k) + dt * cs%diffu(i,j,k) * g%mask2dCu(i,j)
290  enddo ; enddo
291  do j=jsq,jeq ; do i=is,ie
292  v(i,j,k) = v(i,j,k) + dt * cs%diffv(i,j,k) * g%mask2dCv(i,j)
293  enddo ; enddo
294  do j=js-2,je+2 ; do i=isq-2,ieq+2
295  uhtr(i,j,k) = uhtr(i,j,k) + 0.5*dt*uh(i,j,k)
296  enddo ; enddo
297  do j=jsq-2,jeq+2 ; do i=is-2,ie+2
298  vhtr(i,j,k) = vhtr(i,j,k) + 0.5*dt*vh(i,j,k)
299  enddo ; enddo
300  enddo
301  call cpu_clock_end(id_clock_mom_update)
302  call pass_vector(u, v, g%Domain, clock=id_clock_pass)
303 
304 ! CAu = -(f+zeta)/h_av vh + d/dx KE
305  call cpu_clock_begin(id_clock_cor)
306  call coradcalc(u, v, h_av, uh, vh, cs%CAu, cs%CAv, cs%OBC, cs%ADp, &
307  g, gv, us, cs%CoriolisAdv_CSp)
308  call cpu_clock_end(id_clock_cor)
309 
310 ! PFu = d/dx M(h_av,T,S)
311  call cpu_clock_begin(id_clock_pres)
312  if (dyn_p_surf) then ; do j=js-2,je+2 ; do i=is-2,ie+2
313  p_surf(i,j) = 0.75*p_surf_begin(i,j) + 0.25*p_surf_end(i,j)
314  enddo ; enddo ; endif
315  call pressureforce(h_av, tv, cs%PFu, cs%PFv, g, gv, us, &
316  cs%PressureForce_CSp, cs%ALE_CSp, p_surf)
317  call cpu_clock_end(id_clock_pres)
318 
319  if (associated(cs%OBC)) then; if (cs%OBC%update_OBC) then
320  call update_obc_data(cs%OBC, g, gv, us, tv, h, cs%update_OBC_CSp, time_local)
321  endif; endif
322  if (associated(cs%OBC)) then
323  call open_boundary_zero_normal_flow(cs%OBC, g, cs%PFu, cs%PFv)
324  call open_boundary_zero_normal_flow(cs%OBC, g, cs%CAu, cs%CAv)
325  endif
326 
327 ! up = u + dt_pred * (PFu + CAu)
328  call cpu_clock_begin(id_clock_mom_update)
329  do k=1,nz ; do j=js,je ; do i=isq,ieq
330  up(i,j,k) = g%mask2dCu(i,j) * (u(i,j,k) + dt_pred * (cs%PFu(i,j,k) + cs%CAu(i,j,k)))
331  enddo ; enddo ; enddo
332  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
333  vp(i,j,k) = g%mask2dCv(i,j) * (v(i,j,k) + dt_pred * (cs%PFv(i,j,k) + cs%CAv(i,j,k)))
334  enddo ; enddo ; enddo
335  call cpu_clock_end(id_clock_mom_update)
336 
337  if (cs%debug) then
338  call mom_state_chksum("Predictor 1", up, vp, h_av, uh, vh, g, gv, us)
339  call mom_accel_chksum("Predictor 1 accel", cs%CAu, cs%CAv, cs%PFu, cs%PFv, &
340  cs%diffu, cs%diffv, g, gv, us)
341  endif
342 
343  ! up <- up + dt/2 d/dz visc d/dz up
344  call cpu_clock_begin(id_clock_vertvisc)
345  call enable_averages(dt, time_local, cs%diag)
346  dt_visc = 0.5*dt ; if (cs%use_correct_dt_visc) dt_visc = dt
347  call set_viscous_ml(u, v, h_av, tv, forces, visc, dt_visc, g, gv, us, cs%set_visc_CSp)
348  call disable_averaging(cs%diag)
349 
350  dt_visc = 0.5*dt ; if (cs%use_correct_dt_visc) dt_visc = dt_pred
351  call vertvisc_coef(up, vp, h_av, forces, visc, dt_visc, g, gv, us, cs%vertvisc_CSp, cs%OBC)
352  call vertvisc(up, vp, h_av, forces, visc, dt_visc, cs%OBC, cs%ADp, cs%CDp, &
353  g, gv, us, cs%vertvisc_CSp, waves=waves)
354  call cpu_clock_end(id_clock_vertvisc)
355  call pass_vector(up, vp, g%Domain, clock=id_clock_pass)
356 
357 ! uh = up * hp
358 ! h_av = hp + dt/2 div . uh
359  call cpu_clock_begin(id_clock_continuity)
360  call continuity(up, vp, hp, h_av, uh, vh, (0.5*dt), g, gv, us, cs%continuity_CSp, obc=cs%OBC)
361  call cpu_clock_end(id_clock_continuity)
362  call pass_var(h_av, g%Domain, clock=id_clock_pass)
363  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
364 
365 ! h_av <- (hp + h_av)/2
366  do k=1,nz ; do j=js-2,je+2 ; do i=is-2,ie+2
367  h_av(i,j,k) = (hp(i,j,k) + h_av(i,j,k)) * 0.5
368  enddo ; enddo ; enddo
369 
370 ! CAu = -(f+zeta(up))/h_av vh + d/dx KE(up)
371  call cpu_clock_begin(id_clock_cor)
372  call coradcalc(up, vp, h_av, uh, vh, cs%CAu, cs%CAv, cs%OBC, cs%ADp, &
373  g, gv, us, cs%CoriolisAdv_CSp)
374  call cpu_clock_end(id_clock_cor)
375 
376 ! PFu = d/dx M(h_av,T,S)
377  call cpu_clock_begin(id_clock_pres)
378  if (dyn_p_surf) then ; do j=js-2,je+2 ; do i=is-2,ie+2
379  p_surf(i,j) = 0.25*p_surf_begin(i,j) + 0.75*p_surf_end(i,j)
380  enddo ; enddo ; endif
381  call pressureforce(h_av, tv, cs%PFu, cs%PFv, g, gv, us, &
382  cs%PressureForce_CSp, cs%ALE_CSp, p_surf)
383  call cpu_clock_end(id_clock_pres)
384 
385  if (associated(cs%OBC)) then; if (cs%OBC%update_OBC) then
386  call update_obc_data(cs%OBC, g, gv, us, tv, h, cs%update_OBC_CSp, time_local)
387  endif; endif
388  if (associated(cs%OBC)) then
389  call open_boundary_zero_normal_flow(cs%OBC, g, cs%PFu, cs%PFv)
390  call open_boundary_zero_normal_flow(cs%OBC, g, cs%CAu, cs%CAv)
391  endif
392 
393 ! upp = u + dt/2 * ( PFu + CAu )
394  call cpu_clock_begin(id_clock_mom_update)
395  do k=1,nz ; do j=js,je ; do i=isq,ieq
396  upp(i,j,k) = g%mask2dCu(i,j) * (u(i,j,k) + dt * 0.5 * (cs%PFu(i,j,k) + cs%CAu(i,j,k)))
397  enddo ; enddo ; enddo
398  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
399  vpp(i,j,k) = g%mask2dCv(i,j) * (v(i,j,k) + dt * 0.5 * (cs%PFv(i,j,k) + cs%CAv(i,j,k)))
400  enddo ; enddo ; enddo
401  call cpu_clock_end(id_clock_mom_update)
402 
403  if (cs%debug) then
404  call mom_state_chksum("Predictor 2", upp, vpp, h_av, uh, vh, g, gv, us)
405  call mom_accel_chksum("Predictor 2 accel", cs%CAu, cs%CAv, cs%PFu, cs%PFv, &
406  cs%diffu, cs%diffv, g, gv, us)
407  endif
408 
409 ! upp <- upp + dt/2 d/dz visc d/dz upp
410  call cpu_clock_begin(id_clock_vertvisc)
411  call vertvisc_coef(upp, vpp, hp, forces, visc, dt*0.5, g, gv, us, cs%vertvisc_CSp, cs%OBC)
412  call vertvisc(upp, vpp, hp, forces, visc, dt*0.5, cs%OBC, cs%ADp, cs%CDp, &
413  g, gv, us, cs%vertvisc_CSp, waves=waves)
414  call cpu_clock_end(id_clock_vertvisc)
415  call pass_vector(upp, vpp, g%Domain, clock=id_clock_pass)
416 
417 ! uh = upp * hp
418 ! h = hp + dt/2 div . uh
419  call cpu_clock_begin(id_clock_continuity)
420  call continuity(upp, vpp, hp, h, uh, vh, (dt*0.5), g, gv, us, cs%continuity_CSp, obc=cs%OBC)
421  call cpu_clock_end(id_clock_continuity)
422  call pass_var(h, g%Domain, clock=id_clock_pass)
423  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
424  ! Whenever thickness changes let the diag manager know, target grids
425  ! for vertical remapping may need to be regenerated.
426  call diag_update_remap_grids(cs%diag)
427 
428  call enable_averages(0.5*dt, time_local, cs%diag)
429 ! Here the second half of the thickness fluxes are offered for averaging.
430  if (cs%id_uh > 0) call post_data(cs%id_uh, uh, cs%diag)
431  if (cs%id_vh > 0) call post_data(cs%id_vh, vh, cs%diag)
432  call disable_averaging(cs%diag)
433  call enable_averages(dt, time_local, cs%diag)
434 
435 ! h_av = (h + hp)/2
436  do k=1,nz
437  do j=js-2,je+2 ; do i=is-2,ie+2
438  h_av(i,j,k) = 0.5*(h(i,j,k) + hp(i,j,k))
439  enddo ; enddo
440  do j=js-2,je+2 ; do i=isq-2,ieq+2
441  uhtr(i,j,k) = uhtr(i,j,k) + 0.5*dt*uh(i,j,k)
442  enddo ; enddo
443  do j=jsq-2,jeq+2 ; do i=is-2,ie+2
444  vhtr(i,j,k) = vhtr(i,j,k) + 0.5*dt*vh(i,j,k)
445  enddo ; enddo
446  enddo
447 
448 ! CAu = -(f+zeta(upp))/h_av vh + d/dx KE(upp)
449  call cpu_clock_begin(id_clock_cor)
450  call coradcalc(upp, vpp, h_av, uh, vh, cs%CAu, cs%CAv, cs%OBC, cs%ADp, &
451  g, gv, us, cs%CoriolisAdv_CSp)
452  call cpu_clock_end(id_clock_cor)
453 
454 ! PFu = d/dx M(h_av,T,S)
455  call cpu_clock_begin(id_clock_pres)
456  call pressureforce(h_av, tv, cs%PFu, cs%PFv, g, gv, us, &
457  cs%PressureForce_CSp, cs%ALE_CSp, p_surf)
458  call cpu_clock_end(id_clock_pres)
459 
460  if (associated(cs%OBC)) then; if (cs%OBC%update_OBC) then
461  call update_obc_data(cs%OBC, g, gv, us, tv, h, cs%update_OBC_CSp, time_local)
462  endif; endif
463 
464 ! u = u + dt * ( PFu + CAu )
465  if (associated(cs%OBC)) then
466  call open_boundary_zero_normal_flow(cs%OBC, g, cs%PFu, cs%PFv)
467  call open_boundary_zero_normal_flow(cs%OBC, g, cs%CAu, cs%CAv)
468  endif
469  do k=1,nz ; do j=js,je ; do i=isq,ieq
470  u(i,j,k) = g%mask2dCu(i,j) * (u(i,j,k) + dt * (cs%PFu(i,j,k) + cs%CAu(i,j,k)))
471  enddo ; enddo ; enddo
472  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
473  v(i,j,k) = g%mask2dCv(i,j) * (v(i,j,k) + dt * (cs%PFv(i,j,k) + cs%CAv(i,j,k)))
474  enddo ; enddo ; enddo
475 
476 ! u <- u + dt d/dz visc d/dz u
477  call cpu_clock_begin(id_clock_vertvisc)
478  call vertvisc_coef(u, v, h_av, forces, visc, dt, g, gv, us, cs%vertvisc_CSp, cs%OBC)
479  call vertvisc(u, v, h_av, forces, visc, dt, cs%OBC, cs%ADp, cs%CDp, &
480  g, gv, us, cs%vertvisc_CSp, cs%taux_bot, cs%tauy_bot, waves=waves)
481  call cpu_clock_end(id_clock_vertvisc)
482  call pass_vector(u, v, g%Domain, clock=id_clock_pass)
483 
484  if (cs%debug) then
485  call mom_state_chksum("Corrector", u, v, h, uh, vh, g, gv, us)
486  call mom_accel_chksum("Corrector accel", cs%CAu, cs%CAv, cs%PFu, cs%PFv, &
487  cs%diffu, cs%diffv, g, gv, us)
488  endif
489 
490  if (gv%Boussinesq) then
491  do j=js,je ; do i=is,ie ; eta_av(i,j) = -gv%Z_to_H*g%bathyT(i,j) ; enddo ; enddo
492  else
493  do j=js,je ; do i=is,ie ; eta_av(i,j) = 0.0 ; enddo ; enddo
494  endif
495  do k=1,nz ; do j=js,je ; do i=is,ie
496  eta_av(i,j) = eta_av(i,j) + h_av(i,j,k)
497  enddo ; enddo ; enddo
498 
499  if (dyn_p_surf) deallocate(p_surf)
500 
501 ! Here various terms used in to update the momentum equations are
502 ! offered for averaging.
503  if (cs%id_PFu > 0) call post_data(cs%id_PFu, cs%PFu, cs%diag)
504  if (cs%id_PFv > 0) call post_data(cs%id_PFv, cs%PFv, cs%diag)
505  if (cs%id_CAu > 0) call post_data(cs%id_CAu, cs%CAu, cs%diag)
506  if (cs%id_CAv > 0) call post_data(cs%id_CAv, cs%CAv, cs%diag)
507