MOM6
mom_dynamics_unsplit_rk2 Module Reference

Detailed Description

Time steps the ocean dynamics with an unsplit quasi 2nd order Runge-Kutta scheme.

Data Types

type  mom_dyn_unsplit_rk2_cs
 MOM_dynamics_unsplit_RK2 module control structure. More...
 
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_horvisc
 CPU time clock IDs.
 
integer id_clock_continuity
 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.
 
subroutine, public step_mom_dyn_unsplit_rk2 (u_in, v_in, h_in, tv, visc, Time_local, dt, forces, p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, US, CS, VarMix, MEKE)
 Step the MOM6 dynamics using an unsplit quasi-2nd order Runge-Kutta scheme. More...
 
subroutine, public register_restarts_dyn_unsplit_rk2 (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 RK2 time stepping scheme. More...
 
subroutine, public initialize_dyn_unsplit_rk2 (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)
 Initialize parameters and allocate memory associated with the unsplit RK2 dynamics module. More...
 
subroutine, public end_dyn_unsplit_rk2 (CS)
 Clean up and deallocate memory associated with the dyn_unsplit_RK2 module. More...
 

Function/Subroutine Documentation

◆ end_dyn_unsplit_rk2()

subroutine, public mom_dynamics_unsplit_rk2::end_dyn_unsplit_rk2 ( type(mom_dyn_unsplit_rk2_cs), pointer  CS)

Clean up and deallocate memory associated with the dyn_unsplit_RK2 module.

Parameters
csdyn_unsplit_RK2 control structure that will be deallocated in this subroutine.

Definition at line 658 of file MOM_dynamics_unsplit_RK2.F90.

658  type(MOM_dyn_unsplit_RK2_CS), pointer :: CS !< dyn_unsplit_RK2 control structure that
659  !! will be deallocated in this subroutine.
660 
661  dealloc_(cs%diffu) ; dealloc_(cs%diffv)
662  dealloc_(cs%CAu) ; dealloc_(cs%CAv)
663  dealloc_(cs%PFu) ; dealloc_(cs%PFv)
664 
665  deallocate(cs)

◆ initialize_dyn_unsplit_rk2()

subroutine, public mom_dynamics_unsplit_rk2::initialize_dyn_unsplit_rk2 ( 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_rk2_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 
)

Initialize parameters and allocate memory associated with the unsplit RK2 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 [m s-1].
[in,out]vThe meridional velocity [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_RK2.
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).

Definition at line 511 of file MOM_dynamics_unsplit_RK2.F90.

511  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
512  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
513  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
514  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: u !< The zonal velocity [m s-1].
515  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: v !< The meridional velocity [m s-1].
516  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) , intent(inout) :: h !< Layer thicknesses [H ~> m or kg m-2]
517  type(time_type), target, intent(in) :: Time !< The current model time.
518  type(param_file_type), intent(in) :: param_file !< A structure to parse
519  !! for run-time parameters.
520  type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to
521  !! regulate diagnostic output.
522  type(MOM_dyn_unsplit_RK2_CS), pointer :: CS !< The control structure set up
523  !! by initialize_dyn_unsplit_RK2.
524  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart
525  !! control structure.
526  type(accel_diag_ptrs), target, intent(inout) :: Accel_diag !< A set of pointers to the
527  !! various accelerations in the momentum equations, which can
528  !! be used for later derived diagnostics, like energy budgets.
529  type(cont_diag_ptrs), target, intent(inout) :: Cont_diag !< A structure with pointers
530  !! to various terms in the
531  !! continuity equations.
532  type(ocean_internal_state), intent(inout) :: MIS !< The "MOM6 Internal State"
533  !! structure, used to pass around pointers
534  !! to various arrays for diagnostic purposes.
535  type(MEKE_type), pointer :: MEKE !< MEKE data
536  type(ocean_OBC_type), pointer :: OBC !< If open boundary conditions
537  !! are used, this points to the ocean_OBC_type
538  !! that was set up in MOM_initialization.
539  type(update_OBC_CS), pointer :: update_OBC_CSp !< If open boundary
540  !! condition updates are used, this points
541  !! to the appropriate control structure.
542  type(ALE_CS), pointer :: ALE_CSp !< This points to the ALE
543  !! control structure.
544  type(set_visc_CS), pointer :: setVisc_CSp !< This points to the
545  !! set_visc control
546  !! structure.
547  type(vertvisc_type), intent(inout) :: visc !< A structure containing
548  !! vertical viscosities, bottom drag
549  !! viscosities, and related fields.
550  type(directories), intent(in) :: dirs !< A structure containing several
551  !! relevant directory paths.
552  integer, target, intent(inout) :: ntrunc !< A target for the variable
553  !! that records the number of times the
554  !! velocity is truncated (this should be 0).
555 
556  ! This subroutine initializes all of the variables that are used by this
557  ! dynamic core, including diagnostics and the cpu clocks.
558 
559  ! Local varaibles
560  character(len=40) :: mdl = "MOM_dynamics_unsplit_RK2" ! This module's name.
561  character(len=48) :: thickness_units, flux_units
562  real :: H_convert
563  logical :: use_tides
564  integer :: isd, ied, jsd, jed, nz, IsdB, IedB, JsdB, JedB
565  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
566  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
567 
568  if (.not.associated(cs)) call mom_error(fatal, &
569  "initialize_dyn_unsplit_RK2 called with an unassociated control structure.")
570  if (cs%module_is_initialized) then
571  call mom_error(warning, "initialize_dyn_unsplit_RK2 called with a control "// &
572  "structure that has already been initialized.")
573  return
574  endif
575  cs%module_is_initialized = .true.
576 
577  cs%diag => diag
578 
579  call get_param(param_file, mdl, "BE", cs%be, &
580  "If SPLIT is true, BE determines the relative weighting "//&
581  "of a 2nd-order Runga-Kutta baroclinic time stepping "//&
582  "scheme (0.5) and a backward Euler scheme (1) that is "//&
583  "used for the Coriolis and inertial terms. BE may be "//&
584  "from 0.5 to 1, but instability may occur near 0.5. "//&
585  "BE is also applicable if SPLIT is false and USE_RK2 "//&
586  "is true.", units="nondim", default=0.6)
587  call get_param(param_file, mdl, "BEGW", cs%begw, &
588  "If SPLIT is true, BEGW is a number from 0 to 1 that "//&
589  "controls the extent to which the treatment of gravity "//&
590  "waves is forward-backward (0) or simulated backward "//&
591  "Euler (1). 0 is almost always used. "//&
592  "If SPLIT is false and USE_RK2 is true, BEGW can be "//&
593  "between 0 and 0.5 to damp gravity waves.", &
594  units="nondim", default=0.0)
595  call get_param(param_file, mdl, "DEBUG", cs%debug, &
596  "If true, write out verbose debugging data.", &
597  default=.false., debuggingparam=.true.)
598  call get_param(param_file, mdl, "TIDES", use_tides, &
599  "If true, apply tidal momentum forcing.", default=.false.)
600 
601  allocate(cs%taux_bot(isdb:iedb,jsd:jed)) ; cs%taux_bot(:,:) = 0.0
602  allocate(cs%tauy_bot(isd:ied,jsdb:jedb)) ; cs%tauy_bot(:,:) = 0.0
603 
604  mis%diffu => cs%diffu ; mis%diffv => cs%diffv
605  mis%PFu => cs%PFu ; mis%PFv => cs%PFv
606  mis%CAu => cs%CAu ; mis%CAv => cs%CAv
607 
608  cs%ADp => accel_diag ; cs%CDp => cont_diag
609  accel_diag%diffu => cs%diffu ; accel_diag%diffv => cs%diffv
610  accel_diag%PFu => cs%PFu ; accel_diag%PFv => cs%PFv
611  accel_diag%CAu => cs%CAu ; accel_diag%CAv => cs%CAv
612 
613  call continuity_init(time, g, gv, param_file, diag, cs%continuity_CSp)
614  call coriolisadv_init(time, g, param_file, diag, cs%ADp, cs%CoriolisAdv_CSp)
615  if (use_tides) call tidal_forcing_init(time, g, param_file, cs%tides_CSp)
616  call pressureforce_init(time, g, gv, us, param_file, diag, cs%PressureForce_CSp, &
617  cs%tides_CSp)
618  call hor_visc_init(time, g, us, param_file, diag, cs%hor_visc_CSp, meke)
619  call vertvisc_init(mis, time, g, gv, us, param_file, diag, cs%ADp, dirs, &
620  ntrunc, cs%vertvisc_CSp)
621  if (.not.associated(setvisc_csp)) call mom_error(fatal, &
622  "initialize_dyn_unsplit_RK2 called with setVisc_CSp unassociated.")
623  cs%set_visc_CSp => setvisc_csp
624 
625  if (associated(ale_csp)) cs%ALE_CSp => ale_csp
626  if (associated(obc)) cs%OBC => obc
627 
628  flux_units = get_flux_units(gv)
629  h_convert = gv%H_to_m ; if (.not.gv%Boussinesq) h_convert = gv%H_to_kg_m2
630  cs%id_uh = register_diag_field('ocean_model', 'uh', diag%axesCuL, time, &
631  'Zonal Thickness Flux', flux_units, y_cell_method='sum', v_extensive=.true., &
632  conversion=h_convert)
633  cs%id_vh = register_diag_field('ocean_model', 'vh', diag%axesCvL, time, &
634  'Meridional Thickness Flux', flux_units, x_cell_method='sum', v_extensive=.true., &
635  conversion=h_convert)
636  cs%id_CAu = register_diag_field('ocean_model', 'CAu', diag%axesCuL, time, &
637  'Zonal Coriolis and Advective Acceleration', 'meter second-2')
638  cs%id_CAv = register_diag_field('ocean_model', 'CAv', diag%axesCvL, time, &
639  'Meridional Coriolis and Advective Acceleration', 'meter second-2')
640  cs%id_PFu = register_diag_field('ocean_model', 'PFu', diag%axesCuL, time, &
641  'Zonal Pressure Force Acceleration', 'meter second-2')
642  cs%id_PFv = register_diag_field('ocean_model', 'PFv', diag%axesCvL, time, &
643  'Meridional Pressure Force Acceleration', 'meter second-2')
644 
645  id_clock_cor = cpu_clock_id('(Ocean Coriolis & mom advection)', grain=clock_module)
646  id_clock_continuity = cpu_clock_id('(Ocean continuity equation)', grain=clock_module)
647  id_clock_pres = cpu_clock_id('(Ocean pressure force)', grain=clock_module)
648  id_clock_vertvisc = cpu_clock_id('(Ocean vertical viscosity)', grain=clock_module)
649  id_clock_horvisc = cpu_clock_id('(Ocean horizontal viscosity)', grain=clock_module)
650  id_clock_mom_update = cpu_clock_id('(Ocean momentum increments)', grain=clock_module)
651  id_clock_pass = cpu_clock_id('(Ocean message passing)', grain=clock_module)
652  id_clock_pass_init = cpu_clock_id('(Ocean init message passing)', grain=clock_routine)
653 

◆ register_restarts_dyn_unsplit_rk2()

subroutine, public mom_dynamics_unsplit_rk2::register_restarts_dyn_unsplit_rk2 ( 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_rk2_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 RK2 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_RK2.
restart_csA pointer to the restart control structure.

Definition at line 466 of file MOM_dynamics_unsplit_RK2.F90.

466  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure.
467  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
468  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time
469  !! parameters.
470  type(MOM_dyn_unsplit_RK2_CS), pointer :: CS !< The control structure set up by
471  !! initialize_dyn_unsplit_RK2.
472  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control
473  !! structure.
474 ! This subroutine sets up any auxiliary restart variables that are specific
475 ! to the unsplit time stepping scheme. All variables registered here should
476 ! have the ability to be recreated if they are not present in a restart file.
477 
478  ! Local variables
479  character(len=48) :: thickness_units, flux_units
480  integer :: isd, ied, jsd, jed, nz, IsdB, IedB, JsdB, JedB
481  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
482  isdb = hi%IsdB ; iedb = hi%IedB ; jsdb = hi%JsdB ; jedb = hi%JedB
483 
484 ! This is where a control structure that is specific to this module would be allocated.
485  if (associated(cs)) then
486  call mom_error(warning, "register_restarts_dyn_unsplit_RK2 called with an associated "// &
487  "control structure.")
488  return
489  endif
490  allocate(cs)
491 
492  alloc_(cs%diffu(isdb:iedb,jsd:jed,nz)) ; cs%diffu(:,:,:) = 0.0
493  alloc_(cs%diffv(isd:ied,jsdb:jedb,nz)) ; cs%diffv(:,:,:) = 0.0
494  alloc_(cs%CAu(isdb:iedb,jsd:jed,nz)) ; cs%CAu(:,:,:) = 0.0
495  alloc_(cs%CAv(isd:ied,jsdb:jedb,nz)) ; cs%CAv(:,:,:) = 0.0
496  alloc_(cs%PFu(isdb:iedb,jsd:jed,nz)) ; cs%PFu(:,:,:) = 0.0
497  alloc_(cs%PFv(isd:ied,jsdb:jedb,nz)) ; cs%PFv(:,:,:) = 0.0
498 
499  thickness_units = get_thickness_units(gv)
500  flux_units = get_flux_units(gv)
501 
502 ! No extra restart fields are needed with this time stepping scheme.
503 

◆ step_mom_dyn_unsplit_rk2()

subroutine, public mom_dynamics_unsplit_rk2::step_mom_dyn_unsplit_rk2 ( real, dimension(szib_(g),szj_(g),szk_(g)), intent(inout)  u_in,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(inout)  v_in,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(inout)  h_in,
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_rk2_cs), pointer  CS,
type(varmix_cs), pointer  VarMix,
type(meke_type), pointer  MEKE 
)

Step the MOM6 dynamics using an unsplit quasi-2nd order Runge-Kutta scheme.

Parameters
[in,out]gThe ocean's grid structure.
[in]gvThe ocean's vertical grid structure.
[in]usA dimensional unit scaling type
[in,out]u_inThe input and output zonal velocity [m s-1].
[in,out]v_inThe input and output meridional velocity [m s-1].
[in,out]h_inThe input and output layer thicknesses, [H ~> m or kg m-2], depending on whether the Boussinesq approximation is made.
[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 baroclinic dynamics time step [s].
[in]forcesA structure with the driving mechanical forces
p_surf_beginA pointer (perhaps NULL) to the surface pressure at the beginning of this dynamic step [Pa].
p_surf_endA pointer (perhaps NULL) to the surface pressure at the end of this dynamic step [Pa].
[in,out]uhThe zonal volume or mass transport [H m2 s-1 ~> m3 or kg s-1].
[in,out]vhThe meridional volume or mass transport [H m2 s-1 ~> m3 or kg s-1].
[in,out]uhtrThe accumulated zonal volume or mass transport since the last tracer advection [H m2 ~> m3 or kg].
[in,out]vhtrThe accumulated meridional volume or mass transport since the last tracer advection [H m2 ~> 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_RK2.
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.

Definition at line 190 of file MOM_dynamics_unsplit_RK2.F90.

190  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
191  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
192  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
193  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: u_in !< The input and output zonal
194  !! velocity [m s-1].
195  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: v_in !< The input and output meridional
196  !! velocity [m s-1].
197  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h_in !< The input and output layer thicknesses,
198  !! [H ~> m or kg m-2], depending on whether
199  !! the Boussinesq approximation is made.
200  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
201  !! thermodynamic variables.
202  type(vertvisc_type), intent(inout) :: visc !< A structure containing vertical
203  !! viscosities, bottom drag
204  !! viscosities, and related fields.
205  type(time_type), intent(in) :: Time_local !< The model time at the end of
206  !! the time step.
207  real, intent(in) :: dt !< The baroclinic dynamics time step [s].
208  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
209  real, dimension(:,:), pointer :: p_surf_begin !< A pointer (perhaps NULL) to
210  !! the surface pressure at the beginning
211  !! of this dynamic step [Pa].
212  real, dimension(:,:), pointer :: p_surf_end !< A pointer (perhaps NULL) to
213  !! the surface pressure at the end of
214  !! this dynamic step [Pa].
215  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uh !< The zonal volume or mass transport
216  !! [H m2 s-1 ~> m3 or kg s-1].
217  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vh !< The meridional volume or mass
218  !! transport [H m2 s-1 ~> m3 or kg s-1].
219  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uhtr !< The accumulated zonal volume or
220  !! mass transport since the last
221  !! tracer advection [H m2 ~> m3 or kg].
222  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vhtr !< The accumulated meridional volume
223  !! or mass transport since the last
224  !! tracer advection [H m2 ~> m3 or kg].
225  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: eta_av !< The time-mean free surface height
226  !! or column mass [H ~> m or kg m-2].
227  type(MOM_dyn_unsplit_RK2_CS), pointer :: CS !< The control structure set up by
228  !! initialize_dyn_unsplit_RK2.
229  type(VarMix_CS), pointer :: VarMix !< A pointer to a structure with
230  !! fields that specify the spatially
231  !! variable viscosities.
232  type(MEKE_type), pointer :: MEKE !< A pointer to a structure containing
233  !! fields related to the Mesoscale
234  !! Eddy Kinetic Energy.
235  ! Local variables
236  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_av, hp
237  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: up
238  real, dimension(SZI_(G),SZJB_(G),SZK_(G)) :: vp
239  real, dimension(:,:), pointer :: p_surf => null()
240  real :: dt_pred ! The time step for the predictor part of the baroclinic
241  ! time stepping.
242  logical :: dyn_p_surf
243  integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
244  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
245  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
246  dt_pred = dt * cs%BE
247 
248  h_av(:,:,:) = 0; hp(:,:,:) = 0
249  up(:,:,:) = 0
250  vp(:,:,:) = 0
251 
252  dyn_p_surf = associated(p_surf_begin) .and. associated(p_surf_end)
253  if (dyn_p_surf) then
254  call safe_alloc_ptr(p_surf,g%isd,g%ied,g%jsd,g%jed) ; p_surf(:,:) = 0.0
255  else
256  p_surf => forces%p_surf
257  endif
258 
259 ! Runge-Kutta second order accurate two step scheme is used to step
260 ! all of the fields except h. h is stepped separately.
261 
262  if (cs%debug) then
263  call mom_state_chksum("Start Predictor ", u_in, v_in, h_in, uh, vh, g, gv)
264  endif
265 
266 ! diffu = horizontal viscosity terms (u,h)
267  call enable_averaging(dt,time_local, cs%diag)
268  call cpu_clock_begin(id_clock_horvisc)
269  call horizontal_viscosity(u_in, v_in, h_in, cs%diffu, cs%diffv, meke, varmix, &
270  g, gv, us, cs%hor_visc_CSp)
271  call cpu_clock_end(id_clock_horvisc)
272  call disable_averaging(cs%diag)
273  call pass_vector(cs%diffu, cs%diffv, g%Domain, clock=id_clock_pass)
274 
275 ! This continuity step is solely for the Coroilis terms, specifically in the
276 ! denominator of PV and in the mass transport or PV.
277 ! uh = u[n-1]*h[n-1/2]
278 ! hp = h[n-1/2] + dt/2 div . uh
279  call cpu_clock_begin(id_clock_continuity)
280  ! This is a duplicate calculation of the last continuity from the previous step
281  ! and could/should be optimized out. -AJA
282  call continuity(u_in, v_in, h_in, hp, uh, vh, dt_pred, g, gv, us, cs%continuity_CSp, &
283  obc=cs%OBC)
284  call cpu_clock_end(id_clock_continuity)
285  call pass_var(hp, g%Domain, clock=id_clock_pass)
286  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
287 
288 ! h_av = (h + hp)/2 (used in PV denominator)
289  call cpu_clock_begin(id_clock_mom_update)
290  do k=1,nz
291  do j=js-2,je+2 ; do i=is-2,ie+2
292  h_av(i,j,k) = (h_in(i,j,k) + hp(i,j,k)) * 0.5
293  enddo ; enddo ; enddo
294  call cpu_clock_end(id_clock_mom_update)
295 
296 ! CAu = -(f+zeta)/h_av vh + d/dx KE (function of u[n-1] and uh[n-1])
297  call cpu_clock_begin(id_clock_cor)
298  call coradcalc(u_in, v_in, h_av, uh, vh, cs%CAu, cs%CAv, cs%OBC, cs%ADp, &
299  g, gv, us, cs%CoriolisAdv_CSp)
300  call cpu_clock_end(id_clock_cor)
301 
302 ! PFu = d/dx M(h_av,T,S) (function of h[n-1/2])
303  call cpu_clock_begin(id_clock_pres)
304  if (dyn_p_surf) then ; do j=js-2,je+2 ; do i=is-2,ie+2
305  p_surf(i,j) = 0.5*p_surf_begin(i,j) + 0.5*p_surf_end(i,j)
306  enddo ; enddo ; endif
307  call pressureforce(h_in, tv, cs%PFu, cs%PFv, g, gv, us, &
308  cs%PressureForce_CSp, cs%ALE_CSp, p_surf)
309  call cpu_clock_end(id_clock_pres)
310  call pass_vector(cs%PFu, cs%PFv, g%Domain, clock=id_clock_pass)
311  call pass_vector(cs%CAu, cs%CAv, g%Domain, clock=id_clock_pass)
312 
313  if (associated(cs%OBC)) then; if (cs%OBC%update_OBC) then
314  call update_obc_data(cs%OBC, g, gv, us, tv, h_in, cs%update_OBC_CSp, time_local)
315  endif; endif
316  if (associated(cs%OBC)) then
317  call open_boundary_zero_normal_flow(cs%OBC, g, cs%PFu, cs%PFv)
318  call open_boundary_zero_normal_flow(cs%OBC, g, cs%CAu, cs%CAv)
319  call open_boundary_zero_normal_flow(cs%OBC, g, cs%diffu, cs%diffv)
320  endif
321 
322 ! up+[n-1/2] = u[n-1] + dt_pred * (PFu + CAu)
323  call cpu_clock_begin(id_clock_mom_update)
324  do k=1,nz ; do j=js,je ; do i=isq,ieq
325  up(i,j,k) = g%mask2dCu(i,j) * (u_in(i,j,k) + dt_pred * &
326  ((cs%PFu(i,j,k) + cs%CAu(i,j,k)) + us%s_to_T*cs%diffu(i,j,k)))
327  enddo ; enddo ; enddo
328  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
329  vp(i,j,k) = g%mask2dCv(i,j) * (v_in(i,j,k) + dt_pred * &
330  ((cs%PFv(i,j,k) + cs%CAv(i,j,k)) + us%s_to_T*cs%diffv(i,j,k)))
331  enddo ; enddo ; enddo
332  call cpu_clock_end(id_clock_mom_update)
333 
334  if (cs%debug) &
335  call mom_accel_chksum("Predictor 1 accel", cs%CAu, cs%CAv, cs%PFu, cs%PFv,&
336  cs%diffu, cs%diffv, g, gv, us)
337 
338  ! up[n-1/2] <- up*[n-1/2] + dt/2 d/dz visc d/dz up[n-1/2]
339  call cpu_clock_begin(id_clock_vertvisc)
340  call enable_averaging(dt, time_local, cs%diag)
341  call set_viscous_ml(up, vp, h_av, tv, forces, visc, dt_pred, g, gv, us, &
342  cs%set_visc_CSp)
343  call disable_averaging(cs%diag)
344  call vertvisc_coef(up, vp, h_av, forces, visc, dt_pred, g, gv, us, &
345  cs%vertvisc_CSp, cs%OBC)
346  call vertvisc(up, vp, h_av, forces, visc, dt_pred, cs%OBC, cs%ADp, cs%CDp, &
347  g, gv, us, cs%vertvisc_CSp)
348  call cpu_clock_end(id_clock_vertvisc)
349  call pass_vector(up, vp, g%Domain, clock=id_clock_pass)
350 
351 ! uh = up[n-1/2] * h[n-1/2]
352 ! h_av = h + dt div . uh
353  call cpu_clock_begin(id_clock_continuity)
354  call continuity(up, vp, h_in, hp, uh, vh, &
355  dt, g, gv, us, cs%continuity_CSp, obc=cs%OBC)
356  call cpu_clock_end(id_clock_continuity)
357  call pass_var(hp, g%Domain, clock=id_clock_pass)
358  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
359 
360 ! h_av <- (h + hp)/2 (centered at n-1/2)
361  do k=1,nz ; do j=js-2,je+2 ; do i=is-2,ie+2
362  h_av(i,j,k) = (h_in(i,j,k) + hp(i,j,k)) * 0.5
363  enddo ; enddo ; enddo
364 
365  if (cs%debug) &
366  call mom_state_chksum("Predictor 1", up, vp, h_av, uh, vh, g, gv)
367 
368 ! CAu = -(f+zeta(up))/h_av vh + d/dx KE(up) (function of up[n-1/2], h[n-1/2])
369  call cpu_clock_begin(id_clock_cor)
370  call coradcalc(up, vp, h_av, uh, vh, cs%CAu, cs%CAv, cs%OBC, cs%ADp, &
371  g, gv, us, cs%CoriolisAdv_CSp)
372  call cpu_clock_end(id_clock_cor)
373  if (associated(cs%OBC)) then
374  call open_boundary_zero_normal_flow(cs%OBC, g, cs%CAu, cs%CAv)
375  endif
376 
377 ! call enable_averaging(dt,Time_local, CS%diag) ?????????????????????/
378 
379 ! up* = u[n] + (1+gamma) * dt * ( PFu + CAu ) Extrapolated for damping
380 ! u*[n+1] = u[n] + dt * ( PFu + CAu )
381  do k=1,nz ; do j=js,je ; do i=isq,ieq
382  up(i,j,k) = g%mask2dCu(i,j) * (u_in(i,j,k) + dt * (1.+cs%begw) * &
383  ((cs%PFu(i,j,k) + cs%CAu(i,j,k)) + us%s_to_T*cs%diffu(i,j,k)))
384  u_in(i,j,k) = g%mask2dCu(i,j) * (u_in(i,j,k) + dt * &
385  ((cs%PFu(i,j,k) + cs%CAu(i,j,k)) + us%s_to_T*cs%diffu(i,j,k)))
386  enddo ; enddo ; enddo
387  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
388  vp(i,j,k) = g%mask2dCv(i,j) * (v_in(i,j,k) + dt * (1.+cs%begw) * &
389  ((cs%PFv(i,j,k) + cs%CAv(i,j,k)) + us%s_to_T*cs%diffv(i,j,k)))
390  v_in(i,j,k) = g%mask2dCv(i,j) * (v_in(i,j,k) + dt * &
391  ((cs%PFv(i,j,k) + cs%CAv(i,j,k)) + us%s_to_T*cs%diffv(i,j,k)))
392  enddo ; enddo ; enddo
393 
394 ! up[n] <- up* + dt d/dz visc d/dz up
395 ! u[n] <- u*[n] + dt d/dz visc d/dz u[n]
396  call cpu_clock_begin(id_clock_vertvisc)
397  call vertvisc_coef(up, vp, h_av, forces, visc, dt, g, gv, us, &
398  cs%vertvisc_CSp, cs%OBC)
399  call vertvisc(up, vp, h_av, forces, visc, dt, cs%OBC, cs%ADp, cs%CDp, &
400  g, gv, us, cs%vertvisc_CSp, cs%taux_bot, cs%tauy_bot)
401  call vertvisc_coef(u_in, v_in, h_av, forces, visc, dt, g, gv, us, &
402  cs%vertvisc_CSp, cs%OBC)
403  call vertvisc(u_in, v_in, h_av, forces, visc, dt, cs%OBC, cs%ADp, cs%CDp,&
404  g, gv, us, cs%vertvisc_CSp, cs%taux_bot, cs%tauy_bot)
405  call cpu_clock_end(id_clock_vertvisc)
406  call pass_vector(up, vp, g%Domain, clock=id_clock_pass)
407  call pass_vector(u_in, v_in, g%Domain, clock=id_clock_pass)
408 
409 ! uh = up[n] * h[n] (up[n] might be extrapolated to damp GWs)
410 ! h[n+1] = h[n] + dt div . uh
411  call cpu_clock_begin(id_clock_continuity)
412  call continuity(up, vp, h_in, h_in, uh, vh, &
413  dt, g, gv, us, cs%continuity_CSp, obc=cs%OBC)
414  call cpu_clock_end(id_clock_continuity)
415  call pass_var(h_in, g%Domain, clock=id_clock_pass)
416  call pass_vector(uh, vh, g%Domain, clock=id_clock_pass)
417 
418 ! Accumulate mass flux for tracer transport
419  do k=1,nz
420  do j=js-2,je+2 ; do i=isq-2,ieq+2
421  uhtr(i,j,k) = uhtr(i,j,k) + dt*uh(i,j,k)
422  enddo ; enddo
423  do j=jsq-2,jeq+2 ; do i=is-2,ie+2
424  vhtr(i,j,k) = vhtr(i,j,k) + dt*vh(i,j,k)
425  enddo ; enddo
426  enddo
427 
428  if (cs%debug) then
429  call mom_state_chksum("Corrector", u_in, v_in, h_in, uh, vh, g, gv)
430  call mom_accel_chksum("Corrector accel", cs%CAu, cs%CAv, cs%PFu, cs%PFv, &
431  cs%diffu, cs%diffv, g, gv, us)
432  endif
433 
434  if (gv%Boussinesq) then
435  do j=js,je ; do i=is,ie ; eta_av(i,j) = -gv%Z_to_H*g%bathyT(i,j) ; enddo ; enddo
436  else
437  do j=js,je ; do i=is,ie ; eta_av(i,j) = 0.0 ; enddo ; enddo
438  endif
439  do k=1,nz ; do j=js,je ; do i=is,ie
440  eta_av(i,j) = eta_av(i,j) + h_av(i,j,k)
441  enddo ; enddo ; enddo
442 
443  if (dyn_p_surf) deallocate(p_surf)
444 
445 ! Here various terms used in to update the momentum equations are
446 ! offered for averaging.
447  if (cs%id_PFu > 0) call post_data(cs%id_PFu, cs%PFu, cs%diag)
448  if (cs%id_PFv > 0) call post_data(cs%id_PFv, cs%PFv, cs%diag)
449  if (cs%id_CAu > 0) call post_data(cs%id_CAu, cs%CAu, cs%diag)
450  if (cs%id_CAv > 0) call post_data(cs%id_CAv, cs%CAv, cs%diag)
451 
452 ! Here the thickness fluxes are offered for averaging.
453  if (cs%id_uh > 0) call post_data(cs%id_uh, uh, cs%diag)
454  if (cs%id_vh > 0) call post_data(cs%id_vh, vh, cs%diag)
455