MOM6
MOM.F90
Go to the documentation of this file.
1 !> This is the main routine for MOM
2 module mom
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
8 
9 ! A Structure with pointers to forcing fields to drive MOM;
10 ! all fluxes are positive downward.
11 use mom_forcing_type, only : forcing
12 
14 
15 ! A structure containing pointers to various fields
16 ! to describe surface state, and will be returned
17 ! to the calling program.
18 use mom_variables, only : surface
19 
20 ! A structure containing pointers to an assortment of
21 ! thermodynamic fields, including potential/Conservative
22 ! temperature, salinity and mixed layer density.
24 
25 ! Infrastructure modules
26 use mom_debugging, only : mom_debugging_init, hchksum, uvchksum
28 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
29 use mom_cpu_clock, only : clock_component, clock_subcomponent
30 use mom_cpu_clock, only : clock_module_driver, clock_module, clock_routine
31 use mom_coms, only : reproducing_sum
37 use mom_diag_mediator, only : disable_averaging, post_data, safe_alloc_ptr
42 use mom_domains, only : sum_across_pes, pass_var, pass_vector
43 use mom_domains, only : to_north, to_east, to_south, to_west
44 use mom_domains, only : to_all, omit_corners, cgrid_ne, scalar_pair
45 use mom_domains, only : create_group_pass, do_group_pass, group_pass_type
46 use mom_domains, only : start_group_pass, complete_group_pass, omit_corners
47 use mom_error_handler, only : mom_error, fatal, warning, is_root_pe
54 use mom_io, only : mom_io_init, vardesc, var_desc
55 use mom_io, only : slasher, file_exists, read_data
61 use mom_time_manager, only : time_type, set_time, time_type_to_real, operator(+)
62 use mom_time_manager, only : operator(-), operator(>), operator(*), operator(/)
63 use mom_time_manager, only : increment_date
64 use mom_unit_tests, only : unit_tests
65 
66 ! MOM core modules
93 use mom_eos, only : eos_init
94 use mom_eos, only : gsw_sp_from_sr, gsw_pt_from_ct
95 use mom_eos, only : calculate_density
105 use mom_meke_types, only : meke_type
133 ! Offline modules
141 
142 
143 implicit none ; private
144 
145 #include <MOM_memory.h>
146 
147 !> Control structure for this module
148 type, public :: mom_control_struct
149  real allocable_, dimension(NIMEM_,NJMEM_,NKMEM_) :: &
150  h, & !< layer thickness (m or kg/m2 (H))
151  t, & !< potential temperature (degrees C)
152  s !< salinity (ppt)
153  real allocable_, dimension(NIMEMB_PTR_,NJMEM_,NKMEM_) :: &
154  u, & !< zonal velocity component (m/s)
155  uh, & !< uh = u * h * dy at u grid points (m3/s or kg/s)
156  uhtr !< accumulated zonal thickness fluxes to advect tracers (m3 or kg)
157  real allocable_, dimension(NIMEM_,NJMEMB_PTR_,NKMEM_) :: &
158  v, & !< meridional velocity (m/s)
159  vh, & !< vh = v * h * dx at v grid points (m3/s or kg/s)
160  vhtr !< accumulated meridional thickness fluxes to advect tracers (m3 or kg)
161  real allocable_, dimension(NIMEM_,NJMEM_) :: &
162  ave_ssh !< time-averaged (ave over baroclinic time steps) sea surface height (meter)
163  real, pointer, dimension(:,:) :: hml => null() !< active mixed layer depth, in m
164  real, pointer, dimension(:,:,:) :: &
165  u_prev => null(), & !< previous value of u stored for diagnostics
166  v_prev => null() !< previous value of v stored for diagnostics
167 
168  type(ocean_grid_type) :: g !< structure containing metrics and grid info
169  type(verticalgrid_type), pointer :: gv => null() !< structure containing vertical grid info
170  type(thermo_var_ptrs) :: tv !< structure containing pointers to available
171  !! thermodynamic fields
172  type(diag_ctrl) :: diag !< structure to regulate diagnostic output timing
173  type(vertvisc_type) :: visc !< structure containing vertical viscosities,
174  !! bottom drag viscosities, and related fields
175  type(meke_type), pointer :: meke => null() !< structure containing fields
176  !! related to the Mesoscale Eddy Kinetic Energy
177  type(accel_diag_ptrs) :: adp !< structure containing pointers to accelerations,
178  !! for derived diagnostics (e.g., energy budgets)
179  type(cont_diag_ptrs) :: cdp !< structure containing pointers continuity equation
180  !! terms, for derived diagnostics (e.g., energy budgets)
181 
182  logical :: split !< If true, use the split time stepping scheme.
183  logical :: legacy_split !< If true, use the legacy split time stepping
184  !! code with all the options that were available in
185  !! the predecessor isopycnal model "GOLD".
186  logical :: use_rk2 !< If true, use RK2 instead of RK3 in unsplit mode
187  !! (i.e., no split between barotropic and baroclinic).
188  logical :: adiabatic !< If true, then no diapycnal mass fluxes, with no calls
189  !! to routines to calculate or apply diapycnal fluxes.
190  logical :: use_temperature !< If true, temp and saln used as state variables.
191  logical :: calc_rho_for_sea_lev !< If true, calculate rho to convert pressure to sea level
192  logical :: use_frazil !< If true, liquid seawater freezes if temp below freezing,
193  !! with accumulated heat deficit returned to surface ocean.
194  logical :: bound_salinity !< If true, salt is added to keep salinity above
195  !! a minimum value, and the deficit is reported.
196  logical :: bulkmixedlayer !< If true, a refined bulk mixed layer scheme is used
197  !! with nkml sublayers and nkbl buffer layer.
198  logical :: diabatic_first !< If true, apply diabatic and thermodynamic
199  !! processes before time stepping the dynamics.
200  logical :: use_cont_abss !< If true, , the prognostics T&S are the conservative temperature
201  !! and absolute salinity. Care should be taken to convert them
202  !! to potential temperature and practical salinity before
203  !! exchanging them with the coupler and/or reporting T&S diagnostics.
204  logical :: thickness_diffuse !< If true, diffuse interface height w/ a diffusivity KHTH.
205  logical :: thickness_diffuse_first !< If true, diffuse thickness before dynamics.
206  logical :: mixedlayer_restrat !< If true, use submesoscale mixed layer restratifying scheme.
207  logical :: usemeke !< If true, call the MEKE parameterization.
208  logical :: debug !< If true, write verbose checksums for debugging purposes.
209  logical :: debug_truncations !< If true, turn on diagnostics useful for debugging truncations.
210  logical :: use_ale_algorithm !< If true, use the ALE algorithm rather than layered
211  !! isopycnal/stacked shallow water mode. This logical is
212  !! set by calling the function useRegridding() from the
213  !! MOM_regridding module.
214  logical :: do_dynamics !< If false, does not call step_MOM_dyn_*. This is an
215  !! undocumented run-time flag that is fragile.
216  logical :: offline_tracer_mode = .false.
217  !< If true, step_offline() is called instead of step_MOM().
218  !! This is intended for running MOM6 in offline tracer mode
219  logical :: advect_ts !< If false, then no horizontal advection of temperature
220  !! and salnity is performed
221  real :: dt !< (baroclinic) dynamics time step (seconds)
222  real :: dt_therm !< thermodynamics time step (seconds)
223  logical :: thermo_spans_coupling !< If true, thermodynamic and tracer time
224  !! steps can span multiple coupled time steps.
225  real :: t_dyn_rel_adv !< The time of the dynamics relative to tracer
226  !! advection and lateral mixing (in seconds), or
227  !! equivalently the elapsed time since advectively
228  !! updating the tracers. t_dyn_rel_adv is invariably
229  !! positive and may span multiple coupling timesteps.
230  real :: t_dyn_rel_thermo !< The time of the dynamics relative to diabatic
231  !! processes and remapping (in seconds). t_dyn_rel_thermo
232  !! can be negative or positive depending on whether
233  !! the diabatic processes are applied before or after
234  !! the dynamics and may span multiple coupling timesteps.
235  real :: t_dyn_rel_diag !< The time of the diagnostics relative to diabatic
236  !! processes and remapping (in seconds). t_dyn_rel_diag
237  !! is always positive, since the diagnostics must lag.
238  type(time_type) :: z_diag_interval !< amount of time between calculating Z-space diagnostics
239  type(time_type) :: z_diag_time !< next time to compute Z-space diagnostics
240  type(time_type), pointer :: time !< pointer to ocean clock
241  real :: rel_time = 0.0 !< relative time (sec) since start of current execution
242  real :: dtbt_reset_period !< The time interval in seconds between dynamic
243  !! recalculation of the barotropic time step. If
244  !! this is negative, it is never calculated, and
245  !! if it is 0, it is calculated every step.
246 
247  logical :: interp_p_surf !< If true, linearly interpolate surface pressure
248  !! over the coupling time step, using specified value
249  !! at the end of the coupling step. False by default.
250  logical :: p_surf_prev_set !< If true, p_surf_prev has been properly set from
251  !! a previous time-step or the ocean restart file.
252  !! This is only valid when interp_p_surf is true.
253 
254  real :: hmix !< Diagnostic mixed layer thickness (meter) when
255  !! bulk mixed layer is not used.
256  real :: hmix_uv !< Depth scale over which to average surface flow to
257  !! feedback to the coupler/driver (m).
258  !! bulk mixed layer is not used.
259  real :: missing=-1.0e34 !< missing data value for masked fields
260 
261  ! Flags needed to reach between start and finish phases of initialization
262  logical :: write_ic !< If true, then the initial conditions will be written to file
263  character(len=120) :: ic_file !< A file into which the initial conditions are
264  !! written in a new run if SAVE_INITIAL_CONDS is true.
265 
266  integer :: ntrunc !< number u,v truncations since last call to write_energy
267  logical :: check_bad_surface_vals !< If true, scan surface state for ridiculous values.
268  real :: bad_val_ssh_max !< Maximum SSH before triggering bad value message
269  real :: bad_val_sst_max !< Maximum SST before triggering bad value message
270  real :: bad_val_sst_min !< Minimum SST before triggering bad value message
271  real :: bad_val_sss_max !< Maximum SSS before triggering bad value message
272  real :: bad_val_column_thickness!< Minimum column thickness before triggering bad value message
273 
274  real, pointer, dimension(:,:) :: &
275  p_surf_prev => null(), & !< surface pressure (Pa) at end previous call to step_MOM
276  p_surf_begin => null(), & !< surface pressure (Pa) at start of step_MOM_dyn_...
277  p_surf_end => null() !< surface pressure (Pa) at end of step_MOM_dyn_...
278 
279  type(vardesc) :: &
280  vd_t, & !< vardesc array describing potential temperature
281  vd_s !< vardesc array describing salinity
282 
283  real, pointer, dimension(:,:,:) :: & !< diagnostic arrays of advective/diffusive tracer fluxes
284  t_adx => null(), t_ady => null(), t_diffx => null(), t_diffy => null(), &
285  s_adx => null(), s_ady => null(), s_diffx => null(), s_diffy => null()
286 
287  real, pointer, dimension(:,:) :: & !< diagnostic arrays of vertically integrated advective/diffusive fluxes
288  t_adx_2d => null(), t_ady_2d => null(), t_diffx_2d => null(), t_diffy_2d => null(), &
289  s_adx_2d => null(), s_ady_2d => null(), s_diffx_2d => null(), s_diffy_2d => null()
290 
291  real, pointer, dimension(:,:,:) :: & !< diagnostic arrays for advection tendencies and total tendencies
292  t_advection_xy => null(), s_advection_xy => null(), &
293  t_prev => null(), s_prev => null(), &
294  th_prev => null(), sh_prev => null()
295 
296  real, pointer, dimension(:,:,:) :: & !< diagnostic arrays for variance decay through ALE
297  t_squared => null(), s_squared => null()
298 
299  logical :: tendency_diagnostics = .false.
300 
301  ! diagnostic ids
302 
303  ! 3-d state fields
304  integer :: id_u = -1
305  integer :: id_v = -1
306  integer :: id_h = -1
307  integer :: id_t = -1
308  integer :: id_s = -1
309  integer :: id_tcon = -1
310  integer :: id_sabs = -1
311 
312  ! 2-d surface and bottom fields
313  integer :: id_zos = -1
314  integer :: id_zossq = -1
315  integer :: id_volo = -1
316  integer :: id_ssh = -1
317  integer :: id_ssh_ga = -1
318  integer :: id_sst = -1
319  integer :: id_sst_sq = -1
320  integer :: id_sss = -1
321  integer :: id_sss_sq = -1
322  integer :: id_ssu = -1
323  integer :: id_ssv = -1
324  integer :: id_speed = -1
325  integer :: id_ssh_inst = -1
326  integer :: id_tob = -1
327  integer :: id_sob = -1
328  integer :: id_sstcon = -1
329  integer :: id_sssabs = -1
330 
331  ! heat and salt flux fields
332  integer :: id_fraz = -1
333  integer :: id_salt_deficit = -1
334  integer :: id_heat_pme = -1
335  integer :: id_intern_heat = -1
336 
337  ! transport of temperature and salinity
338  integer :: id_tadx = -1
339  integer :: id_tady = -1
340  integer :: id_tdiffx = -1
341  integer :: id_tdiffy = -1
342  integer :: id_sadx = -1
343  integer :: id_sady = -1
344  integer :: id_sdiffx = -1
345  integer :: id_sdiffy = -1
346  integer :: id_tadx_2d = -1
347  integer :: id_tady_2d = -1
348  integer :: id_tdiffx_2d = -1
349  integer :: id_tdiffy_2d = -1
350  integer :: id_sadx_2d = -1
351  integer :: id_sady_2d = -1
352  integer :: id_sdiffx_2d = -1
353  integer :: id_sdiffy_2d = -1
354 
355  ! tendencies for temp/heat and saln/salt
356  integer :: id_t_advection_xy = -1
357  integer :: id_t_advection_xy_2d = -1
358  integer :: id_t_tendency = -1
359  integer :: id_th_tendency = -1
360  integer :: id_th_tendency_2d = -1
361  integer :: id_s_advection_xy = -1
362  integer :: id_s_advection_xy_2d = -1
363  integer :: id_s_tendency = -1
364  integer :: id_sh_tendency = -1
365  integer :: id_sh_tendency_2d = -1
366 
367  ! variance decay for temp and heat
368  integer :: id_t_vardec = -1
369  integer :: id_s_vardec = -1
370 
371  ! fields prior to doing dynamics
372  integer :: id_h_pre_dyn = -1
373 
374  ! diagnostic for fields prior to applying diapycnal physics
375  integer :: id_u_predia = -1
376  integer :: id_v_predia = -1
377  integer :: id_h_predia = -1
378  integer :: id_t_predia = -1
379  integer :: id_s_predia = -1
380  integer :: id_e_predia = -1
381  integer :: id_u_preale = -1
382  integer :: id_v_preale = -1
383  integer :: id_h_preale = -1
384  integer :: id_t_preale = -1
385  integer :: id_s_preale = -1
386  integer :: id_e_preale = -1
387 
388  ! Diagnostics for tracer horizontal transport
389  integer :: id_uhtr = -1, id_umo = -1, id_umo_2d = 1
390  integer :: id_vhtr = -1, id_vmo = -1, id_vmo_2d = 1
391 
392  ! The remainder provides pointers to child module control structures.
393  type(mom_dyn_unsplit_cs), pointer :: dyn_unsplit_csp => null()
394  type(mom_dyn_unsplit_rk2_cs), pointer :: dyn_unsplit_rk2_csp => null()
395  type(mom_dyn_split_rk2_cs), pointer :: dyn_split_rk2_csp => null()
396  type(mom_dyn_legacy_split_cs), pointer :: dyn_legacy_split_csp => null()
397 
398  type(set_visc_cs), pointer :: set_visc_csp => null()
399  type(diabatic_cs), pointer :: diabatic_csp => null()
400  type(thickness_diffuse_cs), pointer :: thickness_diffuse_csp => null()
401  type(mixedlayer_restrat_cs), pointer :: mixedlayer_restrat_csp => null()
402  type(meke_cs), pointer :: meke_csp => null()
403  type(varmix_cs), pointer :: varmix => null()
404  type(tracer_registry_type), pointer :: tracer_reg => null()
405  type(tracer_advect_cs), pointer :: tracer_adv_csp => null()
406  type(tracer_hor_diff_cs), pointer :: tracer_diff_csp => null()
407  type(neutral_diffusion_cs), pointer :: neutral_diffusion_csp => null()
408  type(tracer_flow_control_cs), pointer :: tracer_flow_csp => null()
409  type(diagnostics_cs), pointer :: diagnostics_csp => null()
410  type(diag_to_z_cs), pointer :: diag_to_z_csp => null()
411  type(mom_restart_cs), pointer :: restart_csp => null()
412  type(update_obc_cs), pointer :: update_obc_csp => null()
413  type(ocean_obc_type), pointer :: obc => null()
414  type(sponge_cs), pointer :: sponge_csp => null()
415  type(ale_sponge_cs), pointer :: ale_sponge_csp => null()
416  type(ale_cs), pointer :: ale_csp => null()
417  type(offline_transport_cs), pointer :: offline_csp => null()
418 
419  ! These are used for group halo updates.
420  type(group_pass_type) :: pass_tau_ustar_psurf
421  type(group_pass_type) :: pass_ray
422  type(group_pass_type) :: pass_bbl_thick_kv_bbl
423  type(group_pass_type) :: pass_t_s_h
424  type(group_pass_type) :: pass_t_s
425  type(group_pass_type) :: pass_kv_turb
426  type(group_pass_type) :: pass_uv_t_s_h
427  type(group_pass_type) :: pass_ssh
428 
429 end type mom_control_struct
430 
431 public initialize_mom
433 public step_mom
434 public step_offline
435 public mom_end
437 
438 integer :: id_clock_ocean
440 integer :: id_clock_thermo
441 integer :: id_clock_tracer
443 integer :: id_clock_continuity ! also in dynamics s/r
448 integer :: id_clock_z_diag
449 integer :: id_clock_init
451 integer :: id_clock_pass ! also in dynamics d/r
452 integer :: id_clock_pass_init ! also in dynamics d/r
453 integer :: id_clock_ale
454 integer :: id_clock_other
456 
457 contains
458 
459 
460 !> This subroutine orchestrates the time stepping of MOM. The adiabatic
461 !! dynamics are stepped by calls to one of the step_MOM_dyn_...routines.
462 !! The action of lateral processes on tracers occur in calls to
463 !! advect_tracer and tracer_hordiff. Vertical mixing and possibly remapping
464 !! occur inside of diabatic.
465 subroutine step_mom(fluxes, state, Time_start, time_interval, CS)
466  type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
467  type(surface), intent(inout) :: state !< surface ocean state
468  type(time_type), intent(in) :: Time_start !< starting time of a segment, as a time type
469  real, intent(in) :: time_interval !< time interval covered by this run segment, in s.
470  type(mom_control_struct), pointer :: CS !< control structure from initialize_MOM
471 
472  ! local
473  type(ocean_grid_type), pointer :: G ! pointer to a structure containing
474  ! metrics and related information
475  type(verticalgrid_type), pointer :: GV => null()
476  integer, save :: nt_debug = 1 ! running number of iterations, for debugging only.
477  integer :: ntstep ! time steps between tracer updates or diabatic forcing
478  integer :: n_max ! number of steps to take in this call
479 
480  integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, n
481  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
482 
483  real :: dt ! baroclinic time step (sec)
484  real :: dtth ! time step for thickness diffusion (sec)
485  real :: dtdia ! time step for diabatic processes (sec)
486  real :: dt_therm ! a limited and quantized version of CS%dt_therm (sec)
487  real :: dtbt_reset_time ! value of CS%rel_time when DTBT was last calculated (sec)
488 
489  real :: mass_src_time ! The amount of time for the surface mass source from
490  ! precipitation-evaporation, rivers, etc., that should
491  ! be applied to the start of the barotropic solver to
492  ! avoid generating tsunamis, in s. This is negative
493  ! if the precipation has already been applied to the
494  ! layers, and positive if it will be applied later.
495 
496  real :: wt_end, wt_beg
497  real :: bbl_time_int ! The amount of time over which the calculated BBL
498  ! properties will apply, for use in diagnostics.
499 
500  logical :: calc_dtbt ! Indicates whether the dynamically adjusted
501  ! barotropic time step needs to be updated.
502  logical :: do_advection ! If true, it is time to advect tracers.
503  logical :: do_calc_bbl ! If true, calculate the boundary layer properties.
504  logical :: thermo_does_span_coupling ! If true, thermodynamic forcing spans
505  ! multiple dynamic timesteps.
506  real, dimension(SZI_(CS%G),SZJ_(CS%G)) :: &
507  eta_av, & ! average sea surface height or column mass over a timestep (meter or kg/m2)
508  ssh ! sea surface height based on eta_av (meter or kg/m2)
509 
510  real, pointer, dimension(:,:,:) :: &
511  u, & ! u : zonal velocity component (m/s)
512  v, & ! v : meridional velocity component (m/s)
513  h ! h : layer thickness (meter (Bouss) or kg/m2 (non-Bouss))
514 
515  ! Store the layer thicknesses before any changes by the dynamics. This is necessary for remapped
516  ! mass transport diagnostics
517  real, dimension(SZI_(CS%G),SZJ_(CS%G),SZK_(CS%G)) :: h_pre_dyn
518  real :: tot_wt_ssh, Itot_wt_ssh
519 
520  type(time_type) :: Time_local
521  logical :: showCallTree
522  ! These are used for group halo passes.
523  logical :: do_pass_kv_turb, do_pass_Ray, do_pass_kv_bbl_thick
524 
525  g => cs%G ; gv => cs%GV
526  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
527  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
528  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
529  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
530  u => cs%u ; v => cs%v ; h => cs%h
531 
532  call cpu_clock_begin(id_clock_ocean)
533  call cpu_clock_begin(id_clock_other)
534 
535  if (cs%debug) then
536  call mom_state_chksum("Beginning of step_MOM ", u, v, h, cs%uh, cs%vh, g, gv)
537  call hchksum(cs%h,"CS%h beginning of step_MOM",g%HI, scale=gv%H_to_m)
538  endif
539 
540  showcalltree = calltree_showquery()
541  if (showcalltree) call calltree_enter("step_MOM(), MOM.F90")
542 
543  ! First determine the time step that is consistent with this call.
544  ! It is anticipated that the time step will almost always coincide
545  ! with dt. In addition, ntstep is determined, subject to the constraint
546  ! that ntstep cannot exceed n_max.
547  if (time_interval <= cs%dt) then
548  n_max = 1
549  else
550  n_max = ceiling(time_interval/cs%dt - 0.001)
551  endif
552 
553  dt = time_interval / real(n_max)
554  dtdia = 0.0
555  thermo_does_span_coupling = (cs%thermo_spans_coupling .and. &
556  (cs%dt_therm > 1.5*time_interval))
557  if (thermo_does_span_coupling) then
558  ! Set dt_therm to be an integer multiple of the coupling time step.
559  dt_therm = time_interval * floor(cs%dt_therm / time_interval + 0.001)
560  ntstep = floor(dt_therm/dt + 0.001)
561  else
562  ntstep = max(1,min(n_max,floor(cs%dt_therm/dt + 0.001)))
563  dt_therm = dt*ntstep
564  endif
565 
566  if (.not.ASSOCIATED(fluxes%p_surf)) cs%interp_p_surf = .false.
567 
568  !---------- Begin setup for group halo pass
569 
570  call cpu_clock_begin(id_clock_pass)
571  call create_group_pass(cs%pass_tau_ustar_psurf, fluxes%taux, fluxes%tauy, g%Domain)
572  if (ASSOCIATED(fluxes%ustar)) &
573  call create_group_pass(cs%pass_tau_ustar_psurf, fluxes%ustar(:,:), g%Domain)
574  if (ASSOCIATED(fluxes%p_surf)) &
575  call create_group_pass(cs%pass_tau_ustar_psurf, fluxes%p_surf(:,:), g%Domain)
576 
577  do_pass_ray = .false.
578  if ((.not.g%Domain%symmetric) .and. &
579  associated(cs%visc%Ray_u) .and. associated(cs%visc%Ray_v)) then
580  call create_group_pass(cs%pass_ray, cs%visc%Ray_u, cs%visc%Ray_v, g%Domain, &
581  to_north+to_east+scalar_pair+omit_corners, cgrid_ne, halo=1)
582  do_pass_ray = .true.
583  endif
584  do_pass_kv_bbl_thick = .false.
585  if (associated(cs%visc%bbl_thick_u) .and. associated(cs%visc%bbl_thick_v)) then
586  call create_group_pass(cs%pass_bbl_thick_kv_bbl, cs%visc%bbl_thick_u, &
587  cs%visc%bbl_thick_v, g%Domain, &
588  to_north+to_east+scalar_pair+omit_corners, cgrid_ne, halo=1)
589  do_pass_kv_bbl_thick = .true.
590  endif
591  if (associated(cs%visc%kv_bbl_u) .and. associated(cs%visc%kv_bbl_v)) then
592  call create_group_pass(cs%pass_bbl_thick_kv_bbl, cs%visc%kv_bbl_u, &
593  cs%visc%kv_bbl_v, g%Domain, &
594  to_north+to_east+scalar_pair+omit_corners, cgrid_ne, halo=1)
595  do_pass_kv_bbl_thick = .true.
596  endif
597  do_pass_kv_turb = associated(cs%visc%Kv_turb)
598  if (associated(cs%visc%Kv_turb)) &
599  call create_group_pass(cs%pass_kv_turb, cs%visc%Kv_turb, g%Domain, to_all+omit_corners, halo=1)
600 
601  if (.not.cs%adiabatic .AND. cs%use_ALE_algorithm ) then
602  if (cs%use_temperature) then
603  call create_group_pass(cs%pass_T_S_h, cs%tv%T, g%Domain, to_all+omit_corners, halo=1)
604  call create_group_pass(cs%pass_T_S_h, cs%tv%S, g%Domain, to_all+omit_corners, halo=1)
605  endif
606  call create_group_pass(cs%pass_T_S_h, h, g%Domain, to_all+omit_corners, halo=1)
607  endif
608 
609  if ((cs%adiabatic .OR. cs%diabatic_first) .AND. cs%use_temperature) then
610  call create_group_pass(cs%pass_T_S, cs%tv%T, g%Domain, halo=1) ! Could also omit corners?
611  call create_group_pass(cs%pass_T_S, cs%tv%S, g%Domain, halo=1)
612  endif
613 
614  !---------- End setup for group halo pass
615 
616 
617  if (g%nonblocking_updates) then
618  call start_group_pass(cs%pass_tau_ustar_psurf, g%Domain)
619  else
620  call do_group_pass(cs%pass_tau_ustar_psurf, g%Domain)
621  endif
622  call cpu_clock_end(id_clock_pass)
623 
624  if (ASSOCIATED(cs%tv%frazil)) cs%tv%frazil(:,:) = 0.0
625  if (ASSOCIATED(cs%tv%salt_deficit)) cs%tv%salt_deficit(:,:) = 0.0
626  if (ASSOCIATED(cs%tv%TempxPmE)) cs%tv%TempxPmE(:,:) = 0.0
627  if (ASSOCIATED(cs%tv%internal_heat)) cs%tv%internal_heat(:,:) = 0.0
628 
629  cs%rel_time = 0.0
630 
631  tot_wt_ssh = 0.0
632  do j=js,je ; do i=is,ie ; cs%ave_ssh(i,j) = 0.0 ; ssh(i,j) = cs%missing; enddo ; enddo
633 
634  if (associated(cs%VarMix)) then
635  call enable_averaging(time_interval, time_start+set_time(int(time_interval)), &
636  cs%diag)
637  call calc_resoln_function(h, cs%tv, g, gv, cs%VarMix)
638  call disable_averaging(cs%diag)
639  endif
640 
641  if (g%nonblocking_updates) then
642  call cpu_clock_begin(id_clock_pass)
643  call complete_group_pass(cs%pass_tau_ustar_psurf, g%Domain)
644  call cpu_clock_end(id_clock_pass)
645  endif
646 
647  if (cs%interp_p_surf) then
648  if (.not.ASSOCIATED(cs%p_surf_end)) allocate(cs%p_surf_end(isd:ied,jsd:jed))
649  if (.not.ASSOCIATED(cs%p_surf_begin)) allocate(cs%p_surf_begin(isd:ied,jsd:jed))
650  if (.not.cs%p_surf_prev_set) then
651  do j=jsd,jed ; do i=isd,ied
652  cs%p_surf_prev(i,j) = fluxes%p_surf(i,j)
653  enddo ; enddo
654  cs%p_surf_prev_set = .true.
655  endif
656  else
657  cs%p_surf_end => fluxes%p_surf
658  endif
659 
660  if (cs%debug) then
661  call mom_state_chksum("Before steps ", u, v, h, cs%uh, cs%vh, g, gv)
662  call mom_forcing_chksum("Before steps", fluxes, g, haloshift=0)
663  call check_redundant("Before steps ", u, v, g)
664  call check_redundant("Before steps ", fluxes%taux, fluxes%tauy, g)
665  endif
666  call cpu_clock_end(id_clock_other)
667 
668  do n=1,n_max
669 
670  nt_debug = nt_debug + 1
671 
672  ! Set the universally visible time to the middle of the time step
673  cs%Time = time_start + set_time(int(floor(cs%rel_time+0.5*dt+0.5)))
674  cs%rel_time = cs%rel_time + dt
675 
676  ! Set the local time to the end of the time step.
677  time_local = time_start + set_time(int(floor(cs%rel_time+0.5)))
678  if (showcalltree) call calltree_enter("DT cycles (step_MOM) n=",n)
679 
680  !===========================================================================
681  ! This is the first place where the diabatic processes and remapping could occur.
682  if (cs%diabatic_first .and. (cs%t_dyn_rel_adv==0.0)) then ! do thermodynamics.
683 
684  if (thermo_does_span_coupling) then
685  dtdia = dt_therm
686  if ((fluxes%dt_buoy_accum > 0.0) .and. (dtdia > time_interval) .and. &
687  (abs(fluxes%dt_buoy_accum - dtdia) > 1e-6*dtdia)) then
688  call mom_error(fatal, "step_MOM: Mismatch between long thermodynamic "//&
689  "timestep and time over which buoyancy fluxes have been accumulated.")
690  endif
691  call mom_error(fatal, "MOM is not yet set up to have restarts that work "//&
692  "with THERMO_SPANS_COUPLING and DIABATIC_FIRST.")
693  else
694  dtdia = dt*min(ntstep,n_max-(n-1))
695  endif
696 
697  ! The end-time of the diagnostic interval needs to be set ahead if there
698  ! are multiple dynamic time steps worth of thermodynamics applied here.
699  call enable_averaging(dtdia, time_local + &
700  set_time(int(floor(dtdia-dt+0.5))), cs%diag)
701 
702  if (cs%debug) then
703  call uvchksum("Pre set_viscous_BBL [uv]", u, v, g%HI, haloshift=1)
704  call hchksum(h,"Pre set_viscous_BBL h", g%HI, haloshift=1, scale=gv%H_to_m)
705  if (associated(cs%tv%T)) call hchksum(cs%tv%T, "Pre set_viscous_BBL T", g%HI, haloshift=1)
706  if (associated(cs%tv%S)) call hchksum(cs%tv%S, "Pre set_viscous_BBL S", g%HI, haloshift=1)
707  endif
708 
709  ! Calculate the BBL properties and store them inside visc (u,h).
710  ! This is here so that CS%visc is updated before diabatic() when
711  ! DIABATIC_FIRST=True. Otherwise diabatic() is called after the dynamics
712  ! and set_viscous_BBL is called as a part of the dynamic stepping.
713  call cpu_clock_begin(id_clock_bbl_visc)
714  call set_viscous_bbl(u, v, h, cs%tv, cs%visc, g, gv, cs%set_visc_CSp)
715  call cpu_clock_end(id_clock_bbl_visc)
716 
717  call cpu_clock_begin(id_clock_pass)
718  if (do_pass_ray) call do_group_pass(cs%pass_ray, g%Domain )
719  if (do_pass_kv_bbl_thick) call do_group_pass(cs%pass_bbl_thick_kv_bbl, g%Domain)
720  call cpu_clock_end(id_clock_pass)
721  if (showcalltree) call calltree_waypoint("done with set_viscous_BBL (diabatic_first)")
722 
723  call cpu_clock_begin(id_clock_thermo)
724 
725  ! These adjustments are a part of an archaic time stepping algorithm.
726  if (cs%split .and. cs%legacy_split .and. .not.cs%adiabatic) then
727  call adjustments_dyn_legacy_split(u, v, h, dt, g, gv, cs%dyn_legacy_split_CSp)
728  endif
729 
730  ! Apply diabatic forcing, do mixing, and regrid.
731  call step_mom_thermo(cs, g, gv, u, v, h, cs%tv, fluxes, dtdia)
732 
733  ! The diabatic processes are now ahead of the dynamics by dtdia.
734  cs%t_dyn_rel_thermo = -dtdia
735  if (showcalltree) call calltree_waypoint("finished diabatic_first (step_MOM)")
736 
737  call disable_averaging(cs%diag)
738  call cpu_clock_end(id_clock_thermo)
739 
740  endif ! end of block "(CS%diabatic_first .and. (CS%t_dyn_rel_adv==0.0))"
741 
742  !===========================================================================
743  ! This is the start of the dynamics stepping part of the algorithm.
744 
745  call cpu_clock_begin(id_clock_dynamics)
746  call disable_averaging(cs%diag)
747 
748  if (cs%thickness_diffuse .and. cs%thickness_diffuse_first) then
749  if (cs%t_dyn_rel_adv == 0.0) then
750  if (thermo_does_span_coupling) then
751  dtth = dt_therm
752  else
753  dtth = dt*min(ntstep,n_max-n+1)
754  endif
755 
756  call enable_averaging(dtth,time_local+set_time(int(floor(dtth-dt+0.5))), cs%diag)
757  call cpu_clock_begin(id_clock_thick_diff)
758  if (associated(cs%VarMix)) &
759  call calc_slope_functions(h, cs%tv, dt, g, gv, cs%VarMix)
760  call thickness_diffuse(h, cs%uhtr, cs%vhtr, cs%tv, dtth, g, gv, &
761  cs%MEKE, cs%VarMix, cs%CDp, cs%thickness_diffuse_CSp)
762  call cpu_clock_end(id_clock_thick_diff)
763  call cpu_clock_begin(id_clock_pass)
764  call pass_var(h, g%Domain) !###, halo=max(2,cont_stensil))
765  call cpu_clock_end(id_clock_pass)
766  call disable_averaging(cs%diag)
767  if (showcalltree) call calltree_waypoint("finished thickness_diffuse_first (step_MOM)")
768 
769  ! Whenever thickness changes let the diag manager know, target grids
770  ! for vertical remapping may need to be regenerated.
771  call diag_update_remap_grids(cs%diag)
772 
773  endif
774  endif
775 
776  ! The bottom boundary layer properties are out-of-date and need to be
777  ! recalculated. This always occurs at the start of a coupling time
778  ! step because the externally prescribed stresses may have changed.
779  do_calc_bbl = ((cs%t_dyn_rel_adv == 0.0) .or. (n==1))
780  if (do_calc_bbl) then
781  ! Calculate the BBL properties and store them inside visc (u,h).
782  call cpu_clock_begin(id_clock_bbl_visc)
783  bbl_time_int = max(dt, min(dt_therm - cs%t_dyn_rel_adv, dt*(1+n_max-n)) )
784  call enable_averaging(bbl_time_int, &
785  time_local+set_time(int(bbl_time_int-dt+0.5)), cs%diag)
786  call set_viscous_bbl(u, v, h, cs%tv, cs%visc, g, gv, cs%set_visc_CSp)
787  call disable_averaging(cs%diag)
788  call cpu_clock_end(id_clock_bbl_visc)
789  if (showcalltree) call calltree_waypoint("done with set_viscous_BBL (step_MOM)")
790  endif
791 
792  call cpu_clock_begin(id_clock_pass)
793  if (do_pass_kv_turb) call do_group_pass(cs%pass_kv_turb, g%Domain)
794  call cpu_clock_end(id_clock_pass)
795 
796  if (do_calc_bbl) then
797  call cpu_clock_begin(id_clock_pass)
798  if (g%nonblocking_updates) then
799  if (do_pass_ray) call start_group_pass(cs%pass_Ray, g%Domain)
800  if (do_pass_kv_bbl_thick) call start_group_pass(cs%pass_bbl_thick_kv_bbl, g%Domain)
801  ! do_calc_bbl will be set to .false. when the message passing is complete.
802  else
803  if (do_pass_ray) call do_group_pass(cs%pass_Ray, g%Domain)
804  if (do_pass_kv_bbl_thick) call do_group_pass(cs%pass_bbl_thick_kv_bbl, g%Domain)
805  endif
806  call cpu_clock_end(id_clock_pass)
807  endif
808 
809  if (cs%interp_p_surf) then
810  wt_end = real(n) / real(n_max)
811  wt_beg = real(n-1) / real(n_max)
812  do j=jsd,jed ; do i=isd,ied
813  cs%p_surf_end(i,j) = wt_end * fluxes%p_surf(i,j) + &
814  (1.0-wt_end) * cs%p_surf_prev(i,j)
815  cs%p_surf_begin(i,j) = wt_beg * fluxes%p_surf(i,j) + &
816  (1.0-wt_beg) * cs%p_surf_prev(i,j)
817  enddo ; enddo
818  endif
819 
820  if (associated(cs%u_prev) .and. associated(cs%v_prev)) then
821  do k=1,nz ; do j=jsd,jed ; do i=isdb,iedb
822  cs%u_prev(i,j,k) = u(i,j,k)
823  enddo ; enddo ; enddo
824  do k=1,nz ; do j=jsdb,jedb ; do i=isd,ied
825  cs%v_prev(i,j,k) = u(i,j,k)
826  enddo ; enddo ; enddo
827  endif
828 
829  ! Store pre-dynamics layer thicknesses so that mass fluxes are remapped correctly
830  do k=1,nz ; do j=jsd,jed ; do i=isd,ied
831  h_pre_dyn(i,j,k) = h(i,j,k)
832  enddo ; enddo ; enddo
833 
834  if (g%nonblocking_updates) then ; if (do_calc_bbl) then
835  call cpu_clock_begin(id_clock_pass)
836  if (do_pass_ray) call complete_group_pass(cs%pass_Ray, g%Domain)
837  if (do_pass_kv_bbl_thick) call complete_group_pass(cs%pass_bbl_thick_kv_bbl, g%Domain)
838  call cpu_clock_end(id_clock_pass)
839  endif ; endif
840 
841  if (cs%do_dynamics .and. cs%split) then !--------------------------- start SPLIT
842  ! This section uses a split time stepping scheme for the dynamic equations,
843  ! basically the stacked shallow water equations with viscosity.
844 
845  calc_dtbt = .false.
846  if ((cs%dtbt_reset_period >= 0.0) .and. &
847  ((n==1) .or. (cs%dtbt_reset_period == 0.0) .or. &
848  (cs%rel_time >= dtbt_reset_time + 0.999*cs%dtbt_reset_period))) then
849  calc_dtbt = .true.
850  dtbt_reset_time = cs%rel_time
851  endif
852 
853  mass_src_time = cs%t_dyn_rel_thermo
854  if (cs%legacy_split) then
855  call step_mom_dyn_legacy_split(u, v, h, cs%tv, cs%visc, &
856  time_local, dt, fluxes, cs%p_surf_begin, cs%p_surf_end, &
857  mass_src_time, dt_therm, cs%uh, cs%vh, cs%uhtr, cs%vhtr, &
858  eta_av, g, gv, cs%dyn_legacy_split_CSp, calc_dtbt, cs%VarMix, cs%MEKE)
859  else
860  call step_mom_dyn_split_rk2(u, v, h, cs%tv, cs%visc, &
861  time_local, dt, fluxes, cs%p_surf_begin, cs%p_surf_end, &
862  mass_src_time, dt_therm, cs%uh, cs%vh, cs%uhtr, cs%vhtr, &
863  eta_av, g, gv, cs%dyn_split_RK2_CSp, calc_dtbt, cs%VarMix, cs%MEKE)
864  endif
865  if (showcalltree) call calltree_waypoint("finished step_MOM_dyn_split (step_MOM)")
866 
867 
868  elseif (cs%do_dynamics) then ! --------------------------------------------------- not SPLIT
869  ! This section uses an unsplit stepping scheme for the dynamic
870  ! equations; basically the stacked shallow water equations with viscosity.
871  ! Because the time step is limited by CFL restrictions on the external
872  ! gravity waves, the unsplit is usually much less efficient that the split
873  ! approaches. But because of its simplicity, the unsplit method is very
874  ! useful for debugging purposes.
875 
876  if (cs%use_RK2) then
877  call step_mom_dyn_unsplit_rk2(u, v, h, cs%tv, cs%visc, time_local, dt, fluxes, &
878  cs%p_surf_begin, cs%p_surf_end, cs%uh, cs%vh, cs%uhtr, cs%vhtr, &
879  eta_av, g, gv, cs%dyn_unsplit_RK2_CSp, cs%VarMix, cs%MEKE)
880  else
881  call step_mom_dyn_unsplit(u, v, h, cs%tv, cs%visc, time_local, dt, fluxes, &
882  cs%p_surf_begin, cs%p_surf_end, cs%uh, cs%vh, cs%uhtr, cs%vhtr, &
883  eta_av, g, gv, cs%dyn_unsplit_CSp, cs%VarMix, cs%MEKE)
884  endif
885  if (showcalltree) call calltree_waypoint("finished step_MOM_dyn_unsplit (step_MOM)")
886 
887  endif ! -------------------------------------------------- end SPLIT
888 
889 
890 
891  if (cs%thickness_diffuse .and. .not.cs%thickness_diffuse_first) then
892  call cpu_clock_begin(id_clock_thick_diff)
893 
894  if (cs%debug) call hchksum(h,"Pre-thickness_diffuse h", g%HI, haloshift=0, scale=gv%H_to_m)
895 
896  if (associated(cs%VarMix)) &
897  call calc_slope_functions(h, cs%tv, dt, g, gv, cs%VarMix)
898  call thickness_diffuse(h, cs%uhtr, cs%vhtr, cs%tv, dt, g, gv, &
899  cs%MEKE, cs%VarMix, cs%CDp, cs%thickness_diffuse_CSp)
900 
901  if (cs%debug) call hchksum(h,"Post-thickness_diffuse h", g%HI, haloshift=1, scale=gv%H_to_m)
902  call cpu_clock_end(id_clock_thick_diff)
903  call cpu_clock_begin(id_clock_pass)
904  call pass_var(h, g%Domain) !###, halo=max(2,cont_stensil))
905  call cpu_clock_end(id_clock_pass)
906  if (showcalltree) call calltree_waypoint("finished thickness_diffuse (step_MOM)")
907  endif
908 
909  ! apply the submesoscale mixed layer restratification parameterization
910  if (cs%mixedlayer_restrat) then
911  if (cs%debug) then
912  call hchksum(h,"Pre-mixedlayer_restrat h", g%HI, haloshift=1, scale=gv%H_to_m)
913  call uvchksum("Pre-mixedlayer_restrat uhtr", &
914  cs%uhtr, cs%vhtr, g%HI, haloshift=0)
915  endif
916  call cpu_clock_begin(id_clock_ml_restrat)
917  call mixedlayer_restrat(h, cs%uhtr ,cs%vhtr, cs%tv, fluxes, dt, cs%visc%MLD, &
918  cs%VarMix, g, gv, cs%mixedlayer_restrat_CSp)
919  call cpu_clock_end(id_clock_ml_restrat)
920  call cpu_clock_begin(id_clock_pass)
921  call pass_var(h, g%Domain) !###, halo=max(2,cont_stensil))
922  call cpu_clock_end(id_clock_pass)
923  if (cs%debug) then
924  call hchksum(h,"Post-mixedlayer_restrat h", g%HI, haloshift=1, scale=gv%H_to_m)
925  call uvchksum("Post-mixedlayer_restrat [uv]htr", &
926  cs%uhtr, cs%vhtr, g%HI, haloshift=0)
927  endif
928  endif
929 
930  ! Whenever thickness changes let the diag manager know, target grids
931  ! for vertical remapping may need to be regenerated.
932  call diag_update_remap_grids(cs%diag)
933 
934  if (cs%useMEKE) call step_forward_meke(cs%MEKE, h, cs%VarMix%SN_u, cs%VarMix%SN_v, &
935  cs%visc, dt, g, gv, cs%MEKE_CSp, cs%uhtr, cs%vhtr)
936  call disable_averaging(cs%diag)
937 
938  ! Advance the dynamics time by dt.
939  cs%t_dyn_rel_adv = cs%t_dyn_rel_adv + dt
940  cs%t_dyn_rel_thermo = cs%t_dyn_rel_thermo + dt
941  cs%t_dyn_rel_diag = cs%t_dyn_rel_diag + dt
942 
943  call cpu_clock_end(id_clock_dynamics)
944 
945  !===========================================================================
946  ! This is the start of the tracer advection part of the algorithm.
947 
948  if (thermo_does_span_coupling) then
949  do_advection = (cs%t_dyn_rel_adv + 0.5*dt > dt_therm)
950  else
951  do_advection = ((mod(n,ntstep) == 0) .or. (n==n_max))
952  endif
953 
954  if (do_advection) then ! Do advective transport and lateral tracer mixing.
955 
956  if (cs%debug) then
957  call cpu_clock_begin(id_clock_other)
958  call uvchksum("Pre-advection [uv]", u, v, g%HI, haloshift=2)
959  call hchksum(h,"Pre-advection h", g%HI, haloshift=1, scale=gv%H_to_m)
960  call uvchksum("Pre-advection uhtr", cs%uhtr, cs%vhtr, g%HI, &
961  haloshift=0, scale=gv%H_to_m)
962  ! call MOM_state_chksum("Pre-advection ", u, v, &
963  ! h, CS%uhtr, CS%vhtr, G, GV, haloshift=1)
964  if (associated(cs%tv%T)) call hchksum(cs%tv%T, "Pre-advection T", g%HI, haloshift=1)
965  if (associated(cs%tv%S)) call hchksum(cs%tv%S, "Pre-advection S", g%HI, haloshift=1)
966  if (associated(cs%tv%frazil)) call hchksum(cs%tv%frazil, &
967  "Pre-advection frazil", g%HI, haloshift=0)
968  if (associated(cs%tv%salt_deficit)) call hchksum(cs%tv%salt_deficit, &
969  "Pre-advection salt deficit", g%HI, haloshift=0)
970  ! call MOM_thermo_chksum("Pre-advection ", CS%tv, G)
971  call check_redundant("Pre-advection ", u, v, g)
972  call cpu_clock_end(id_clock_other)
973  endif
974 
975  call cpu_clock_begin(id_clock_thermo) ; call cpu_clock_begin(id_clock_tracer)
976  call enable_averaging(cs%t_dyn_rel_adv, time_local, cs%diag)
977 
978  call advect_tracer(h, cs%uhtr, cs%vhtr, cs%OBC, cs%t_dyn_rel_adv, g, gv, &
979  cs%tracer_adv_CSp, cs%tracer_Reg)
980  call tracer_hordiff(h, cs%t_dyn_rel_adv, cs%MEKE, cs%VarMix, g, gv, &
981  cs%tracer_diff_CSp, cs%tracer_Reg, cs%tv)
982  if (showcalltree) call calltree_waypoint("finished tracer advection/diffusion (step_MOM)")
983  call cpu_clock_end(id_clock_tracer) ; call cpu_clock_end(id_clock_thermo)
984 
985  call cpu_clock_begin(id_clock_other) ; call cpu_clock_begin(id_clock_diagnostics)
986  call post_transport_diagnostics(g, gv, cs, cs%diag, cs%t_dyn_rel_adv, h, h_pre_dyn)
987  ! Rebuild the remap grids now that we've posted the fields which rely on thicknesses
988  ! from before the dynamics calls
989  call diag_update_remap_grids(cs%diag)
990 
991  call disable_averaging(cs%diag)
992  call cpu_clock_end(id_clock_diagnostics) ; call cpu_clock_end(id_clock_other)
993 
994  ! Reset the accumulated transports to 0 and record that the dynamics
995  ! and advective times now agree.
996  call cpu_clock_begin(id_clock_thermo) ; call cpu_clock_begin(id_clock_tracer)
997  cs%uhtr(:,:,:) = 0.0
998  cs%vhtr(:,:,:) = 0.0
999  cs%t_dyn_rel_adv = 0.0
1000  call cpu_clock_end(id_clock_tracer) ; call cpu_clock_end(id_clock_thermo)
1001 
1002  endif
1003 
1004  !===========================================================================
1005  ! This is the second place where the diabatic processes and remapping could occur.
1006  if (cs%t_dyn_rel_adv == 0.0) then
1007  call cpu_clock_begin(id_clock_thermo)
1008 
1009  if (.not.cs%diabatic_first) then
1010  dtdia = cs%t_dyn_rel_thermo
1011  if (thermo_does_span_coupling .and. (abs(dt_therm - dtdia) > 1e-6*dt_therm)) then
1012  call mom_error(fatal, "step_MOM: Mismatch between dt_therm and dtdia "//&
1013  "before call to diabatic.")
1014  endif
1015 
1016  call enable_averaging(cs%t_dyn_rel_thermo, time_local, cs%diag)
1017 
1018  ! These adjustments are a part of an archaic time stepping algorithm.
1019  if (cs%split .and. cs%legacy_split .and. .not.cs%adiabatic) then
1020  call adjustments_dyn_legacy_split(u, v, h, dt, g, gv, cs%dyn_legacy_split_CSp)
1021  endif
1022 
1023  ! Apply diabatic forcing, do mixing, and regrid.
1024  call step_mom_thermo(cs, g, gv, u, v, h, cs%tv, fluxes, dtdia)
1025 
1026  call disable_averaging(cs%diag)
1027 
1028  else ! "else branch for if (.not.CS%diabatic_first) then"
1029  if (abs(cs%t_dyn_rel_thermo) > 1e-6*dt) call mom_error(fatal, &
1030  "step_MOM: Mismatch between the dynamics and diabatic times "//&
1031  "with DIABATIC_FIRST.")
1032 
1033  ! Tracers have been advected and diffused, and need halo updates.
1034  if (cs%use_temperature) then
1035  call cpu_clock_begin(id_clock_pass)
1036  call do_group_pass(cs%pass_T_S, g%Domain)
1037  call cpu_clock_end(id_clock_pass)
1038  endif
1039  endif ! close of "if (.not.CS%diabatic_first) then ; if (.not.CS%adiabatic)"
1040 
1041  ! Record that the dynamics and diabatic processes are synchronized.
1042  cs%t_dyn_rel_thermo = 0.0
1043  call cpu_clock_end(id_clock_thermo)
1044  endif
1045 
1046  call cpu_clock_begin(id_clock_dynamics)
1047 
1048  ! Determining the time-average sea surface height is part of the algorithm.
1049  ! This may be eta_av if Boussinesq, or need to be diagnosed if not.
1050  tot_wt_ssh = tot_wt_ssh + dt
1051  call find_eta(h, cs%tv, gv%g_Earth, g, gv, ssh, eta_av)
1052  do j=js,je ; do i=is,ie
1053  cs%ave_ssh(i,j) = cs%ave_ssh(i,j) + dt*ssh(i,j)
1054  enddo ; enddo
1055  call cpu_clock_end(id_clock_dynamics)
1056 
1057  !===========================================================================
1058  ! Calculate diagnostics at the end of the time step.
1059  call cpu_clock_begin(id_clock_other) ; call cpu_clock_begin(id_clock_diagnostics)
1060 
1061  call enable_averaging(dt,time_local, cs%diag)
1062  ! These diagnostics are available every time step.
1063  if (cs%id_u > 0) call post_data(cs%id_u, u, cs%diag)
1064  if (cs%id_v > 0) call post_data(cs%id_v, v, cs%diag)
1065  if (cs%id_h > 0) call post_data(cs%id_h, h, cs%diag)
1066  if (cs%id_ssh_inst > 0) call post_data(cs%id_ssh_inst, ssh, cs%diag)
1067  call disable_averaging(cs%diag)
1068 
1069  if (cs%t_dyn_rel_adv == 0.0) then
1070  ! Diagnostics that require the complete state to be up-to-date can be calculated.
1071 
1072  call enable_averaging(cs%t_dyn_rel_diag, time_local, cs%diag)
1073  call calculate_diagnostic_fields(u, v, h, cs%uh, cs%vh, cs%tv, cs%ADp, &
1074  cs%CDp, fluxes, cs%t_dyn_rel_diag, g, gv, cs%diagnostics_CSp)
1075  call post_ts_diagnostics(cs, g, gv, cs%tv, cs%diag, cs%t_dyn_rel_diag)
1076  if (showcalltree) call calltree_waypoint("finished calculate_diagnostic_fields (step_MOM)")
1077  call disable_averaging(cs%diag)
1078  cs%t_dyn_rel_diag = 0.0
1079 
1080  call cpu_clock_begin(id_clock_z_diag)
1081  if (time_local + set_time(int(0.5*dt_therm)) > cs%Z_diag_time) then
1082  call enable_averaging(real(time_type_to_real(CS%Z_diag_interval)), &
1083  CS%Z_diag_time, CS%diag)
1084  call calculate_z_diag_fields(u, v, h, ssh, fluxes%frac_shelf_h, &
1085  g, gv, cs%diag_to_Z_CSp)
1086  cs%Z_diag_time = cs%Z_diag_time + cs%Z_diag_interval
1087  call disable_averaging(cs%diag)
1088  if (showcalltree) call calltree_waypoint("finished calculate_Z_diag_fields (step_MOM)")
1089  endif
1090  call cpu_clock_end(id_clock_z_diag)
1091  endif
1092  call cpu_clock_end(id_clock_diagnostics) ; call cpu_clock_end(id_clock_other)
1093 
1094  if (showcalltree) call calltree_leave("DT cycles (step_MOM)")
1095 
1096  enddo ! complete the n loop
1097 
1098  call cpu_clock_begin(id_clock_other)
1099 
1100  itot_wt_ssh = 1.0/tot_wt_ssh
1101  do j=js,je ; do i=is,ie
1102  cs%ave_ssh(i,j) = cs%ave_ssh(i,j)*itot_wt_ssh
1103  enddo ; enddo
1104 
1105  call enable_averaging(dt*n_max, time_local, cs%diag)
1106  call post_integrated_diagnostics(cs, g, gv, cs%diag, dt*n_max, cs%tv, fluxes)
1107  call disable_averaging(cs%diag)
1108 
1109  if (showcalltree) call calltree_waypoint("calling calculate_surface_state (step_MOM)")
1110  call adjust_ssh_for_p_atm(cs, g, gv, cs%ave_ssh, fluxes%p_surf_SSH)
1111  call calculate_surface_state(state, u, v, h, cs%ave_ssh, g, gv, cs)
1112 
1113  call enable_averaging(dt*n_max, time_local, cs%diag)
1114  call post_surface_diagnostics(cs, g, cs%diag, state)
1115  call disable_averaging(cs%diag)
1116 
1117  if (cs%interp_p_surf) then ; do j=jsd,jed ; do i=isd,ied
1118  cs%p_surf_prev(i,j) = fluxes%p_surf(i,j)
1119  enddo ; enddo ; endif
1120 
1121  call cpu_clock_end(id_clock_other)
1122 
1123  if (showcalltree) call calltree_leave("step_MOM()")
1124  call cpu_clock_end(id_clock_ocean)
1125 
1126 end subroutine step_mom
1127 
1128 !> MOM_step_thermo orchestrates the thermodynamic time stepping and vertical
1129 !! remapping, via calls to diabatic (or adiabatic) and ALE_main.
1130 subroutine step_mom_thermo(CS, G, GV, u, v, h, tv, fluxes, dtdia)
1131  type(mom_control_struct), intent(inout) :: CS !< control structure
1132  type(ocean_grid_type), intent(inout) :: G !< ocean grid structure
1133  type(verticalgrid_type), intent(inout) :: GV !< ocean vertical grid structure
1134  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1135  intent(inout) :: u !< zonal velocity (m/s)
1136  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1137  intent(inout) :: v !< meridional velocity (m/s)
1138  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1139  intent(inout) :: h !< layer thickness (m or kg/m2)
1140  type(thermo_var_ptrs), intent(inout) :: tv !< A structure pointing to various thermodynamic variables
1141  type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
1142  real, intent(in) :: dtdia !< The time interval over which to advance, in s
1143 
1144  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: eta_predia, eta_preale
1145  integer :: i, j, k, is, ie, js, je, nz! , Isq, Ieq, Jsq, Jeq, n
1146  logical :: use_ice_shelf ! Needed for selecting the right ALE interface.
1147  logical :: showCallTree
1148 
1149  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1150  showcalltree = calltree_showquery()
1151  if (showcalltree) call calltree_enter("step_MOM_thermo(), MOM.F90")
1152 
1153  use_ice_shelf = .false.
1154  if (associated(fluxes%frac_shelf_h)) use_ice_shelf = .true.
1155 
1156  if (.not.cs%adiabatic) then
1157 
1158  if (cs%debug) then
1159  call uvchksum("Pre-diabatic [uv]", u, v, g%HI, haloshift=2)
1160  call hchksum(h,"Pre-diabatic h", g%HI, haloshift=1, scale=gv%H_to_m)
1161  call uvchksum("Pre-diabatic [uv]h", cs%uhtr, cs%vhtr, g%HI, &
1162  haloshift=0, scale=gv%H_to_m)
1163  ! call MOM_state_chksum("Pre-diabatic ",u, v, h, CS%uhtr, CS%vhtr, G, GV)
1164  call mom_thermo_chksum("Pre-diabatic ", cs%tv, g,haloshift=0)
1165  call check_redundant("Pre-diabatic ", u, v, g)
1166  call mom_forcing_chksum("Pre-diabatic", fluxes, g, haloshift=0)
1167  endif
1168 
1169  if (cs%id_u_predia > 0) call post_data(cs%id_u_predia, u, cs%diag)
1170  if (cs%id_v_predia > 0) call post_data(cs%id_v_predia, v, cs%diag)
1171  if (cs%id_h_predia > 0) call post_data(cs%id_h_predia, h, cs%diag)
1172  if (cs%id_T_predia > 0) call post_data(cs%id_T_predia, cs%tv%T, cs%diag)
1173  if (cs%id_S_predia > 0) call post_data(cs%id_S_predia, cs%tv%S, cs%diag)
1174  if (cs%id_e_predia > 0) then
1175  call find_eta(h, cs%tv, gv%g_Earth, g, gv, eta_predia)
1176  call post_data(cs%id_e_predia, eta_predia, cs%diag)
1177  endif
1178 
1179  call cpu_clock_begin(id_clock_diabatic)
1180  call diabatic(u, v, h, tv, cs%Hml, fluxes, cs%visc, cs%ADp, cs%CDp, &
1181  dtdia, g, gv, cs%diabatic_CSp)
1182  fluxes%fluxes_used = .true.
1183  call cpu_clock_end(id_clock_diabatic)
1184 
1185  if (cs%id_u_preale > 0) call post_data(cs%id_u_preale, u, cs%diag)
1186  if (cs%id_v_preale > 0) call post_data(cs%id_v_preale, v, cs%diag)
1187  if (cs%id_h_preale > 0) call post_data(cs%id_h_preale, h, cs%diag)
1188  if (cs%id_T_preale > 0) call post_data(cs%id_T_preale, tv%T, cs%diag)
1189  if (cs%id_S_preale > 0) call post_data(cs%id_S_preale, tv%S, cs%diag)
1190  if (cs%id_e_preale > 0) then
1191  call find_eta(h, tv, gv%g_Earth, g, gv, eta_preale)
1192  call post_data(cs%id_e_preale, eta_preale, cs%diag)
1193  endif
1194 
1195  if (showcalltree) call calltree_waypoint("finished diabatic (step_MOM_thermo)")
1196 
1197  ! Regridding/remapping is done here, at end of thermodynamics time step
1198  ! (that may comprise several dynamical time steps)
1199  ! The routine 'ALE_main' can be found in 'MOM_ALE.F90'.
1200  if ( cs%use_ALE_algorithm ) then
1201 ! call pass_vector(u, v, G%Domain)
1202  call do_group_pass(cs%pass_T_S_h, g%Domain)
1203 
1204  ! update squared quantities
1205  if (associated(cs%S_squared)) then ; do k=1,nz ; do j=js,je ; do i=is,ie
1206  cs%S_squared(i,j,k) = tv%S(i,j,k)**2
1207  enddo ; enddo ; enddo ; endif
1208  if (associated(cs%T_squared)) then ; do k=1,nz ; do j=js,je ; do i=is,ie
1209  cs%T_squared(i,j,k) = tv%T(i,j,k)**2
1210  enddo ; enddo ; enddo ; endif
1211 
1212  if (cs%debug) then
1213  call mom_state_chksum("Pre-ALE ", u, v, h, cs%uh, cs%vh, g, gv)
1214  call hchksum(tv%T,"Pre-ALE T", g%HI, haloshift=1)
1215  call hchksum(tv%S,"Pre-ALE S", g%HI, haloshift=1)
1216  call check_redundant("Pre-ALE ", u, v, g)
1217  endif
1218  call cpu_clock_begin(id_clock_ale)
1219  if (use_ice_shelf) then
1220  call ale_main(g, gv, h, u, v, tv, cs%tracer_Reg, cs%ALE_CSp, dtdia, &
1221  fluxes%frac_shelf_h)
1222  else
1223  call ale_main(g, gv, h, u, v, tv, cs%tracer_Reg, cs%ALE_CSp, dtdia)
1224  endif
1225 
1226  if (showcalltree) call calltree_waypoint("finished ALE_main (step_MOM_thermo)")
1227  call cpu_clock_end(id_clock_ale)
1228  endif ! endif for the block "if ( CS%use_ALE_algorithm )"
1229 
1230  call cpu_clock_begin(id_clock_pass)
1231  call do_group_pass(cs%pass_uv_T_S_h, g%Domain)
1232  call cpu_clock_end(id_clock_pass)
1233 
1234  if (cs%debug .and. cs%use_ALE_algorithm) then
1235  call mom_state_chksum("Post-ALE ", u, v, h, cs%uh, cs%vh, g, gv)
1236  call hchksum(tv%T, "Post-ALE T", g%HI, haloshift=1)
1237  call hchksum(tv%S, "Post-ALE S", g%HI, haloshift=1)
1238  call check_redundant("Post-ALE ", u, v, g)
1239  endif
1240 
1241  ! Whenever thickness changes let the diag manager know, target grids
1242  ! for vertical remapping may need to be regenerated. This needs to
1243  ! happen after the H update and before the next post_data.
1244  call diag_update_remap_grids(cs%diag)
1245 
1246  call post_diags_ts_vardec(g, cs, dtdia)
1247 
1248  if (cs%debug) then
1249  call uvchksum("Post-diabatic u", u, v, g%HI, haloshift=2)
1250  call hchksum(h, "Post-diabatic h", g%HI, haloshift=1, scale=gv%H_to_m)
1251  call uvchksum("Post-diabatic [uv]h", cs%uhtr, cs%vhtr, g%HI, &
1252  haloshift=0, scale=gv%H_to_m)
1253  ! call MOM_state_chksum("Post-diabatic ", u, v, &
1254  ! h, CS%uhtr, CS%vhtr, G, GV, haloshift=1)
1255  if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", g%HI, haloshift=1)
1256  if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", g%HI, haloshift=1)
1257  if (associated(tv%frazil)) call hchksum(tv%frazil, &
1258  "Post-diabatic frazil", g%HI, haloshift=0)
1259  if (associated(tv%salt_deficit)) call hchksum(tv%salt_deficit, &
1260  "Post-diabatic salt deficit", g%HI, haloshift=0)
1261  ! call MOM_thermo_chksum("Post-diabatic ", tv, G)
1262  call check_redundant("Post-diabatic ", u, v, g)
1263  endif
1264 
1265  else ! complement of "if (.not.CS%adiabatic)"
1266 
1267  call cpu_clock_begin(id_clock_diabatic)
1268  call adiabatic(h, tv, fluxes, dtdia, g, gv, cs%diabatic_CSp)
1269  fluxes%fluxes_used = .true.
1270  call cpu_clock_end(id_clock_diabatic)
1271 
1272  if (cs%use_temperature) then
1273  call cpu_clock_begin(id_clock_pass)
1274  call do_group_pass(cs%pass_T_S, g%Domain)
1275  call cpu_clock_end(id_clock_pass)
1276  if (cs%debug) then
1277  if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", g%HI, haloshift=1)
1278  if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", g%HI, haloshift=1)
1279  endif
1280  endif
1281 
1282  endif ! endif for the block "if (.not.CS%adiabatic)"
1283 
1284  if (showcalltree) call calltree_leave("step_MOM_thermo(), MOM.F90")
1285 
1286 end subroutine step_mom_thermo
1287 
1288 
1289 !> step_offline is the main driver for running tracers offline in MOM6. This has been primarily
1290 !! developed with ALE configurations in mind. Some work has been done in isopycnal configuration, but
1291 !! the work is very preliminary. Some more detail about this capability along with some of the subroutines
1292 !! called here can be found in tracers/MOM_offline_control.F90
1293 subroutine step_offline(fluxes, state, Time_start, time_interval, CS)
1294  type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
1295  type(surface), intent(inout) :: state !< surface ocean state
1296  type(time_type), intent(in) :: Time_start !< starting time of a segment, as a time type
1297  real, intent(in) :: time_interval !< time interval
1298  type(mom_control_struct), pointer :: CS !< control structure from initialize_MOM
1299 
1300  ! Local pointers
1301  type(ocean_grid_type), pointer :: G => null() ! Pointer to a structure containing
1302  ! metrics and related information
1303  type(verticalgrid_type), pointer :: GV => null() ! Pointer to structure containing information
1304  ! about the vertical grid
1305 
1306  logical :: first_iter !< True if this is the first time step_offline has been called in a given interval
1307  logical :: last_iter !< True if this is the last time step_tracer is to be called in an offline interval
1308  logical :: do_vertical !< If enough time has elapsed, do the diabatic tracer sources/sinks
1309  logical :: adv_converged !< True if all the horizontal fluxes have been used
1310 
1311  integer :: dt_offline, dt_offline_vertical
1312  logical :: skip_diffusion
1313  integer :: id_eta_diff_end
1314 
1315  integer, pointer :: accumulated_time
1316  integer :: i,j,k
1317  integer :: is, ie, js, je, isd, ied, jsd, jed
1318 
1319  ! 3D pointers
1320  real, dimension(:,:,:), pointer :: &
1321  uhtr, vhtr, &
1322  eatr, ebtr, &
1323  h_end
1324 
1325  ! 2D Array for diagnostics
1326  real, dimension(SZI_(CS%G),SZJ_(CS%G)) :: eta_pre, eta_end
1327  type(time_type) :: Time_end ! End time of a segment, as a time type
1328 
1329  ! Grid-related pointer assignments
1330  g => cs%G
1331  gv => cs%GV
1332 
1333  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1334  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1335 
1336  call cpu_clock_begin(id_clock_offline_tracer)
1337  call extract_offline_main(cs%offline_CSp, uhtr, vhtr, eatr, ebtr, h_end, accumulated_time, &
1338  dt_offline, dt_offline_vertical, skip_diffusion)
1339  time_end = increment_date(time_start, seconds=floor(time_interval+0.001))
1340  call enable_averaging(time_interval, time_end, cs%diag)
1341 
1342  ! Check to see if this is the first iteration of the offline interval
1343  if(accumulated_time==0) then
1344  first_iter = .true.
1345  else ! This is probably unnecessary but is used to guard against unwanted behavior
1346  first_iter = .false.
1347  endif
1348 
1349  ! Check to see if vertical tracer functions should be done
1350  if ( mod(accumulated_time, dt_offline_vertical) == 0 ) then
1351  do_vertical = .true.
1352  else
1353  do_vertical = .false.
1354  endif
1355 
1356  ! Increment the amount of time elapsed since last read and check if it's time to roll around
1357  accumulated_time = mod(accumulated_time + int(time_interval), dt_offline)
1358  if(accumulated_time==0) then
1359  last_iter = .true.
1360  else
1361  last_iter = .false.
1362  endif
1363 
1364  if(cs%use_ALE_algorithm) then
1365  ! If this is the first iteration in the offline timestep, then we need to read in fields and
1366  ! perform the main advection.
1367  if (first_iter) then
1368  if(is_root_pe()) print *, "Reading in new offline fields"
1369  ! Read in new transport and other fields
1370  ! call update_transport_from_files(G, GV, CS%offline_CSp, h_end, eatr, ebtr, uhtr, vhtr, &
1371  ! CS%tv%T, CS%tv%S, fluxes, CS%use_ALE_algorithm)
1372  ! call update_transport_from_arrays(CS%offline_CSp)
1373  call update_offline_fields(cs%offline_CSp, cs%h, fluxes, cs%use_ALE_algorithm)
1374 
1375  ! Apply any fluxes into the ocean
1376  call offline_fw_fluxes_into_ocean(g, gv, cs%offline_CSp, fluxes, cs%h)
1377 
1378  if (.not.cs%diabatic_first) then
1379  call offline_advection_ale(fluxes, time_start, time_interval, cs%offline_CSp, id_clock_ale, &
1380  cs%h, uhtr, vhtr, converged=adv_converged)
1381 
1382  ! Redistribute any remaining transport
1383  call offline_redistribute_residual(cs%offline_CSp, cs%h, uhtr, vhtr, adv_converged)
1384 
1385  ! Perform offline diffusion if requested
1386  if (.not. skip_diffusion) then
1387  if (associated(cs%VarMix)) then
1388  call pass_var(cs%h,g%Domain)
1389  call calc_resoln_function(cs%h, cs%tv, g, gv, cs%VarMix)
1390  call calc_slope_functions(cs%h, cs%tv, REAL(dt_offline), G, GV, CS%VarMix)
1391  endif
1392  call tracer_hordiff(cs%h, REAL(dt_offline), CS%MEKE, CS%VarMix, G, GV, &
1393  CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
1394  endif
1395  endif
1396  endif
1397  ! The functions related to column physics of tracers is performed separately in ALE mode
1398  if (do_vertical) then
1399  call offline_diabatic_ale(fluxes, time_start, time_end, cs%offline_CSp, cs%h, eatr, ebtr)
1400  endif
1401 
1402  ! Last thing that needs to be done is the final ALE remapping
1403  if(last_iter) then
1404  if (cs%diabatic_first) then
1405  call offline_advection_ale(fluxes, time_start, time_interval, cs%offline_CSp, id_clock_ale, &
1406  cs%h, uhtr, vhtr, converged=adv_converged)
1407 
1408  ! Redistribute any remaining transport and perform the remaining advection
1409  call offline_redistribute_residual(cs%offline_CSp, cs%h, uhtr, vhtr, adv_converged)
1410  ! Perform offline diffusion if requested
1411  if (.not. skip_diffusion) then
1412  if (associated(cs%VarMix)) then
1413  call pass_var(cs%h,g%Domain)
1414  call calc_resoln_function(cs%h, cs%tv, g, gv, cs%VarMix)
1415  call calc_slope_functions(cs%h, cs%tv, REAL(dt_offline), G, GV, CS%VarMix)
1416  endif
1417  call tracer_hordiff(cs%h, REAL(dt_offline), CS%MEKE, CS%VarMix, G, GV, &
1418  CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
1419  endif
1420  endif
1421 
1422  if(is_root_pe()) print *, "Last iteration of offline interval"
1423 
1424  ! Apply freshwater fluxes out of the ocean
1425  call offline_fw_fluxes_out_ocean(g, gv, cs%offline_CSp, fluxes, cs%h)
1426  ! These diagnostic can be used to identify which grid points did not converge within
1427  ! the specified number of advection sub iterations
1428  call post_offline_convergence_diags(cs%offline_CSp, cs%h, h_end, uhtr, vhtr)
1429 
1430  ! Call ALE one last time to make sure that tracers are remapped onto the layer thicknesses
1431  ! stored from the forward run
1432  call cpu_clock_begin(id_clock_ale)
1433  call ale_offline_tracer_final( g, gv, cs%h, cs%tv, h_end, cs%tracer_Reg, cs%ALE_CSp)
1434  call cpu_clock_end(id_clock_ale)
1435  call pass_var(cs%h, g%Domain)
1436  endif
1437  else ! NON-ALE MODE...NOT WELL TESTED
1438  call mom_error(warning, &
1439  "Offline tracer mode in non-ALE configuration has not been thoroughly tested")
1440  ! Note that for the layer mode case, the calls to tracer sources and sinks is embedded in
1441  ! main_offline_advection_layer. Warning: this may not be appropriate for tracers that
1442  ! exchange with the atmosphere
1443  if(time_interval .NE. dt_offline) then
1444  call mom_error(fatal, &
1445  "For offline tracer mode in a non-ALE configuration, dt_offline must equal time_interval")
1446  endif
1447  call update_offline_fields(cs%offline_CSp, cs%h, fluxes, cs%use_ALE_algorithm)
1448  call offline_advection_layer(fluxes, time_start, time_interval, cs%offline_CSp, &
1449  cs%h, eatr, ebtr, uhtr, vhtr)
1450  ! Perform offline diffusion if requested
1451  if (.not. skip_diffusion) then
1452  call tracer_hordiff(h_end, REAL(dt_offline), CS%MEKE, CS%VarMix, G, GV, &
1453  CS%tracer_diff_CSp, CS%tracer_Reg, CS%tv)
1454  endif
1455 
1456  cs%h = h_end
1457 
1458  call pass_var(cs%tv%T, g%Domain)
1459  call pass_var(cs%tv%S, g%Domain)
1460  call pass_var(cs%h, g%Domain)
1461 
1462  endif
1463 
1464  call adjust_ssh_for_p_atm(cs, g, gv, cs%ave_ssh, fluxes%p_surf_SSH)
1465  call calculate_surface_state(state, cs%u, cs%v, cs%h, cs%ave_ssh, g, gv, cs)
1466 
1467  call disable_averaging(cs%diag)
1468  call pass_var(cs%tv%T,g%Domain)
1469  call pass_var(cs%tv%S,g%Domain)
1470  call pass_var(cs%h,g%Domain)
1471 
1472  fluxes%fluxes_used = .true.
1473 
1474  call cpu_clock_end(id_clock_offline_tracer)
1475 
1476 end subroutine step_offline
1477 
1478 !> This subroutine initializes MOM.
1479 subroutine initialize_mom(Time, param_file, dirs, CS, Time_in, offline_tracer_mode)
1480  type(time_type), target, intent(inout) :: Time !< model time, set in this routine
1481  type(param_file_type), intent(out) :: param_file !< structure indicating paramater file to parse
1482  type(directories), intent(out) :: dirs !< structure with directory paths
1483  type(mom_control_struct), pointer :: CS !< pointer set in this routine to MOM control structure
1484  type(time_type), optional, intent(in) :: Time_in !< time passed to MOM_initialize_state when
1485  !! model is not being started from a restart file
1486  logical, optional, intent(out) :: offline_tracer_mode !< True if tracers are being run offline
1487 
1488  ! local
1489  type(ocean_grid_type), pointer :: G => null() ! A pointer to a structure with metrics and related
1490  type(hor_index_type) :: HI ! A hor_index_type for array extents
1491  type(verticalgrid_type), pointer :: GV => null()
1492  type(dyn_horgrid_type), pointer :: dG => null()
1493  type(diag_ctrl), pointer :: diag
1494 
1495  character(len=4), parameter :: vers_num = 'v2.0'
1496 
1497 ! This include declares and sets the variable "version".
1498 #include "version_variable.h"
1499 
1500  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz
1501  integer :: IsdB, IedB, JsdB, JedB
1502  real :: dtbt
1503  real :: Z_diag_int ! minimum interval between calc depth-space diagnostics (sec)
1504 
1505  real, allocatable, dimension(:,:,:) :: e ! interface heights (meter)
1506  real, allocatable, dimension(:,:) :: eta ! free surface height (m) or bottom press (Pa)
1507  real, allocatable, dimension(:,:) :: area_shelf_h ! area occupied by ice shelf
1508  real, dimension(:,:), allocatable, target :: frac_shelf_h ! fraction of total area occupied by ice shelf
1509  real, dimension(:,:), pointer :: shelf_area
1510  type(mom_restart_cs), pointer :: restart_CSp_tmp => null()
1511  type(group_pass_type) :: tmp_pass_uv_T_S_h
1512 
1513  real :: default_val ! default value for a parameter
1514  logical :: write_geom_files ! If true, write out the grid geometry files.
1515  logical :: new_sim
1516  logical :: use_geothermal ! If true, apply geothermal heating.
1517  logical :: use_EOS ! If true, density calculated from T & S using an equation of state.
1518  logical :: symmetric ! If true, use symmetric memory allocation.
1519  logical :: save_IC ! If true, save the initial conditions.
1520  logical :: do_unit_tests ! If true, call unit tests.
1521  logical :: test_grid_copy = .false.
1522  logical :: use_ice_shelf ! Needed for ALE
1523  logical :: global_indexing ! If true use global horizontal index values instead
1524  ! of having the data domain on each processor start at 1.
1525  logical :: bathy_at_vel ! If true, also define bathymetric fields at the
1526  ! the velocity points.
1527  integer :: first_direction ! An integer that indicates which direction is to be
1528  ! updated first in directionally split parts of the
1529  ! calculation. This can be altered during the course
1530  ! of the run via calls to set_first_direction.
1531  integer :: nkml, nkbl, verbosity, write_geom
1532  integer :: dynamics_stencil ! The computational stencil for the calculations
1533  ! in the dynamic core.
1534 
1535  type(time_type) :: Start_time
1536  type(ocean_internal_state) :: MOM_internal_state
1537  character(len=200) :: area_varname, ice_shelf_file, inputdir, filename
1538 
1539  if (associated(cs)) then
1540  call mom_error(warning, "initialize_MOM called with an associated "// &
1541  "control structure.")
1542  return
1543  endif
1544  allocate(cs)
1545 
1546  if (test_grid_copy) then ; allocate(g)
1547  else ; g => cs%G ; endif
1548 
1549  cs%Time => time
1550 
1551  id_clock_init = cpu_clock_id('Ocean Initialization', grain=clock_subcomponent)
1552  call cpu_clock_begin(id_clock_init)
1553 
1554  start_time = time ; if (present(time_in)) start_time = time_in
1555 
1556  call get_mom_input(param_file, dirs)
1557 
1558  verbosity = 2 ; call read_param(param_file, "VERBOSITY", verbosity)
1559  call mom_set_verbosity(verbosity)
1560  call calltree_enter("initialize_MOM(), MOM.F90")
1561 
1562  call find_obsolete_params(param_file)
1563 
1564  ! Read relevant parameters and write them to the model log.
1565  call log_version(param_file, "MOM", version, "")
1566  call get_param(param_file, "MOM", "VERBOSITY", verbosity, &
1567  "Integer controlling level of messaging\n" // &
1568  "\t0 = Only FATAL messages\n" // &
1569  "\t2 = Only FATAL, WARNING, NOTE [default]\n" // &
1570  "\t9 = All)", default=2)
1571  call get_param(param_file, "MOM", "DO_UNIT_TESTS", do_unit_tests, &
1572  "If True, exercises unit tests at model start up.", &
1573  default=.false.)
1574  if (do_unit_tests) then
1575  call unit_tests(verbosity)
1576  endif
1577 
1578  call get_param(param_file, "MOM", "SPLIT", cs%split, &
1579  "Use the split time stepping if true.", default=.true.)
1580  if (cs%split) then
1581  call get_param(param_file, "MOM", "USE_LEGACY_SPLIT", cs%legacy_split, &
1582  "If true, use the full range of options available from \n"//&
1583  "the older GOLD-derived split time stepping code.", &
1584  default=.false.)
1585  cs%use_RK2 = .false.
1586  else
1587  call get_param(param_file, "MOM", "USE_RK2", cs%use_RK2, &
1588  "If true, use RK2 instead of RK3 in the unsplit time stepping.", &
1589  default=.false.)
1590  cs%legacy_split = .false.
1591  endif
1592 
1593  call get_param(param_file, "MOM", "CALC_RHO_FOR_SEA_LEVEL", cs%calc_rho_for_sea_lev, &
1594  "If true, the in-situ density is used to calculate the\n"//&
1595  "effective sea level that is returned to the coupler. If false,\n"//&
1596  "the Boussinesq parameter RHO_0 is used.", default=.false.)
1597  call get_param(param_file, "MOM", "ENABLE_THERMODYNAMICS", cs%use_temperature, &
1598  "If true, Temperature and salinity are used as state \n"//&
1599  "variables.", default=.true.)
1600  call get_param(param_file, "MOM", "USE_EOS", use_eos, &
1601  "If true, density is calculated from temperature and \n"//&
1602  "salinity with an equation of state. If USE_EOS is \n"//&
1603  "true, ENABLE_THERMODYNAMICS must be true as well.", &
1604  default=cs%use_temperature)
1605  call get_param(param_file, "MOM", "DIABATIC_FIRST", cs%diabatic_first, &
1606  "If true, apply diabatic and thermodynamic processes, \n"//&
1607  "including buoyancy forcing and mass gain or loss, \n"//&
1608  "before stepping the dynamics forward.", default=.false.)
1609  call get_param(param_file, "MOM", "USE_CONTEMP_ABSSAL", cs%use_conT_absS, &
1610  "If true, , the prognostics T&S are the conservative temperature \n"//&
1611  "and absolute salinity. Care should be taken to convert them \n"//&
1612  "to potential temperature and practical salinity before \n"//&
1613  "exchanging them with the coupler and/or reporting T&S diagnostics. \n"&
1614  , default=.false.)
1615  call get_param(param_file, "MOM", "ADIABATIC", cs%adiabatic, &
1616  "There are no diapycnal mass fluxes if ADIABATIC is \n"//&
1617  "true. This assumes that KD = KDML = 0.0 and that \n"//&
1618  "there is no buoyancy forcing, but makes the model \n"//&
1619  "faster by eliminating subroutine calls.", default=.false.)
1620  call get_param(param_file, "MOM", "DO_DYNAMICS", cs%do_dynamics, &
1621  "If False, skips the dynamics calls that update u & v, as well as\n"//&
1622  "the gravity wave adjustment to h. This is a fragile feature and\n"//&
1623  "thus undocumented.", default=.true., do_not_log=.true. )
1624  call get_param(param_file, "MOM", "ADVECT_TS", cs%advect_TS , &
1625  "If True, advect temperature and salinity horizontally\n"//&
1626  "If False, T/S are registered for advection.\n"//&
1627  "This is intended only to be used in offline tracer mode.", &
1628  "and is by default false in that case", &
1629  do_not_log = .true., default=.true. )
1630  if (present(offline_tracer_mode)) then ! Only read this parameter in solo mode
1631  call get_param(param_file, "MOM", "OFFLINE_TRACER_MODE", cs%offline_tracer_mode, &
1632  "If true, barotropic and baroclinic dynamics, thermodynamics\n"//&
1633  "are all bypassed with all the fields necessary to integrate\n"//&
1634  "the tracer advection and diffusion equation are read in from\n"//&
1635  "files stored from a previous integration of the prognostic model.\n"//&
1636  "NOTE: This option only used in the ocean_solo_driver.", default=.false.)
1637  if(cs%offline_tracer_mode) then
1638  call get_param(param_file, "MOM", "ADVECT_TS", cs%advect_TS , &
1639  "If True, advect temperature and salinity horizontally\n"//&
1640  "If False, T/S are registered for advection.\n"//&
1641  "This is intended only to be used in offline tracer mode."//&
1642  "and is by default false in that case", &
1643  default=.false. )
1644  endif
1645  endif
1646  call get_param(param_file, "MOM", "USE_REGRIDDING", cs%use_ALE_algorithm , &
1647  "If True, use the ALE algorithm (regridding/remapping).\n"//&
1648  "If False, use the layered isopycnal algorithm.", default=.false. )
1649  call get_param(param_file, "MOM", "BULKMIXEDLAYER", cs%bulkmixedlayer, &
1650  "If true, use a Kraus-Turner-like bulk mixed layer \n"//&
1651  "with transitional buffer layers. Layers 1 through \n"//&
1652  "NKML+NKBL have variable densities. There must be at \n"//&
1653  "least NKML+NKBL+1 layers if BULKMIXEDLAYER is true. \n"//&
1654  "BULKMIXEDLAYER can not be used with USE_REGRIDDING. \n"//&
1655  "The default is influenced by ENABLE_THERMODYNAMICS.", &
1656  default=cs%use_temperature .and. .not.cs%use_ALE_algorithm)
1657  call get_param(param_file, "MOM", "THICKNESSDIFFUSE", cs%thickness_diffuse, &
1658  "If true, interface heights are diffused with a \n"//&
1659  "coefficient of KHTH.", default=.false.)
1660  call get_param(param_file, "MOM", "THICKNESSDIFFUSE_FIRST", &
1661  cs%thickness_diffuse_first, &
1662  "If true, do thickness diffusion before dynamics.\n"//&
1663  "This is only used if THICKNESSDIFFUSE is true.", &
1664  default=.false.)
1665  call get_param(param_file, "MOM", "BATHYMETRY_AT_VEL", bathy_at_vel, &
1666  "If true, there are separate values for the basin depths \n"//&
1667  "at velocity points. Otherwise the effects of topography \n"//&
1668  "are entirely determined from thickness points.", &
1669  default=.false.)
1670 
1671  call get_param(param_file, "MOM", "DEBUG", cs%debug, &
1672  "If true, write out verbose debugging data.", default=.false.)
1673  call get_param(param_file, "MOM", "DEBUG_TRUNCATIONS", cs%debug_truncations, &
1674  "If true, calculate all diagnostics that are useful for \n"//&
1675  "debugging truncations.", default=.false.)
1676 
1677  call get_param(param_file, "MOM", "DT", cs%dt, &
1678  "The (baroclinic) dynamics time step. The time-step that \n"//&
1679  "is actually used will be an integer fraction of the \n"//&
1680  "forcing time-step (DT_FORCING in ocean-only mode or the \n"//&
1681  "coupling timestep in coupled mode.)", units="s", &
1682  fail_if_missing=.true.)
1683  call get_param(param_file, "MOM", "DT_THERM", cs%dt_therm, &
1684  "The thermodynamic and tracer advection time step. \n"//&
1685  "Ideally DT_THERM should be an integer multiple of DT \n"//&
1686  "and less than the forcing or coupling time-step, unless \n"//&
1687  "THERMO_SPANS_COUPLING is true, in which case DT_THERM \n"//&
1688  "can be an integer multiple of the coupling timestep. By \n"//&
1689  "default DT_THERM is set to DT.", units="s", default=cs%dt)
1690  call get_param(param_file, "MOM", "THERMO_SPANS_COUPLING", cs%thermo_spans_coupling, &
1691  "If true, the MOM will take thermodynamic and tracer \n"//&
1692  "timesteps that can be longer than the coupling timestep. \n"//&
1693  "The actual thermodynamic timestep that is used in this \n"//&
1694  "case is the largest integer multiple of the coupling \n"//&
1695  "timestep that is less than or equal to DT_THERM.", default=.false.)
1696 
1697  if (.not.cs%bulkmixedlayer) then
1698  call get_param(param_file, "MOM", "HMIX_SFC_PROP", cs%Hmix, &
1699  "If BULKMIXEDLAYER is false, HMIX_SFC_PROP is the depth \n"//&
1700  "over which to average to find surface properties like \n"//&
1701  "SST and SSS or density (but not surface velocities).", &
1702  units="m", default=1.0)
1703  call get_param(param_file, "MOM", "HMIX_UV_SFC_PROP", cs%Hmix_UV, &
1704  "If BULKMIXEDLAYER is false, HMIX_UV_SFC_PROP is the depth\n"//&
1705  "over which to average to find surface flow properties,\n"//&
1706  "SSU, SSV. A non-positive value indicates no averaging.", &
1707  units="m", default=0.)
1708  endif
1709  call get_param(param_file, "MOM", "MIN_Z_DIAG_INTERVAL", z_diag_int, &
1710  "The minimum amount of time in seconds between \n"//&
1711  "calculations of depth-space diagnostics. Making this \n"//&
1712  "larger than DT_THERM reduces the performance penalty \n"//&
1713  "of regridding to depth online.", units="s", default=0.0)
1714  call get_param(param_file, "MOM", "INTERPOLATE_P_SURF", cs%interp_p_surf, &
1715  "If true, linearly interpolate the surface pressure \n"//&
1716  "over the coupling time step, using the specified value \n"//&
1717  "at the end of the step.", default=.false.)
1718 
1719  if (cs%split) then
1720  call get_param(param_file, "MOM", "DTBT", dtbt, default=-0.98)
1721  default_val = cs%dt_therm ; if (dtbt > 0.0) default_val = -1.0
1722  cs%dtbt_reset_period = -1.0
1723  call get_param(param_file, "MOM", "DTBT_RESET_PERIOD", cs%dtbt_reset_period, &
1724  "The period between recalculations of DTBT (if DTBT <= 0). \n"//&
1725  "If DTBT_RESET_PERIOD is negative, DTBT is set based \n"//&
1726  "only on information available at initialization. If \n"//&
1727  "dynamic, DTBT will be set at least every forcing time \n"//&
1728  "step, and if 0, every dynamics time step. The default is \n"//&
1729  "set by DT_THERM. This is only used if SPLIT is true.", &
1730  units="s", default=default_val, do_not_read=(dtbt > 0.0))
1731  endif
1732 
1733  ! This is here in case these values are used inappropriately.
1734  cs%use_frazil = .false. ; cs%bound_salinity = .false. ; cs%tv%P_Ref = 2.0e7
1735  if (cs%use_temperature) then
1736  call get_param(param_file, "MOM", "FRAZIL", cs%use_frazil, &
1737  "If true, water freezes if it gets too cold, and the \n"//&
1738  "the accumulated heat deficit is returned in the \n"//&
1739  "surface state. FRAZIL is only used if \n"//&
1740  "ENABLE_THERMODYNAMICS is true.", default=.false.)
1741  call get_param(param_file, "MOM", "DO_GEOTHERMAL", use_geothermal, &
1742  "If true, apply geothermal heating.", default=.false.)
1743  call get_param(param_file, "MOM", "BOUND_SALINITY", cs%bound_salinity, &
1744  "If true, limit salinity to being positive. (The sea-ice \n"//&
1745  "model may ask for more salt than is available and \n"//&
1746  "drive the salinity negative otherwise.)", default=.false.)
1747  call get_param(param_file, "MOM", "C_P", cs%tv%C_p, &
1748  "The heat capacity of sea water, approximated as a \n"//&
1749  "constant. This is only used if ENABLE_THERMODYNAMICS is \n"//&
1750  "true. The default value is from the TEOS-10 definition \n"//&
1751  "of conservative temperature.", units="J kg-1 K-1", &
1752  default=3991.86795711963)
1753  endif
1754  if (use_eos) call get_param(param_file, "MOM", "P_REF", cs%tv%P_Ref, &
1755  "The pressure that is used for calculating the coordinate \n"//&
1756  "density. (1 Pa = 1e4 dbar, so 2e7 is commonly used.) \n"//&
1757  "This is only used if USE_EOS and ENABLE_THERMODYNAMICS \n"//&
1758  "are true.", units="Pa", default=2.0e7)
1759 
1760  if (cs%bulkmixedlayer) then
1761  call get_param(param_file, "MOM", "NKML", nkml, &
1762  "The number of sublayers within the mixed layer if \n"//&
1763  "BULKMIXEDLAYER is true.", units="nondim", default=2)
1764  call get_param(param_file, "MOM", "NKBL", nkbl, &
1765  "The number of layers that are used as variable density \n"//&
1766  "buffer layers if BULKMIXEDLAYER is true.", units="nondim", &
1767  default=2)
1768  endif
1769 
1770  call get_param(param_file, "MOM", "GLOBAL_INDEXING", global_indexing, &
1771  "If true, use a global lateral indexing convention, so \n"//&
1772  "that corresponding points on different processors have \n"//&
1773  "the same index. This does not work with static memory.", &
1774  default=.false., layoutparam=.true.)
1775 #ifdef STATIC_MEMORY_
1776  if (global_indexing) call mom_error(fatal, "initialize_MOM: "//&
1777  "GLOBAL_INDEXING can not be true with STATIC_MEMORY.")
1778 #endif
1779  call get_param(param_file, "MOM", "FIRST_DIRECTION", first_direction, &
1780  "An integer that indicates which direction goes first \n"//&
1781  "in parts of the code that use directionally split \n"//&
1782  "updates, with even numbers (or 0) used for x- first \n"//&
1783  "and odd numbers used for y-first.", default=0)
1784 
1785  call get_param(param_file, "MOM", "CHECK_BAD_SURFACE_VALS", &
1786  cs%check_bad_surface_vals, &
1787  "If true, check the surface state for ridiculous values.", &
1788  default=.false.)
1789  if (cs%check_bad_surface_vals) then
1790  call get_param(param_file, "MOM", "BAD_VAL_SSH_MAX", cs%bad_val_ssh_max, &
1791  "The value of SSH above which a bad value message is \n"//&
1792  "triggered, if CHECK_BAD_SURFACE_VALS is true.", units="m", &
1793  default=20.0)
1794  call get_param(param_file, "MOM", "BAD_VAL_SSS_MAX", cs%bad_val_sss_max, &
1795  "The value of SSS above which a bad value message is \n"//&
1796  "triggered, if CHECK_BAD_SURFACE_VALS is true.", units="PPT", &
1797  default=45.0)
1798  call get_param(param_file, "MOM", "BAD_VAL_SST_MAX", cs%bad_val_sst_max, &
1799  "The value of SST above which a bad value message is \n"//&
1800  "triggered, if CHECK_BAD_SURFACE_VALS is true.", &
1801  units="deg C", default=45.0)
1802  call get_param(param_file, "MOM", "BAD_VAL_SST_MIN", cs%bad_val_sst_min, &
1803  "The value of SST below which a bad value message is \n"//&
1804  "triggered, if CHECK_BAD_SURFACE_VALS is true.", &
1805  units="deg C", default=-2.1)
1806  call get_param(param_file, "MOM", "BAD_VAL_COLUMN_THICKNESS", cs%bad_val_column_thickness, &
1807  "The value of column thickness below which a bad value message is \n"//&
1808  "triggered, if CHECK_BAD_SURFACE_VALS is true.", units="m", &
1809  default=0.0)
1810  endif
1811 
1812  call get_param(param_file, "MOM", "SAVE_INITIAL_CONDS", save_ic, &
1813  "If true, write the initial conditions to a file given \n"//&
1814  "by IC_OUTPUT_FILE.", default=.false.)
1815  call get_param(param_file, "MOM", "IC_OUTPUT_FILE", cs%IC_file, &
1816  "The file into which to write the initial conditions.", &
1817  default="MOM_IC")
1818  call get_param(param_file, "MOM", "WRITE_GEOM", write_geom, &
1819  "If =0, never write the geometry and vertical grid files.\n"//&
1820  "If =1, write the geometry and vertical grid files only for\n"//&
1821  "a new simulation. If =2, always write the geometry and\n"//&
1822  "vertical grid files. Other values are invalid.", default=1)
1823  if (write_geom<0 .or. write_geom>2) call mom_error(fatal,"MOM: "//&
1824  "WRITE_GEOM must be equal to 0, 1 or 2.")
1825  write_geom_files = ((write_geom==2) .or. ((write_geom==1) .and. &
1826  ((dirs%input_filename(1:1)=='n') .and. (len_trim(dirs%input_filename)==1))))
1827 
1828  ! Check for inconsistent parameter settings.
1829  if (cs%use_ALE_algorithm .and. cs%bulkmixedlayer) call mom_error(fatal, &
1830  "MOM: BULKMIXEDLAYER can not currently be used with the ALE algorithm.")
1831  if (cs%use_ALE_algorithm .and. .not.cs%use_temperature) call mom_error(fatal, &
1832  "MOM: At this time, USE_EOS should be True when using the ALE algorithm.")
1833  if (cs%adiabatic .and. cs%use_temperature) call mom_error(warning, &
1834  "MOM: ADIABATIC and ENABLE_THERMODYNAMICS both defined is usually unwise.")
1835  if (use_eos .and. .not.cs%use_temperature) call mom_error(fatal, &
1836  "MOM: ENABLE_THERMODYNAMICS must be defined to use USE_EOS.")
1837  if (cs%adiabatic .and. cs%bulkmixedlayer) call mom_error(fatal, &
1838  "MOM: ADIABATIC and BULKMIXEDLAYER can not both be defined.")
1839  if (cs%bulkmixedlayer .and. .not.use_eos) call mom_error(fatal, &
1840  "initialize_MOM: A bulk mixed layer can only be used with T & S as "//&
1841  "state variables. Add USE_EOS = True to MOM_input.")
1842 
1843  call get_param(param_file, 'MOM', "ICE_SHELF", use_ice_shelf, default=.false., do_not_log=.true.)
1844  if (use_ice_shelf) then
1845  inputdir = "." ; call get_param(param_file, 'MOM', "INPUTDIR", inputdir)
1846  inputdir = slasher(inputdir)
1847  call get_param(param_file, 'MOM', "ICE_THICKNESS_FILE", ice_shelf_file, &
1848  "The file from which the ice bathymetry and area are read.", &
1849  fail_if_missing=.true.)
1850  call get_param(param_file, 'MOM', "ICE_AREA_VARNAME", area_varname, &
1851  "The name of the area variable in ICE_THICKNESS_FILE.", &
1852  fail_if_missing=.true.)
1853  endif
1854 
1855 
1856  call calltree_waypoint("MOM parameters read (initialize_MOM)")
1857 
1858  ! Set up the model domain and grids.
1859 #ifdef SYMMETRIC_MEMORY_
1860  symmetric = .true.
1861 #else
1862  symmetric = .false.
1863 #endif
1864 #ifdef STATIC_MEMORY_
1865  call mom_domains_init(g%domain, param_file, symmetric=symmetric, &
1866  static_memory=.true., nihalo=nihalo_, njhalo=njhalo_, &
1867  niglobal=niglobal_, njglobal=njglobal_, niproc=niproc_, &
1868  njproc=njproc_)
1869 #else
1870  call mom_domains_init(g%domain, param_file, symmetric=symmetric)
1871 #endif
1872  call calltree_waypoint("domains initialized (initialize_MOM)")
1873 
1874  call mom_debugging_init(param_file)
1875  call diag_mediator_infrastructure_init()
1876  call mom_io_init(param_file)
1877 
1878  call hor_index_init(g%Domain, hi, param_file, &
1879  local_indexing=.not.global_indexing)
1880 
1881  call create_dyn_horgrid(dg, hi, bathymetry_at_vel=bathy_at_vel)
1882  call clone_mom_domain(g%Domain, dg%Domain)
1883 
1884  call verticalgridinit( param_file, cs%GV )
1885  gv => cs%GV
1886 ! dG%g_Earth = GV%g_Earth
1887 
1888  ! Allocate the auxiliary non-symmetric domain for debugging or I/O purposes.
1889  if (cs%debug .or. dg%symmetric) &
1890  call clone_mom_domain(dg%Domain, dg%Domain_aux, symmetric=.false.)
1891 
1892  call calltree_waypoint("grids initialized (initialize_MOM)")
1893 
1894 
1895  call mom_timing_init(cs)
1896 
1897  call tracer_registry_init(param_file, cs%tracer_Reg)
1898 
1899  is = dg%isc ; ie = dg%iec ; js = dg%jsc ; je = dg%jec ; nz = gv%ke
1900  isd = dg%isd ; ied = dg%ied ; jsd = dg%jsd ; jed = dg%jed
1901  isdb = dg%IsdB ; iedb = dg%IedB ; jsdb = dg%JsdB ; jedb = dg%JedB
1902 
1903  ! Allocate and initialize space for primary MOM variables.
1904  alloc_(cs%u(isdb:iedb,jsd:jed,nz)) ; cs%u(:,:,:) = 0.0
1905  alloc_(cs%v(isd:ied,jsdb:jedb,nz)) ; cs%v(:,:,:) = 0.0
1906  alloc_(cs%h(isd:ied,jsd:jed,nz)) ; cs%h(:,:,:) = gv%Angstrom
1907  alloc_(cs%uh(isdb:iedb,jsd:jed,nz)) ; cs%uh(:,:,:) = 0.0
1908  alloc_(cs%vh(isd:ied,jsdb:jedb,nz)) ; cs%vh(:,:,:) = 0.0
1909  if (cs%use_temperature) then
1910  alloc_(cs%T(isd:ied,jsd:jed,nz)) ; cs%T(:,:,:) = 0.0
1911  alloc_(cs%S(isd:ied,jsd:jed,nz)) ; cs%S(:,:,:) = 0.0
1912  cs%tv%T => cs%T ; cs%tv%S => cs%S
1913  cs%vd_T = var_desc(name="T",units="degC",longname="Potential Temperature", &
1914  cmor_field_name="thetao",cmor_units="C", &
1915  conversion=cs%tv%C_p)
1916  cs%vd_S = var_desc(name="S",units="PPT",longname="Salinity",&
1917  cmor_field_name="so",cmor_units="ppt", &
1918  conversion=0.001)
1919  if(cs%advect_TS) then
1920  call register_tracer(cs%tv%T, cs%vd_T, param_file, dg%HI, gv, cs%tracer_Reg, cs%vd_T)
1921  call register_tracer(cs%tv%S, cs%vd_S, param_file, dg%HI, gv, cs%tracer_Reg, cs%vd_S)
1922  endif
1923  endif
1924  if (cs%use_frazil) then
1925  allocate(cs%tv%frazil(isd:ied,jsd:jed)) ; cs%tv%frazil(:,:) = 0.0
1926  endif
1927  if (cs%bound_salinity) then
1928  allocate(cs%tv%salt_deficit(isd:ied,jsd:jed)) ; cs%tv%salt_deficit(:,:)=0.0
1929  endif
1930 
1931  if (cs%bulkmixedlayer .or. cs%use_temperature) then
1932  allocate(cs%Hml(isd:ied,jsd:jed)) ; cs%Hml(:,:) = 0.0
1933  endif
1934 
1935  if (cs%bulkmixedlayer) then
1936  gv%nkml = nkml ; gv%nk_rho_varies = nkml + nkbl
1937  else
1938  gv%nkml = 0 ; gv%nk_rho_varies = 0
1939  endif
1940  if (cs%use_ALE_algorithm) then
1941  call get_param(param_file, "MOM", "NK_RHO_VARIES", gv%nk_rho_varies, default=0) ! Will default to nz later... -AJA
1942  endif
1943 
1944  alloc_(cs%uhtr(isdb:iedb,jsd:jed,nz)) ; cs%uhtr(:,:,:) = 0.0
1945  alloc_(cs%vhtr(isd:ied,jsdb:jedb,nz)) ; cs%vhtr(:,:,:) = 0.0
1946  cs%t_dyn_rel_adv = 0.0 ; cs%t_dyn_rel_thermo = 0.0 ; cs%t_dyn_rel_diag = 0.0
1947 
1948  if (cs%debug_truncations) then
1949  allocate(cs%u_prev(isdb:iedb,jsd:jed,nz)) ; cs%u_prev(:,:,:) = 0.0
1950  allocate(cs%v_prev(isd:ied,jsdb:jedb,nz)) ; cs%u_prev(:,:,:) = 0.0
1951  endif
1952 
1953  mom_internal_state%u => cs%u ; mom_internal_state%v => cs%v
1954  mom_internal_state%h => cs%h
1955  mom_internal_state%uh => cs%uh ; mom_internal_state%vh => cs%vh
1956  if (cs%use_temperature) then
1957  mom_internal_state%T => cs%T ; mom_internal_state%S => cs%S
1958  endif
1959 
1960  cs%CDp%uh => cs%uh ; cs%CDp%vh => cs%vh
1961 
1962  if (cs%interp_p_surf) then
1963  allocate(cs%p_surf_prev(isd:ied,jsd:jed)) ; cs%p_surf_prev(:,:) = 0.0
1964  endif
1965 
1966  alloc_(cs%ave_ssh(isd:ied,jsd:jed)) ; cs%ave_ssh(:,:) = 0.0
1967 
1968  ! Use the Wright equation of state by default, unless otherwise specified
1969  ! Note: this line and the following block ought to be in a separate
1970  ! initialization routine for tv.
1971  if (use_eos) call eos_init(param_file, cs%tv%eqn_of_state)
1972  if (cs%use_temperature) then
1973  allocate(cs%tv%TempxPmE(isd:ied,jsd:jed))
1974  cs%tv%TempxPmE(:,:) = 0.0
1975  if (use_geothermal) then
1976  allocate(cs%tv%internal_heat(isd:ied,jsd:jed))
1977  cs%tv%internal_heat(:,:) = 0.0
1978  endif
1979  endif
1980  call calltree_waypoint("state variables allocated (initialize_MOM)")
1981 
1982  ! Set the fields that are needed for bitwise identical restarting
1983  ! the time stepping scheme.
1984  call restart_init(param_file, cs%restart_CSp)
1985  call set_restart_fields(gv, param_file, cs)
1986  if (cs%split) then
1987  if (cs%legacy_split) then
1988  call register_restarts_dyn_legacy_split(dg%HI, gv, param_file, &
1989  cs%dyn_legacy_split_CSp, cs%restart_CSp, cs%uh, cs%vh)
1990  else
1991  call register_restarts_dyn_split_rk2(dg%HI, gv, param_file, &
1992  cs%dyn_split_RK2_CSp, cs%restart_CSp, cs%uh, cs%vh)
1993  endif
1994  else
1995  if (cs%use_RK2) then
1996  call register_restarts_dyn_unsplit_rk2(dg%HI, gv, param_file, &
1997  cs%dyn_unsplit_RK2_CSp, cs%restart_CSp)
1998  else
1999  call register_restarts_dyn_unsplit(dg%HI, gv, param_file, &
2000  cs%dyn_unsplit_CSp, cs%restart_CSp)
2001  endif
2002  endif
2003 
2004  ! This subroutine calls user-specified tracer registration routines.
2005  ! Additional calls can be added to MOM_tracer_flow_control.F90.
2006  call call_tracer_register(dg%HI, gv, param_file, cs%tracer_flow_CSp, &
2007  cs%tracer_Reg, cs%restart_CSp)
2008 
2009  call meke_alloc_register_restart(dg%HI, param_file, cs%MEKE, cs%restart_CSp)
2010  call set_visc_register_restarts(dg%HI, gv, param_file, cs%visc, cs%restart_CSp)
2011  call mixedlayer_restrat_register_restarts(dg%HI, param_file, cs%mixedlayer_restrat_CSp, cs%restart_CSp)
2012 
2013  ! Initialize fields
2014  call calltree_waypoint("restart registration complete (initialize_MOM)")
2015 
2016  call cpu_clock_begin(id_clock_mom_init)
2017  call mom_initialize_fixed(dg, cs%OBC, param_file, write_geom_files, dirs%output_directory)
2018  call calltree_waypoint("returned from MOM_initialize_fixed() (initialize_MOM)")
2019 
2020  if (associated(cs%OBC)) call call_obc_register(param_file, cs%update_OBC_CSp, cs%OBC)
2021 
2022  call mom_initialize_coord(gv, param_file, write_geom_files, &
2023  dirs%output_directory, cs%tv, dg%max_depth)
2024  call calltree_waypoint("returned from MOM_initialize_coord() (initialize_MOM)")
2025 
2026  if (cs%use_ALE_algorithm) then
2027  call ale_init(param_file, gv, dg%max_depth, cs%ALE_CSp)
2028  call calltree_waypoint("returned from ALE_init() (initialize_MOM)")
2029  endif
2030 
2031  ! Shift from using the temporary dynamic grid type to using the final
2032  ! (potentially static) ocean-specific grid type.
2033  ! The next line would be needed if G%Domain had not already been init'd above:
2034  ! call clone_MOM_domain(dG%Domain, G%Domain)
2035  call mom_grid_init(g, param_file, hi, bathymetry_at_vel=bathy_at_vel)
2036  call copy_dyngrid_to_mom_grid(dg, g)
2037  call destroy_dyn_horgrid(dg)
2038 
2039  ! Set a few remaining fields that are specific to the ocean grid type.
2040  call set_first_direction(g, first_direction)
2041  ! Allocate the auxiliary non-symmetric domain for debugging or I/O purposes.
2042  if (cs%debug .or. g%symmetric) &
2043  call clone_mom_domain(g%Domain, g%Domain_aux, symmetric=.false.)
2044  ! Copy common variables from the vertical grid to the horizontal grid.
2045  ! Consider removing this later?
2046  g%ke = gv%ke ; g%g_Earth = gv%g_Earth
2047 
2048  call mom_initialize_state(cs%u, cs%v, cs%h, cs%tv, time, g, gv, param_file, &
2049  dirs, cs%restart_CSp, cs%ALE_CSp, cs%tracer_Reg, &
2050  cs%sponge_CSp, cs%ALE_sponge_CSp, cs%OBC, time_in)
2051  call cpu_clock_end(id_clock_mom_init)
2052  call calltree_waypoint("returned from MOM_initialize_state() (initialize_MOM)")
2053 
2054  ! From this point, there may be pointers being set, so the final grid type
2055  ! that will persist throughout the run has to be used.
2056 
2057  if (test_grid_copy) then
2058  ! Copy the data from the temporary grid to the dyn_hor_grid to CS%G.
2059  call create_dyn_horgrid(dg, g%HI)
2060  call clone_mom_domain(g%Domain, dg%Domain)
2061 
2062  call clone_mom_domain(g%Domain, cs%G%Domain)
2063  call mom_grid_init(cs%G, param_file)
2064 
2065  call copy_mom_grid_to_dyngrid(g, dg)
2066  call copy_dyngrid_to_mom_grid(dg, cs%G)
2067 
2068  call destroy_dyn_horgrid(dg)
2069  call mom_grid_end(g) ; deallocate(g)
2070 
2071  g => cs%G
2072  if (cs%debug .or. cs%G%symmetric) &
2073  call clone_mom_domain(cs%G%Domain, cs%G%Domain_aux, symmetric=.false.)
2074  g%ke = gv%ke ; g%g_Earth = gv%g_Earth
2075  endif
2076 
2077 
2078  ! At this point, all user-modified initialization code has been called. The
2079  ! remainder of this subroutine is controlled by the parameters that have
2080  ! have already been set.
2081 
2082  if (ale_remap_init_conds(cs%ALE_CSp) .and. .not. query_initialized(cs%h,"h",cs%restart_CSp)) then
2083  ! This block is controlled by the ALE parameter REMAP_AFTER_INITIALIZATION.
2084  ! \todo This block exists for legacy reasons and we should phase it out of
2085  ! all examples.
2086  if (cs%debug) then
2087  call uvchksum("Pre ALE adjust init cond [uv]", &
2088  cs%u, cs%v, g%HI, haloshift=1)
2089  call hchksum(cs%h,"Pre ALE adjust init cond h", g%HI, haloshift=1, scale=gv%H_to_m)
2090  endif
2091  call calltree_waypoint("Calling adjustGridForIntegrity() to remap initial conditions (initialize_MOM)")
2092  call adjustgridforintegrity(cs%ALE_CSp, g, gv, cs%h )
2093  call calltree_waypoint("Calling ALE_main() to remap initial conditions (initialize_MOM)")
2094  if (use_ice_shelf) then
2095  filename = trim(inputdir)//trim(ice_shelf_file)
2096  if (.not.file_exists(filename, g%Domain)) call mom_error(fatal, &
2097  "MOM: Unable to open "//trim(filename))
2098 
2099  allocate(area_shelf_h(isd:ied,jsd:jed))
2100  allocate(frac_shelf_h(isd:ied,jsd:jed))
2101  call read_data(filename,trim(area_varname),area_shelf_h,domain=g%Domain%mpp_domain)
2102  ! initialize frac_shelf_h with zeros (open water everywhere)
2103  frac_shelf_h(:,:) = 0.0
2104  ! compute fractional ice shelf coverage of h
2105  do j=jsd,jed ; do i=isd,ied
2106  if (g%areaT(i,j) > 0.0) &
2107  frac_shelf_h(i,j) = area_shelf_h(i,j) / g%areaT(i,j)
2108  enddo ; enddo
2109  ! pass to the pointer
2110  shelf_area => frac_shelf_h
2111  call ale_main(g, gv, cs%h, cs%u, cs%v, cs%tv, cs%tracer_Reg, cs%ALE_CSp, &
2112  frac_shelf_h = shelf_area)
2113  else
2114  call ale_main( g, gv, cs%h, cs%u, cs%v, cs%tv, cs%tracer_Reg, cs%ALE_CSp )
2115  endif
2116  call cpu_clock_begin(id_clock_pass_init)
2117  call create_group_pass(tmp_pass_uv_t_s_h, cs%u, cs%v, g%Domain)
2118  if (cs%use_temperature) then
2119  call create_group_pass(tmp_pass_uv_t_s_h, cs%tv%T, g%Domain, halo=1)
2120  call create_group_pass(tmp_pass_uv_t_s_h, cs%tv%S, g%Domain, halo=1)
2121  endif
2122  call create_group_pass(tmp_pass_uv_t_s_h, cs%h, g%Domain, halo=1)
2123  call do_group_pass(tmp_pass_uv_t_s_h, g%Domain)
2124  call cpu_clock_end(id_clock_pass_init)
2125 
2126  if (cs%debug) then
2127  call uvchksum("Post ALE adjust init cond [uv]", cs%u, cs%v, g%HI, haloshift=1)
2128  call hchksum(cs%h, "Post ALE adjust init cond h", g%HI, haloshift=1, scale=gv%H_to_m)
2129  endif
2130  endif
2131  if ( cs%use_ALE_algorithm ) call ale_updateverticalgridtype( cs%ALE_CSp, gv )
2132 
2133  diag => cs%diag
2134  ! Initialize the diag mediator.
2135  call diag_mediator_init(g, gv%ke, param_file, diag, doc_file_dir=dirs%output_directory)
2136 
2137  ! Initialize the diagnostics mask arrays.
2138  ! This step has to be done after call to MOM_initialize_state
2139  ! and before MOM_diagnostics_init
2140  call diag_masks_set(g, gv%ke, cs%missing, diag)
2141 
2142  ! Set up pointers within diag mediator control structure,
2143  ! this needs to occur _after_ CS%h etc. have been allocated.
2144  call diag_set_state_ptrs(cs%h, cs%T, cs%S, cs%tv%eqn_of_state, diag)
2145 
2146  ! This call sets up the diagnostic axes. These are needed,
2147  ! e.g. to generate the target grids below.
2148  call set_axes_info(g, gv, param_file, diag)
2149 
2150  ! Whenever thickness/T/S changes let the diag manager know, target grids
2151  ! for vertical remapping may need to be regenerated.
2152  ! FIXME: are h, T, S updated at the same time? Review these for T, S updates.
2153  call diag_update_remap_grids(diag)
2154 
2155  ! Diagnose static fields AND associate areas/volumes with axes
2156  call write_static_fields(g, cs%diag)
2157  call calltree_waypoint("static fields written (initialize_MOM)")
2158 
2159  call cpu_clock_begin(id_clock_mom_init)
2160  if (cs%use_ALE_algorithm) then
2161  call ale_writecoordinatefile( cs%ALE_CSp, gv, dirs%output_directory )
2162  endif
2163  call cpu_clock_end(id_clock_mom_init)
2164  call calltree_waypoint("ALE initialized (initialize_MOM)")
2165 
2166  cs%useMEKE = meke_init(time, g, param_file, diag, cs%MEKE_CSp, cs%MEKE, cs%restart_CSp)
2167 
2168  call varmix_init(time, g, param_file, diag, cs%VarMix)
2169  call set_visc_init(time, g, gv, param_file, diag, cs%visc, cs%set_visc_CSp,cs%OBC)
2170  if (cs%split) then
2171  allocate(eta(szi_(g),szj_(g))) ; eta(:,:) = 0.0
2172  if (cs%legacy_split) then
2173  call initialize_dyn_legacy_split(cs%u, cs%v, cs%h, cs%uh, cs%vh, eta, time, &
2174  g, gv, param_file, diag, cs%dyn_legacy_split_CSp, cs%restart_CSp, &
2175  cs%dt, cs%ADp, cs%CDp, mom_internal_state, cs%VarMix, cs%MEKE, &
2176  cs%OBC, cs%update_OBC_CSp, cs%ALE_CSp, cs%set_visc_CSp, cs%visc, &
2177  dirs, cs%ntrunc)
2178  else
2179  call initialize_dyn_split_rk2(cs%u, cs%v, cs%h, cs%uh, cs%vh, eta, time, &
2180  g, gv, param_file, diag, cs%dyn_split_RK2_CSp, cs%restart_CSp, &
2181  cs%dt, cs%ADp, cs%CDp, mom_internal_state, cs%VarMix, cs%MEKE, &
2182  cs%OBC, cs%update_OBC_CSp, cs%ALE_CSp, cs%set_visc_CSp, &
2183  cs%visc, dirs, cs%ntrunc)
2184  endif
2185  else
2186  if (cs%use_RK2) then
2187  call initialize_dyn_unsplit_rk2(cs%u, cs%v, cs%h, time, g, gv, &
2188  param_file, diag, cs%dyn_unsplit_RK2_CSp, cs%restart_CSp, &
2189  cs%ADp, cs%CDp, mom_internal_state, cs%OBC, cs%update_OBC_CSp, &
2190  cs%ALE_CSp, cs%set_visc_CSp, cs%visc, dirs, cs%ntrunc)
2191  else
2192  call initialize_dyn_unsplit(cs%u, cs%v, cs%h, time, g, gv, &
2193  param_file, diag, cs%dyn_unsplit_CSp, cs%restart_CSp, &
2194  cs%ADp, cs%CDp, mom_internal_state, cs%OBC, cs%update_OBC_CSp, &
2195  cs%ALE_CSp, cs%set_visc_CSp, cs%visc, dirs, cs%ntrunc)
2196  endif
2197  endif
2198  call calltree_waypoint("dynamics initialized (initialize_MOM)")
2199 
2200  call thickness_diffuse_init(time, g, gv, param_file, diag, cs%CDp, cs%thickness_diffuse_CSp)
2201  cs%mixedlayer_restrat = mixedlayer_restrat_init(time, g, gv, param_file, diag, &
2202  cs%mixedlayer_restrat_CSp)
2203  if (cs%mixedlayer_restrat) then
2204  if (.not.(cs%bulkmixedlayer .or. cs%use_ALE_algorithm)) &
2205  call mom_error(fatal, "MOM: MIXEDLAYER_RESTRAT true requires a boundary layer scheme.")
2206  ! When DIABATIC_FIRST=False and using CS%visc%ML in mixedlayer_restrat we need to update after a restart
2207  if (.not. cs%diabatic_first .and. associated(cs%visc%MLD)) &
2208  call pass_var(cs%visc%MLD, g%domain, halo=1)
2209  endif
2210 
2211  call mom_diagnostics_init(mom_internal_state, cs%ADp, cs%CDp, time, g, gv, &
2212  param_file, diag, cs%diagnostics_CSp)
2213 
2214  cs%Z_diag_interval = set_time(int((cs%dt_therm) * &
2215  max(1,floor(0.01 + z_diag_int/(cs%dt_therm)))))
2216  call mom_diag_to_z_init(time, g, gv, param_file, diag, cs%diag_to_Z_CSp)
2217  cs%Z_diag_time = start_time + cs%Z_diag_interval * (1 + &
2218  ((time + set_time(int(cs%dt_therm))) - start_time) / cs%Z_diag_interval)
2219 
2220  if (associated(cs%sponge_CSp)) &
2221  call init_sponge_diags(time, g, diag, cs%sponge_CSp)
2222 
2223  if (associated(cs%ALE_sponge_CSp)) &
2224  call init_ale_sponge_diags(time, g, diag, cs%ALE_sponge_CSp)
2225 
2226  if (cs%adiabatic) then
2227  call adiabatic_driver_init(time, g, param_file, diag, cs%diabatic_CSp, &
2228  cs%tracer_flow_CSp, cs%diag_to_Z_CSp)
2229  else
2230  call diabatic_driver_init(time, g, gv, param_file, cs%use_ALE_algorithm, diag, &
2231  cs%ADp, cs%CDp, cs%diabatic_CSp, cs%tracer_flow_CSp, &
2232  cs%sponge_CSp, cs%ALE_sponge_CSp, cs%diag_to_Z_CSp)
2233  endif
2234 
2235  call tracer_advect_init(time, g, param_file, diag, cs%tracer_adv_CSp)
2236  call tracer_hor_diff_init(time, g, param_file, diag, cs%tracer_diff_CSp, cs%neutral_diffusion_CSp)
2237 
2238  if (cs%use_ALE_algorithm) &
2239  call register_diags_ts_vardec(time, g%HI, gv, param_file, cs)
2240 
2241  call lock_tracer_registry(cs%tracer_Reg)
2242  call calltree_waypoint("tracer registry now locked (initialize_MOM)")
2243 
2244  ! now register some diagnostics since tracer registry is locked
2245  call register_diags(time, g, gv, cs, cs%ADp)
2246  call register_diags_ts_tendency(time, g, cs)
2247  if (cs%use_ALE_algorithm) then
2248  call ale_register_diags(time, g, diag, cs%tv%C_p, cs%tracer_Reg, cs%ALE_CSp)
2249  endif
2250 
2251 
2252 
2253  ! If need a diagnostic field, then would have been allocated in register_diags.
2254  if (cs%use_temperature) then
2255  if(cs%advect_TS) then
2256  call add_tracer_diagnostics("T", cs%tracer_Reg, cs%T_adx, cs%T_ady, &
2257  cs%T_diffx, cs%T_diffy, cs%T_adx_2d, cs%T_ady_2d, &
2258  cs%T_diffx_2d, cs%T_diffy_2d, cs%T_advection_xy)
2259  call add_tracer_diagnostics("S", cs%tracer_Reg, cs%S_adx, cs%S_ady, &
2260  cs%S_diffx, cs%S_diffy, cs%S_adx_2d, cs%S_ady_2d, &
2261  cs%S_diffx_2d, cs%S_diffy_2d, cs%S_advection_xy)
2262  endif
2263  call register_z_tracer(cs%tv%T, "temp", "Potential Temperature", "degC", time, &
2264  g, cs%diag_to_Z_CSp, cmor_field_name="thetao", cmor_units="C", &
2265  cmor_standard_name="sea_water_potential_temperature", &
2266  cmor_long_name ="Sea Water Potential Temperature")
2267  call register_z_tracer(cs%tv%S, "salt", "Salinity", "PPT", time, &
2268  g, cs%diag_to_Z_CSp, cmor_field_name="so", cmor_units="ppt", &
2269  cmor_standard_name="sea_water_salinity", &
2270  cmor_long_name ="Sea Water Salinity")
2271  endif
2272 
2273  ! This subroutine initializes any tracer packages.
2274  new_sim = ((dirs%input_filename(1:1) == 'n') .and. &
2275  (len_trim(dirs%input_filename) == 1))
2276  call tracer_flow_control_init(.not.new_sim, time, g, gv, cs%h, param_file, &
2277  cs%diag, cs%OBC, cs%tracer_flow_CSp, cs%sponge_CSp, &
2278  cs%ALE_sponge_CSp, cs%diag_to_Z_CSp, cs%tv)
2279 
2280 
2281  ! If running in offline tracer mode, initialize the necessary control structure and
2282  ! parameters
2283  if(present(offline_tracer_mode)) offline_tracer_mode=cs%offline_tracer_mode
2284 
2285  if(cs%offline_tracer_mode) then
2286  ! Setup some initial parameterizations and also assign some of the subtypes
2287  call offline_transport_init(param_file, cs%offline_CSp, cs%diabatic_CSp, g, gv)
2288  call insert_offline_main( cs=cs%offline_CSp, ale_csp=cs%ALE_CSp, diabatic_csp=cs%diabatic_CSp, &
2289  diag=cs%diag, obc=cs%OBC, tracer_adv_csp=cs%tracer_adv_CSp, &
2290  tracer_flow_csp=cs%tracer_flow_CSp, tracer_reg=cs%tracer_Reg, &
2291  tv=cs%tv, x_before_y = (mod(first_direction,2)==0), debug=cs%debug )
2292  call register_diags_offline_transport(time, cs%diag, cs%offline_CSp)
2293  endif
2294 
2295  call cpu_clock_begin(id_clock_pass_init)
2296  !--- set up group pass for u,v,T,S and h. pass_uv_T_S_h also is used in step_MOM
2297 
2298  dynamics_stencil = min(3, g%Domain%nihalo, g%Domain%njhalo)
2299  call create_group_pass(cs%pass_uv_T_S_h, cs%u, cs%v, g%Domain, halo=dynamics_stencil)
2300  if (cs%use_temperature) then
2301  call create_group_pass(cs%pass_uv_T_S_h, cs%tv%T, g%Domain, halo=dynamics_stencil)
2302  call create_group_pass(cs%pass_uv_T_S_h, cs%tv%S, g%Domain, halo=dynamics_stencil)
2303  endif
2304  call create_group_pass(cs%pass_uv_T_S_h, cs%h, g%Domain, halo=dynamics_stencil)
2305 
2306  call do_group_pass(cs%pass_uv_T_S_h, g%Domain)
2307  call cpu_clock_end(id_clock_pass_init)
2308 
2309  call register_obsolete_diagnostics(param_file, cs%diag)
2310  call neutral_diffusion_diag_init(time, g, diag, cs%tv%C_p, cs%tracer_Reg, cs%neutral_diffusion_CSp)
2311 
2312  if (cs%use_frazil) then
2313  if (.not.query_initialized(cs%tv%frazil,"frazil",cs%restart_CSp)) &
2314  cs%tv%frazil(:,:) = 0.0
2315  endif
2316 
2317  if (cs%interp_p_surf) then
2318  cs%p_surf_prev_set = &
2319  query_initialized(cs%p_surf_prev,"p_surf_prev",cs%restart_CSp)
2320 
2321  if (cs%p_surf_prev_set) call pass_var(cs%p_surf_prev, g%domain)
2322  endif
2323 
2324  if (.not.query_initialized(cs%ave_ssh,"ave_ssh",cs%restart_CSp)) then
2325  if (cs%split) then
2326  call find_eta(cs%h, cs%tv, gv%g_Earth, g, gv, cs%ave_ssh, eta)
2327  else
2328  call find_eta(cs%h, cs%tv, gv%g_Earth, g, gv, cs%ave_ssh)
2329  endif
2330  endif
2331  if (cs%split) deallocate(eta)
2332 
2333  ! Flag whether to save initial conditions in finish_MOM_initialization() or not.
2334  cs%write_IC = save_ic .and. &
2335  .not.((dirs%input_filename(1:1) == 'r') .and. &
2336  (len_trim(dirs%input_filename) == 1))
2337 
2338  call calltree_leave("initialize_MOM()")
2339  call cpu_clock_end(id_clock_init)
2340 
2341 end subroutine initialize_mom
2342 
2343 !> This subroutine finishes initializing MOM and writes out the initial conditions.
2344 subroutine finish_mom_initialization(Time, dirs, CS, fluxes)
2345  type(time_type), intent(in) :: Time !< model time, used in this routine
2346  type(directories), intent(in) :: dirs !< structure with directory paths
2347  type(mom_control_struct), pointer :: CS !< pointer set in this routine to MOM control structure
2348  type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
2349  ! Local variables
2350  type(ocean_grid_type), pointer :: G => null()
2351  type(verticalgrid_type), pointer :: GV => null()
2352  type(mom_restart_cs), pointer :: restart_CSp_tmp => null()
2353  real, allocatable :: z_interface(:,:,:) ! Interface heights (meter)
2354  real, allocatable :: eta(:,:) ! Interface heights (meter)
2355  type(vardesc) :: vd
2356 
2357  call cpu_clock_begin(id_clock_init)
2358  call calltree_enter("finish_MOM_initialization()")
2359 
2360  ! Pointers for convenience
2361  g => cs%G ; gv => cs%GV
2362 
2363  ! Write initial conditions
2364  if (cs%write_IC) then
2365  allocate(restart_csp_tmp)
2366  restart_csp_tmp = cs%restart_CSp
2367  allocate(z_interface(szi_(g),szj_(g),szk_(g)+1))
2368  call find_eta(cs%h, cs%tv, gv%g_Earth, g, gv, z_interface)
2369  vd = var_desc("eta","meter","Interface heights",z_grid='i')
2370  call register_restart_field(z_interface, vd, .true., restart_csp_tmp)
2371 
2372  call save_restart(dirs%output_directory, time, g, &
2373  restart_csp_tmp, filename=cs%IC_file, gv=gv)
2374  deallocate(z_interface)
2375  deallocate(restart_csp_tmp)
2376  endif
2377 
2378  call calltree_leave("finish_MOM_initialization()")
2379  call cpu_clock_end(id_clock_init)
2380 
2381 end subroutine finish_mom_initialization
2382 
2383 !> Register the diagnostics
2384 subroutine register_diags(Time, G, GV, CS, ADp)
2385  type(time_type), intent(in) :: Time !< current model time
2386  type(ocean_grid_type), intent(inout) :: G !< ocean grid structu
2387  type(verticalgrid_type), intent(inout) :: GV !< ocean vertical grid structure
2388  type(mom_control_struct), pointer :: CS !< control structure set up by initialize_MOM
2389  type(accel_diag_ptrs), intent(inout) :: ADp !< structure pointing to accelerations in momentum equation
2390 
2391  character(len=48) :: thickness_units, flux_units, T_flux_units, S_flux_units
2392  type(diag_ctrl), pointer :: diag
2393  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB, nz
2394  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
2395  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
2396 
2397  diag => cs%diag
2398 
2399  thickness_units = get_thickness_units(gv)
2400  flux_units = get_flux_units(gv)
2401  t_flux_units = get_tr_flux_units(gv, "Celsius")
2402  s_flux_units = get_tr_flux_units(gv, "PPT")
2403 
2404  !Initialize the diagnostics mask arrays.
2405  !This has to be done after MOM_initialize_state call.
2406  !call diag_masks_set(G, CS%missing)
2407 
2408  cs%id_u = register_diag_field('ocean_model', 'u', diag%axesCuL, time, &
2409  'Zonal velocity', 'meter second-1', cmor_field_name='uo', cmor_units='m s-1', &
2410  cmor_standard_name='sea_water_x_velocity', cmor_long_name='Sea Water X Velocity')
2411  cs%id_v = register_diag_field('ocean_model', 'v', diag%axesCvL, time, &
2412  'Meridional velocity', 'meter second-1', cmor_field_name='vo', cmor_units='m s-1', &
2413  cmor_standard_name='sea_water_y_velocity', cmor_long_name='Sea Water Y Velocity')
2414  cs%id_h = register_diag_field('ocean_model', 'h', diag%axesTL, time, &
2415  'Layer Thickness', thickness_units, v_extensive=.true.)
2416 
2417  cs%id_volo = register_scalar_field('ocean_model', 'volo', time, diag,&
2418  long_name='Total volume of liquid ocean', units='m3', &
2419  standard_name='sea_water_volume')
2420  cs%id_zos = register_diag_field('ocean_model', 'zos', diag%axesT1, time,&
2421  standard_name = 'sea_surface_height_above_geoid', &
2422  long_name= 'Sea surface height above geoid', units='meter', missing_value=cs%missing)
2423  cs%id_zossq = register_diag_field('ocean_model', 'zossq', diag%axesT1, time,&
2424  standard_name='square_of_sea_surface_height_above_geoid', &
2425  long_name='Square of sea surface height above geoid', units='m2', missing_value=cs%missing)
2426  cs%id_ssh = register_diag_field('ocean_model', 'SSH', diag%axesT1, time, &
2427  'Sea Surface Height', 'meter', cs%missing)
2428  cs%id_ssh_ga = register_scalar_field('ocean_model', 'ssh_ga', time, diag,&
2429  long_name='Area averaged sea surface height', units='m', &
2430  standard_name='area_averaged_sea_surface_height')
2431  cs%id_ssh_inst = register_diag_field('ocean_model', 'SSH_inst', diag%axesT1, time, &
2432  'Instantaneous Sea Surface Height', 'meter', cs%missing)
2433  cs%id_ssu = register_diag_field('ocean_model', 'SSU', diag%axesCu1, time, &
2434  'Sea Surface Zonal Velocity', 'meter second-1', cs%missing)
2435  cs%id_ssv = register_diag_field('ocean_model', 'SSV', diag%axesCv1, time, &
2436  'Sea Surface Meridional Velocity', 'meter second-1', cs%missing)
2437  cs%id_speed = register_diag_field('ocean_model', 'speed', diag%axesT1, time, &
2438  'Sea Surface Speed', 'meter second-1', cs%missing)
2439 
2440  if (cs%use_temperature) then
2441  cs%id_T = register_diag_field('ocean_model', 'temp', diag%axesTL, time, &
2442  'Potential Temperature', 'Celsius', &
2443  cmor_field_name="thetao", cmor_units="C", &
2444  cmor_standard_name="sea_water_potential_temperature", &
2445  cmor_long_name ="Sea Water Potential Temperature")
2446  cs%id_S = register_diag_field('ocean_model', 'salt', diag%axesTL, time, &
2447  long_name='Salinity', units='PPT', cmor_field_name='so', &
2448  cmor_long_name='Sea Water Salinity', cmor_units='ppt', &
2449  cmor_standard_name='sea_water_salinity')
2450  cs%id_tob = register_diag_field('ocean_model','tob', diag%axesT1, time, &
2451  long_name='Sea Water Potential Temperature at Sea Floor', &
2452  standard_name='sea_water_potential_temperature_at_sea_floor', units='degC')
2453  cs%id_sob = register_diag_field('ocean_model','sob',diag%axesT1, time, &
2454  long_name='Sea Water Salinity at Sea Floor', &
2455  standard_name='sea_water_salinity_at_sea_floor', units='ppt')
2456  cs%id_sst = register_diag_field('ocean_model', 'SST', diag%axesT1, time, &
2457  'Sea Surface Temperature', 'Celsius', cs%missing, cmor_field_name='tos', &
2458  cmor_long_name='Sea Surface Temperature', cmor_units='degC', &
2459  cmor_standard_name='sea_surface_temperature')
2460  cs%id_sst_sq = register_diag_field('ocean_model', 'SST_sq', diag%axesT1, time, &
2461  'Sea Surface Temperature Squared', 'Celsius**2', cs%missing, cmor_field_name='tossq', &
2462  cmor_long_name='Square of Sea Surface Temperature ', cmor_units='degC^2', &
2463  cmor_standard_name='square_of_sea_surface_temperature')
2464  cs%id_sss = register_diag_field('ocean_model', 'SSS', diag%axesT1, time, &
2465  'Sea Surface Salinity', 'PPT', cs%missing, cmor_field_name='sos', &
2466  cmor_long_name='Sea Surface Salinity', cmor_units='ppt', &
2467  cmor_standard_name='sea_surface_salinity')
2468  cs%id_sss_sq = register_diag_field('ocean_model', 'SSS_sq', diag%axesT1, time, &
2469  'Sea Surface Salinity Squared', 'ppt**2', cs%missing, cmor_field_name='sossq', &
2470  cmor_long_name='Square of Sea Surface Salinity ', cmor_units='ppt^2', &
2471  cmor_standard_name='square_of_sea_surface_salinity')
2472  cs%id_Tcon = register_diag_field('ocean_model', 'contemp', diag%axesTL, time, &
2473  'Conservative Temperature', 'Celsius')
2474  cs%id_Sabs = register_diag_field('ocean_model', 'abssalt', diag%axesTL, time, &
2475  long_name='Absolute Salinity', units='g/Kg')
2476  cs%id_sstcon = register_diag_field('ocean_model', 'conSST', diag%axesT1, time, &
2477  'Sea Surface Conservative Temperature', 'Celsius', cs%missing)
2478  cs%id_sssabs = register_diag_field('ocean_model', 'absSSS', diag%axesT1, time, &
2479  'Sea Surface Absolute Salinity', 'g/Kg', cs%missing)
2480 
2481  endif
2482 
2483  if (cs%use_temperature .and. cs%use_frazil) then
2484  cs%id_fraz = register_diag_field('ocean_model', 'frazil', diag%axesT1, time, &
2485  'Heat from frazil formation', 'Watt meter-2', cmor_field_name='hfsifrazil', &
2486  cmor_units='W m-2', cmor_standard_name='heat_flux_into_sea_water_due_to_frazil_ice_formation', &
2487  cmor_long_name='Heat Flux into Sea Water due to Frazil Ice Formation')
2488  endif
2489 
2490  cs%id_salt_deficit = register_diag_field('ocean_model', 'salt_deficit', diag%axesT1, time, &
2491  'Salt sink in ocean due to ice flux', 'g Salt meter-2 s-1')
2492  cs%id_Heat_PmE = register_diag_field('ocean_model', 'Heat_PmE', diag%axesT1, time, &
2493  'Heat flux into ocean from mass flux into ocean', 'Watt meter-2')
2494  cs%id_intern_heat = register_diag_field('ocean_model', 'internal_heat', diag%axesT1, time,&
2495  'Heat flux into ocean from geothermal or other internal sources', 'Watt meter-2')
2496 
2497 
2498  ! lateral heat advective and diffusive fluxes
2499  cs%id_Tadx = register_diag_field('ocean_model', 'T_adx', diag%axesCuL, time, &
2500  'Advective (by residual mean) Zonal Flux of Potential Temperature', t_flux_units)
2501  cs%id_Tady = register_diag_field('ocean_model', 'T_ady', diag%axesCvL, time, &
2502  'Advective (by residual mean) Meridional Flux of Potential Temperature', t_flux_units)
2503  cs%id_Tdiffx = register_diag_field('ocean_model', 'T_diffx', diag%axesCuL, time, &
2504  'Diffusive Zonal Flux of Potential Temperature', t_flux_units)
2505  cs%id_Tdiffy = register_diag_field('ocean_model', 'T_diffy', diag%axesCvL, time, &
2506  'Diffusive Meridional Flux of Potential Temperature', t_flux_units)
2507  if (cs%id_Tadx > 0) call safe_alloc_ptr(cs%T_adx,isdb,iedb,jsd,jed,nz)
2508  if (cs%id_Tady > 0) call safe_alloc_ptr(cs%T_ady,isd,ied,jsdb,jedb,nz)
2509  if (cs%id_Tdiffx > 0) call safe_alloc_ptr(cs%T_diffx,isdb,iedb,jsd,jed,nz)
2510  if (cs%id_Tdiffy > 0) call safe_alloc_ptr(cs%T_diffy,isd,ied,jsdb,jedb,nz)
2511 
2512 
2513  ! lateral salt advective and diffusive fluxes
2514  cs%id_Sadx = register_diag_field('ocean_model', 'S_adx', diag%axesCuL, time, &
2515  'Advective (by residual mean) Zonal Flux of Salinity', s_flux_units)
2516  cs%id_Sady = register_diag_field('ocean_model', 'S_ady', diag%axesCvL, time, &
2517  'Advective (by residual mean) Meridional Flux of Salinity', s_flux_units)
2518  cs%id_Sdiffx = register_diag_field('ocean_model', 'S_diffx', diag%axesCuL, time, &
2519  'Diffusive Zonal Flux of Salinity', s_flux_units)
2520  cs%id_Sdiffy = register_diag_field('ocean_model', 'S_diffy', diag%axesCvL, time, &
2521  'Diffusive Meridional Flux of Salinity', s_flux_units)
2522  if (cs%id_Sadx > 0) call safe_alloc_ptr(cs%S_adx,isdb,iedb,jsd,jed,nz)
2523  if (cs%id_Sady > 0) call safe_alloc_ptr(cs%S_ady,isd,ied,jsdb,jedb,nz)
2524  if (cs%id_Sdiffx > 0) call safe_alloc_ptr(cs%S_diffx,isdb,iedb,jsd,jed,nz)
2525  if (cs%id_Sdiffy > 0) call safe_alloc_ptr(cs%S_diffy,isd,ied,jsdb,jedb,nz)
2526 
2527 
2528  ! vertically integrated lateral heat advective and diffusive fluxes
2529  cs%id_Tadx_2d = register_diag_field('ocean_model', 'T_adx_2d', diag%axesCu1, time, &
2530  'Vertically Integrated Advective Zonal Flux of Potential Temperature', t_flux_units)
2531  cs%id_Tady_2d = register_diag_field('ocean_model', 'T_ady_2d', diag%axesCv1, time, &
2532  'Vertically Integrated Advective Meridional Flux of Potential Temperature', t_flux_units)
2533  cs%id_Tdiffx_2d = register_diag_field('ocean_model', 'T_diffx_2d', diag%axesCu1, time, &
2534  'Vertically Integrated Diffusive Zonal Flux of Potential Temperature', t_flux_units)
2535  cs%id_Tdiffy_2d = register_diag_field('ocean_model', 'T_diffy_2d', diag%axesCv1, time, &
2536  'Vertically Integrated Diffusive Meridional Flux of Potential Temperature', t_flux_units)
2537  if (cs%id_Tadx_2d > 0) call safe_alloc_ptr(cs%T_adx_2d,isdb,iedb,jsd,jed)
2538  if (cs%id_Tady_2d > 0) call safe_alloc_ptr(cs%T_ady_2d,isd,ied,jsdb,jedb)
2539  if (cs%id_Tdiffx_2d > 0) call safe_alloc_ptr(cs%T_diffx_2d,isdb,iedb,jsd,jed)
2540  if (cs%id_Tdiffy_2d > 0) call safe_alloc_ptr(cs%T_diffy_2d,isd,ied,jsdb,jedb)
2541 
2542  ! vertically integrated lateral salt advective and diffusive fluxes
2543  cs%id_Sadx_2d = register_diag_field('ocean_model', 'S_adx_2d', diag%axesCu1, time, &
2544  'Vertically Integrated Advective Zonal Flux of Salinity', s_flux_units)
2545  cs%id_Sady_2d = register_diag_field('ocean_model', 'S_ady_2d', diag%axesCv1, time, &
2546  'Vertically Integrated Advective Meridional Flux of Salinity', s_flux_units)
2547  cs%id_Sdiffx_2d = register_diag_field('ocean_model', 'S_diffx_2d', diag%axesCu1, time, &
2548  'Vertically Integrated Diffusive Zonal Flux of Salinity', s_flux_units)
2549  cs%id_Sdiffy_2d = register_diag_field('ocean_model', 'S_diffy_2d', diag%axesCv1, time, &
2550  'Vertically Integrated Diffusive Meridional Flux of Salinity', s_flux_units)
2551  if (cs%id_Sadx_2d > 0) call safe_alloc_ptr(cs%S_adx_2d,isdb,iedb,jsd,jed)
2552  if (cs%id_Sady_2d > 0) call safe_alloc_ptr(cs%S_ady_2d,isd,ied,jsdb,jedb)
2553  if (cs%id_Sdiffx_2d > 0) call safe_alloc_ptr(cs%S_diffx_2d,isdb,iedb,jsd,jed)
2554  if (cs%id_Sdiffy_2d > 0) call safe_alloc_ptr(cs%S_diffy_2d,isd,ied,jsdb,jedb)
2555 
2556 
2557  if (cs%debug_truncations) then
2558  call safe_alloc_ptr(adp%du_dt_visc,isdb,iedb,jsd,jed,nz)
2559  call safe_alloc_ptr(adp%dv_dt_visc,isd,ied,jsdb,jedb,nz)
2560  if (.not.cs%adiabatic) then
2561  call safe_alloc_ptr(adp%du_dt_dia,isdb,iedb,jsd,jed,nz)
2562  call safe_alloc_ptr(adp%dv_dt_dia,isd,ied,jsdb,jedb,nz)
2563  endif
2564  endif
2565 
2566  ! fields posted prior to dynamics step
2567  cs%id_h_pre_dyn = register_diag_field('ocean_model', 'h_pre_dyn', diag%axesTL, time, &
2568  'Layer Thickness before dynamics step', thickness_units)
2569 
2570  ! diagnostics for values prior to diabatic and prior to ALE
2571  cs%id_u_predia = register_diag_field('ocean_model', 'u_predia', diag%axesCuL, time, &
2572  'Zonal velocity before diabatic forcing', 'meter second-1')
2573  cs%id_v_predia = register_diag_field('ocean_model', 'v_predia', diag%axesCvL, time, &
2574  'Meridional velocity before diabatic forcing', 'meter second-1')
2575  cs%id_h_predia = register_diag_field('ocean_model', 'h_predia', diag%axesTL, time, &
2576  'Layer Thickness before diabatic forcing', thickness_units, v_extensive=.true.)
2577  cs%id_e_predia = register_diag_field('ocean_model', 'e_predia', diag%axesTi, time, &
2578  'Interface Heights before diabatic forcing', 'meter')
2579  if (.not. cs%adiabatic) then
2580  cs%id_u_preale = register_diag_field('ocean_model', 'u_preale', diag%axesCuL, time, &
2581  'Zonal velocity before remapping', 'meter second-1')
2582  cs%id_v_preale = register_diag_field('ocean_model', 'v_preale', diag%axesCvL, time, &
2583  'Meridional velocity before remapping', 'meter second-1')
2584  cs%id_h_preale = register_diag_field('ocean_model', 'h_preale', diag%axesTL, time, &
2585  'Layer Thickness before remapping', thickness_units, v_extensive=.true.)
2586  cs%id_T_preale = register_diag_field('ocean_model', 'T_preale', diag%axesTL, time, &
2587  'Temperature before remapping', 'degC')
2588  cs%id_S_preale = register_diag_field('ocean_model', 'S_preale', diag%axesTL, time, &
2589  'Salinity before remapping', 'ppt')
2590  cs%id_e_preale = register_diag_field('ocean_model', 'e_preale', diag%axesTi, time, &
2591  'Interface Heights before remapping', 'meter')
2592  endif
2593 
2594  if (cs%use_temperature) then
2595  cs%id_T_predia = register_diag_field('ocean_model', 'temp_predia', diag%axesTL, time, &
2596  'Potential Temperature', 'Celsius')
2597  cs%id_S_predia = register_diag_field('ocean_model', 'salt_predia', diag%axesTL, time, &
2598  'Salinity', 'PPT')
2599  endif
2600 
2601  ! Diagnostics related to tracer transport
2602  cs%id_uhtr = register_diag_field('ocean_model', 'uhtr', diag%axesCuL, time, &
2603  'Accumulated zonal thickness fluxes to advect tracers', 'kg', &
2604  y_cell_method='sum', v_extensive=.true.)
2605  cs%id_vhtr = register_diag_field('ocean_model', 'vhtr', diag%axesCvL, time, &
2606  'Accumulated meridional thickness fluxes to advect tracers', 'kg', &
2607  x_cell_method='sum', v_extensive=.true.)
2608  cs%id_umo = register_diag_field('ocean_model', 'umo', &
2609  diag%axesCuL, time, 'Ocean Mass X Transport', 'kg/s', &
2610  standard_name='ocean_mass_x_transport', y_cell_method='sum', v_extensive=.true.)
2611  cs%id_vmo = register_diag_field('ocean_model', 'vmo', &
2612  diag%axesCvL, time, 'Ocean Mass Y Transport', 'kg/s', &
2613  standard_name='ocean_mass_y_transport', x_cell_method='sum', v_extensive=.true.)
2614  cs%id_umo_2d = register_diag_field('ocean_model', 'umo_2d', &
2615  diag%axesCu1, time, 'Ocean Mass X Transport Vertical Sum', 'kg/s', &
2616  standard_name='ocean_mass_x_transport_vertical_sum', y_cell_method='sum')
2617  cs%id_vmo_2d = register_diag_field('ocean_model', 'vmo_2d', &
2618  diag%axesCv1, time, 'Ocean Mass Y Transport Vertical Sum', 'kg/s', &
2619  standard_name='ocean_mass_y_transport_vertical_sum', x_cell_method='sum')
2620 
2621 end subroutine register_diags
2622 
2623 
2624 !> Initialize diagnostics for temp/heat and saln/salt tendencies.
2625 subroutine register_diags_ts_tendency(Time, G, CS)
2626  type(time_type), intent(in) :: Time !< current model time
2627  type(ocean_grid_type), intent(inout) :: G !< ocean grid structure
2628  type(mom_control_struct), pointer :: CS !< control structure set up by initialize_MOM
2629 
2630  type(diag_ctrl), pointer :: diag
2631  integer :: i, j, k
2632  integer :: isd, ied, jsd, jed, nz
2633  integer :: is, ie, js, je
2634 
2635  diag => cs%diag
2636  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
2637  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2638 
2639 
2640  ! heat tendencies from lateral advection
2641  cs%id_T_advection_xy = register_diag_field('ocean_model', 'T_advection_xy', diag%axesTL, time, &
2642  'Horizontal convergence of residual mean heat advective fluxes', 'W/m2',v_extensive=.true.)
2643  cs%id_T_advection_xy_2d = register_diag_field('ocean_model', 'T_advection_xy_2d', diag%axesT1, time,&
2644  'Vertical sum of horizontal convergence of residual mean heat advective fluxes', 'W/m2')
2645  if (cs%id_T_advection_xy > 0 .or. cs%id_T_advection_xy_2d > 0) then
2646  call safe_alloc_ptr(cs%T_advection_xy,isd,ied,jsd,jed,nz)
2647  cs%tendency_diagnostics = .true.
2648  endif
2649 
2650  ! net temperature and heat tendencies
2651  cs%id_T_tendency = register_diag_field('ocean_model', 'T_tendency', diag%axesTL, time, &
2652  'Net time tendency for temperature', 'degC/s')
2653  cs%id_Th_tendency = register_diag_field('ocean_model', 'Th_tendency', diag%axesTL, time, &
2654  'Net time tendency for heat', 'W/m2', &
2655  cmor_field_name="opottemptend", cmor_units="W m-2", &
2656  cmor_standard_name="tendency_of_sea_water_potential_temperature_expressed_as_heat_content", &
2657  cmor_long_name ="Tendency of Sea Water Potential Temperature Expressed as Heat Content", &
2658  v_extensive=.true.)
2659  cs%id_Th_tendency_2d = register_diag_field('ocean_model', 'Th_tendency_2d', diag%axesT1, time, &
2660  'Vertical sum of net time tendency for heat', 'W/m2', &
2661  cmor_field_name="opottemptend_2d", cmor_units="W m-2", &
2662  cmor_standard_name="tendency_of_sea_water_potential_temperature_expressed_as_heat_content_vertical_sum",&
2663  cmor_long_name ="Tendency of Sea Water Potential Temperature Expressed as Heat Content Vertical Sum")
2664  if (cs%id_T_tendency > 0) then
2665  cs%tendency_diagnostics = .true.
2666  call safe_alloc_ptr(cs%T_prev,isd,ied,jsd,jed,nz)
2667  do k=1,nz ; do j=js,je ; do i=is,ie
2668  cs%T_prev(i,j,k) = cs%tv%T(i,j,k)
2669  enddo ; enddo ; enddo
2670  endif
2671  if (cs%id_Th_tendency > 0 .or. cs%id_Th_tendency_2d > 0) then
2672  cs%tendency_diagnostics = .true.
2673  call safe_alloc_ptr(cs%Th_prev,isd,ied,jsd,jed,nz)
2674  do k=1,nz ; do j=js,je ; do i=is,ie
2675  cs%Th_prev(i,j,k) = cs%tv%T(i,j,k) * cs%h(i,j,k)
2676  enddo ; enddo ; enddo
2677  endif
2678 
2679 
2680  ! salt tendencies from lateral advection
2681  cs%id_S_advection_xy = register_diag_field('ocean_model', 'S_advection_xy', diag%axesTL, time, &
2682  'Horizontal convergence of residual mean salt advective fluxes', 'kg/(m2 * s)', v_extensive=.true.)
2683  cs%id_S_advection_xy_2d = register_diag_field('ocean_model', 'S_advection_xy_2d', diag%axesT1, time,&
2684  'Vertical sum of horizontal convergence of residual mean salt advective fluxes', 'kg/(m2 * s)')
2685  if (cs%id_S_advection_xy > 0 .or. cs%id_S_advection_xy_2d > 0) then
2686  call safe_alloc_ptr(cs%S_advection_xy,isd,ied,jsd,jed,nz)
2687  cs%tendency_diagnostics = .true.
2688  endif
2689 
2690  ! net salinity and salt tendencies
2691  cs%id_S_tendency = register_diag_field('ocean_model', 'S_tendency', diag%axesTL, time, &
2692  'Net time tendency for salinity', 'PPT/s')
2693  cs%id_Sh_tendency = register_diag_field('ocean_model', 'Sh_tendency', diag%axesTL, time,&
2694  'Net time tendency for salt', 'kg/(m2 * s)', &
2695  cmor_field_name="osalttend", cmor_units="kg m-2 s-1", &
2696  cmor_standard_name="tendency_of_sea_water_salinity_expressed_as_salt_content", &
2697  cmor_long_name ="Tendency of Sea Water Salinity Expressed as Salt Content", &
2698  v_extensive=.true.)
2699  cs%id_Sh_tendency_2d = register_diag_field('ocean_model', 'Sh_tendency_2d', diag%axesT1, time, &
2700  'Vertical sum of net time tendency for salt', 'kg/(m2 * s)', &
2701  cmor_field_name="osalttend_2d", cmor_units="kg m-2 s-1", &
2702  cmor_standard_name="tendency_of_sea_water_salinity_expressed_as_salt_content_vertical_sum",&
2703  cmor_long_name ="Tendency of Sea Water Salinity Expressed as Salt Content Vertical Sum")
2704  if (cs%id_S_tendency > 0) then
2705  cs%tendency_diagnostics = .true.
2706  call safe_alloc_ptr(cs%S_prev,isd,ied,jsd,jed,nz)
2707  do k=1,nz ; do j=js,je ; do i=is,ie
2708  cs%S_prev(i,j,k) = cs%tv%S(i,j,k)
2709  enddo ; enddo ; enddo
2710  endif
2711  if (cs%id_Sh_tendency > 0 .or. cs%id_Sh_tendency_2d > 0) then
2712  cs%tendency_diagnostics = .true.
2713  call safe_alloc_ptr(cs%Sh_prev,isd,ied,jsd,jed,nz)
2714  do k=1,nz ; do j=js,je ; do i=is,ie
2715  cs%Sh_prev(i,j,k) = cs%tv%S(i,j,k) * cs%h(i,j,k)
2716  enddo ; enddo ; enddo
2717  endif
2718 
2719 end subroutine register_diags_ts_tendency
2720 
2721 
2722 !> Initialize diagnostics for the variance decay of temp/salt
2723 !! across regridding/remapping
2724 subroutine register_diags_ts_vardec(Time, HI, GV, param_file, CS)
2725  type(time_type), intent(in) :: Time !< current model time
2726  type(hor_index_type), intent(in) :: HI !< horizontal index type
2727  type(verticalgrid_type), intent(in) :: GV !< ocean vertical grid structure
2728  type(param_file_type), intent(in) :: param_file !< parameter file
2729  type(mom_control_struct), pointer :: CS !< control structure for MOM
2730 
2731  integer :: isd, ied, jsd, jed, nz
2732  type(vardesc) :: vd_tmp
2733  type(diag_ctrl), pointer :: diag
2734 
2735  diag => cs%diag
2736  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
2737 
2738  ! variancy decay through ALE operation
2739  cs%id_T_vardec = register_diag_field('ocean_model', 'T_vardec', diag%axesTL, time, &
2740  'ALE variance decay for temperature', 'degC2 s-1')
2741  if (cs%id_T_vardec > 0) then
2742  call safe_alloc_ptr(cs%T_squared,isd,ied,jsd,jed,nz)
2743  cs%T_squared(:,:,:) = 0.
2744 
2745  vd_tmp = var_desc(name="T2", units="degC2", longname="Squared Potential Temperature")
2746  call register_tracer(cs%T_squared, vd_tmp, param_file, hi, gv, cs%tracer_reg)
2747  endif
2748 
2749  cs%id_S_vardec = register_diag_field('ocean_model', 'S_vardec', diag%axesTL, time, &
2750  'ALE variance decay for salinity', 'PPT2 s-1')
2751  if (cs%id_S_vardec > 0) then
2752  call safe_alloc_ptr(cs%S_squared,isd,ied,jsd,jed,nz)
2753  cs%S_squared(:,:,:) = 0.
2754 
2755  vd_tmp = var_desc(name="S2", units="PPT2", longname="Squared Salinity")
2756  call register_tracer(cs%S_squared, vd_tmp, param_file, hi, gv, cs%tracer_reg)
2757  endif
2758 
2759 end subroutine register_diags_ts_vardec
2760 
2761 !> This subroutine sets up clock IDs for timing various subroutines.
2762 subroutine mom_timing_init(CS)
2763  type(mom_control_struct), intent(in) :: CS !< control structure set up by initialize_MOM.
2764 
2765  id_clock_ocean = cpu_clock_id('Ocean', grain=clock_component)
2766  id_clock_dynamics = cpu_clock_id('Ocean dynamics', grain=clock_subcomponent)
2767  id_clock_thermo = cpu_clock_id('Ocean thermodynamics and tracers', grain=clock_subcomponent)
2768  id_clock_other = cpu_clock_id('Ocean Other', grain=clock_subcomponent)
2769  id_clock_tracer = cpu_clock_id('(Ocean tracer advection)', grain=clock_module_driver)
2770  if (.not.cs%adiabatic) &
2771  id_clock_diabatic = cpu_clock_id('(Ocean diabatic driver)', grain=clock_module_driver)
2772 
2773  id_clock_continuity = cpu_clock_id('(Ocean continuity equation *)', grain=clock_module)
2774  id_clock_bbl_visc = cpu_clock_id('(Ocean set BBL viscosity)', grain=clock_module)
2775  id_clock_pass = cpu_clock_id('(Ocean message passing *)', grain=clock_module)
2776  id_clock_mom_init = cpu_clock_id('(Ocean MOM_initialize_state)', grain=clock_module)
2777  id_clock_pass_init = cpu_clock_id('(Ocean init message passing *)', grain=clock_routine)
2778  if (cs%thickness_diffuse) &
2779  id_clock_thick_diff = cpu_clock_id('(Ocean thickness diffusion *)', grain=clock_module)
2780 !if (CS%mixedlayer_restrat) &
2781  id_clock_ml_restrat = cpu_clock_id('(Ocean mixed layer restrat)', grain=clock_module)
2782  id_clock_diagnostics = cpu_clock_id('(Ocean collective diagnostics)', grain=clock_module)
2783  id_clock_z_diag = cpu_clock_id('(Ocean Z-space diagnostics)', grain=clock_module)
2784  id_clock_ale = cpu_clock_id('(Ocean ALE)', grain=clock_module)
2785  if(cs%offline_tracer_mode) then
2786  id_clock_offline_tracer = cpu_clock_id('Ocean offline tracers', grain=clock_subcomponent)
2787  endif
2788 
2789 end subroutine mom_timing_init
2790 
2791 !> This routine posts diagnostics of the transports, including the subgridscale
2792 !! contributions.
2793 subroutine post_transport_diagnostics(G, GV, CS, diag, dt_trans, h, h_pre_dyn)
2794  type(ocean_grid_type), intent(inout) :: G !< ocean grid structure
2795  type(verticalgrid_type), intent(in) :: GV !< ocean vertical grid structure
2796  type(mom_control_struct), intent(in) :: CS !< control structure
2797  type(diag_ctrl), intent(inout) :: diag !< regulates diagnostic output
2798  real , intent(in) :: dt_trans !< total time step associated with the transports, in s.
2799  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
2800  intent(in) :: h !< The updated layer thicknesses, in H
2801  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
2802  intent(in) :: h_pre_dyn !< The thickness before the transports, in H.
2803 
2804  real, dimension(SZIB_(G), SZJ_(G)) :: umo2d ! Diagnostics of integrated mass transport, in kg s-1
2805  real, dimension(SZI_(G), SZJB_(G)) :: vmo2d ! Diagnostics of integrated mass transport, in kg s-1
2806  real, dimension(SZIB_(G), SZJ_(G), SZK_(G)) :: umo ! Diagnostics of layer mass transport, in kg s-1
2807  real, dimension(SZI_(G), SZJB_(G), SZK_(G)) :: vmo ! Diagnostics of layer mass transport, in kg s-1
2808  real :: H_to_kg_m2_dt ! A conversion factor from accumulated transports to fluxes, in kg m-2 H-1 s-1.
2809  integer :: i, j, k, is, ie, js, je, nz
2810  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
2811 
2812  call cpu_clock_begin(id_clock_z_diag)
2813  call calculate_z_transport(cs%uhtr, cs%vhtr, h, dt_trans, g, gv, &
2814  cs%diag_to_Z_CSp)
2815  call cpu_clock_end(id_clock_z_diag)
2816 
2817  ! Post mass transports, including SGS
2818  ! Build the remap grids using the layer thicknesses from before the dynamics
2819  call diag_update_remap_grids(diag, alt_h = h_pre_dyn)
2820 
2821  h_to_kg_m2_dt = gv%H_to_kg_m2 / dt_trans
2822  if (cs%id_umo_2d > 0) then
2823  umo2d(:,:) = 0.0
2824  do k=1,nz ; do j=js,je ; do i=is-1,ie
2825  umo2d(i,j) = umo2d(i,j) + cs%uhtr(i,j,k) * h_to_kg_m2_dt
2826  enddo ; enddo ; enddo
2827  call post_data(cs%id_umo_2d, umo2d, diag)
2828  endif
2829  if (cs%id_umo > 0) then
2830  ! Convert to kg/s. Modifying the array for diagnostics is allowed here since it is set to zero immediately below
2831  do k=1,nz ; do j=js,je ; do i=is-1,ie
2832  umo(i,j,k) = cs%uhtr(i,j,k) * h_to_kg_m2_dt
2833  enddo ; enddo ; enddo
2834  call post_data(cs%id_umo, umo, diag, alt_h = h_pre_dyn)
2835  endif
2836  if (cs%id_vmo_2d > 0) then
2837  vmo2d(:,:) = 0.0
2838  do k=1,nz ; do j=js-1,je ; do i=is,ie
2839  vmo2d(i,j) = vmo2d(i,j) + cs%vhtr(i,j,k) * h_to_kg_m2_dt
2840  enddo ; enddo ; enddo
2841  call post_data(cs%id_vmo_2d, vmo2d, diag)
2842  endif
2843  if (cs%id_vmo > 0) then
2844  ! Convert to kg/s. Modifying the array for diagnostics is allowed here since it is set to zero immediately below
2845  do k=1,nz ; do j=js-1,je ; do i=is,ie
2846  vmo(i,j,k) = cs%vhtr(i,j,k) * h_to_kg_m2_dt
2847  enddo ; enddo ; enddo
2848  call post_data(cs%id_vmo, vmo, diag, alt_h = h_pre_dyn)
2849  endif
2850 
2851  if (cs%id_uhtr > 0) call post_data(cs%id_uhtr, cs%uhtr, diag, alt_h = h_pre_dyn)
2852  if (cs%id_vhtr > 0) call post_data(cs%id_vhtr, cs%vhtr, diag, alt_h = h_pre_dyn)
2853 
2854 end subroutine post_transport_diagnostics
2855 
2856 !> Post diagnostics of temperatures and salinities, their fluxes, and tendencies.
2857 subroutine post_ts_diagnostics(CS, G, GV, tv, diag, dt)
2858  type(mom_control_struct), intent(inout) :: CS !< control structure
2859  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
2860  type(verticalgrid_type), intent(in) :: GV !< ocean vertical grid structure
2861  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
2862  type(diag_ctrl), intent(in) :: diag !< regulates diagnostic output
2863  real, intent(in) :: dt !< total time step for T,S update
2864 
2865  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: potTemp, pracSal !TEOS10 Diagnostics
2866  real :: work3d(szi_(g),szj_(g),szk_(g))
2867  real :: work2d(szi_(g),szj_(g))
2868  real :: Idt, ppt2mks
2869  integer :: i, j, k, is, ie, js, je, nz
2870  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
2871 
2872  if (.NOT. cs%use_conT_absS) then
2873  !Internal T&S variables are assumed to be potential&practical
2874  if (cs%id_T > 0) call post_data(cs%id_T, tv%T, diag)
2875  if (cs%id_S > 0) call post_data(cs%id_S, tv%S, diag)
2876 
2877  if (cs%id_tob > 0) call post_data(cs%id_tob, tv%T(:,:,g%ke), diag, mask=g%mask2dT)
2878  if (cs%id_sob > 0) call post_data(cs%id_sob, tv%S(:,:,g%ke), diag, mask=g%mask2dT)
2879  else
2880  !Internal T&S variables are assumed to be conservative&absolute
2881  if (cs%id_Tcon > 0) call post_data(cs%id_Tcon, tv%T, diag)
2882  if (cs%id_Sabs > 0) call post_data(cs%id_Sabs, tv%S, diag)
2883  !Using TEOS-10 function calls convert T&S diagnostics
2884  !from conservative temp to potential temp and
2885  !from absolute salinity to practical salinity
2886  do k=1,nz ; do j=js,je ; do i=is,ie
2887  pracsal(i,j,k) = gsw_sp_from_sr(tv%S(i,j,k))
2888  pottemp(i,j,k) = gsw_pt_from_ct(tv%S(i,j,k),tv%T(i,j,k))
2889  enddo; enddo ; enddo
2890  if (cs%id_T > 0) call post_data(cs%id_T, pottemp, diag)
2891  if (cs%id_S > 0) call post_data(cs%id_S, pracsal, diag)
2892  if (cs%id_tob > 0) call post_data(cs%id_tob, pottemp(:,:,g%ke), diag, mask=g%mask2dT)
2893  if (cs%id_sob > 0) call post_data(cs%id_sob, pracsal(:,:,g%ke), diag, mask=g%mask2dT)
2894  endif
2895 
2896  if (cs%id_Tadx > 0) call post_data(cs%id_Tadx, cs%T_adx, diag)
2897  if (cs%id_Tady > 0) call post_data(cs%id_Tady, cs%T_ady, diag)
2898  if (cs%id_Tdiffx > 0) call post_data(cs%id_Tdiffx, cs%T_diffx, diag)
2899  if (cs%id_Tdiffy > 0) call post_data(cs%id_Tdiffy, cs%T_diffy, diag)
2900 
2901  if (cs%id_Sadx > 0) call post_data(cs%id_Sadx, cs%S_adx, diag)
2902  if (cs%id_Sady > 0) call post_data(cs%id_Sady, cs%S_ady, diag)
2903  if (cs%id_Sdiffx > 0) call post_data(cs%id_Sdiffx, cs%S_diffx, diag)
2904  if (cs%id_Sdiffy > 0) call post_data(cs%id_Sdiffy, cs%S_diffy, diag)
2905 
2906  if (cs%id_Tadx_2d > 0) call post_data(cs%id_Tadx_2d, cs%T_adx_2d, diag)
2907  if (cs%id_Tady_2d > 0) call post_data(cs%id_Tady_2d, cs%T_ady_2d, diag)
2908  if (cs%id_Tdiffx_2d > 0) call post_data(cs%id_Tdiffx_2d, cs%T_diffx_2d, diag)
2909  if (cs%id_Tdiffy_2d > 0) call post_data(cs%id_Tdiffy_2d, cs%T_diffy_2d, diag)
2910 
2911  if (cs%id_Sadx_2d > 0) call post_data(cs%id_Sadx_2d, cs%S_adx_2d, diag)
2912  if (cs%id_Sady_2d > 0) call post_data(cs%id_Sady_2d, cs%S_ady_2d, diag)
2913  if (cs%id_Sdiffx_2d > 0) call post_data(cs%id_Sdiffx_2d, cs%S_diffx_2d, diag)
2914  if (cs%id_Sdiffy_2d > 0) call post_data(cs%id_Sdiffy_2d, cs%S_diffy_2d, diag)
2915 
2916  if(.not. cs%tendency_diagnostics) return
2917 
2918  idt = 0.; if (dt/=0.) idt = 1.0 / dt ! The "if" is in case the diagnostic is called for a zero length interval
2919  ppt2mks = 0.001
2920  work3d(:,:,:) = 0.0
2921  work2d(:,:) = 0.0
2922 
2923  ! Diagnose tendency of heat from convergence of lateral advective,
2924  ! fluxes, where advective transport arises from residual mean velocity.
2925  if (cs%id_T_advection_xy > 0 .or. cs%id_T_advection_xy_2d > 0) then
2926  do k=1,nz ; do j=js,je ; do i=is,ie
2927  work3d(i,j,k) = cs%T_advection_xy(i,j,k) * gv%H_to_kg_m2 * tv%C_p
2928  enddo ; enddo ; enddo
2929  if (cs%id_T_advection_xy > 0) call post_data(cs%id_T_advection_xy, work3d, diag)
2930  if (cs%id_T_advection_xy_2d > 0) then
2931  do j=js,je ; do i=is,ie
2932  work2d(i,j) = 0.0
2933  do k=1,nz
2934  work2d(i,j) = work2d(i,j) + work3d(i,j,k)
2935  enddo
2936  enddo ; enddo
2937  call post_data(cs%id_T_advection_xy_2d, work2d, diag)
2938  endif
2939  endif
2940 
2941  ! Diagnose tendency of salt from convergence of lateral advective
2942  ! fluxes, where advective transport arises from residual mean velocity.
2943  if (cs%id_S_advection_xy > 0 .or. cs%id_S_advection_xy_2d > 0) then
2944  do k=1,nz ; do j=js,je ; do i=is,ie
2945  work3d(i,j,k) = cs%S_advection_xy(i,j,k) * gv%H_to_kg_m2 * ppt2mks
2946  enddo ; enddo ; enddo
2947  if (cs%id_S_advection_xy > 0) call post_data(cs%id_S_advection_xy, work3d, diag)
2948  if (cs%id_S_advection_xy_2d > 0) then
2949  do j=js,je ; do i=is,ie
2950  work2d(i,j) = 0.0
2951  do k=1,nz
2952  work2d(i,j) = work2d(i,j) + work3d(i,j,k)
2953  enddo
2954  enddo ; enddo
2955  call post_data(cs%id_S_advection_xy_2d, work2d, diag)
2956  endif
2957  endif
2958 
2959  ! diagnose net tendency for temperature over a time step and update T_prev
2960  if (cs%id_T_tendency > 0) then
2961  do k=1,nz ; do j=js,je ; do i=is,ie
2962  work3d(i,j,k) = (tv%T(i,j,k) - cs%T_prev(i,j,k))*idt
2963  cs%T_prev(i,j,k) = tv%T(i,j,k)
2964  enddo ; enddo ; enddo
2965  call post_data(cs%id_T_tendency, work3d, diag)
2966  endif
2967 
2968  ! diagnose net tendency for salinity over a time step and update S_prev
2969  if (cs%id_S_tendency > 0) then
2970  do k=1,nz ; do j=js,je ; do i=is,ie
2971  work3d(i,j,k) = (tv%S(i,j,k) - cs%S_prev(i,j,k))*idt
2972  cs%S_prev(i,j,k) = tv%S(i,j,k)
2973  enddo ; enddo ; enddo
2974  call post_data(cs%id_S_tendency, work3d, diag)
2975  endif
2976 
2977  ! diagnose net tendency for heat content of a grid cell over a time step and update Th_prev
2978  if (cs%id_Th_tendency > 0 .or. cs%id_Th_tendency_2d > 0) then
2979  do k=1,nz ; do j=js,je ; do i=is,ie
2980  work3d(i,j,k) = (tv%T(i,j,k)*cs%h(i,j,k) - cs%Th_prev(i,j,k)) * idt * gv%H_to_kg_m2 * tv%C_p
2981  cs%Th_prev(i,j,k) = tv%T(i,j,k)*cs%h(i,j,k)
2982  enddo ; enddo ; enddo
2983  if (cs%id_Th_tendency > 0) call post_data(cs%id_Th_tendency, work3d, diag)
2984  if (cs%id_Th_tendency_2d > 0) then
2985  do j=js,je ; do i=is,ie
2986  work2d(i,j) = 0.0
2987  do k=1,nz
2988  work2d(i,j) = work2d(i,j) + work3d(i,j,k)
2989  enddo
2990  enddo ; enddo
2991  call post_data(cs%id_Th_tendency_2d, work2d, diag)
2992  endif
2993  endif
2994 
2995  ! diagnose net tendency for salt content of a grid cell over a time step and update Sh_prev
2996  if (cs%id_Sh_tendency > 0 .or. cs%id_Sh_tendency_2d > 0) then
2997  do k=1,nz ; do j=js,je ; do i=is,ie
2998  work3d(i,j,k) = (tv%S(i,j,k)*cs%h(i,j,k) - cs%Sh_prev(i,j,k)) * idt * gv%H_to_kg_m2 * ppt2mks
2999  cs%Sh_prev(i,j,k) = tv%S(i,j,k)*cs%h(i,j,k)
3000  enddo ; enddo ; enddo
3001  if (cs%id_Sh_tendency > 0) call post_data(cs%id_Sh_tendency, work3d, diag)
3002  if (cs%id_Sh_tendency_2d > 0) then
3003  do j=js,je ; do i=is,ie
3004  work2d(i,j) = 0.0
3005  do k=1,nz
3006  work2d(i,j) = work2d(i,j) + work3d(i,j,k)
3007  enddo
3008  enddo ; enddo
3009  call post_data(cs%id_Sh_tendency_2d, work2d, diag)
3010  endif
3011  endif
3012 
3013 end subroutine post_ts_diagnostics
3014 
3015 !> Calculate and post variance decay diagnostics for temp/salt
3016 subroutine post_diags_ts_vardec(G, CS, dt)
3017  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
3018  type(mom_control_struct), intent(in) :: CS !< control structure
3019  real, intent(in) :: dt !< total time step
3020 
3021  real :: work(szi_(g),szj_(g),szk_(g))
3022  real :: Idt
3023  integer :: i, j, k, is, ie, js, je, nz
3024  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3025 
3026  idt = 0.; if (dt/=0.) idt = 1.0 / dt ! The "if" is in case the diagnostic is called for a zero length interval
3027 
3028  if (cs%id_T_vardec > 0) then
3029  do k=1,nz ; do j=js,je ; do i=is,ie
3030  work(i,j,k) = (cs%T_squared(i,j,k) - cs%tv%T(i,j,k)**2) * idt
3031  enddo ; enddo ; enddo
3032  call post_data(cs%id_T_vardec, work, cs%diag)
3033  endif
3034 
3035  if (cs%id_S_vardec > 0) then
3036  do k=1,nz ; do j=js,je ; do i=is,ie
3037  work(i,j,k) = (cs%S_squared(i,j,k) - cs%tv%S(i,j,k)**2) * idt
3038  enddo ; enddo ; enddo
3039  call post_data(cs%id_S_vardec, work, cs%diag)
3040  endif
3041 end subroutine post_diags_ts_vardec
3042 
3043 !> This routine posts diagnostics of various integrated quantities.
3044 subroutine post_integrated_diagnostics(CS, G, GV, diag, dt_int, tv, fluxes)
3045  type(mom_control_struct), intent(in) :: CS !< control structure
3046  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
3047  type(verticalgrid_type), intent(in) :: GV !< ocean vertical grid structure
3048  type(diag_ctrl), intent(in) :: diag !< regulates diagnostic output
3049  real, intent(in) :: dt_int !< total time step associated with these diagnostics, in s.
3050  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables type(forcing), intent(inout) :: fluxes !< pointers to forcing fields
3051  type(forcing), intent(in) :: fluxes !< pointers to forcing fields
3052 
3053  real, allocatable, dimension(:,:) :: &
3054  tmp, & ! temporary 2d field
3055  zos, & ! dynamic sea lev (zero area mean) from inverse-barometer adjusted ssh (meter)
3056  zossq, & ! square of zos (m^2)
3057  sfc_speed, & ! sea surface speed at h-points (m/s)
3058  frazil_ave, & ! average frazil heat flux required to keep temp above freezing (W/m2)
3059  salt_deficit_ave, & ! average salt flux required to keep salinity above 0.01ppt (gSalt m-2 s-1)
3060  Heat_PmE_ave, & ! average effective heat flux into the ocean due to
3061  ! the exchange of water with other components, times the
3062  ! heat capacity of water, in W m-2.
3063  intern_heat_ave ! avg heat flux into ocean from geothermal or
3064  ! other internal heat sources (W/m2)
3065  real :: I_time_int ! The inverse of the time interval in s-1.
3066  real :: zos_area_mean, volo, ssh_ga
3067  integer :: i, j, k, is, ie, js, je, nz! , Isq, Ieq, Jsq, Jeq
3068 
3069  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3070 
3071  ! area mean SSH
3072  if (cs%id_ssh_ga > 0) then
3073  ssh_ga = global_area_mean(cs%ave_ssh, g)
3074  call post_data(cs%id_ssh_ga, ssh_ga, diag)
3075  endif
3076 
3077  i_time_int = 1.0 / dt_int
3078  if (cs%id_ssh > 0) &
3079  call post_data(cs%id_ssh, cs%ave_ssh, diag, mask=g%mask2dT)
3080 
3081  ! post the dynamic sea level, zos, and zossq.
3082  ! zos is ave_ssh with sea ice inverse barometer removed,
3083  ! and with zero global area mean.
3084  if(cs%id_zos > 0 .or. cs%id_zossq > 0) then
3085  allocate(zos(g%isd:g%ied,g%jsd:g%jed))
3086  zos(:,:) = 0.0
3087  do j=js,je ; do i=is,ie
3088  zos(i,j) = cs%ave_ssh(i,j)
3089  enddo ; enddo
3090  if (ASSOCIATED(fluxes%p_surf)) then
3091  do j=js,je ; do i=is,ie
3092  zos(i,j) = zos(i,j) + g%mask2dT(i,j)*fluxes%p_surf(i,j) / &
3093  (gv%Rho0 * gv%g_Earth)
3094  enddo ; enddo
3095  endif
3096  zos_area_mean = global_area_mean(zos, g)
3097  do j=js,je ; do i=is,ie
3098  zos(i,j) = zos(i,j) - g%mask2dT(i,j)*zos_area_mean
3099  enddo ; enddo
3100  if(cs%id_zos > 0) then
3101  call post_data(cs%id_zos, zos, diag, mask=g%mask2dT)
3102  endif
3103  if(cs%id_zossq > 0) then
3104  allocate(zossq(g%isd:g%ied,g%jsd:g%jed))
3105  zossq(:,:) = 0.0
3106  do j=js,je ; do i=is,ie
3107  zossq(i,j) = zos(i,j)*zos(i,j)
3108  enddo ; enddo
3109  call post_data(cs%id_zossq, zossq, diag, mask=g%mask2dT)
3110  deallocate(zossq)
3111  endif
3112  deallocate(zos)
3113  endif
3114 
3115  ! post total volume of the liquid ocean
3116  if(cs%id_volo > 0) then
3117  allocate(tmp(g%isd:g%ied,g%jsd:g%jed))
3118  do j=js,je ; do i=is,ie
3119  tmp(i,j) = g%mask2dT(i,j)*(cs%ave_ssh(i,j) + g%bathyT(i,j))
3120  enddo ; enddo
3121  volo = global_area_integral(tmp, g)
3122  call post_data(cs%id_volo, volo, diag)
3123  deallocate(tmp)
3124  endif
3125 
3126  ! post frazil
3127  if (ASSOCIATED(tv%frazil) .and. (cs%id_fraz > 0)) then
3128  allocate(frazil_ave(g%isd:g%ied,g%jsd:g%jed))
3129  do j=js,je ; do i=is,ie
3130  frazil_ave(i,j) = tv%frazil(i,j) * i_time_int
3131  enddo ; enddo
3132  call post_data(cs%id_fraz, frazil_ave, diag, mask=g%mask2dT)
3133  deallocate(frazil_ave)
3134  endif
3135 
3136  ! post the salt deficit
3137  if (ASSOCIATED(tv%salt_deficit) .and. (cs%id_salt_deficit > 0)) then
3138  allocate(salt_deficit_ave(g%isd:g%ied,g%jsd:g%jed))
3139  do j=js,je ; do i=is,ie
3140  salt_deficit_ave(i,j) = tv%salt_deficit(i,j) * i_time_int
3141  enddo ; enddo
3142  call post_data(cs%id_salt_deficit, salt_deficit_ave, diag, mask=g%mask2dT)
3143  deallocate(salt_deficit_ave)
3144  endif
3145 
3146  ! post temperature of P-E+R
3147  if (ASSOCIATED(tv%TempxPmE) .and. (cs%id_Heat_PmE > 0)) then
3148  allocate(heat_pme_ave(g%isd:g%ied,g%jsd:g%jed))
3149  do j=js,je ; do i=is,ie
3150  heat_pme_ave(i,j) = tv%TempxPmE(i,j) * (tv%C_p * i_time_int)
3151  enddo ; enddo
3152  call post_data(cs%id_Heat_PmE, heat_pme_ave, diag, mask=g%mask2dT)
3153  deallocate(heat_pme_ave)
3154  endif
3155 
3156  ! post geothermal heating or internal heat source/sinks
3157  if (ASSOCIATED(tv%internal_heat) .and. (cs%id_intern_heat > 0)) then
3158  allocate(intern_heat_ave(g%isd:g%ied,g%jsd:g%jed))
3159  do j=js,je ; do i=is,ie
3160  intern_heat_ave(i,j) = tv%internal_heat(i,j) * (tv%C_p * i_time_int)
3161  enddo ; enddo
3162  call post_data(cs%id_intern_heat, intern_heat_ave, diag, mask=g%mask2dT)
3163  deallocate(intern_heat_ave)
3164  endif
3165 
3166 end subroutine post_integrated_diagnostics
3167 
3168 !> This routine posts diagnostics of various ocean surface quantities.
3169 subroutine post_surface_diagnostics(CS, G, diag, state)
3170  type(mom_control_struct), intent(in) :: CS !< control structure
3171  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
3172  type(diag_ctrl), intent(in) :: diag !< regulates diagnostic output
3173  type(surface), intent(in) :: state !< ocean surface state
3174 
3175  real, dimension(SZI_(G),SZJ_(G)) :: &
3176  potTemp, & ! TEOS10 potential temperature (deg C)
3177  pracSal, & ! TEOS10 practical salinity
3178  SST_sq, & ! Surface temperature squared, in degC^2
3179  SSS_sq, & ! Surface salinity squared, in salnity units^2
3180  sfc_speed ! sea surface speed at h-points (m/s)
3181 
3182  integer :: i, j, is, ie, js, je
3183 
3184  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3185 
3186  if (.NOT.cs%use_conT_absS) then
3187  !Internal T&S variables are assumed to be potential&practical
3188  if (cs%id_sst > 0) call post_data(cs%id_sst, state%SST, diag, mask=g%mask2dT)
3189  if (cs%id_sss > 0) call post_data(cs%id_sss, state%SSS, diag, mask=g%mask2dT)
3190  else
3191  !Internal T&S variables are assumed to be conservative&absolute
3192  if (cs%id_sstcon > 0) call post_data(cs%id_sstcon, state%SST, diag, mask=g%mask2dT)
3193  if (cs%id_sssabs > 0) call post_data(cs%id_sssabs, state%SSS, diag, mask=g%mask2dT)
3194  !Using TEOS-10 function calls convert T&S diagnostics
3195  !from conservative temp to potential temp and
3196  !from absolute salinity to practical salinity
3197  do j=js,je ; do i=is,ie
3198  pracsal(i,j) = gsw_sp_from_sr(state%SSS(i,j))
3199  pottemp(i,j) = gsw_pt_from_ct(state%SSS(i,j),state%SST(i,j))
3200  enddo ; enddo
3201  if (cs%id_sst > 0) call post_data(cs%id_sst, pottemp, diag, mask=g%mask2dT)
3202  if (cs%id_sss > 0) call post_data(cs%id_sss, pracsal, diag, mask=g%mask2dT)
3203  endif
3204 
3205  if (cs%id_sst_sq > 0) then
3206  do j=js,je ; do i=is,ie
3207  sst_sq(i,j) = state%SST(i,j)*state%SST(i,j)
3208  enddo ; enddo
3209  call post_data(cs%id_sst_sq, sst_sq, diag, mask=g%mask2dT)
3210  endif
3211  if (cs%id_sss_sq > 0) then
3212  do j=js,je ; do i=is,ie
3213  sss_sq(i,j) = state%SSS(i,j)*state%SSS(i,j)
3214  enddo ; enddo
3215  call post_data(cs%id_sss_sq, sss_sq, diag, mask=g%mask2dT)
3216  endif
3217 
3218  if (cs%id_ssu > 0) &
3219  call post_data(cs%id_ssu, state%u, diag, mask=g%mask2dCu)
3220  if (cs%id_ssv > 0) &
3221  call post_data(cs%id_ssv, state%v, diag, mask=g%mask2dCv)
3222 
3223  if (cs%id_speed > 0) then
3224  do j=js,je ; do i=is,ie
3225  sfc_speed(i,j) = sqrt(0.5*(state%u(i-1,j)**2 + state%u(i,j)**2) + &
3226  0.5*(state%v(i,j-1)**2 + state%v(i,j)**2))
3227  enddo ; enddo
3228  call post_data(cs%id_speed, sfc_speed, diag, mask=g%mask2dT)
3229  endif
3230 
3231 end subroutine post_surface_diagnostics
3232 
3233 !> Offers the static fields in the ocean grid type
3234 !! for output via the diag_manager.
3235 subroutine write_static_fields(G, diag)
3236  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
3237  type(diag_ctrl), target, intent(inout) :: diag !< regulates diagnostic output
3238 
3239  ! The out_X arrays are needed because some of the elements of the grid
3240  ! type may be reduced rank macros.
3241  real :: out_h(szi_(g),szj_(g))
3242  integer :: id, i, j, is, ie, js, je
3243  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3244 
3245  out_h(:,:) = 0.0
3246 
3247  id = register_static_field('ocean_model', 'geolat', diag%axesT1, &
3248  'Latitude of tracer (T) points', 'degrees_N')
3249  if (id > 0) call post_data(id, g%geoLatT, diag, .true.)
3250 
3251  id = register_static_field('ocean_model', 'geolon', diag%axesT1, &
3252  'Longitude of tracer (T) points', 'degrees_E')
3253  if (id > 0) call post_data(id, g%geoLonT, diag, .true.)
3254 
3255  id = register_static_field('ocean_model', 'geolat_c', diag%axesB1, &
3256  'Latitude of corner (Bu) points', 'degrees_N', interp_method='none')
3257  if (id > 0) call post_data(id, g%geoLatBu, diag, .true.)
3258 
3259  id = register_static_field('ocean_model', 'geolon_c', diag%axesB1, &
3260  'Longitude of corner (Bu) points', 'degrees_E', interp_method='none')
3261  if (id > 0) call post_data(id, g%geoLonBu, diag, .true.)
3262 
3263  id = register_static_field('ocean_model', 'geolat_v', diag%axesCv1, &
3264  'Latitude of meridional velocity (Cv) points', 'degrees_N', interp_method='none')
3265  if (id > 0) call post_data(id, g%geoLatCv, diag, .true.)
3266 
3267  id = register_static_field('ocean_model', 'geolon_v', diag%axesCv1, &
3268  'Longitude of meridional velocity (Cv) points', 'degrees_E', interp_method='none')
3269  if (id > 0) call post_data(id, g%geoLonCv, diag, .true.)
3270 
3271  id = register_static_field('ocean_model', 'geolat_u', diag%axesCu1, &
3272  'Latitude of zonal velocity (Cu) points', 'degrees_N', interp_method='none')
3273  if (id > 0) call post_data(id, g%geoLatCu, diag, .true.)
3274 
3275  id = register_static_field('ocean_model', 'geolon_u', diag%axesCu1, &
3276  'Longitude of zonal velocity (Cu) points', 'degrees_E', interp_method='none')
3277  if (id > 0) call post_data(id, g%geoLonCu, diag, .true.)
3278 
3279  id = register_static_field('ocean_model', 'area_t', diag%axesT1, &
3280  'Surface area of tracer (T) cells', 'm2', &
3281  cmor_field_name='areacello', cmor_standard_name='cell_area', &
3282  cmor_units='m2', cmor_long_name='Ocean Grid-Cell Area')
3283  if (id > 0) then
3284  do j=js,je ; do i=is,ie ; out_h(i,j) = g%areaT(i,j) ; enddo ; enddo
3285  call post_data(id, out_h, diag, .true.)
3286  call diag_register_area_ids(diag, id_area_t=id)
3287  endif
3288 
3289  id = register_static_field('ocean_model', 'depth_ocean', diag%axesT1, &
3290  'Depth of the ocean at tracer points', 'm', &
3291  standard_name='sea_floor_depth_below_geoid', &
3292  cmor_field_name='deptho', cmor_long_name='Sea Floor Depth', &
3293  cmor_units='m', cmor_standard_name='sea_floor_depth_below_geoid',&
3294  area=diag%axesT1%id_area)
3295  if (id > 0) call post_data(id, g%bathyT, diag, .true., mask=g%mask2dT)
3296 
3297  id = register_static_field('ocean_model', 'wet', diag%axesT1, &
3298  '0 if land, 1 if ocean at tracer points', 'none', area=diag%axesT1%id_area)
3299  if (id > 0) call post_data(id, g%mask2dT, diag, .true.)
3300 
3301  id = register_static_field('ocean_model', 'wet_c', diag%axesB1, &
3302  '0 if land, 1 if ocean at corner (Bu) points', 'none', interp_method='none')
3303  if (id > 0) call post_data(id, g%mask2dBu, diag, .true.)
3304 
3305  id = register_static_field('ocean_model', 'wet_u', diag%axesCu1, &
3306  '0 if land, 1 if ocean at zonal velocity (Cu) points', 'none', interp_method='none')
3307  if (id > 0) call post_data(id, g%mask2dCu, diag, .true.)
3308 
3309  id = register_static_field('ocean_model', 'wet_v', diag%axesCv1, &
3310  '0 if land, 1 if ocean at meridional velocity (Cv) points', 'none', interp_method='none')
3311  if (id > 0) call post_data(id, g%mask2dCv, diag, .true.)
3312 
3313  id = register_static_field('ocean_model', 'Coriolis', diag%axesB1, &
3314  'Coriolis parameter at corner (Bu) points', 's-1', interp_method='none')
3315  if (id > 0) call post_data(id, g%CoriolisBu, diag, .true.)
3316 
3317  id = register_static_field('ocean_model', 'dxt', diag%axesT1, &
3318  'Delta(x) at thickness/tracer points (meter)', 'm', interp_method='none')
3319  if (id > 0) call post_data(id, g%dxt, diag, .true.)
3320 
3321  id = register_static_field('ocean_model', 'dyt', diag%axesT1, &
3322  'Delta(y) at thickness/tracer points (meter)', 'm', interp_method='none')
3323  if (id > 0) call post_data(id, g%dyt, diag, .true.)
3324 
3325  id = register_static_field('ocean_model', 'dxCu', diag%axesCu1, &
3326  'Delta(x) at u points (meter)', 'm', interp_method='none')
3327  if (id > 0) call post_data(id, g%dxCu, diag, .true.)
3328 
3329  id = register_static_field('ocean_model', 'dyCu', diag%axesCu1, &
3330  'Delta(y) at u points (meter)', 'm', interp_method='none')
3331  if (id > 0) call post_data(id, g%dyCu, diag, .true.)
3332 
3333  id = register_static_field('ocean_model', 'dxCv', diag%axesCv1, &
3334  'Delta(x) at v points (meter)', 'm', interp_method='none')
3335  if (id > 0) call post_data(id, g%dxCv, diag, .true.)
3336 
3337  id = register_static_field('ocean_model', 'dyCv', diag%axesCv1, &
3338  'Delta(y) at v points (meter)', 'm', interp_method='none')
3339  if (id > 0) call post_data(id, g%dyCv, diag, .true.)
3340 
3341 end subroutine write_static_fields
3342 
3343 
3344 !> Set the fields that are needed for bitwise identical restarting
3345 !! the time stepping scheme. In addition to those specified here
3346 !! directly, there may be fields related to the forcing or to the
3347 !! barotropic solver that are needed; these are specified in sub-
3348 !! routines that are called from this one.
3349 !!
3350 !! This routine should be altered if there are any changes to the
3351 !! time stepping scheme. The CHECK_RESTART facility may be used to
3352 !! confirm that all needed restart fields have been included.
3353 subroutine set_restart_fields(GV, param_file, CS)
3354  type(verticalgrid_type), intent(inout) :: GV !< ocean vertical grid structure
3355  type(param_file_type), intent(in) :: param_file !< opened file for parsing to get parameters
3356  type(mom_control_struct), intent(in) :: CS !< control structure set up by inialize_MOM
3357  ! Local variables
3358  logical :: use_ice_shelf ! Needed to determine whether to add CS%Hml to restarts
3359  type(vardesc) :: vd
3360  character(len=48) :: thickness_units, flux_units
3361 
3362  call get_param(param_file, '', "ICE_SHELF", use_ice_shelf, default=.false., do_not_log=.true.)
3363 
3364  thickness_units = get_thickness_units(gv)
3365  flux_units = get_flux_units(gv)
3366 
3367  if (cs%use_temperature) then
3368  vd = var_desc("Temp","degC","Potential Temperature")
3369  call register_restart_field(cs%tv%T, vd, .true., cs%restart_CSp)
3370 
3371  vd = var_desc("Salt","PPT","Salinity")
3372  call register_restart_field(cs%tv%S, vd, .true., cs%restart_CSp)
3373  endif
3374 
3375  vd = var_desc("h",thickness_units,"Layer Thickness")
3376  call register_restart_field(cs%h, vd, .true., cs%restart_CSp)
3377 
3378  vd = var_desc("u","meter second-1","Zonal velocity",'u','L')
3379  call register_restart_field(cs%u, vd, .true., cs%restart_CSp)
3380 
3381  vd = var_desc("v","meter second-1","Meridional velocity",'v','L')
3382  call register_restart_field(cs%v, vd, .true., cs%restart_CSp)
3383 
3384  if (cs%use_frazil) then
3385  vd = var_desc("frazil","J m-2","Frazil heat flux into ocean",'h','1')
3386  call register_restart_field(cs%tv%frazil, vd, .false., cs%restart_CSp)
3387  endif
3388 
3389  if (cs%interp_p_surf) then
3390  vd = var_desc("p_surf_prev","Pa","Previous ocean surface pressure",'h','1')
3391  call register_restart_field(cs%p_surf_prev, vd, .false., cs%restart_CSp)
3392  endif
3393 
3394  vd = var_desc("ave_ssh","meter","Time average sea surface height",'h','1')
3395  call register_restart_field(cs%ave_ssh, vd, .false., cs%restart_CSp)
3396 
3397  ! hML is needed when using the ice shelf module
3398  if (use_ice_shelf .and. associated(cs%Hml)) then
3399  vd = var_desc("hML","meter","Mixed layer thickness",'h','1')
3400  call register_restart_field(cs%Hml, vd, .false., cs%restart_CSp)
3401  endif
3402 
3403 end subroutine set_restart_fields
3404 
3405 !> This subroutine applies a correction to the sea surface height to compensate
3406 !! for the atmospheric pressure (the inverse barometer).
3407 subroutine adjust_ssh_for_p_atm(CS, G, GV, ssh, p_atm)
3408  type(mom_control_struct), intent(in) :: CS !< control structure
3409  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
3410  type(verticalgrid_type), intent(in) :: GV !< ocean vertical grid structure
3411  real, dimension(SZI_(G),SZJ_(G)), intent(inout) :: ssh !< time mean surface height (m)
3412  real, dimension(:,:), optional, pointer :: p_atm !< atmospheric pressure (Pascal)
3413 
3414  real :: Rho_conv ! The density used to convert surface pressure to
3415  ! a corrected effective SSH, in kg m-3.
3416  real :: IgR0 ! The SSH conversion factor from Pa to m.
3417  integer :: i, j, is, ie, js, je
3418 
3419  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3420  if (ASSOCIATED(p_atm)) then
3421  ! Correct the output sea surface height for the contribution from the
3422  ! atmospheric pressure
3423  do j=js,je ; do i=is,ie
3424  if ((ASSOCIATED(cs%tv%eqn_of_state)) .and. (cs%calc_rho_for_sea_lev)) then
3425  call calculate_density(cs%tv%T(i,j,1), cs%tv%S(i,j,1), p_atm(i,j)/2.0, &
3426  rho_conv, cs%tv%eqn_of_state)
3427  else
3428  rho_conv=gv%Rho0
3429  endif
3430  igr0 = 1.0 / (rho_conv * gv%g_Earth)
3431  ssh(i,j) = ssh(i,j) + p_atm(i,j) * igr0
3432  enddo ; enddo
3433  endif
3434 
3435 end subroutine adjust_ssh_for_p_atm
3436 
3437 !> This subroutine sets the surface (return) properties of the ocean
3438 !! model by setting the appropriate fields in state. Unused fields
3439 !! are set to NULL or are unallocated.
3440 subroutine calculate_surface_state(state, u, v, h, ssh, G, GV, CS)
3441  type(ocean_grid_type), intent(inout) :: G !< ocean grid structure
3442  type(verticalgrid_type), intent(inout) :: GV !< ocean vertical grid structure
3443  type(surface), intent(inout) :: state !< ocean surface state
3444  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(in) :: u !< zonal velocity (m/s)
3445  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(in) :: v !< meridional velocity (m/s)
3446  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< layer thickness (m or kg/m2)
3447  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: ssh !< time mean surface height (m)
3448  type(mom_control_struct), intent(inout) :: CS !< control structure
3449 
3450  ! local
3451  real :: depth(szi_(g)) ! distance from the surface (meter)
3452  real :: depth_ml ! depth over which to average to
3453  ! determine mixed layer properties (meter)
3454  real :: dh ! thickness of a layer within mixed layer (meter)
3455  real :: mass ! mass per unit area of a layer (kg/m2)
3456 
3457  real :: hu, hv
3458  integer :: i, j, k, is, ie, js, je, nz, numberOfErrors
3459  integer :: isd, ied, jsd, jed
3460  integer :: iscB, iecB, jscB, jecB, isdB, iedB, jsdB, jedB
3461  logical :: localError
3462  character(240) :: msg
3463 
3464  call calltree_enter("calculate_surface_state(), MOM.F90")
3465  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3466  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
3467  iscb = g%iscB ; iecb = g%iecB; jscb = g%jscB ; jecb = g%jecB
3468  isdb = g%isdB ; iedb = g%iedB; jsdb = g%jsdB ; jedb = g%jedB
3469 
3470  if (.not.state%arrays_allocated) then
3471  if (cs%use_temperature) then
3472  allocate(state%SST(isd:ied,jsd:jed)) ; state%SST(:,:) = 0.0
3473  allocate(state%SSS(isd:ied,jsd:jed)) ; state%SSS(:,:) = 0.0
3474  else
3475  allocate(state%sfc_density(isd:ied,jsd:jed)) ; state%sfc_density(:,:) = 0.0
3476  endif
3477  allocate(state%sea_lev(isd:ied,jsd:jed)) ; state%sea_lev(:,:) = 0.0
3478  allocate(state%Hml(isd:ied,jsd:jed)) ; state%Hml(:,:) = 0.0
3479  allocate(state%u(isdb:iedb,jsd:jed)) ; state%u(:,:) = 0.0
3480  allocate(state%v(isd:ied,jsdb:jedb)) ; state%v(:,:) = 0.0
3481 
3482  ! Allocate structures for ocean_mass, ocean_heat, and ocean_salt. This could
3483  ! be wrapped in a run-time flag to disable it for economy, since the 3-d
3484  ! sums are not negligible.
3485  allocate(state%ocean_mass(isd:ied,jsd:jed)) ; state%ocean_mass(:,:) = 0.0
3486  if (cs%use_temperature) then
3487  allocate(state%ocean_heat(isd:ied,jsd:jed)) ; state%ocean_heat(:,:) = 0.0
3488  allocate(state%ocean_salt(isd:ied,jsd:jed)) ; state%ocean_salt(:,:) = 0.0
3489  endif
3490  allocate(state%salt_deficit(isd:ied,jsd:jed)) ; state%salt_deficit(:,:) = 0.0
3491 
3492  state%arrays_allocated = .true.
3493  endif
3494  state%frazil => cs%tv%frazil
3495  state%TempxPmE => cs%tv%TempxPmE
3496  state%internal_heat => cs%tv%internal_heat
3497  if (associated(cs%visc%taux_shelf)) state%taux_shelf => cs%visc%taux_shelf
3498  if (associated(cs%visc%tauy_shelf)) state%tauy_shelf => cs%visc%tauy_shelf
3499 
3500  do j=js,je ; do i=is,ie
3501  state%sea_lev(i,j) = ssh(i,j)
3502  enddo ; enddo
3503 
3504  if (cs%bulkmixedlayer) then
3505  if (cs%use_temperature) then ; do j=js,je ; do i=is,ie
3506  state%SST(i,j) = cs%tv%T(i,j,1)
3507  state%SSS(i,j) = cs%tv%S(i,j,1)
3508  enddo ; enddo ; endif
3509  do j=js,je ; do i=iscb,iecb
3510  state%u(i,j) = u(i,j,1)
3511  enddo ; enddo
3512  do j=jscb,jecb ; do i=is,ie
3513  state%v(i,j) = v(i,j,1)
3514  enddo ; enddo
3515 
3516  if (associated(cs%Hml)) then ; do j=js,je ; do i=is,ie
3517  state%Hml(i,j) = cs%Hml(i,j)
3518  enddo ; enddo ; endif
3519  else
3520 
3521  depth_ml = cs%Hmix
3522  ! Determine the mean tracer properties of the uppermost depth_ml fluid.
3523  !$OMP parallel do default(shared) private(depth,dh)
3524  do j=js,je
3525  do i=is,ie
3526  depth(i) = 0.0
3527  if (cs%use_temperature) then
3528  state%SST(i,j) = 0.0 ; state%SSS(i,j) = 0.0
3529  else
3530  state%sfc_density(i,j) = 0.0
3531  endif
3532  enddo
3533 
3534  do k=1,nz ; do i=is,ie
3535  if (depth(i) + h(i,j,k)*gv%H_to_m < depth_ml) then
3536  dh = h(i,j,k)*gv%H_to_m
3537  elseif (depth(i) < depth_ml) then
3538  dh = depth_ml - depth(i)
3539  else
3540  dh = 0.0
3541  endif
3542  if (cs%use_temperature) then
3543  state%SST(i,j) = state%SST(i,j) + dh * cs%tv%T(i,j,k)
3544  state%SSS(i,j) = state%SSS(i,j) + dh * cs%tv%S(i,j,k)
3545  else
3546  state%sfc_density(i,j) = state%sfc_density(i,j) + dh * gv%Rlay(k)
3547  endif
3548  depth(i) = depth(i) + dh
3549  enddo ; enddo
3550  ! Calculate the average properties of the mixed layer depth.
3551  do i=is,ie
3552  if (depth(i) < gv%H_subroundoff*gv%H_to_m) &
3553  depth(i) = gv%H_subroundoff*gv%H_to_m
3554  if (cs%use_temperature) then
3555  state%SST(i,j) = state%SST(i,j) / depth(i)
3556  state%SSS(i,j) = state%SSS(i,j) / depth(i)
3557  else
3558  state%sfc_density(i,j) = state%sfc_density(i,j) / depth(i)
3559  endif
3560  state%Hml(i,j) = depth(i)
3561  enddo
3562  enddo ! end of j loop
3563 
3564 ! Determine the mean velocities in the uppermost depth_ml fluid.
3565  if (cs%Hmix_UV>0.) then
3566  depth_ml = cs%Hmix_UV
3567  !$OMP parallel do default(shared) private(depth,dh,hv)
3568  do j=jscb,jecb
3569  do i=is,ie
3570  depth(i) = 0.0
3571  state%v(i,j) = 0.0
3572  enddo
3573  do k=1,nz ; do i=is,ie
3574  hv = 0.5 * (h(i,j,k) + h(i,j+1,k)) * gv%H_to_m
3575  if (depth(i) + hv < depth_ml) then
3576  dh = hv
3577  elseif (depth(i) < depth_ml) then
3578  dh = depth_ml - depth(i)
3579  else
3580  dh = 0.0
3581  endif
3582  state%v(i,j) = state%v(i,j) + dh * v(i,j,k)
3583  depth(i) = depth(i) + dh
3584  enddo ; enddo
3585  ! Calculate the average properties of the mixed layer depth.
3586  do i=is,ie
3587  if (depth(i) < gv%H_subroundoff*gv%H_to_m) &
3588  depth(i) = gv%H_subroundoff*gv%H_to_m
3589  state%v(i,j) = state%v(i,j) / depth(i)
3590  enddo
3591  enddo ! end of j loop
3592 
3593  !$OMP parallel do default(shared) private(depth,dh,hu)
3594  do j=js,je
3595  do i=iscb,iecb
3596  depth(i) = 0.0
3597  state%u(i,j) = 0.0
3598  enddo
3599  do k=1,nz ; do i=iscb,iecb
3600  hu = 0.5 * (h(i,j,k) + h(i+1,j,k)) * gv%H_to_m
3601  if (depth(i) + hu < depth_ml) then
3602  dh = hu
3603  elseif (depth(i) < depth_ml) then
3604  dh = depth_ml - depth(i)
3605  else
3606  dh = 0.0
3607  endif
3608  state%u(i,j) = state%u(i,j) + dh * u(i,j,k)
3609  depth(i) = depth(i) + dh
3610  enddo ; enddo
3611  ! Calculate the average properties of the mixed layer depth.
3612  do i=iscb,iecb
3613  if (depth(i) < gv%H_subroundoff*gv%H_to_m) &
3614  depth(i) = gv%H_subroundoff*gv%H_to_m
3615  state%u(i,j) = state%u(i,j) / depth(i)
3616  enddo
3617  enddo ! end of j loop
3618  else ! Hmix_UV<=0.
3619  do j=js,je ; do i=iscb,iecb
3620  state%u(i,j) = u(i,j,1)
3621  enddo ; enddo
3622  do j=jscb,jecb ; do i=is,ie
3623  state%v(i,j) = v(i,j,1)
3624  enddo ; enddo
3625  endif
3626  endif ! end BULKMIXEDLAYER
3627 
3628  if (allocated(state%salt_deficit) .and. associated(cs%tv%salt_deficit)) then
3629  !$OMP parallel do default(shared)
3630  do j=js,je ; do i=is,ie
3631  ! Convert from gSalt to kgSalt
3632  state%salt_deficit(i,j) = 1000.0 * cs%tv%salt_deficit(i,j)
3633  enddo ; enddo
3634  endif
3635 
3636  if (allocated(state%ocean_mass) .and. allocated(state%ocean_heat) .and. &
3637  allocated(state%ocean_salt)) then
3638  !$OMP parallel do default(shared)
3639  do j=js,je ; do i=is,ie
3640  state%ocean_mass(i,j) = 0.0
3641  state%ocean_heat(i,j) = 0.0 ; state%ocean_salt(i,j) = 0.0
3642  enddo ; enddo
3643  !$OMP parallel do default(shared) private(mass)
3644  do j=js,je ; do k=1,nz; do i=is,ie
3645  mass = gv%H_to_kg_m2*h(i,j,k)
3646  state%ocean_mass(i,j) = state%ocean_mass(i,j) + mass
3647  state%ocean_heat(i,j) = state%ocean_heat(i,j) + mass*cs%tv%T(i,j,k)
3648  state%ocean_salt(i,j) = state%ocean_salt(i,j) + &
3649  mass * (1.0e-3*cs%tv%S(i,j,k))
3650  enddo ; enddo ; enddo
3651  else
3652  if (allocated(state%ocean_mass)) then
3653  !$OMP parallel do default(shared)
3654  do j=js,je ; do i=is,ie ; state%ocean_mass(i,j) = 0.0 ; enddo ; enddo
3655  !$OMP parallel do default(shared)
3656  do j=js,je ; do k=1,nz ; do i=is,ie
3657  state%ocean_mass(i,j) = state%ocean_mass(i,j) + gv%H_to_kg_m2*h(i,j,k)
3658  enddo ; enddo ; enddo
3659  endif
3660  if (allocated(state%ocean_heat)) then
3661  !$OMP parallel do default(shared)
3662  do j=js,je ; do i=is,ie ; state%ocean_heat(i,j) = 0.0 ; enddo ; enddo
3663  !$OMP parallel do default(shared) private(mass)
3664  do j=js,je ; do k=1,nz ; do i=is,ie
3665  mass = gv%H_to_kg_m2*h(i,j,k)
3666  state%ocean_heat(i,j) = state%ocean_heat(i,j) + mass*cs%tv%T(i,j,k)
3667  enddo ; enddo ; enddo
3668  endif
3669  if (allocated(state%ocean_salt)) then
3670  !$OMP parallel do default(shared)
3671  do j=js,je ; do i=is,ie ; state%ocean_salt(i,j) = 0.0 ; enddo ; enddo
3672  !$OMP parallel do default(shared) private(mass)
3673  do j=js,je ; do k=1,nz ; do i=is,ie
3674  mass = gv%H_to_kg_m2*h(i,j,k)
3675  state%ocean_salt(i,j) = state%ocean_salt(i,j) + &
3676  mass * (1.0e-3*cs%tv%S(i,j,k))
3677  enddo ; enddo ; enddo
3678  endif
3679  endif
3680 
3681  if (associated(cs%tracer_flow_CSp)) then
3682  if (.not.associated(state%tr_fields)) allocate(state%tr_fields)
3683  call call_tracer_surface_state(state, h, g, cs%tracer_flow_CSp)
3684  endif
3685 
3686  if (cs%check_bad_surface_vals) then
3687  numberoferrors=0 ! count number of errors
3688  do j=js,je; do i=is,ie
3689  if (g%mask2dT(i,j)>0.) then
3690  localerror = state%sea_lev(i,j)<=-g%bathyT(i,j) &
3691  .or. state%sea_lev(i,j)>= cs%bad_val_ssh_max &
3692  .or. state%sea_lev(i,j)<=-cs%bad_val_ssh_max &
3693  .or. state%sea_lev(i,j)+g%bathyT(i,j) < cs%bad_val_column_thickness
3694  if (cs%use_temperature) localerror = localerror &
3695  .or. state%SSS(i,j)<0. &
3696  .or. state%SSS(i,j)>=cs%bad_val_sss_max &
3697  .or. state%SST(i,j)< cs%bad_val_sst_min &
3698  .or. state%SST(i,j)>=cs%bad_val_sst_max
3699  if (localerror) then
3700  numberoferrors=numberoferrors+1
3701  if (numberoferrors<9) then ! Only report details for the first few errors
3702  if (cs%use_temperature) then
3703  write(msg(1:240),'(2(a,i4,x),2(a,f8.3,x),8(a,es11.4,x))') &
3704  'Extreme surface state detected: i=',i,'j=',j, &
3705  'x=',g%geoLonT(i,j),'y=',g%geoLatT(i,j), &
3706  'D=',g%bathyT(i,j), &
3707  'SSH=',state%sea_lev(i,j), &
3708  'SST=',state%SST(i,j), &
3709  'SSS=',state%SSS(i,j), &
3710  'U-=',state%u(i-1,j), &
3711  'U+=',state%u(i,j), &
3712  'V-=',state%v(i,j-1), &
3713  'V+=',state%v(i,j)
3714  else
3715  write(msg(1:240),'(2(a,i4,x),2(a,f8.3,x),6(a,es11.4))') &
3716  'Extreme surface state detected: i=',i,'j=',j, &
3717  'x=',g%geoLonT(i,j),'y=',g%geoLatT(i,j), &
3718  'D=',g%bathyT(i,j), &
3719  'SSH=',state%sea_lev(i,j), &
3720  'U-=',state%u(i-1,j), &
3721  'U+=',state%u(i,j), &
3722  'V-=',state%v(i,j-1), &
3723  'V+=',state%v(i,j)
3724  endif
3725  call mom_error(warning, trim(msg), all_print=.true.)
3726  elseif (numberoferrors==9) then ! Indicate once that there are more errors
3727  call mom_error(warning, 'There were more unreported extreme events!', all_print=.true.)
3728  endif ! numberOfErrors
3729  endif ! localError
3730  endif ! mask2dT
3731  enddo; enddo
3732  call sum_across_pes(numberoferrors)
3733  if (numberoferrors>0) then
3734  write(msg(1:240),'(3(a,i9,x))') 'There were a total of ',numberoferrors, &
3735  'locations detected with extreme surface values!'
3736  call mom_error(fatal, trim(msg))
3737  endif
3738  endif
3739 
3740  call calltree_leave("calculate_surface_state()")
3741 end subroutine calculate_surface_state
3742 
3743 
3744 !> End of model
3745 subroutine mom_end(CS)
3746  type(mom_control_struct), pointer :: CS !< MOM control structure
3747 
3748  if (cs%use_ALE_algorithm) then
3749  call ale_end(cs%ALE_CSp)
3750  endif
3751 
3752  dealloc_(cs%u) ; dealloc_(cs%v) ; dealloc_(cs%h)
3753  dealloc_(cs%uh) ; dealloc_(cs%vh)
3754 
3755  if (cs%use_temperature) then
3756  dealloc_(cs%T) ; cs%tv%T => null() ; dealloc_(cs%S) ; cs%tv%S => null()
3757  endif
3758  if (associated(cs%tv%frazil)) deallocate(cs%tv%frazil)
3759  if (associated(cs%tv%salt_deficit)) deallocate(cs%tv%salt_deficit)
3760  if (associated(cs%Hml)) deallocate(cs%Hml)
3761 
3762  call tracer_advect_end(cs%tracer_adv_CSp)
3763  call tracer_hor_diff_end(cs%tracer_diff_CSp)
3764  call tracer_registry_end(cs%tracer_Reg)
3765  call tracer_flow_control_end(cs%tracer_flow_CSp)
3766 
3767  if(cs%offline_tracer_mode) then
3768  call offline_transport_end(cs%offline_CSp)
3769  endif
3770 
3771  dealloc_(cs%uhtr) ; dealloc_(cs%vhtr)
3772  if (cs%split) then ; if (cs%legacy_split) then
3773  call end_dyn_legacy_split(cs%dyn_legacy_split_CSp)
3774  else
3775  call end_dyn_split_rk2(cs%dyn_split_RK2_CSp)
3776  endif ; else ; if (cs%use_RK2) then
3777  call end_dyn_unsplit_rk2(cs%dyn_unsplit_RK2_CSp)
3778  else
3779  call end_dyn_unsplit(cs%dyn_unsplit_CSp)
3780  endif ; endif
3781  dealloc_(cs%ave_ssh)
3782  if (associated(cs%update_OBC_CSp)) call obc_register_end(cs%update_OBC_CSp)
3783 
3784  call verticalgridend(cs%GV)
3785  call mom_grid_end(cs%G)
3786 
3787  deallocate(cs)
3788 
3789 end subroutine mom_end
3790 
3791 !> \namespace mom
3792 !!
3793 !! Modular Ocean Model (MOM) Version 6.0 (MOM6)
3794 !!
3795 !! \authors Alistair Adcroft, Robert Hallberg, and Stephen Griffies
3796 !!
3797 !! Additional contributions from:
3798 !! * Whit Anderson
3799 !! * Brian Arbic
3800 !! * Will Cooke
3801 !! * Anand Gnanadesikan
3802 !! * Matthew Harrison
3803 !! * Mehmet Ilicak
3804 !! * Laura Jackson
3805 !! * Jasmine John
3806 !! * John Krasting
3807 !! * Zhi Liang
3808 !! * Bonnie Samuels
3809 !! * Harper Simmons
3810 !! * Laurent White
3811 !! * Niki Zadeh
3812 !!
3813 !! MOM ice-shelf code was developed by
3814 !! * Daniel Goldberg
3815 !! * Robert Hallberg
3816 !! * Chris Little
3817 !! * Olga Sergienko
3818 !!
3819 !! \section section_overview Overview of MOM
3820 !!
3821 !! This program (MOM) simulates the ocean by numerically solving
3822 !! the hydrostatic primitive equations in generalized Lagrangian
3823 !! vertical coordinates, typically tracking stretched pressure (p*)
3824 !! surfaces or following isopycnals in the ocean's interior, and
3825 !! general orthogonal horizontal coordinates. Unlike earlier versions
3826 !! of MOM, in MOM6 these equations are horizontally discretized on an
3827 !! Arakawa C-grid. (It remains to be seen whether a B-grid dynamic
3828 !! core will be revived in MOM6 at a later date; for now applications
3829 !! requiring a B-grid discretization should use MOM5.1.) MOM6 offers
3830 !! a range of options for the physical parameterizations, from those
3831 !! most appropriate to highly idealized models for geophysical fluid
3832 !! dynamics studies to a rich suite of processes appropriate for
3833 !! realistic ocean simulations. The thermodynamic options typically
3834 !! use conservative temperature and preformed salinity as conservative
3835 !! state variables and a full nonlinear equation of state, but there
3836 !! are also idealized adiabatic configurations of the model that use
3837 !! fixed density layers. Version 6.0 of MOM continues in the long
3838 !! tradition of a commitment to climate-quality ocean simulations
3839 !! embodied in previous versions of MOM, even as it draws extensively
3840 !! on the lessons learned in the development of the Generalized Ocean
3841 !! Layered Dynamics (GOLD) ocean model, which was also primarily
3842 !! developed at NOAA/GFDL. MOM has also benefited tremendously from
3843 !! the FMS infrastructure, which it utilizes and shares with other
3844 !! component models developed at NOAA/GFDL.
3845 !!
3846 !! When run is isopycnal-coordinate mode, the uppermost few layers
3847 !! are often used to describe a bulk mixed layer, including the
3848 !! effects of penetrating shortwave radiation. Either a split-
3849 !! explicit time stepping scheme or a non-split scheme may be used
3850 !! for the dynamics, while the time stepping may be split (and use
3851 !! different numbers of steps to cover the same interval) for the
3852 !! forcing, the thermodynamics, and for the dynamics. Most of the
3853 !! numerics are second order accurate in space. MOM can run with an
3854 !! absurdly thin minimum layer thickness. A variety of non-isopycnal
3855 !! vertical coordinate options are under development, but all exploit
3856 !! the advantages of a Lagrangian vertical coordinate, as discussed
3857 !! in detail by Adcroft and Hallberg (Ocean Modelling, 2006).
3858 !!
3859 !! Details of the numerics and physical parameterizations are
3860 !! provided in the appropriate source files. All of the available
3861 !! options are selected at run-time by parsing the input files,
3862 !! usually MOM_input and MOM_override, and the options choices are
3863 !! then documented for each run in MOM_param_docs.
3864 !!
3865 !! MOM6 integrates the equations forward in time in three distinct
3866 !! phases. In one phase, the dynamic equations for the velocities
3867 !! and layer thicknesses are advanced, capturing the propagation of
3868 !! external and internal inertia-gravity waves, Rossby waves, and
3869 !! other strictly adiabatic processes, including lateral stresses,
3870 !! vertical viscosity and momentum forcing, and interface height
3871 !! diffusion (commonly called Gent-McWilliams diffusion in depth-
3872 !! coordinate models). In the second phase, all tracers are advected
3873 !! and diffused along the layers. The third phase applies diabatic
3874 !! processes, vertical mixing of water properties, and perhaps
3875 !! vertical remapping to cause the layers to track the desired
3876 !! vertical coordinate.
3877 !!
3878 !! The present file (MOM.F90) orchestrates the main time stepping
3879 !! loops. One time integration option for the dynamics uses a split
3880 !! explicit time stepping scheme to rapidly step the barotropic
3881 !! pressure and velocity fields. The barotropic velocities are
3882 !! averaged over the baroclinic time step before they are used to
3883 !! advect thickness and determine the baroclinic accelerations. As
3884 !! described in Hallberg and Adcroft (2009), a barotropic correction
3885 !! is applied to the time-mean layer velocities to ensure that the
3886 !! sum of the layer transports agrees with the time-mean barotropic
3887 !! transport, thereby ensuring that the estimates of the free surface
3888 !! from the sum of the layer thicknesses agrees with the final free
3889 !! surface height as calculated by the barotropic solver. The
3890 !! barotropic and baroclinic velocities are kept consistent by
3891 !! recalculating the barotropic velocities from the baroclinic
3892 !! transports each time step. This scheme is described in Hallberg,
3893 !! 1997, J. Comp. Phys. 135, 54-65 and in Hallberg and Adcroft, 2009,
3894 !! Ocean Modelling, 29, 15-26.
3895 !!
3896 !! The other time integration options use non-split time stepping
3897 !! schemes based on the 3-step third order Runge-Kutta scheme
3898 !! described in Matsuno, 1966, J. Met. Soc. Japan, 44, 85-88, or on
3899 !! a two-step quasi-2nd order Runge-Kutta scheme. These are much
3900 !! slower than the split time-stepping scheme, but they are useful
3901 !! for providing a more robust solution for debugging cases where the
3902 !! more complicated split time-stepping scheme may be giving suspect
3903 !! solutions.
3904 !!
3905 !! There are a range of closure options available. Horizontal
3906 !! velocities are subject to a combination of horizontal biharmonic
3907 !! and Laplacian friction (based on a stress tensor formalism) and a
3908 !! vertical Fickian viscosity (perhaps using the kinematic viscosity
3909 !! of water). The horizontal viscosities may be constant, spatially
3910 !! varying or may be dynamically calculated using Smagorinsky's
3911 !! approach. A diapycnal diffusion of density and thermodynamic
3912 !! quantities is also allowed, but not required, as is horizontal
3913 !! diffusion of interface heights (akin to the Gent-McWilliams
3914 !! closure of geopotential coordinate models). The diapycnal mixing
3915 !! may use a fixed diffusivity or it may use the shear Richardson
3916 !! number dependent closure, like that described in Jackson et al.
3917 !! (JPO, 2008). When there is diapycnal diffusion, it applies to
3918 !! momentum as well. As this is in addition to the vertical viscosity,
3919 !! the vertical Prandtl always exceeds 1. A refined bulk-mixed layer
3920 !! is often used to describe the planetary boundary layer in realistic
3921 !! ocean simulations.
3922 !!
3923 !! MOM has a number of noteworthy debugging capabilities.
3924 !! Excessively large velocities are truncated and MOM will stop
3925 !! itself after a number of such instances to keep the model from
3926 !! crashing altogether. This is useful in diagnosing failures,
3927 !! or (by accepting some truncations) it may be useful for getting
3928 !! the model past the adjustment from an ill-balanced initial
3929 !! condition. In addition, all of the accelerations in the columns
3930 !! with excessively large velocities may be directed to a text file.
3931 !! Parallelization errors may be diagnosed using the DEBUG option,
3932 !! which causes extensive checksums to be written out along with
3933 !! comments indicating where in the algorithm the sums originate and
3934 !! what variable is being summed. The point where these checksums
3935 !! differ between runs is usually a good indication of where in the
3936 !! code the problem lies. All of the test cases provided with MOM
3937 !! are routinely tested to ensure that they give bitwise identical
3938 !! results regardless of the domain decomposition, or whether they
3939 !! use static or dynamic memory allocation.
3940 !!
3941 !! \section section_structure Structure of MOM
3942 !!
3943 !! About 115 other files of source code and 4 header files comprise
3944 !! the MOM code, although there are several hundred more files that
3945 !! make up the FMS infrastructure upon which MOM is built. Each of
3946 !! the MOM files contains comments documenting what it does, and
3947 !! most of the file names are fairly self-evident. In addition, all
3948 !! subroutines and data types are referenced via a module use, only
3949 !! statement, and the module names are consistent with the file names,
3950 !! so it is not too hard to find the source file for a subroutine.
3951 !!
3952 !! The typical MOM directory tree is as follows:
3953 !!
3954 !! \verbatim
3955 !! ../MOM
3956 !! |-- config_src
3957 !! | |-- coupled_driver
3958 !! | |-- dynamic
3959 !! | `-- solo_driver
3960 !! |-- examples
3961 !! | |-- CM2G
3962 !! | |-- ...
3963 !! | `-- torus_advection_test
3964 !! `-- src
3965 !! |-- core
3966 !! |-- diagnostics
3967 !! |-- equation_of_state
3968 !! |-- framework
3969 !! |-- ice_shelf
3970 !! |-- initialization
3971 !! |-- parameterizations
3972 !! | |-- lateral
3973 !! | `-- vertical
3974 !! |-- tracer
3975 !! `-- user
3976 !! \endverbatim
3977 !!
3978 !! Rather than describing each file here, each directory contents
3979 !! will be described to give a broad overview of the MOM code
3980 !! structure.
3981 !!
3982 !! The directories under config_src contain files that are used for
3983 !! configuring the code, for instance for coupled or ocean-only runs.
3984 !! Only one or two of these directories are used in compiling any,
3985 !! particular run.
3986 !!
3987 !! * config_src/coupled_driver:
3988 !! The files here are used to couple MOM as a component in a larger
3989 !! run driven by the FMS coupler. This includes code that converts
3990 !! various forcing fields into the code structures and flux and unit
3991 !! conventions used by MOM, and converts the MOM surface fields
3992 !! back to the forms used by other FMS components.
3993 !!
3994 !! * config_src/dynamic:
3995 !! The only file here is the version of MOM_memory.h that is used
3996 !! for dynamic memory configurations of MOM.
3997 !!
3998 !! * config_src/solo_driver:
3999 !! The files here are include the _main driver that is used when
4000 !! MOM is configured as an ocean-only model, as well as the files
4001 !! that specify the surface forcing in this configuration.
4002 !!
4003 !! The directories under examples provide a large number of working
4004 !! configurations of MOM, along with reference solutions for several
4005 !! different compilers on GFDL's latest large computer. The versions
4006 !! of MOM_memory.h in these directories need not be used if dynamic
4007 !! memory allocation is desired, and the answers should be unchanged.
4008 !!
4009 !! The directories under src contain most of the MOM files. These
4010 !! files are used in every configuration using MOM.
4011 !!
4012 !! * src/core:
4013 !! The files here constitute the MOM dynamic core. This directory
4014 !! also includes files with the types that describe the model's
4015 !! lateral grid and have defined types that are shared across
4016 !! various MOM modules to allow for more succinct and flexible
4017 !! subroutine argument lists.
4018 !!
4019 !! * src/diagnostics:
4020 !! The files here calculate various diagnostics that are anciliary
4021 !! to the model itself. While most of these diagnostics do not
4022 !! directly affect the model's solution, there are some, like the
4023 !! calculation of the deformation radius, that are used in some
4024 !! of the process parameterizations.
4025 !!
4026 !! * src/equation_of_state:
4027 !! These files describe the physical properties of sea-water,
4028 !! including both the equation of state and when it freezes.
4029 !!
4030 !! * src/framework:
4031 !! These files provide infrastructure utilities for MOM. Many are
4032 !! simply wrappers for capabilities provided by FMS, although others
4033 !! provide capabilities (like the file_parser) that are unique to
4034 !! MOM. When MOM is adapted to use a modeling infrastructure
4035 !! distinct from FMS, most of the required changes are in this
4036 !! directory.
4037 !!
4038 !! * src/initialization:
4039 !! These are the files that are used to initialize the MOM grid
4040 !! or provide the initial physical state for MOM. These files are
4041 !! not intended to be modified, but provide a means for calling
4042 !! user-specific initialization code like the examples in src/user.
4043 !!
4044 !! * src/parameterizations/lateral:
4045 !! These files implement a number of quasi-lateral (along-layer)
4046 !! process parameterizations, including lateral viscosities,
4047 !! parameterizations of eddy effects, and the calculation of tidal
4048 !! forcing.
4049 !!
4050 !! * src/parameterizations/vertical:
4051 !! These files implement a number of vertical mixing or diabatic
4052 !! processes, including the effects of vertical viscosity and
4053 !! code to parameterize the planetary boundary layer. There is a
4054 !! separate driver that orchestrates this portion of the algorithm,
4055 !! and there is a diversity of parameterizations to be found here.
4056 !!
4057 !! * src/tracer:
4058 !! These files handle the lateral transport and diffusion of
4059 !! tracers, or are the code to implement various passive tracer
4060 !! packages. Additional tracer packages are readily accomodated.
4061 !!
4062 !! * src/user:
4063 !! These are either stub routines that a user could use to change
4064 !! the model's initial conditions or forcing, or are examples that
4065 !! implement specific test cases. These files can easily be hand
4066 !! edited to create new analytically specified configurations.
4067 !!
4068 !!
4069 !! Most simulations can be set up by modifying only the files
4070 !! MOM_input, and possibly one or two of the files in src/user.
4071 !! In addition, the diag_table (MOM_diag_table) will commonly be
4072 !! modified to tailor the output to the needs of the question at
4073 !! hand. The FMS utility mkmf works with a file called path_names
4074 !! to build an appropriate makefile, and path_names should be edited
4075 !! to reflect the actual location of the desired source code.
4076 !!
4077 !!
4078 !! There are 3 publicly visible subroutines in this file (MOM.F90).
4079 !! * step_MOM steps MOM over a specified interval of time.
4080 !! * MOM_initialize calls initialize and does other initialization
4081 !! that does not warrant user modification.
4082 !! * calculate_surface_state determines the surface (bulk mixed layer
4083 !! if traditional isoycnal vertical coordinate) properties of the
4084 !! current model state and packages pointers to these fields into an
4085 !! exported structure.
4086 !!
4087 !! The remaining subroutines in this file (src/core/MOM.F90) are:
4088 !! * find_total_transport determines the barotropic mass transport.
4089 !! * register_diags registers many diagnostic fields for the dynamic
4090 !! solver, or of the main model variables.
4091 !! * MOM_timing_init initializes various CPU time clocks.
4092 !! * write_static_fields writes out various time-invariant fields.
4093 !! * set_restart_fields is used to specify those fields that are
4094 !! written to and read from the restart file.
4095 !!
4096 !! \section section_heat_budget Diagnosing MOM heat budget
4097 !!
4098 !! Here are some example heat budgets for the ALE version of MOM6.
4099 !!
4100 !! \subsection subsection_2d_heat_budget Depth integrated heat budget
4101 !!
4102 !! Depth integrated heat budget diagnostic for MOM.
4103 !!
4104 !! * OPOTTEMPTEND_2d = T_ADVECTION_XY_2d + OPOTTEMPPMDIFF_2d + HFDS + HFGEOU
4105 !!
4106 !! * T_ADVECTION_XY_2d = horizontal advection
4107 !! * OPOTTEMPPMDIFF_2d = neutral diffusion
4108 !! * HFDS = net surface boundary heat flux
4109 !! * HFGEOU = geothermal heat flux
4110 !!
4111 !! * HFDS = net surface boundary heat flux entering the ocean
4112 !! = rsntds + rlntds + hfls + hfss + heat_pme + hfsifrazil
4113 !!
4114 !! * More heat flux cross-checks
4115 !! * hfds = net_heat_coupler + hfsifrazil + heat_pme
4116 !! * heat_pme = heat_content_surfwater
4117 !! = heat_content_massin + heat_content_massout
4118 !! = heat_content_fprec + heat_content_cond + heat_content_vprec
4119 !! + hfrunoffds + hfevapds + hfrainds
4120 !!
4121 !! \subsection subsection_3d_heat_budget Depth integrated heat budget
4122 !!
4123 !! Here is an example 3d heat budget diagnostic for MOM.
4124 !!
4125 !! * OPOTTEMPTEND = T_ADVECTION_XY + TH_TENDENCY_VERT_REMAP + OPOTTEMPDIFF + OPOTTEMPPMDIFF
4126 !! + BOUNDARY_FORCING_HEAT_TENDENCY + FRAZIL_HEAT_TENDENCY
4127 !!
4128 !! * OPOTTEMPTEND = net tendency of heat as diagnosed in MOM.F90
4129 !! * T_ADVECTION_XY = heating of a cell from lateral advection
4130 !! * TH_TENDENCY_VERT_REMAP = heating of a cell from vertical remapping
4131 !! * OPOTTEMPDIFF = heating of a cell from diabatic diffusion
4132 !! * OPOTTEMPPMDIFF = heating of a cell from neutral diffusion
4133 !! * BOUNDARY_FORCING_HEAT_TENDENCY = heating of cell from boundary fluxes
4134 !! * FRAZIL_HEAT_TENDENCY = heating of cell from frazil
4135 !!
4136 !! * TH_TENDENCY_VERT_REMAP has zero vertical sum, as it redistributes heat in vertical.
4137 !!
4138 !! * OPOTTEMPDIFF has zero vertical sum, as it redistributes heat in the vertical.
4139 !!
4140 !! * BOUNDARY_FORCING_HEAT_TENDENCY generally has 3d structure, with k > 1 contributions from
4141 !! penetrative shortwave, and from other fluxes for the case when layers are tiny, in which
4142 !! case MOM6 partitions tendencies into k > 1 layers.
4143 !!
4144 !! * FRAZIL_HEAT_TENDENCY generally has 3d structure, since MOM6 frazil calculation checks the
4145 !! full ocean column.
4146 !!
4147 !! * FRAZIL_HEAT_TENDENCY[k=\@sum] = HFSIFRAZIL = column integrated frazil heating.
4148 !!
4149 !! * HFDS = FRAZIL_HEAT_TENDENCY[k=\@sum] + BOUNDARY_FORCING_HEAT_TENDENCY[k=\@sum]
4150 !!
4151 !! Here is an example 2d heat budget (depth summed) diagnostic for MOM.
4152 !!
4153 !! * OPOTTEMPTEND_2d = T_ADVECTION_XY_2d + OPOTTEMPPMDIFF_2d + HFDS
4154 !!
4155 !!
4156 !! Here is an example 3d salt budget diagnostic for MOM.
4157 !!
4158 !! * OSALTTEND = S_ADVECTION_XY + SH_TENDENCY_VERT_REMAP + OSALTDIFF + OSALTPMDIFF
4159 !! + BOUNDARY_FORCING_SALT_TENDENCY
4160 !!
4161 !! * OSALTTEND = net tendency of salt as diagnosed in MOM.F90
4162 !! * S_ADVECTION_XY = salt convergence to cell from lateral advection
4163 !! * SH_TENDENCY_VERT_REMAP = salt convergence to cell from vertical remapping
4164 !! * OSALTDIFF = salt convergence to cell from diabatic diffusion
4165 !! * OSALTPMDIFF = salt convergence to cell from neutral diffusion
4166 !! * BOUNDARY_FORCING_SALT_TENDENCY = salt convergence to cell from boundary fluxes
4167 !!
4168 !! * SH_TENDENCY_VERT_REMAP has zero vertical sum, as it redistributes salt in vertical.
4169 !!
4170 !! * OSALTDIFF has zero vertical sum, as it redistributes salt in the vertical.
4171 !!
4172 !! * BOUNDARY_FORCING_SALT_TENDENCY generally has 3d structure, with k > 1 contributions from
4173 !! the case when layers are tiny, in which case MOM6 partitions tendencies into k > 1 layers.
4174 !!
4175 !! * SFDSI = BOUNDARY_FORCING_SALT_TENDENCY[k=\@sum]
4176 !!
4177 !! Here is an example 2d salt budget (depth summed) diagnostic for MOM.
4178 !!
4179 !! * OSALTTEND_2d = S_ADVECTION_XY_2d + OSALTPMDIFF_2d + SFDSI (+ SALT_FLUX_RESTORE)
4180 !!
4181 !!
4182 !!
4183 
4184 
4185 end module mom
4186 
subroutine, public diag_mediator_infrastructure_init(err_msg)
subroutine, public mom_io_init(param_file)
Initialize the MOM_io module.
Definition: MOM_io.F90:840
subroutine post_transport_diagnostics(G, GV, CS, diag, dt_trans, h, h_pre_dyn)
This routine posts diagnostics of the transports, including the subgridscale contributions.
Definition: MOM.F90:2794
integer id_clock_ocean
Definition: MOM.F90:438
subroutine, public step_mom_dyn_unsplit_rk2(u_in, v_in, h_in, tv, visc, Time_local, dt, fluxes, p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, CS, VarMix, MEKE)
subroutine, public register_diags_offline_transport(Time, diag, CS)
Initialize additional diagnostics required for offline tracer transport.
Control structure for mom_mixed_layer_restrat.
The following structure contains pointers to various fields which may be used describe the surface st...
subroutine, public ale_writecoordinatefile(CS, GV, directory)
Write the vertical coordinate information into a file. This subroutine writes out a file containing a...
Definition: MOM_ALE.F90:1276
The routines here implement the offline tracer algorithm used in MOM6. These are called from step_off...
subroutine, public end_dyn_unsplit(CS)
subroutine, public mom_grid_init(G, param_file, HI, global_indexing, bathymetry_at_vel)
MOM_grid_init initializes the ocean grid array sizes and grid memory.
Definition: MOM_grid.F90:176
subroutine, public calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, fluxes, dt, G, GV, CS, eta_bt)
Diagnostics not more naturally calculated elsewhere are computed here.
subroutine, public mom_thermo_chksum(mesg, tv, G, haloshift)
subroutine, public coradcalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, CS)
Calculates the Coriolis and momentum advection contributions to the acceleration. ...
subroutine post_surface_diagnostics(CS, G, diag, state)
This routine posts diagnostics of various ocean surface quantities.
Definition: MOM.F90:3170
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
Definition: MOM_io.F90:585
subroutine, public initialize_dyn_split_rk2(u, v, h, uh, vh, eta, Time, G, GV, param_file, diag, CS, restart_CS, dt, Accel_diag, Cont_diag, MIS, VarMix, MEKE, OBC, update_OBC_CSp, ALE_CSp, setVisc_CSp, visc, dirs, ntrunc)
This subroutine initializes all of the variables that are used by this dynamic core, including diagnostics and the cpu clocks.
subroutine, public initialize_dyn_unsplit(u, v, h, Time, G, GV, param_file, diag, CS, restart_CS, Accel_diag, Cont_diag, MIS, OBC, update_OBC_CSp, ALE_CSp, setVisc_CSp, visc, dirs, ntrunc)
subroutine, public initialize_mom(Time, param_file, dirs, CS, Time_in, offline_tracer_mode)
This subroutine initializes MOM.
Definition: MOM.F90:1480
subroutine, public end_dyn_unsplit_rk2(CS)
This module contains the main regridding routines. Regridding comprises two steps: (1) Interpolation ...
Definition: MOM_ALE.F90:7
subroutine post_diags_ts_vardec(G, CS, dt)
Calculate and post variance decay diagnostics for temp/salt.
Definition: MOM.F90:3017
subroutine, public step_mom_dyn_split_rk2(u, v, h, tv, visc, Time_local, dt, fluxes, p_surf_begin, p_surf_end, dt_since_flux, dt_therm, uh, vh, uhtr, vhtr, eta_av, G, GV, CS, calc_dtbt, VarMix, MEKE)
RK2 splitting for time stepping MOM adiabatic dynamics.
subroutine, public mom_diagnostics_init(MIS, ADp, CDp, Time, G, GV, param_file, diag, CS)
Provides a mechanism for recording diagnostic variables that are no longer valid, along with their re...
Methods for testing for, and list of, obsolete run-time parameters.
character(len=48) function, public get_flux_units(GV)
Returns the model&#39;s thickness flux units, usually m^3/s or kg/s.
This module implements boundary forcing for MOM6.
subroutine, public offline_diabatic_ale(fluxes, Time_start, Time_end, CS, h_pre, eatr, ebtr)
The vertical/diabatic driver for offline tracers. First the eatr/ebtr associated with the interpolate...
subroutine, public set_viscous_bbl(u, v, h, tv, visc, G, GV, CS)
The following subroutine calculates the thickness of the bottom boundary layer and the viscosity with...
subroutine, public step_mom_dyn_legacy_split(u, v, h, tv, visc, Time_local, dt, fluxes, p_surf_begin, p_surf_end, dt_since_flux, dt_therm, uh, vh, uhtr, vhtr, eta_av, G, GV, CS, calc_dtbt, VarMix, MEKE)
Control structure for this module.
integer function, public register_scalar_field(module_name, field_name, init_time, diag_cs, long_name, units, missing_value, range, standard_name, do_not_log, err_msg, interp_method, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
subroutine, public enable_averaging(time_int_in, time_end_in, diag_cs)
subroutine, public set_visc_register_restarts(HI, GV, param_file, visc, restart_CS)
This subroutine is used to register any fields associated with the vertvisc_type. ...
subroutine, public get_mom_input(param_file, dirs, check_params)
integer id_clock_offline_tracer
Definition: MOM.F90:455
subroutine, public register_restarts_dyn_unsplit_rk2(HI, GV, param_file, CS, restart_CS)
subroutine, public mom_initialize_coord(GV, PF, write_geom, output_dir, tv, max_depth)
MOM_initialize_coord sets up time-invariant quantities related to MOM6&#39;s vertical coordinate...
Initializes fixed aspects of the model, such as horizontal grid metrics, topography and Coriolis...
subroutine, public tracer_registry_init(param_file, Reg)
This routine include declares and sets the variable "version".
subroutine, public continuity_init(Time, G, GV, param_file, diag, CS)
Initializes continuity_cs.
subroutine, public mixedlayer_restrat(h, uhtr, vhtr, tv, fluxes, dt, MLD, VarMix, G, GV, CS)
Driver for the mixed-layer restratification parameterization. The code branches between two different...
integer, parameter, public to_all
subroutine, public hor_visc_init(Time, G, param_file, diag, CS)
This subroutine allocates space for and calculates static variables used by this module. The metrics may be 0, 1, or 2-D arrays, while fields like the background viscosities are 2-D arrays. ALLOC is a macro defined in MOM_memory.h to either allocate for dynamic memory, or do nothing when using static memory.
The module calculates interface heights, including free surface height.
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
integer id_clock_thick_diff
Definition: MOM.F90:444
integer id_clock_mom_init
Definition: MOM.F90:450
This is the main routine for MOM.
Definition: MOM.F90:2
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
subroutine, public adiabatic_driver_init(Time, G, param_file, diag, CS, tracer_flow_CSp, diag_to_Z_CSp)
A simplified version of diabatic_driver_init that will allow tracer column functions to be called wit...
subroutine, public initialize_dyn_unsplit_rk2(u, v, h, Time, G, GV, param_file, diag, CS, restart_CS, Accel_diag, Cont_diag, MIS, OBC, update_OBC_CSp, ALE_CSp, setVisc_CSp, visc, dirs, ntrunc)
subroutine, public diabatic(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, G, GV, CS)
This subroutine imposes the diapycnal mass fluxes and the accompanying diapycnal advection of momentu...
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:45
subroutine, public set_visc_init(Time, G, GV, param_file, diag, visc, CS, OBC)
Solve the layer continuity equation.
Controls where open boundary conditions are applied.
subroutine, public offline_advection_ale(fluxes, Time_start, time_interval, CS, id_clock_ale, h_pre, uhtr, vhtr, converged)
3D advection is done by doing flux-limited nonlinear horizontal advection interspersed with an ALE re...
integer id_clock_dynamics
Definition: MOM.F90:439
subroutine, public tracer_flow_control_init(restart, day, G, GV, h, param_file, diag, OBC, CS, sponge_CSp, ALE_sponge_CSp, diag_to_Z_CSp, tv)
This subroutine calls all registered tracer initialization subroutines.
subroutine, public vertvisc_remnant(visc, visc_rem_u, visc_rem_v, dt, G, GV, CS)
Calculate the fraction of momentum originally in a layer that remains after a time-step of viscosity...
subroutine register_diags(Time, G, GV, CS, ADp)
Register the diagnostics.
Definition: MOM.F90:2385
Implements vertical viscosity (vertvisc)
Provides the ocean grid type.
Definition: MOM_grid.F90:2
real function, dimension(cs%nk+1), public ale_getcoordinate(CS)
Query the target coordinate interfaces positions.
Definition: MOM_ALE.F90:1208
subroutine, public do_group_pass(group, MOM_dom)
The vertvisc_type structure contains vertical viscosities, drag coefficients, and related fields...
subroutine, public register_restarts_dyn_split_rk2(HI, GV, param_file, CS, restart_CS, uh, vh)
This subroutine sets up any auxiliary restart variables that are specific to the unsplit time steppin...
logical function, public mixedlayer_restrat_init(Time, G, GV, param_file, diag, CS)
Initialize the mixed layer restratification module.
subroutine, public mom_forcing_chksum(mesg, fluxes, G, haloshift)
Write out chksums for basic state variables.
subroutine, public pressureforce_init(Time, G, GV, param_file, diag, CS, tides_CSp)
Initialize the pressure force control structure.
subroutine, public offline_fw_fluxes_into_ocean(G, GV, CS, fluxes, h, in_flux_optional)
Apply positive freshwater fluxes (into the ocean) and update netMassOut with only the negative (out o...
This routine drives the diabatic/dianeutral physics for MOM.
subroutine, public set_axes_info(G, GV, param_file, diag_cs, set_vertical)
Sets up diagnostics axes.
subroutine set_restart_fields(GV, param_file, CS)
Set the fields that are needed for bitwise identical restarting the time stepping scheme...
Definition: MOM.F90:3354
subroutine, public set_first_direction(G, y_first)
Definition: MOM_grid.F90:440
Main routine for lateral (along surface or neutral) diffusion of tracers.
Accelerations due to the Coriolis force and momentum advection.
subroutine, public call_tracer_register(HI, GV, param_file, CS, tr_Reg, restart_CS)
The following 5 subroutines and associated definitions provide the machinery to register and call the...
subroutine, public mom_initialize_state(u, v, h, tv, Time, G, GV, PF, dirs, restart_CS, ALE_CSp, tracer_Reg, sponge_CSp, ALE_sponge_CSp, OBC, Time_in)
subroutine, public post_offline_convergence_diags(CS, h_off, h_end, uhtr, vhtr)
Posts diagnostics related to offline convergence diagnostics.
integer id_clock_diabatic
Definition: MOM.F90:442
subroutine, public ale_register_diags(Time, G, diag, C_p, Reg, CS)
Initialize diagnostics for the ALE module.
Definition: MOM_ALE.F90:261
subroutine, public diag_mediator_init(G, nz, param_file, diag_cs, doc_file_dir)
diag_mediator_init initializes the MOM diag_mediator and opens the available diagnostics file...
subroutine, public calltree_leave(mesg)
Writes a message about leaving a subroutine if call tree reporting is active.
A thin wrapper for Boussinesq/non-Boussinesq forms of the pressure force calculation.
subroutine post_ts_diagnostics(CS, G, GV, tv, diag, dt)
Post diagnostics of temperatures and salinities, their fluxes, and tendencies.
Definition: MOM.F90:2858
subroutine, public end_dyn_split_rk2(CS)
Close the dyn_split_RK2 module.
subroutine, public hor_index_init(Domain, HI, param_file, local_indexing, index_offset)
Sets various index values in a hor_index_type.
subroutine, public eos_init(param_file, EOS)
Initializes EOS_type by allocating and reading parameters.
Definition: MOM_EOS.F90:459
subroutine, public register_restarts_dyn_legacy_split(HI, GV, param_file, CS, restart_CS, uh, vh)
This module contains I/O framework code.
Definition: MOM_io.F90:2
subroutine, public offline_redistribute_residual(CS, h_pre, uhtr, vhtr, converged)
In the case where the main advection routine did not converge, something needs to be done with the re...
Defines the horizontal index type (hor_index_type) used for providing index ranges.
subroutine, public mom_accel_chksum(mesg, CAu, CAv, PFu, PFv, diffu, diffv, G, GV, pbce, u_accel_bt, v_accel_bt, symmetric)
integer id_clock_pass_init
Definition: MOM.F90:452
subroutine unit_tests(verbosity)
Calls unit tests for other modules. Note that if a unit test returns true, a FATAL error is triggered...
The accel_diag_ptrs structure contains pointers to arrays with accelerations, which can later be used...
subroutine, public mom_diag_to_z_end(CS)
subroutine, public advect_tracer(h_end, uhtr, vhtr, OBC, dt, G, GV, CS, Reg, h_prev_opt, max_iter_in, x_first_in, uhr_out, vhr_out, h_out)
This routine time steps the tracer concentration using a monotonic, conservative, weakly diffusive sc...
Variable mixing coefficients.
This module contains the routines used to apply sponge layers when using the ALE mode. Applying sponges requires the following: (1) initialize_ALE_sponge (2) set_up_ALE_sponge_field (tracers) and set_up_ALE_sponge_vel_field (vel) (3) apply_ALE_sponge (4) init_ALE_sponge_diags (not being used for now) (5) ALE_sponge_end (not being used for now)
subroutine, public coriolisadv_init(Time, G, param_file, diag, AD, CS)
Initializes the control structure for coriolisadv_cs.
subroutine, public diag_register_area_ids(diag_cs, id_area_t, id_area_q)
Attaches the id of cell areas to axes groups for use with cell_measures.
subroutine, public ale_updateverticalgridtype(CS, GV)
Update the vertical grid type with ALE information. This subroutine sets information in the verticalG...
Definition: MOM_ALE.F90:1256
SPONGE control structure.
character(len=48) function, public get_tr_flux_units(GV, tr_units, tr_vol_conc_units, tr_mass_conc_units)
Returns the model&#39;s tracer flux units.
Container for horizontal index ranges for data, computational and global domains. ...
Control structure for mom_coriolisadv.
subroutine, public varmix_init(Time, G, param_file, diag, CS)
Initializes the variables mixing coefficients container.
subroutine, public tracer_hor_diff_end(CS)
subroutine, public verticalgridinit(param_file, GV)
Allocates and initializes the model&#39;s vertical grid structure.
subroutine, public ale_end(CS)
End of regridding (memory deallocation). This routine is typically called (from MOM_end in file MOM...
Definition: MOM_ALE.F90:361
integer id_clock_tracer
Definition: MOM.F90:441
subroutine adjust_ssh_for_p_atm(CS, G, GV, ssh, p_atm)
This subroutine applies a correction to the sea surface height to compensate for the atmospheric pres...
Definition: MOM.F90:3408
real function, public global_area_integral(var, G)
subroutine, public end_dyn_legacy_split(CS)
subroutine, public register_tracer(tr1, tr_desc, param_file, HI, GV, Reg, tr_desc_ptr, ad_x, ad_y, df_x, df_y, OBC_inflow, OBC_in_u, OBC_in_v, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine registers a tracer to be advected and laterally diffused.
subroutine, public find_obsolete_params(param_file)
Scans input parameter file for list obsolete parameters.
subroutine, public horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, CS, OBC)
This subroutine determines the acceleration due to the horizontal viscosity. A combination of biharmo...
subroutine, public verticalgridend(GV)
Deallocates the model&#39;s vertical grid structure.
subroutine, public offline_transport_end(CS)
Deallocates (if necessary) arrays within the offline control structure.
subroutine, public diag_masks_set(G, nz, missing_value, diag_cs)
diag_masks_set sets up the 2d and 3d masks for diagnostics
subroutine, public destroy_dyn_horgrid(G)
Release memory used by the dyn_horgrid_type and related structures.
Control structure that contains MEKE parameters and diagnostics handles.
Definition: MOM_MEKE.F90:29
subroutine, public mom_grid_end(G)
Release memory used by the ocean_grid_type and related structures.
Definition: MOM_grid.F90:521
subroutine, public copy_dyngrid_to_mom_grid(dG, oG)
Copies information from a dynamic (shared) horizontal grid type into an ocean_grid_type.
subroutine, public extract_offline_main(CS, uhtr, vhtr, eatr, ebtr, h_end, accumulated_time, dt_offline, dt_offline_vertical, skip_diffusion)
Extracts members of the offline main control structure. All arguments are optional except the control...
subroutine step_mom_thermo(CS, G, GV, u, v, h, tv, fluxes, dtdia)
MOM_step_thermo orchestrates the thermodynamic time stepping and vertical remapping, via calls to diabatic (or adiabatic) and ALE_main.
Definition: MOM.F90:1131
subroutine, public start_group_pass(group, MOM_dom)
logical function, public meke_init(Time, G, param_file, diag, CS, MEKE, restart_CS)
Initializes the MOM_MEKE module and reads parameters. Returns True if module is to be used...
Definition: MOM_MEKE.F90:789
subroutine, public calltree_waypoint(mesg, n)
Writes a message about reaching a milestone if call tree reporting is active.
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
subroutine, public adjustments_dyn_legacy_split(u, v, h, dt, G, GV, CS)
logical function, public ale_remap_init_conds(CS)
Returns true if initial conditions should be regridded and remapped.
Definition: MOM_ALE.F90:1229
integer id_clock_bbl_visc
Definition: MOM.F90:445
Control structure for mom_continuity.
subroutine, public call_tracer_surface_state(state, h, G, CS)
This subroutine calls all registered tracer packages to enable them to add to the surface state retur...
character(len=20) function, public ale_getcoordinateunits(CS)
Query the target coordinate units.
Definition: MOM_ALE.F90:1218
subroutine, public tracer_advect_init(Time, G, param_file, diag, CS)
Initialize lateral tracer advection module.
subroutine, public register_restarts_dyn_unsplit(HI, GV, param_file, CS, restart_CS)
subroutine, public init_sponge_diags(Time, G, diag, CS)
Definition: MOM_sponge.F90:247
subroutine, public calculate_z_diag_fields(u, v, h, ssh_in, frac_shelf_h, G, GV, CS)
This subroutine maps tracers and velocities into depth space for diagnostics.
Invokes unit tests in all modules that have them.
subroutine, public step_forward_meke(MEKE, h, SN_u, SN_v, visc, dt, G, GV, CS, hu, hv)
Integrates forward-in-time the MEKE eddy energy equation. See MEKE equations.
Definition: MOM_MEKE.F90:88
Type to carry basic OBC information needed for updating values.
subroutine, public calc_resoln_function(h, tv, G, GV, CS)
Calculates and stores the non-dimensional resolution functions.
Type to carry basic tracer information.
subroutine, public update_offline_fields(CS, h, fluxes, do_ale)
Update fields used in this round of offline transport. First fields are updated from files or from ar...
integer id_clock_ml_restrat
Definition: MOM.F90:446
subroutine, public mom_domains_init(MOM_dom, param_file, symmetric, static_memory, NIHALO, NJHALO, NIGLOBAL, NJGLOBAL, NIPROC, NJPROC, min_halo, domain_name, include_name, param_suffix)
Thickness diffusion (or Gent McWilliams)
logical function, public is_root_pe()
subroutine, public complete_group_pass(group, MOM_dom)
The cont_diag_ptrs structure contains pointers to arrays with transports, which can later be used for...
subroutine, public tracer_flow_control_end(CS)
subroutine, public ale_offline_tracer_final(G, GV, h, tv, h_target, Reg, CS)
Remaps all tracers from h onto h_target. This is intended to be called when tracers are done offline...
Definition: MOM_ALE.F90:579
integer id_clock_thermo
Definition: MOM.F90:440
subroutine, public pressureforce(h, tv, PFu, PFv, G, GV, CS, ALE_CSp, p_atm, pbce, eta)
A thin layer between the model and the Boussinesq and non-Boussinesq pressure force routines...
subroutine, public register_z_tracer(tr_ptr, name, long_name, units, Time, G, CS, standard_name, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
This subroutine registers a tracer to be output in depth space.
Control structure for this module.
Definition: MOM.F90:148
subroutine, public diabatic_driver_end(CS)
Routine to close the diabatic driver module.
subroutine, public add_tracer_diagnostics(name, Reg, ad_x, ad_y, df_x, df_y, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine adds diagnostic arrays for a tracer that has previously been registered by a call to ...
subroutine, public mom_set_verbosity(verb)
subroutine, public adiabatic(h, tv, fluxes, dt, G, GV, CS)
Routine called for adiabatic physics.
character(len=48) function, public get_thickness_units(GV)
Returns the model&#39;s thickness units, usually m or kg/m^2.
subroutine, public tracer_advect_end(CS)
Close the tracer advection module.
The ocean_internal_state structure contains pointers to all of the prognostic variables allocated in ...
Implements the Mesoscale Eddy Kinetic Energy framework.
Definition: MOM_MEKE.F90:2
subroutine post_integrated_diagnostics(CS, G, GV, diag, dt_int, tv, fluxes)
This routine posts diagnostics of various integrated quantities.
Definition: MOM.F90:3045
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public vertvisc_init(MIS, Time, G, GV, param_file, diag, ADp, dirs, ntrunc, CS)
Initialise the vertical friction module.
subroutine, public set_viscous_ml(u, v, h, tv, fluxes, visc, dt, G, GV, CS)
The following subroutine calculates the thickness of the surface boundary layer for applying an eleva...
subroutine, public calc_slope_functions(h, tv, dt, G, GV, CS)
Calculates and stores functions of isopycnal slopes, e.g. Sx, Sy, S*N, mostly used in the Visbeck et ...
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
subroutine write_static_fields(G, diag)
Offers the static fields in the ocean grid type for output via the diag_manager.
Definition: MOM.F90:3236
logical function, public calltree_showquery()
Returns True, if the verbosity>=6 indicating to show the call tree.
subroutine register_diags_ts_vardec(Time, HI, GV, param_file, CS)
Initialize diagnostics for the variance decay of temp/salt across regridding/remapping.
Definition: MOM.F90:2725
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:51
subroutine, public tracer_registry_end(Reg)
This routine closes the tracer registry module.
Control structure for this module.
subroutine, public tracer_hordiff(h, dt, MEKE, VarMix, G, GV, CS, Reg, tv, do_online_flag, read_khdt_x, read_khdt_y)
Compute along-coordinate diffusion of all tracers using the diffusivity in CSKhTr, or using space-dependent diffusivity. Multiple iterations are used (if necessary) so that there is no limit on the acceptable time increment.
integer id_clock_diagnostics
Definition: MOM.F90:447
integer function, public continuity_stencil(CS)
continuity_stencil returns the continuity solver stencil size
integer function, public register_static_field(module_name, field_name, axes, long_name, units, missing_value, range, mask_variant, standard_name, do_not_log, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, area)
Registers a static diagnostic, returning an integer handle.
subroutine, public adjustgridforintegrity(CS, G, GV, h)
Crudely adjust (initial) grid for integrity. This routine is typically called (from initialize_MOM in...
Definition: MOM_ALE.F90:347
integer id_clock_continuity
Definition: MOM.F90:443
subroutine, public calculate_z_transport(uh_int, vh_int, h, dt, G, GV, CS)
This subroutine maps horizontal transport into depth space for diagnostic output. ...
subroutine mom_timing_init(CS)
This subroutine sets up clock IDs for timing various subroutines.
Definition: MOM.F90:2763
subroutine, public init_ale_sponge_diags(Time, G, diag, CS)
Initialize diagnostics for the ALE_sponge module.
subroutine, public lock_tracer_registry(Reg)
This subroutine locks the tracer registry to prevent the addition of more tracers. After locked=.true., can then register common diagnostics.
integer id_clock_other
Definition: MOM.F90:454
subroutine, public tidal_forcing_init(Time, G, param_file, CS)
This subroutine allocates space for the static variables used by this module. The metrics may be effe...
subroutine, public calculate_surface_state(state, u, v, h, ssh, G, GV, CS)
This subroutine sets the surface (return) properties of the ocean model by setting the appropriate fi...
Definition: MOM.F90:3441
integer id_clock_pass
Definition: MOM.F90:451
integer id_clock_init
Definition: MOM.F90:449
subroutine, public continuity(u, v, hin, h, uh, vh, dt, G, GV, CS, uhbt, vhbt, OBC, visc_rem_u, visc_rem_v, u_cor, v_cor, uhbt_aux, vhbt_aux, u_cor_aux, v_cor_aux, BT_cont)
Time steps the layer thicknesses, using a monotonically limited, directionally split PPM scheme...
Initialize state variables, u, v, h, T and S.
Initializes fixed aspects of the related to its vertical coordinate.
subroutine, public tracer_hor_diff_init(Time, G, param_file, diag, CS, CSnd)
Initialize lateral tracer diffusion module.
subroutine register_diags_ts_tendency(Time, G, CS)
Initialize diagnostics for temp/heat and saln/salt tendencies.
Definition: MOM.F90:2626
subroutine, public mom_initialize_fixed(G, OBC, PF, write_geom, output_dir)
MOM_initialize_fixed sets up time-invariant quantities related to MOM6&#39;s horizontal grid...
subroutine, public step_offline(fluxes, state, Time_start, time_interval, CS)
step_offline is the main driver for running tracers offline in MOM6. This has been primarily develope...
Definition: MOM.F90:1294
subroutine, public save_restart(directory, time, G, CS, time_stamped, filename, GV)
subroutine, public vertvisc_limit_vel(u, v, h, ADp, CDp, fluxes, visc, dt, G, GV, CS)
Velocity components which exceed a threshold for physically reasonable values are truncated...
subroutine, public insert_offline_main(CS, ALE_CSp, diabatic_CSp, diag, OBC, tracer_adv_CSp, tracer_flow_CSp, tracer_Reg, tv, G, GV, x_before_y, debug)
Inserts (assigns values to) members of the offline main control structure. All arguments are optional...
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine, public copy_mom_grid_to_dyngrid(oG, dG)
Copies information from an ocean_grid_type into a dynamic (shared) horizontal grid type...
subroutine, public offline_advection_layer(fluxes, Time_start, time_interval, CS, h_pre, eatr, ebtr, uhtr, vhtr)
When in layer mode, 3D horizontal advection using stored mass fluxes must be used. Horizontal advection is done via tracer_advect, whereas the vertical component is actually handled by vertdiff in tracer_column_fns.
This program contains the subroutines that advect tracers along coordinate surfaces.
subroutine, public meke_alloc_register_restart(HI, param_file, MEKE, restart_CS)
Allocates memory and register restart fields for the MOM_MEKE module.
Definition: MOM_MEKE.F90:1043
subroutine, public step_mom(fluxes, state, Time_start, time_interval, CS)
This subroutine orchestrates the time stepping of MOM. The adiabatic dynamics are stepped by calls to...
Definition: MOM.F90:466
A column-wise toolbox for implementing neutral diffusion.
Control structure for thickness diffusion.
subroutine, public disable_averaging(diag_cs)
subroutine, public mom_debugging_init(param_file)
MOM_debugging_init initializes the MOM_debugging module, and sets the parameterts that control which ...
integer id_clock_z_diag
Definition: MOM.F90:448
subroutine, public thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, MEKE, VarMix, CDp, CS)
Calculates thickness diffusion coefficients and applies thickness diffusion to layer thicknesses...
subroutine, public diag_set_state_ptrs(h, T, S, eqn_of_state, diag_cs)
subroutine, public ale_main_offline(G, GV, h, tv, Reg, CS, dt)
Takes care of (1) building a new grid and (2) remapping all variables between the old grid and the ne...
Definition: MOM_ALE.F90:446
subroutine, public obc_register_end(CS)
Clean up the OBC registry.
subroutine, public ale_init(param_file, GV, max_depth, CS)
This routine is typically called (from initialize_MOM in file MOM.F90) before the main time integrati...
Definition: MOM_ALE.F90:138
subroutine, public thickness_diffuse_init(Time, G, GV, param_file, diag, CDp, CS)
Initialize the thickness diffusion module/structure.
subroutine, public mom_diag_to_z_init(Time, G, GV, param_file, diag, CS)
Controls where open boundary conditions are applied.
subroutine, public register_obsolete_diagnostics(param_file, diag)
Scan through the diag_table searching for obsolete parameters and issue informational messages and op...
subroutine, public create_dyn_horgrid(G, HI, bathymetry_at_vel)
Allocate memory used by the dyn_horgrid_type and related structures.
subroutine, public step_mom_dyn_unsplit(u, v, h, tv, visc, Time_local, dt, fluxes, p_surf_begin, p_surf_end, uh, vh, uhtr, vhtr, eta_av, G, GV, CS, VarMix, MEKE)
ALE control structure.
Definition: MOM_ALE.F90:61
subroutine, public mom_end(CS)
End of model.
Definition: MOM.F90:3746
subroutine, public mixedlayer_restrat_register_restarts(HI, param_file, CS, restart_CS)
Allocate and register fields in the mixed layer restratification structure for restarts.
subroutine, public ale_main(G, GV, h, u, v, tv, Reg, CS, dt, frac_shelf_h)
Takes care of (1) building a new grid and (2) remapping all variables between the old grid and the ne...
Definition: MOM_ALE.F90:376
subroutine, public restart_init(param_file, CS, restart_root)
subroutine, public vertvisc(u, v, h, fluxes, visc, dt, OBC, ADp, CDp, G, GV, CS, taux_bot, tauy_bot)
Perform a fully implicit vertical diffusion of momentum. Stress top and bottom boundary conditions ar...
real function, public global_area_mean(var, G)
subroutine, public call_obc_register(param_file, CS, OBC)
The following subroutines and associated definitions provide the machinery to register and call the s...
subroutine, public initialize_dyn_legacy_split(u, v, h, uh, vh, eta, Time, G, GV, param_file, diag, CS, restart_CS, dt, Accel_diag, Cont_diag, MIS, VarMix, MEKE, OBC, update_OBC_CSp, ALE_CSp, setVisc_CSp, visc, dirs, ntrunc)
integer function, public register_diag_field(module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived fr...
subroutine, public mom_error(level, message, all_print)
subroutine, public offline_transport_init(param_file, CS, diabatic_CSp, G, GV)
Initializes the control structure for offline transport and reads in some of the. ...
subroutine, public finish_mom_initialization(Time, dirs, CS, fluxes)
This subroutine finishes initializing MOM and writes out the initial conditions.
Definition: MOM.F90:2345
subroutine, public diag_update_remap_grids(diag_cs, alt_h)
Build/update vertical grids for diagnostic remapping.
Time step the adiabatic dynamic core of MOM using RK2 method.
subroutine, public neutral_diffusion_diag_init(Time, G, diag, C_p, Reg, CS)
Diagnostic handles for neutral diffusion tendencies.
integer id_clock_ale
Definition: MOM.F90:453
subroutine, public diabatic_driver_init(Time, G, GV, param_file, useALEalgorithm, diag, ADp, CDp, CS, tracer_flow_CSp, sponge_CSp, ALE_sponge_CSp, diag_to_Z_CSp)
This routine initializes the diabatic driver module.
Parameterization of mixed layer restratification by unresolved mixed-layer eddies.
subroutine, public offline_fw_fluxes_out_ocean(G, GV, CS, fluxes, h, out_flux_optional)
Apply negative freshwater fluxes (out of the ocean)
subroutine, public calltree_enter(mesg, n)
Writes a message about entering a subroutine if call tree reporting is active.