MOM6
MOM_mixed_layer_restrat.F90
1 !> \brief Parameterization of mixed layer restratification by unresolved mixed-layer eddies.
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_debugging, only : hchksum
7 use mom_diag_mediator, only : post_data, query_averaging_enabled, diag_ctrl
8 use mom_diag_mediator, only : register_diag_field, safe_alloc_ptr, time_type
9 use mom_diag_mediator, only : diag_update_remap_grids
10 use mom_domains, only : pass_var, to_west, to_south, omit_corners
11 use mom_error_handler, only : mom_error, fatal, warning
14 use mom_grid, only : ocean_grid_type
15 use mom_hor_index, only : hor_index_type
16 use mom_io, only : vardesc, var_desc
22 use mom_eos, only : calculate_density
23 
24 implicit none ; private
25 
26 #include <MOM_memory.h>
27 
28 public mixedlayer_restrat
29 public mixedlayer_restrat_init
30 public mixedlayer_restrat_register_restarts
31 
32 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
33 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
34 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
35 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
36 
37 !> Control structure for mom_mixed_layer_restrat
38 type, public :: mixedlayer_restrat_cs ; private
39  real :: ml_restrat_coef !< A non-dimensional factor by which the instability is enhanced
40  !! over what would be predicted based on the resolved gradients
41  !! [nondim]. This increases with grid spacing^2, up to something
42  !! of order 500.
43  real :: ml_restrat_coef2 !< As for ml_restrat_coef but using the slow filtered MLD [nondim].
44  real :: front_length !< If non-zero, is the frontal-length scale [m] used to calculate the
45  !! upscaling of buoyancy gradients that is otherwise represented
46  !! by the parameter FOX_KEMPER_ML_RESTRAT_COEF. If MLE_FRONT_LENGTH is
47  !! non-zero, it is recommended to set FOX_KEMPER_ML_RESTRAT_COEF=1.0.
48  logical :: mle_use_pbl_mld !< If true, use the MLD provided by the PBL parameterization.
49  !! if false, MLE will calculate a MLD based on a density difference
50  !! based on the parameter MLE_DENSITY_DIFF.
51  real :: mle_mld_decay_time !< Time-scale to use in a running-mean when MLD is retreating [s].
52  real :: mle_mld_decay_time2 !< Time-scale to use in a running-mean when filtered MLD is retreating [s].
53  real :: mle_density_diff !< Density difference used in detecting mixed-layer depth [kgm-3].
54  real :: mle_tail_dh !< Fraction by which to extend the mixed-layer restratification
55  !! depth used for a smoother stream function at the base of
56  !! the mixed-layer [nondim].
57  real :: mle_mld_stretch !< A scaling coefficient for stretching/shrinking the MLD used in
58  !! the MLE scheme [nondim]. This simply multiplies MLD wherever used.
59  logical :: mle_use_mld_ave_bug !< If true, do not account for MLD mismatch to interface positions.
60  logical :: debug = .false. !< If true, calculate checksums of fields for debugging.
61  type(diag_ctrl), pointer :: diag !< A structure that is used to regulate the
62  !! timing of diagnostic output.
63 
64  real, dimension(:,:), pointer :: &
65  mld_filtered => null(), & !< Time-filtered MLD [H ~> m or kg m-2]
66  mld_filtered_slow => null() !< Slower time-filtered MLD [H ~> m or kg m-2]
67 
68  !>@{
69  !! Diagnostic identifier
70  integer :: id_urestrat_time = -1
71  integer :: id_vrestrat_time = -1
72  integer :: id_uhml = -1
73  integer :: id_vhml = -1
74  integer :: id_mld = -1
75  integer :: id_rml = -1
76  integer :: id_udml = -1
77  integer :: id_vdml = -1
78  integer :: id_uml = -1
79  integer :: id_vml = -1
80  !>@}
81 
82 end type mixedlayer_restrat_cs
83 
84 character(len=40) :: mdl = "MOM_mixed_layer_restrat" !< This module's name.
85 
86 contains
87 
88 !> Driver for the mixed-layer restratification parameterization.
89 !! The code branches between two different implementations depending
90 !! on whether the bulk-mixed layer or a general coordinate are in use.
91 subroutine mixedlayer_restrat(h, uhtr, vhtr, tv, forces, dt, MLD, VarMix, G, GV, US, CS)
92  type(ocean_grid_type), intent(inout) :: g !< Ocean grid structure
93  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
94  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
95  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]
96  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uhtr !< Accumulated zonal mass flux
97  !! [H m2 ~> m3 or kg]
98  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vhtr !< Accumulated meridional mass flux
99  !! [H m2 ~> m3 or kg]
100  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables structure
101  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
102  real, intent(in) :: dt !< Time increment [s]
103  real, dimension(:,:), pointer :: mld !< Mixed layer depth provided by the
104  !! PBL scheme [H ~> m or kg m-2]
105  type(varmix_cs), pointer :: varmix !< Container for derived fields
106  type(mixedlayer_restrat_cs), pointer :: cs !< Module control structure
107 
108  if (.not. associated(cs)) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
109  "Module must be initialized before it is used.")
110 
111  if (gv%nkml>0) then
112  call mixedlayer_restrat_bml(h, uhtr, vhtr, tv, forces, dt, g, gv, us, cs)
113  else
114  call mixedlayer_restrat_general(h, uhtr, vhtr, tv, forces, dt, mld, varmix, g, gv, us, cs)
115  endif
116 
117 end subroutine mixedlayer_restrat
118 
119 !> Calculates a restratifying flow in the mixed layer.
120 subroutine mixedlayer_restrat_general(h, uhtr, vhtr, tv, forces, dt, MLD_in, VarMix, G, GV, US, CS)
121  ! Arguments
122  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
123  type(verticalgrid_type), intent(in) :: GV !< Ocean vertical grid structure
124  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
125  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]
126  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uhtr !< Accumulated zonal mass flux
127  !! [H m2 ~> m3 or kg]
128  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vhtr !< Accumulated meridional mass flux
129  !! [H m2 ~> m3 or kg]
130  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables structure
131  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
132  real, intent(in) :: dt !< Time increment [s]
133  real, dimension(:,:), pointer :: MLD_in !< Mixed layer depth provided by the
134  !! PBL scheme [m] (not H)
135  type(varmix_cs), pointer :: VarMix !< Container for derived fields
136  type(mixedlayer_restrat_cs), pointer :: CS !< Module control structure
137  ! Local variables
138  real :: uhml(SZIB_(G),SZJ_(G),SZK_(G)) ! zonal mixed layer transport [H m2 s-1 ~> m3 s-1 or kg s-1]
139  real :: vhml(SZI_(G),SZJB_(G),SZK_(G)) ! merid mixed layer transport [H m2 s-1 ~> m3 s-1 or kg s-1]
140  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
141  h_avail ! The volume available for diffusion out of each face of each
142  ! sublayer of the mixed layer, divided by dt [H m2 s-1 ~> m3 s-1 or kg s-1].
143  real, dimension(SZI_(G),SZJ_(G)) :: &
144  MLD_fast, & ! Mixed layer depth actually used in MLE restratification parameterization [H ~> m or kg m-2]
145  htot_fast, & ! The sum of the thicknesses of layers in the mixed layer [H ~> m or kg m-2]
146  Rml_av_fast, & ! g_Rho0 times the average mixed layer density [m s-2]
147  MLD_slow, & ! Mixed layer depth actually used in MLE restratification parameterization [H ~> m or kg m-2]
148  htot_slow, & ! The sum of the thicknesses of layers in the mixed layer [H ~> m or kg m-2]
149  Rml_av_slow ! g_Rho0 times the average mixed layer density [m s-2]
150  real :: g_Rho0 ! G_Earth/Rho0 [m5 Z-1 s-2 kg-1 ~> m4 s-2 kg-1]
151  real :: rho_ml(SZI_(G)) ! Potential density relative to the surface [kg m-3]
152  real :: p0(SZI_(G)) ! A pressure of 0 [Pa]
153 
154  real :: h_vel ! htot interpolated onto velocity points [Z ~> m] (not H).
155  real :: absf ! absolute value of f, interpolated to velocity points [s-1]
156  real :: u_star ! surface friction velocity, interpolated to velocity points [Z s-1 ~> m s-1].
157  real :: mom_mixrate ! rate at which momentum is homogenized within mixed layer [s-1]
158  real :: timescale ! mixing growth timescale [s]
159  real :: h_neglect ! tiny thickness usually lost in roundoff so can be neglected [H ~> m or kg m-2]
160  real :: dz_neglect ! A tiny thickness that is usually lost in roundoff so can be neglected [Z ~> m]
161  real :: I4dt ! 1/(4 dt) [s-1]
162  real :: Ihtot,Ihtot_slow! Inverses of the total mixed layer thickness [H-1 ~> m-1 or m2 kg-1]
163  real :: a(SZK_(G)) ! A non-dimensional value relating the overall flux
164  ! magnitudes (uDml & vDml) to the realized flux in a
165  ! layer. The vertical sum of a() through the pieces of
166  ! the mixed layer must be 0.
167  real :: b(SZK_(G)) ! As for a(k) but for the slow-filtered MLD
168  real :: uDml(SZIB_(G)) ! The zonal and meridional volume fluxes in the upper
169  real :: vDml(SZI_(G)) ! half of the mixed layer [H m2 s-1 ~> m3 s-1 or kg s-1].
170  real :: uDml_slow(SZIB_(G)) ! The zonal and meridional volume fluxes in the upper
171  real :: vDml_slow(SZI_(G)) ! half of the mixed layer [H m2 s-1 ~> m3 s-1 or kg s-1].
172  real :: utimescale_diag(SZIB_(G),SZJ_(G)) ! restratification timescales in the zonal and
173  real :: vtimescale_diag(SZI_(G),SZJB_(G)) ! meridional directions [s], stored in 2-D arrays
174  ! for diagnostic purposes.
175  real :: uDml_diag(SZIB_(G),SZJ_(G)), vDml_diag(SZI_(G),SZJB_(G))
176  integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
177  real, dimension(SZI_(G)) :: rhoSurf, deltaRhoAtKm1, deltaRhoAtK
178  real, dimension(SZI_(G)) :: dK, dKm1 ! Depths of layer centers [H ~> m or kg m-2].
179  real, dimension(SZI_(G)) :: pRef_MLD ! A reference pressure for calculating the mixed layer densities [Pa].
180  real, dimension(SZI_(G)) :: rhoAtK, rho1, d1, pRef_N2 ! Used for N2
181  real :: aFac, bFac, ddRho
182  real :: hAtVel, zpa, zpb, dh, res_scaling_fac, I_l_f
183  logical :: proper_averaging, line_is_empty, keep_going, res_upscale
184 
185  real :: PSI, PSI1, z, BOTTOP, XP, DD ! For the following statement functions
186  ! Stream function as a function of non-dimensional position within mixed-layer (F77 statement function)
187  !PSI1(z) = max(0., (1. - (2.*z+1.)**2 ) )
188  psi1(z) = max(0., (1. - (2.*z+1.)**2 ) * (1. + (5./21.)*(2.*z+1.)**2) )
189  bottop(z) = 0.5*(1.-sign(1.,z+0.5)) ! =0 for z>-0.5, =1 for z<-0.5
190  xp(z) = max(0., min(1., (-z-0.5)*2./(1.+2.*cs%MLE_tail_dh) ) )
191  dd(z) = (1.-3.*(xp(z)**2)+2.*(xp(z)**3))**(1.+2.*cs%MLE_tail_dh)
192  psi(z) = max( psi1(z), dd(z)*bottop(z) ) ! Combines original PSI1 with tail
193 
194  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
195  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
196 
197  if (.not.associated(tv%eqn_of_state)) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
198  "An equation of state must be used with this module.")
199  if (.not.associated(varmix) .and. cs%front_length>0.) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
200  "The resolution argument, Rd/dx, was not associated.")
201 
202  if (cs%MLE_density_diff > 0.) then ! We need to calculate a mixed layer depth, MLD.
203  !! TODO: use derivatives and mid-MLD pressure. Currently this is sigma-0. -AJA
204  pref_mld(:) = 0.
205  do j = js-1, je+1
206  dk(:) = 0.5 * h(:,j,1) ! Depth of center of surface layer
207  call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pref_mld, rhosurf, is-1, ie-is+3, tv%eqn_of_state)
208  deltarhoatk(:) = 0.
209  mld_fast(:,j) = 0.
210  do k = 2, nz
211  dkm1(:) = dk(:) ! Depth of center of layer K-1
212  dk(:) = dk(:) + 0.5 * ( h(:,j,k) + h(:,j,k-1) ) ! Depth of center of layer K
213  ! Mixed-layer depth, using sigma-0 (surface reference pressure)
214  deltarhoatkm1(:) = deltarhoatk(:) ! Store value from previous iteration of K
215  call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pref_mld, deltarhoatk, is-1, ie-is+3, tv%eqn_of_state)
216  deltarhoatk(:) = deltarhoatk(:) - rhosurf(:) ! Density difference between layer K and surface
217  do i = is-1, ie+1
218  ddrho = deltarhoatk(i) - deltarhoatkm1(i)
219  if ((mld_fast(i,j)==0.) .and. (ddrho>0.) .and. &
220  (deltarhoatkm1(i)<cs%MLE_density_diff) .and. (deltarhoatk(i)>=cs%MLE_density_diff)) then
221  afac = ( cs%MLE_density_diff - deltarhoatkm1(i) ) / ddrho
222  mld_fast(i,j) = dk(i) * afac + dkm1(i) * (1. - afac)
223  endif
224  enddo ! i-loop
225  enddo ! k-loop
226  do i = is-1, ie+1
227  mld_fast(i,j) = cs%MLE_MLD_stretch * mld_fast(i,j)
228  if ((mld_fast(i,j)==0.) .and. (deltarhoatk(i)<cs%MLE_density_diff)) &
229  mld_fast(i,j) = dk(i) ! Assume mixing to the bottom
230  enddo
231  enddo ! j-loop
232  elseif (cs%MLE_use_PBL_MLD) then
233  if (.not. associated(mld_in)) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
234  "Argument MLD_in was not associated!")
235  do j = js-1, je+1 ; do i = is-1, ie+1
236  mld_fast(i,j) = (cs%MLE_MLD_stretch * gv%m_to_H) * mld_in(i,j)
237  enddo ; enddo
238  else
239  call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
240  "No MLD to use for MLE parameterization.")
241  endif
242 
243  ! Apply time filter (to remove diurnal cycle)
244  if (cs%MLE_MLD_decay_time>0.) then
245  if (cs%debug) then
246  call hchksum(cs%MLD_filtered,'mixed_layer_restrat: MLD_filtered',g%HI,haloshift=1,scale=gv%H_to_m)
247  call hchksum(mld_in,'mixed_layer_restrat: MLD in',g%HI,haloshift=1)
248  endif
249  afac = cs%MLE_MLD_decay_time / ( dt + cs%MLE_MLD_decay_time )
250  bfac = dt / ( dt + cs%MLE_MLD_decay_time )
251  do j = js-1, je+1 ; do i = is-1, ie+1
252  ! Expression bFac*MLD_fast(i,j) + aFac*CS%MLD_filtered(i,j) is the time-filtered
253  ! (running mean) of MLD. The max() allows the "running mean" to be reset
254  ! instantly to a deeper MLD.
255  cs%MLD_filtered(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered(i,j) )
256  mld_fast(i,j) = cs%MLD_filtered(i,j)
257  enddo ; enddo
258  endif
259 
260  ! Apply slower time filter (to remove seasonal cycle) on already filtered MLD_fast
261  if (cs%MLE_MLD_decay_time2>0.) then
262  if (cs%debug) then
263  call hchksum(cs%MLD_filtered_slow,'mixed_layer_restrat: MLD_filtered_slow',g%HI,haloshift=1,scale=gv%H_to_m)
264  call hchksum(mld_fast,'mixed_layer_restrat: MLD fast',g%HI,haloshift=1,scale=gv%H_to_m)
265  endif
266  afac = cs%MLE_MLD_decay_time2 / ( dt + cs%MLE_MLD_decay_time2 )
267  bfac = dt / ( dt + cs%MLE_MLD_decay_time2 )
268  do j = js-1, je+1 ; do i = is-1, ie+1
269  ! Expression bFac*MLD_fast(i,j) + aFac*CS%MLD_filtered(i,j) is the time-filtered
270  ! (running mean) of MLD. The max() allows the "running mean" to be reset
271  ! instantly to a deeper MLD.
272  cs%MLD_filtered_slow(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered_slow(i,j) )
273  mld_slow(i,j) = cs%MLD_filtered_slow(i,j)
274  enddo ; enddo
275  else
276  do j = js-1, je+1 ; do i = is-1, ie+1
277  mld_slow(i,j) = mld_fast(i,j)
278  enddo ; enddo
279  endif
280 
281  udml(:) = 0.0 ; vdml(:) = 0.0
282  udml_slow(:) = 0.0 ; vdml_slow(:) = 0.0
283  i4dt = 0.25 / dt
284  g_rho0 = gv%g_Earth*us%L_to_m**2*us%s_to_T**2 / gv%Rho0
285  h_neglect = gv%H_subroundoff
286  dz_neglect = gv%H_subroundoff*gv%H_to_Z
287  proper_averaging = .not. cs%MLE_use_MLD_ave_bug
288  if (cs%front_length>0.) then
289  res_upscale = .true.
290  i_l_f = 1./cs%front_length
291  else
292  res_upscale = .false.
293  endif
294 
295  p0(:) = 0.0
296 !$OMP parallel default(none) shared(is,ie,js,je,G,GV,US,htot_fast,Rml_av_fast,tv,p0,h,h_avail,&
297 !$OMP h_neglect,g_Rho0,I4dt,CS,uhml,uhtr,dt,vhml,vhtr, &
298 !$OMP utimescale_diag,vtimescale_diag,forces,dz_neglect, &
299 !$OMP htot_slow,MLD_slow,Rml_av_slow,VarMix,I_l_f, &
300 !$OMP res_upscale, &
301 !$OMP nz,MLD_fast,uDml_diag,vDml_diag,proper_averaging) &
302 !$OMP private(rho_ml,h_vel,u_star,absf,mom_mixrate,timescale, &
303 !$OMP line_is_empty, keep_going,res_scaling_fac, &
304 !$OMP a,IhTot,b,Ihtot_slow,zpb,hAtVel,zpa,dh) &
305 !$OMP firstprivate(uDml,vDml,uDml_slow,vDml_slow)
306 !$OMP do
307  do j=js-1,je+1
308  do i=is-1,ie+1
309  htot_fast(i,j) = 0.0 ; rml_av_fast(i,j) = 0.0
310  htot_slow(i,j) = 0.0 ; rml_av_slow(i,j) = 0.0
311  enddo
312  keep_going = .true.
313  do k=1,nz
314  do i=is-1,ie+1
315  h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom_H),0.0)
316  enddo
317  if (keep_going) then
318  call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho_ml(:),is-1,ie-is+3,tv%eqn_of_state)
319  line_is_empty = .true.
320  do i=is-1,ie+1
321  if (htot_fast(i,j) < mld_fast(i,j)) then
322  dh = h(i,j,k)
323  if (proper_averaging) dh = min( h(i,j,k), mld_fast(i,j)-htot_fast(i,j) )
324  rml_av_fast(i,j) = rml_av_fast(i,j) + dh*rho_ml(i)
325  htot_fast(i,j) = htot_fast(i,j) + dh
326  line_is_empty = .false.
327  endif
328  if (htot_slow(i,j) < mld_slow(i,j)) then
329  dh = min( h(i,j,k), mld_slow(i,j)-htot_slow(i,j) )
330  rml_av_slow(i,j) = rml_av_slow(i,j) + dh*rho_ml(i)
331  htot_slow(i,j) = htot_slow(i,j) + dh
332  line_is_empty = .false.
333  endif
334  enddo
335  if (line_is_empty) keep_going=.false.
336  endif
337  enddo
338 
339  do i=is-1,ie+1
340  rml_av_fast(i,j) = -(g_rho0*rml_av_fast(i,j)) / (htot_fast(i,j) + h_neglect)
341  rml_av_slow(i,j) = -(g_rho0*rml_av_slow(i,j)) / (htot_slow(i,j) + h_neglect)
342  enddo
343  enddo
344 
345  if (cs%debug) then
346  call hchksum(h,'mixed_layer_restrat: h',g%HI,haloshift=1,scale=gv%H_to_m)
347  call hchksum(forces%ustar,'mixed_layer_restrat: u*',g%HI,haloshift=1,scale=us%Z_to_m*us%s_to_T)
348  call hchksum(mld_fast,'mixed_layer_restrat: MLD',g%HI,haloshift=1,scale=gv%H_to_m)
349  call hchksum(rml_av_fast,'mixed_layer_restrat: rml',g%HI,haloshift=1, scale=us%m_to_Z)
350  endif
351 
352 ! TO DO:
353 ! 1. Mixing extends below the mixing layer to the mixed layer. Find it!
354 ! 2. Add exponential tail to stream-function?
355 
356 ! U - Component
357 !$OMP do
358  do j=js,je ; do i=is-1,ie
359  u_star = us%s_to_T*0.5*(forces%ustar(i,j) + forces%ustar(i+1,j))
360  absf = 0.5*us%s_to_T*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
361  ! If needed, res_scaling_fac = min( ds, L_d ) / l_f
362  if (res_upscale) res_scaling_fac = &
363  ( sqrt( 0.5 * ( g%dxCu(i,j)**2 + g%dyCu(i,j)**2 ) ) * i_l_f ) &
364  * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i+1,j) ) )
365 
366  ! peak ML visc: u_star * 0.41 * (h_ml*u_star)/(absf*h_ml + 4.0*u_star)
367  ! momentum mixing rate: pi^2*visc/h_ml^2
368  ! 0.41 is the von Karmen constant, 9.8696 = pi^2.
369  h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect) * gv%H_to_Z
370  mom_mixrate = (0.41*9.8696)*u_star**2 / &
371  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
372  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
373  timescale = timescale * cs%ml_restrat_coef
374  if (res_upscale) timescale = timescale * res_scaling_fac
375  udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
376  g%IdxCu(i,j)*(rml_av_fast(i+1,j)-rml_av_fast(i,j)) * (h_vel**2 * gv%Z_to_H)
377  ! As above but using the slow filtered MLD
378  h_vel = 0.5*((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect) * gv%H_to_Z
379  mom_mixrate = (0.41*9.8696)*u_star**2 / &
380  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
381  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
382  timescale = timescale * cs%ml_restrat_coef2
383  if (res_upscale) timescale = timescale * res_scaling_fac
384  udml_slow(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
385  g%IdxCu(i,j)*(rml_av_slow(i+1,j)-rml_av_slow(i,j)) * (h_vel**2 * gv%Z_to_H)
386 
387  if (udml(i) + udml_slow(i) == 0.) then
388  do k=1,nz ; uhml(i,j,k) = 0.0 ; enddo
389  else
390  ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
391  ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect)
392  zpa = 0.0 ; zpb = 0.0
393  ! a(k) relates the sublayer transport to uDml with a linear profile.
394  ! The sum of a(k) through the mixed layers must be 0.
395  do k=1,nz
396  hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
397  a(k) = psi(zpa) ! Psi(z/MLD) for upper interface
398  zpa = zpa - (hatvel * ihtot) ! z/H for lower interface
399  a(k) = a(k) - psi(zpa) ! Transport profile
400  ! Limit magnitude (uDml) if it would violate CFL
401  if (a(k)*udml(i) > 0.0) then
402  if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
403  elseif (a(k)*udml(i) < 0.0) then
404  if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k) / a(k)
405  endif
406  enddo
407  do k=1,nz
408  ! Transport for slow-filtered MLD
409  hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
410  b(k) = psi(zpb) ! Psi(z/MLD) for upper interface
411  zpb = zpb - (hatvel * ihtot_slow) ! z/H for lower interface
412  b(k) = b(k) - psi(zpb) ! Transport profile
413  ! Limit magnitude (uDml_slow) if it would violate CFL when added to uDml
414  if (b(k)*udml_slow(i) > 0.0) then
415  if (b(k)*udml_slow(i) > h_avail(i,j,k) - a(k)*udml(i)) &
416  udml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*udml(i) ) / b(k)
417  elseif (b(k)*udml_slow(i) < 0.0) then
418  if (-b(k)*udml_slow(i) > h_avail(i+1,j,k) + a(k)*udml(i)) &
419  udml_slow(i) = -max( 0., h_avail(i+1,j,k) + a(k)*udml(i) ) / b(k)
420  endif
421  enddo
422  do k=1,nz
423  uhml(i,j,k) = a(k)*udml(i) + b(k)*udml_slow(i)
424  uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
425  enddo
426  endif
427 
428  utimescale_diag(i,j) = timescale
429  udml_diag(i,j) = udml(i)
430  enddo ; enddo
431 
432 ! V- component
433 !$OMP do
434  do j=js-1,je ; do i=is,ie
435  u_star = us%s_to_T*0.5*(forces%ustar(i,j) + forces%ustar(i,j+1))
436  absf = 0.5*us%s_to_T*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
437  ! If needed, res_scaling_fac = min( ds, L_d ) / l_f
438  if (res_upscale) res_scaling_fac = &
439  ( sqrt( 0.5 * ( g%dxCv(i,j)**2 + g%dyCv(i,j)**2 ) ) * i_l_f ) &
440  * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i,j+1) ) )
441 
442  ! peak ML visc: u_star * 0.41 * (h_ml*u_star)/(absf*h_ml + 4.0*u_star)
443  ! momentum mixing rate: pi^2*visc/h_ml^2
444  ! 0.41 is the von Karmen constant, 9.8696 = pi^2.
445  h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect) * gv%H_to_Z
446  mom_mixrate = (0.41*9.8696)*u_star**2 / &
447  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
448  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
449  timescale = timescale * cs%ml_restrat_coef
450  if (res_upscale) timescale = timescale * res_scaling_fac
451  vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
452  g%IdyCv(i,j)*(rml_av_fast(i,j+1)-rml_av_fast(i,j)) * (h_vel**2 * gv%Z_to_H)
453  ! As above but using the slow filtered MLD
454  h_vel = 0.5*((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect) * gv%H_to_Z
455  mom_mixrate = (0.41*9.8696)*u_star**2 / &
456  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
457  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
458  timescale = timescale * cs%ml_restrat_coef2
459  if (res_upscale) timescale = timescale * res_scaling_fac
460  vdml_slow(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
461  g%IdyCv(i,j)*(rml_av_slow(i,j+1)-rml_av_slow(i,j)) * (h_vel**2 * gv%Z_to_H)
462 
463  if (vdml(i) + vdml_slow(i) == 0.) then
464  do k=1,nz ; vhml(i,j,k) = 0.0 ; enddo
465  else
466  ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
467  ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect)
468  zpa = 0.0 ; zpb = 0.0
469  ! a(k) relates the sublayer transport to vDml with a linear profile.
470  ! The sum of a(k) through the mixed layers must be 0.
471  do k=1,nz
472  hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
473  a(k) = psi( zpa ) ! Psi(z/MLD) for upper interface
474  zpa = zpa - (hatvel * ihtot) ! z/H for lower interface
475  a(k) = a(k) - psi( zpa ) ! Transport profile
476  ! Limit magnitude (vDml) if it would violate CFL
477  if (a(k)*vdml(i) > 0.0) then
478  if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
479  elseif (a(k)*vdml(i) < 0.0) then
480  if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k) / a(k)
481  endif
482  enddo
483  do k=1,nz
484  ! Transport for slow-filtered MLD
485  hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
486  b(k) = psi(zpb) ! Psi(z/MLD) for upper interface
487  zpb = zpb - (hatvel * ihtot_slow) ! z/H for lower interface
488  b(k) = b(k) - psi(zpb) ! Transport profile
489  ! Limit magnitude (vDml_slow) if it would violate CFL when added to vDml
490  if (b(k)*vdml_slow(i) > 0.0) then
491  if (b(k)*vdml_slow(i) > h_avail(i,j,k) - a(k)*vdml(i)) &
492  vdml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*vdml(i) ) / b(k)
493  elseif (b(k)*vdml_slow(i) < 0.0) then
494  if (-b(k)*vdml_slow(i) > h_avail(i,j+1,k) + a(k)*vdml(i)) &
495  vdml_slow(i) = -max( 0., h_avail(i,j+1,k) + a(k)*vdml(i) ) / b(k)
496  endif
497  enddo
498  do k=1,nz
499  vhml(i,j,k) = a(k)*vdml(i) + b(k)*vdml_slow(i)
500  vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
501  enddo
502  endif
503 
504  vtimescale_diag(i,j) = timescale
505  vdml_diag(i,j) = vdml(i)
506  enddo ; enddo
507 
508 !$OMP do
509  do j=js,je ; do k=1,nz ; do i=is,ie
510  h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
511  ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
512  enddo ; enddo ; enddo
513 !$OMP end parallel
514 
515  ! Offer diagnostic fields for averaging.
516  if (query_averaging_enabled(cs%diag)) then
517  if (cs%id_urestrat_time > 0) call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
518  if (cs%id_vrestrat_time > 0) call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
519  if (cs%id_uhml > 0) call post_data(cs%id_uhml, uhml, cs%diag)
520  if (cs%id_vhml > 0) call post_data(cs%id_vhml, vhml, cs%diag)
521  if (cs%id_MLD > 0) call post_data(cs%id_MLD, mld_fast, cs%diag)
522  if (cs%id_Rml > 0) call post_data(cs%id_Rml, rml_av_fast, cs%diag)
523  if (cs%id_uDml > 0) call post_data(cs%id_uDml, udml_diag, cs%diag)
524  if (cs%id_vDml > 0) call post_data(cs%id_vDml, vdml_diag, cs%diag)
525 
526  if (cs%id_uml > 0) then
527  do j=js,je ; do i=is-1,ie
528  h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
529  udml_diag(i,j) = udml_diag(i,j) / (0.01*h_vel) * g%IdyCu(i,j) * (psi(0.)-psi(-.01))
530  enddo ; enddo
531  call post_data(cs%id_uml, udml_diag, cs%diag)
532  endif
533  if (cs%id_vml > 0) then
534  do j=js-1,je ; do i=is,ie
535  h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
536  vdml_diag(i,j) = vdml_diag(i,j) / (0.01*h_vel) * g%IdxCv(i,j) * (psi(0.)-psi(-.01))
537  enddo ; enddo
538  call post_data(cs%id_vml, vdml_diag, cs%diag)
539  endif
540  endif
541  ! Whenever thickness changes let the diag manager know, target grids
542  ! for vertical remapping may need to be regenerated.
543  ! This needs to happen after the H update and before the next post_data.
544  call diag_update_remap_grids(cs%diag)
545 
546 end subroutine mixedlayer_restrat_general
547 
548 
549 !> Calculates a restratifying flow assuming a 2-layer bulk mixed layer.
550 subroutine mixedlayer_restrat_bml(h, uhtr, vhtr, tv, forces, dt, G, GV, US, CS)
551  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
552  type(verticalgrid_type), intent(in) :: GV !< Ocean vertical grid structure
553  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
554  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]
555  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(inout) :: uhtr !< Accumulated zonal mass flux
556  !! [H m2 ~> m3 or kg]
557  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(inout) :: vhtr !< Accumulated meridional mass flux
558  !! [H m2 ~> m3 or kg]
559  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables structure
560  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
561  real, intent(in) :: dt !< Time increment [s]
562  type(mixedlayer_restrat_cs), pointer :: CS !< Module control structure
563  ! Local variables
564  real :: uhml(SZIB_(G),SZJ_(G),SZK_(G)) ! zonal mixed layer transport [H m2 s-1 ~> m3 s-1 or kg s-1]
565  real :: vhml(SZI_(G),SZJB_(G),SZK_(G)) ! merid mixed layer transport [H m2 s-1 ~> m3 s-1 or kg s-1]
566  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
567  h_avail ! The volume available for diffusion out of each face of each
568  ! sublayer of the mixed layer, divided by dt [H m2 s-1 ~> m3 s-1 or kg s-1].
569  real, dimension(SZI_(G),SZJ_(G)) :: &
570  htot, & ! The sum of the thicknesses of layers in the mixed layer [H ~> m or kg m-2]
571  Rml_av ! g_Rho0 times the average mixed layer density [m s-2]
572  real :: g_Rho0 ! G_Earth/Rho0 [m5 Z-1 s-2 kg-1 ~> m4 s-2 kg-1]
573  real :: Rho0(SZI_(G)) ! Potential density relative to the surface [kg m-3]
574  real :: p0(SZI_(G)) ! A pressure of 0 [Pa]
575 
576  real :: h_vel ! htot interpolated onto velocity points [Z ~> m]. (The units are not H.)
577  real :: absf ! absolute value of f, interpolated to velocity points [s-1]
578  real :: u_star ! surface friction velocity, interpolated to velocity points [Z s-1 ~> m s-1].
579  real :: mom_mixrate ! rate at which momentum is homogenized within mixed layer [s-1]
580  real :: timescale ! mixing growth timescale [s]
581  real :: h_neglect ! tiny thickness usually lost in roundoff and can be neglected [H ~> m or kg m-2]
582  real :: dz_neglect ! tiny thickness that usually lost in roundoff and can be neglected [Z ~> m]
583  real :: I4dt ! 1/(4 dt)
584  real :: I2htot ! Twice the total mixed layer thickness at velocity points [H ~> m or kg m-2]
585  real :: z_topx2 ! depth of the top of a layer at velocity points [H ~> m or kg m-2]
586  real :: hx2 ! layer thickness at velocity points [H ~> m or kg m-2]
587  real :: a(SZK_(G)) ! A non-dimensional value relating the overall flux
588  ! magnitudes (uDml & vDml) to the realized flux in a
589  ! layer. The vertical sum of a() through the pieces of
590  ! the mixed layer must be 0.
591  real :: uDml(SZIB_(G)) ! The zonal and meridional volume fluxes in the upper
592  real :: vDml(SZI_(G)) ! half of the mixed layer [H m2 s-1 ~> m3 s-1 or kg s-1].
593  real :: utimescale_diag(SZIB_(G),SZJ_(G)) ! The restratification timescales
594  real :: vtimescale_diag(SZI_(G),SZJB_(G)) ! in the zonal and meridional
595  ! directions [s], stored in 2-D
596  ! arrays for diagnostic purposes.
597  real :: uDml_diag(SZIB_(G),SZJ_(G)), vDml_diag(SZI_(G),SZJB_(G))
598  logical :: use_EOS ! If true, density is calculated from T & S using an equation of state.
599 
600  integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, nkml
601  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
602  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nkml = gv%nkml
603 
604  if (.not. associated(cs)) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
605  "Module must be initialized before it is used.")
606  if ((nkml<2) .or. (cs%ml_restrat_coef<=0.0)) return
607 
608  udml(:) = 0.0 ; vdml(:) = 0.0
609  i4dt = 0.25 / dt
610  g_rho0 = gv%g_Earth*us%L_to_m**2*us%s_to_T**2 / gv%Rho0
611  use_eos = associated(tv%eqn_of_state)
612  h_neglect = gv%H_subroundoff
613  dz_neglect = gv%H_subroundoff*gv%H_to_Z
614 
615  if (.not.use_eos) call mom_error(fatal, "MOM_mixedlayer_restrat: "// &
616  "An equation of state must be used with this module.")
617 
618  ! Fix this later for nkml >= 3.
619 
620  p0(:) = 0.0
621 !$OMP parallel default(none) shared(is,ie,js,je,G,GV,US,htot,Rml_av,tv,p0,h,h_avail, &
622 !$OMP h_neglect,g_Rho0,I4dt,CS,uhml,uhtr,dt,vhml,vhtr, &
623 !$OMP utimescale_diag,vtimescale_diag,forces,dz_neglect, &
624 !$OMP uDml_diag,vDml_diag,nkml) &
625 !$OMP private(Rho0,h_vel,u_star,absf,mom_mixrate,timescale, &
626 !$OMP I2htot,z_topx2,hx2,a) &
627 !$OMP firstprivate(uDml,vDml)
628 !$OMP do
629  do j=js-1,je+1
630  do i=is-1,ie+1
631  htot(i,j) = 0.0 ; rml_av(i,j) = 0.0
632  enddo
633  do k=1,nkml
634  call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho0(:),is-1,ie-is+3,tv%eqn_of_state)
635  do i=is-1,ie+1
636  rml_av(i,j) = rml_av(i,j) + h(i,j,k)*rho0(i)
637  htot(i,j) = htot(i,j) + h(i,j,k)
638  h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom_H),0.0)
639  enddo
640  enddo
641 
642  do i=is-1,ie+1
643  rml_av(i,j) = (g_rho0*rml_av(i,j)) / (htot(i,j) + h_neglect)
644  enddo
645  enddo
646 
647 ! TO DO:
648 ! 1. Mixing extends below the mixing layer to the mixed layer. Find it!
649 ! 2. Add exponential tail to stream-function?
650 
651 ! U - Component
652 !$OMP do
653  do j=js,je; do i=is-1,ie
654  h_vel = 0.5*(htot(i,j) + htot(i+1,j)) * gv%H_to_Z
655 
656  u_star = us%s_to_T*0.5*(forces%ustar(i,j) + forces%ustar(i+1,j))
657  absf = 0.5*us%s_to_T*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
658  ! peak ML visc: u_star * 0.41 * (h_ml*u_star)/(absf*h_ml + 4.0*u_star)
659  ! momentum mixing rate: pi^2*visc/h_ml^2
660  ! 0.41 is the von Karmen constant, 9.8696 = pi^2.
661  mom_mixrate = (0.41*9.8696)*u_star**2 / &
662  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
663  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
664 
665  timescale = timescale * cs%ml_restrat_coef
666 ! timescale = timescale*(2?)*(L_def/L_MLI)*min(EKE/MKE,1.0 + G%dyCv(i,j)**2/L_def**2))
667 
668  udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
669  g%IdxCu(i,j)*(rml_av(i+1,j)-rml_av(i,j)) * (h_vel**2 * gv%Z_to_H)
670 
671  if (udml(i) == 0) then
672  do k=1,nkml ; uhml(i,j,k) = 0.0 ; enddo
673  else
674  i2htot = 1.0 / (htot(i,j) + htot(i+1,j) + h_neglect)
675  z_topx2 = 0.0
676  ! a(k) relates the sublayer transport to uDml with a linear profile.
677  ! The sum of a(k) through the mixed layers must be 0.
678  do k=1,nkml
679  hx2 = (h(i,j,k) + h(i+1,j,k) + h_neglect)
680  a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
681  z_topx2 = z_topx2 + hx2
682  if (a(k)*udml(i) > 0.0) then
683  if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
684  else
685  if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k)/a(k)
686  endif
687  enddo
688  do k=1,nkml
689  uhml(i,j,k) = a(k)*udml(i)
690  uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
691  enddo
692  endif
693 
694  udml_diag(i,j) = udml(i)
695  utimescale_diag(i,j) = timescale
696  enddo; enddo
697 
698 ! V- component
699 !$OMP do
700  do j=js-1,je ; do i=is,ie
701  h_vel = 0.5*(htot(i,j) + htot(i,j+1)) * gv%H_to_Z
702 
703  u_star = us%s_to_T*0.5*(forces%ustar(i,j) + forces%ustar(i,j+1))
704  absf = 0.5*us%s_to_T*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
705  ! peak ML visc: u_star * 0.41 * (h_ml*u_star)/(absf*h_ml + 4.0*u_star)
706  ! momentum mixing rate: pi^2*visc/h_ml^2
707  ! 0.41 is the von Karmen constant, 9.8696 = pi^2.
708  mom_mixrate = (0.41*9.8696)*u_star**2 / &
709  (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
710  timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
711 
712  timescale = timescale * cs%ml_restrat_coef
713 ! timescale = timescale*(2?)*(L_def/L_MLI)*min(EKE/MKE,1.0 + G%dyCv(i,j)**2/L_def**2))
714 
715  vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
716  g%IdyCv(i,j)*(rml_av(i,j+1)-rml_av(i,j)) * (h_vel**2 * gv%Z_to_H)
717  if (vdml(i) == 0) then
718  do k=1,nkml ; vhml(i,j,k) = 0.0 ; enddo
719  else
720  i2htot = 1.0 / (htot(i,j) + htot(i,j+1) + h_neglect)
721  z_topx2 = 0.0
722  ! a(k) relates the sublayer transport to uDml with a linear profile.
723  ! The sum of a(k) through the mixed layers must be 0.
724  do k=1,nkml
725  hx2 = (h(i,j,k) + h(i,j+1,k) + h_neglect)
726  a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
727  z_topx2 = z_topx2 + hx2
728  if (a(k)*vdml(i) > 0.0) then
729  if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
730  else
731  if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k)/a(k)
732  endif
733  enddo
734  do k=1,nkml
735  vhml(i,j,k) = a(k)*vdml(i)
736  vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
737  enddo
738  endif
739 
740  vtimescale_diag(i,j) = timescale
741  vdml_diag(i,j) = vdml(i)
742  enddo; enddo
743 
744 !$OMP do
745  do j=js,je ; do k=1,nkml ; do i=is,ie
746  h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
747  ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
748  enddo ; enddo ; enddo
749 !$OMP end parallel
750 
751  ! Whenever thickness changes let the diag manager know, target grids
752  ! for vertical remapping may need to be regenerated.
753  if (cs%id_uhml > 0 .or. cs%id_vhml > 0) &
754  ! Remapped uhml and vhml require east/north halo updates of h
755  call pass_var(h, g%domain, to_west+to_south+omit_corners, halo=1)
756  call diag_update_remap_grids(cs%diag)
757 
758  ! Offer diagnostic fields for averaging.
759  if (query_averaging_enabled(cs%diag) .and. &
760  ((cs%id_urestrat_time > 0) .or. (cs%id_vrestrat_time > 0))) then
761  call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
762  call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
763  endif
764  if (query_averaging_enabled(cs%diag) .and. &
765  ((cs%id_uhml>0) .or. (cs%id_vhml>0))) then
766  do k=nkml+1,nz
767  do j=js,je ; do i=isq,ieq ; uhml(i,j,k) = 0.0 ; enddo ; enddo
768  do j=jsq,jeq ; do i=is,ie ; vhml(i,j,k) = 0.0 ; enddo ; enddo
769  enddo
770  if (cs%id_uhml > 0) call post_data(cs%id_uhml, uhml, cs%diag)
771  if (cs%id_vhml > 0) call post_data(cs%id_vhml, vhml, cs%diag)
772  if (cs%id_MLD > 0) call post_data(cs%id_MLD, htot, cs%diag)
773  if (cs%id_Rml > 0) call post_data(cs%id_Rml, rml_av, cs%diag)
774  if (cs%id_uDml > 0) call post_data(cs%id_uDml, udml_diag, cs%diag)
775  if (cs%id_vDml > 0) call post_data(cs%id_vDml, vdml_diag, cs%diag)
776  endif
777 
778 end subroutine mixedlayer_restrat_bml
779 
780 
781 !> Initialize the mixed layer restratification module
782 logical function mixedlayer_restrat_init(Time, G, GV, US, param_file, diag, CS, restart_CS)
783  type(time_type), intent(in) :: time !< Current model time
784  type(ocean_grid_type), intent(inout) :: g !< Ocean grid structure
785  type(verticalgrid_type), intent(in) :: gv !< Ocean vertical grid structure
786  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
787  type(param_file_type), intent(in) :: param_file !< Parameter file to parse
788  type(diag_ctrl), target, intent(inout) :: diag !< Regulate diagnostics
789  type(mixedlayer_restrat_cs), pointer :: cs !< Module control structure
790  type(mom_restart_cs), pointer :: restart_cs !< A pointer to the restart control structure
791 
792  ! Local variables
793  real :: h_rescale ! A rescaling factor for thicknesses from the representation in
794  ! a restart file to the internal representation in this run.
795  real :: flux_to_kg_per_s ! A unit conversion factor for fluxes.
796  ! This include declares and sets the variable "version".
797 # include "version_variable.h"
798  integer :: i, j
799 
800  ! Read all relevant parameters and write them to the model log.
801  call log_version(param_file, mdl, version, "")
802  call get_param(param_file, mdl, "MIXEDLAYER_RESTRAT", mixedlayer_restrat_init, &
803  "If true, a density-gradient dependent re-stratifying "//&
804  "flow is imposed in the mixed layer. Can be used in ALE mode "//&
805  "without restriction but in layer mode can only be used if "//&
806  "BULKMIXEDLAYER is true.", default=.false.)
807  if (.not. mixedlayer_restrat_init) return
808 
809  if (.not.associated(cs)) then
810  call mom_error(fatal, "mixedlayer_restrat_init called without an "// &
811  "associated control structure.")
812  endif
813 
814  ! Nonsense values to cause problems when these parameters are not used
815  cs%MLE_MLD_decay_time = -9.e9
816  cs%MLE_density_diff = -9.e9
817  cs%MLE_tail_dh = -9.e9
818  cs%MLE_use_PBL_MLD = .false.
819  cs%MLE_MLD_stretch = -9.e9
820 
821  call get_param(param_file, mdl, "DEBUG", cs%debug, default=.false., do_not_log=.true.)
822  call get_param(param_file, mdl, "FOX_KEMPER_ML_RESTRAT_COEF", cs%ml_restrat_coef, &
823  "A nondimensional coefficient that is proportional to "//&
824  "the ratio of the deformation radius to the dominant "//&
825  "lengthscale of the submesoscale mixed layer "//&
826  "instabilities, times the minimum of the ratio of the "//&
827  "mesoscale eddy kinetic energy to the large-scale "//&
828  "geostrophic kinetic energy or 1 plus the square of the "//&
829  "grid spacing over the deformation radius, as detailed "//&
830  "by Fox-Kemper et al. (2010)", units="nondim", default=0.0)
831  ! We use GV%nkml to distinguish between the old and new implementation of MLE.
832  ! The old implementation only works for the layer model with nkml>0.
833  if (gv%nkml==0) then
834  call get_param(param_file, mdl, "FOX_KEMPER_ML_RESTRAT_COEF2", cs%ml_restrat_coef2, &
835  "As for FOX_KEMPER_ML_RESTRAT_COEF but used in a second application "//&
836  "of the MLE restratification parameterization.", units="nondim", default=0.0)
837  call get_param(param_file, mdl, "MLE_FRONT_LENGTH", cs%front_length, &
838  "If non-zero, is the frontal-length scale used to calculate the "//&
839  "upscaling of buoyancy gradients that is otherwise represented "//&
840  "by the parameter FOX_KEMPER_ML_RESTRAT_COEF. If MLE_FRONT_LENGTH is "//&
841  "non-zero, it is recommended to set FOX_KEMPER_ML_RESTRAT_COEF=1.0.",&
842  units="m", default=0.0)
843  call get_param(param_file, mdl, "MLE_USE_PBL_MLD", cs%MLE_use_PBL_MLD, &
844  "If true, the MLE parameterization will use the mixed-layer "//&
845  "depth provided by the active PBL parameterization. If false, "//&
846  "MLE will estimate a MLD based on a density difference with the "//&
847  "surface using the parameter MLE_DENSITY_DIFF.", default=.false.)
848  call get_param(param_file, mdl, "MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
849  "The time-scale for a running-mean filter applied to the mixed-layer "//&
850  "depth used in the MLE restratification parameterization. When "//&
851  "the MLD deepens below the current running-mean the running-mean "//&
852  "is instantaneously set to the current MLD.", units="s", default=0.)
853  call get_param(param_file, mdl, "MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
854  "The time-scale for a running-mean filter applied to the filtered "//&
855  "mixed-layer depth used in a second MLE restratification parameterization. "//&
856  "When the MLD deepens below the current running-mean the running-mean "//&
857  "is instantaneously set to the current MLD.", units="s", default=0.)
858  if (.not. cs%MLE_use_PBL_MLD) then
859  call get_param(param_file, mdl, "MLE_DENSITY_DIFF", cs%MLE_density_diff, &
860  "Density difference used to detect the mixed-layer "//&
861  "depth used for the mixed-layer eddy parameterization "//&
862  "by Fox-Kemper et al. (2010)", units="kg/m3", default=0.03)
863  endif
864  call get_param(param_file, mdl, "MLE_TAIL_DH", cs%MLE_tail_dh, &
865  "Fraction by which to extend the mixed-layer restratification "//&
866  "depth used for a smoother stream function at the base of "//&
867  "the mixed-layer.", units="nondim", default=0.0)
868  call get_param(param_file, mdl, "MLE_MLD_STRETCH", cs%MLE_MLD_stretch, &
869  "A scaling coefficient for stretching/shrinking the MLD "//&
870  "used in the MLE scheme. This simply multiplies MLD wherever used.",&
871  units="nondim", default=1.0)
872  call get_param(param_file, mdl, "MLE_USE_MLD_AVE_BUG", cs%MLE_use_MLD_ave_bug, &
873  "If true, do not account for MLD mismatch to interface positions.",&
874  default=.false.)
875  endif
876 
877  cs%diag => diag
878 
879  if (gv%Boussinesq) then ; flux_to_kg_per_s = gv%Rho0
880  else ; flux_to_kg_per_s = 1. ; endif
881 
882  cs%id_uhml = register_diag_field('ocean_model', 'uhml', diag%axesCuL, time, &
883  'Zonal Thickness Flux to Restratify Mixed Layer', 'kg s-1', conversion=flux_to_kg_per_s, &
884  y_cell_method='sum', v_extensive=.true.)
885  cs%id_vhml = register_diag_field('ocean_model', 'vhml', diag%axesCvL, time, &
886  'Meridional Thickness Flux to Restratify Mixed Layer', 'kg s-1', conversion=flux_to_kg_per_s, &
887  x_cell_method='sum', v_extensive=.true.)
888  cs%id_urestrat_time = register_diag_field('ocean_model', 'MLu_restrat_time', diag%axesCu1, time, &
889  'Mixed Layer Zonal Restratification Timescale', 's')
890  cs%id_vrestrat_time = register_diag_field('ocean_model', 'MLv_restrat_time', diag%axesCv1, time, &
891  'Mixed Layer Meridional Restratification Timescale', 's')
892  cs%id_MLD = register_diag_field('ocean_model', 'MLD_restrat', diag%axesT1, time, &
893  'Mixed Layer Depth as used in the mixed-layer restratification parameterization', 'm')
894  cs%id_Rml = register_diag_field('ocean_model', 'ML_buoy_restrat', diag%axesT1, time, &
895  'Mixed Layer Buoyancy as used in the mixed-layer restratification parameterization', &
896  'm s2', conversion=us%m_to_Z)
897  cs%id_uDml = register_diag_field('ocean_model', 'udml_restrat', diag%axesCu1, time, &
898  'Transport stream function amplitude for zonal restratification of mixed layer', 'm3 s-1')
899  cs%id_vDml = register_diag_field('ocean_model', 'vdml_restrat', diag%axesCv1, time, &
900  'Transport stream function amplitude for meridional restratification of mixed layer', 'm3 s-1')
901  cs%id_uml = register_diag_field('ocean_model', 'uml_restrat', diag%axesCu1, time, &
902  'Surface zonal velocity component of mixed layer restratification', 'm s-1')
903  cs%id_vml = register_diag_field('ocean_model', 'vml_restrat', diag%axesCv1, time, &
904  'Surface meridional velocity component of mixed layer restratification', 'm s-1')
905 
906  ! Rescale variables from restart files if the internal dimensional scalings have changed.
907  if (cs%MLE_MLD_decay_time>0. .or. cs%MLE_MLD_decay_time2>0.) then
908  if (query_initialized(cs%MLD_filtered, "MLD_MLE_filtered", restart_cs) .and. &
909  (gv%m_to_H_restart /= 0.0) .and. (gv%m_to_H_restart /= gv%m_to_H)) then
910  h_rescale = gv%m_to_H / gv%m_to_H_restart
911  do j=g%jsc,g%jec ; do i=g%isc,g%iec
912  cs%MLD_filtered(i,j) = h_rescale * cs%MLD_filtered(i,j)
913  enddo ; enddo
914  endif
915  endif
916  if (cs%MLE_MLD_decay_time2>0.) then
917  if (query_initialized(cs%MLD_filtered_slow, "MLD_MLE_filtered_slow", restart_cs) .and. &
918  (gv%m_to_H_restart /= 0.0) .and. (gv%m_to_H_restart /= gv%m_to_H)) then
919  h_rescale = gv%m_to_H / gv%m_to_H_restart
920  do j=g%jsc,g%jec ; do i=g%isc,g%iec
921  cs%MLD_filtered_slow(i,j) = h_rescale * cs%MLD_filtered_slow(i,j)
922  enddo ; enddo
923  endif
924  endif
925 
926  ! If MLD_filtered is being used, we need to update halo regions after a restart
927  if (associated(cs%MLD_filtered)) call pass_var(cs%MLD_filtered, g%domain)
928 
929 end function mixedlayer_restrat_init
930 
931 !> Allocate and register fields in the mixed layer restratification structure for restarts
932 subroutine mixedlayer_restrat_register_restarts(HI, param_file, CS, restart_CS)
933  ! Arguments
934  type(hor_index_type), intent(in) :: hi !< Horizontal index structure
935  type(param_file_type), intent(in) :: param_file !< Parameter file to parse
936  type(mixedlayer_restrat_cs), pointer :: cs !< Module control structure
937  type(mom_restart_cs), pointer :: restart_cs !< A pointer to the restart control structure
938  ! Local variables
939  type(vardesc) :: vd
940  logical :: mixedlayer_restrat_init
941 
942  ! Check to see if this module will be used
943  call get_param(param_file, mdl, "MIXEDLAYER_RESTRAT", mixedlayer_restrat_init, &
944  default=.false., do_not_log=.true.)
945  if (.not. mixedlayer_restrat_init) return
946 
947  ! Allocate the control structure. CS will be later populated by mixedlayer_restrat_init()
948  if (associated(cs)) call mom_error(fatal, &
949  "mixedlayer_restrat_register_restarts called with an associated control structure.")
950  allocate(cs)
951 
952  call get_param(param_file, mdl, "MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
953  default=0., do_not_log=.true.)
954  call get_param(param_file, mdl, "MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
955  default=0., do_not_log=.true.)
956  if (cs%MLE_MLD_decay_time>0. .or. cs%MLE_MLD_decay_time2>0.) then
957  ! CS%MLD_filtered is used to keep a running mean of the PBL's actively mixed MLD.
958  allocate(cs%MLD_filtered(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered(:,:) = 0.
959  vd = var_desc("MLD_MLE_filtered","m","Time-filtered MLD for use in MLE", &
960  hor_grid='h', z_grid='1')
961  call register_restart_field(cs%MLD_filtered, vd, .false., restart_cs)
962  endif
963  if (cs%MLE_MLD_decay_time2>0.) then
964  ! CS%MLD_filtered_slow is used to keep a running mean of the PBL's seasonal or winter MLD.
965  allocate(cs%MLD_filtered_slow(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered_slow(:,:) = 0.
966  vd = var_desc("MLD_MLE_filtered_slow","m","c Slower time-filtered MLD for use in MLE", &
967  hor_grid='h', z_grid='1')
968  call register_restart_field(cs%MLD_filtered_slow, vd, .false., restart_cs)
969  endif
970 
971 end subroutine mixedlayer_restrat_register_restarts
972 
973 !> \namespace mom_mixed_layer_restrat
974 !!
975 !! \section section_mle Mixed-layer eddy parameterization module
976 !!
977 !! The subroutines in this file implement a parameterization of unresolved viscous
978 !! mixed layer restratification of the mixed layer as described in Fox-Kemper et
979 !! al., 2008, and whose impacts are described in Fox-Kemper et al., 2011.
980 !! This is derived in part from the older parameterization that is described in
981 !! Hallberg (Aha Hulikoa, 2003), which this new parameterization surpasses, which
982 !! in turn is based on the sub-inertial mixed layer theory of Young (JPO, 1994).
983 !! There is no net horizontal volume transport due to this parameterization, and
984 !! no direct effect below the mixed layer.
985 !!
986 !! This parameterization sets the restratification timescale to agree with
987 !! high-resolution studies of mixed layer restratification.
988 !!
989 !! The run-time parameter FOX_KEMPER_ML_RESTRAT_COEF is a non-dimensional number of
990 !! order a few tens, proportional to the ratio of the deformation radius or the
991 !! grid scale (whichever is smaller to the dominant horizontal length-scale of the
992 !! sub-meso-scale mixed layer instabilities.
993 !!
994 !! \subsection section_mle_nutshell "Sub-meso" in a nutshell
995 !!
996 !! The parameterization is colloquially referred to as "sub-meso".
997 !!
998 !! The original Fox-Kemper et al., (2008b) paper proposed a quasi-Stokes
999 !! advection described by the stream function (eq. 5 of Fox-Kemper et al., 2011):
1000 !! \f[
1001 !! {\bf \Psi}_o = C_e \frac{ H^2 \nabla \bar{b} \times \hat{\bf z} }{ |f| } \mu(z)
1002 !! \f]
1003 !!
1004 !! where the vertical profile function is
1005 !! \f[
1006 !! \mu(z) = \max \left\{ 0, \left[ 1 - \left(\frac{2z}{H}+1\right)^2 \right]
1007 !! \left[ 1 + \frac{5}{21} \left(\frac{2z}{H}+1\right)^2 \right] \right\}
1008 !! \f]
1009 !! and \f$ H \f$ is the mixed-layer depth, \f$ f \f$ is the local Coriolis parameter, \f$ C_e \sim 0.06-0.08 \f$ and
1010 !! \f$ \nabla \bar{b} \f$ is a depth mean buoyancy gradient averaged over the mixed layer.
1011 !!
1012 !! For use in coarse-resolution models, an upscaling of the buoyancy gradients and adaption for the equator
1013 !! leads to the following parameterization (eq. 6 of Fox-Kemper et al., 2011):
1014 !! \f[
1015 !! {\bf \Psi} = C_e \Gamma_\Delta \frac{\Delta s}{l_f} \frac{ H^2 \nabla \bar{b} \times \hat{\bf z} }
1016 !! { \sqrt{ f^2 + \tau^{-2}} } \mu(z)
1017 !! \f]
1018 !! where \f$ \Delta s \f$ is the minimum of grid-scale and deformation radius,
1019 !! \f$ l_f \f$ is the width of the mixed-layer fronts, and \f$ \Gamma_\Delta=1 \f$.
1020 !! \f$ \tau \f$ is a time-scale for mixing momentum across the mixed layer.
1021 !! \f$ l_f \f$ is thought to be of order hundreds of meters.
1022 !!
1023 !! The upscaling factor \f$ \frac{\Delta s}{l_f} \f$ can be a global constant, model parameter FOX_KEMPER_ML_RESTRAT,
1024 !! so that in practice the parameterization is:
1025 !! \f[
1026 !! {\bf \Psi} = C_e \Gamma_\Delta \frac{ H^2 \nabla \bar{b} \times \hat{\bf z} }{ \sqrt{ f^2 + \tau^{-2}} } \mu(z)
1027 !! \f]
1028 !! with non-unity \f$ \Gamma_\Delta \f$.
1029 !!
1030 !! \f$ C_e \f$ is hard-coded as 0.0625. \f$ \tau \f$ is calculated from the surface friction velocity \f$ u^* \f$.
1031 !! \todo Explain expression for momentum mixing time-scale.
1032 !!
1033 !! \subsection section_mle_filtering Time-filtering of mixed-layer depth
1034 !!
1035 !! Using the instantaneous mixed-layer depth is inconsistent with the finite life-time of
1036 !! mixed-layer instabilities. We provide a one-sided running-mean filter of mixed-layer depth, \f$ H \f$, of the form:
1037 !! \f[
1038 !! \bar{H} \leftarrow \max \left( H, \frac{ \Delta t H + \tau_h \bar{H} }{ \Delta t + \tau_h } \right)
1039 !! \f]
1040 !! which allows the effective mixed-layer depth seen by the parameterization, \f$\bar{H}\f$, to instantaneously deepen
1041 !! but to decay with time-scale \f$ \tau_h \f$.
1042 !! \f$ \bar{H} \f$ is substituted for \f$ H \f$ in the above equations.
1043 !!
1044 !! \subsection section_mle_mld Defining the mixed-layer-depth
1045 !!
1046 !! If the parameter MLE_USE_PBL_MLD=True then the mixed-layer depth is defined/diagnosed by the
1047 !! boundary-layer parameterization (e.g. ePBL, KPP, etc.).
1048 !!
1049 !! If the parameter MLE_USE_PBL_MLD=False then the mixed-layer depth is diagnosed in this module
1050 !! as the depth of a given density difference, \f$ \Delta \rho \f$, with the surface where the
1051 !! density difference is the parameter MLE_DENSITY_DIFF.
1052 !!
1053 !! \subsection section_mle_ref References
1054 !!
1055 !! Fox-Kemper, B., Ferrari, R. and Hallberg, R., 2008:
1056 !! Parameterization of Mixed Layer Eddies. Part I: Theory and Diagnosis
1057 !! J. Phys. Oceangraphy, 38 (6), p1145-1165.
1058 !! https://doi.org/10.1175/2007JPO3792.1
1059 !!
1060 !! Fox-Kemper, B. and Ferrari, R. 2008:
1061 !! Parameterization of Mixed Layer Eddies. Part II: Prognosis and Impact
1062 !! J. Phys. Oceangraphy, 38 (6), p1166-1179.
1063 !! https://doi.org/10.1175/2007JPO3788.1
1064 !!
1065 !! B. Fox-Kemper, G. Danabasoglu, R. Ferrari, S.M. Griffies, R.W. Hallberg, M.M. Holland, M.E. Maltrud,
1066 !! S. Peacock, and B.L. Samuels, 2011: Parameterization of mixed layer eddies. III: Implementation and impact
1067 !! in global ocean climate simulations. Ocean Modell., 39(1), p61-78.
1068 !! https://doi.org/10.1016/j.ocemod.2010.09.002
1069 !!
1070 !! | Symbol | Module parameter |
1071 !! | ---------------------------- | --------------------- |
1072 !! | \f$ \Gamma_\Delta \f$ | FOX_KEMPER_ML_RESTRAT |
1073 !! | \f$ l_f \f$ | MLE_FRONT_LENGTH |
1074 !! | \f$ \tau_h \f$ | MLE_MLD_DECAY_TIME |
1075 !! | \f$ \Delta \rho \f$ | MLE_DENSITY_DIFF |
1076 
1077 end module mom_mixed_layer_restrat
mom_forcing_type::mech_forcing
Structure that contains pointers to the mechanical forcing at the surface used to drive the liquid oc...
Definition: MOM_forcing_type.F90:185
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_mixed_layer_restrat
Parameterization of mixed layer restratification by unresolved mixed-layer eddies.
Definition: MOM_mixed_layer_restrat.F90:2
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_variables::thermo_var_ptrs
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Definition: MOM_variables.F90:82
mom_eos
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
mom_domains::pass_var
Do a halo update on an array.
Definition: MOM_domains.F90:49
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_hor_index
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Definition: MOM_hor_index.F90:2
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_restart::mom_restart_cs
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:72
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_restart
The MOM6 facility for reading and writing restart files, and querying what has been read.
Definition: MOM_restart.F90:2
mom_domains
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
mom_lateral_mixing_coeffs::varmix_cs
Variable mixing coefficients.
Definition: MOM_lateral_mixing_coeffs.F90:26
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_hor_index::hor_index_type
Container for horizontal index ranges for data, computational and global domains.
Definition: MOM_hor_index.F90:15
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_restart::register_restart_field
Register fields for restarts.
Definition: MOM_restart.F90:107
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_debugging
Provides checksumming functions for debugging.
Definition: MOM_debugging.F90:7
mom_mixed_layer_restrat::mixedlayer_restrat_cs
Control structure for mom_mixed_layer_restrat.
Definition: MOM_mixed_layer_restrat.F90:38
mom_io::vardesc
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:53
mom_lateral_mixing_coeffs
Variable mixing coefficients.
Definition: MOM_lateral_mixing_coeffs.F90:2
mom_restart::query_initialized
Indicate whether a field has been read from a restart file.
Definition: MOM_restart.F90:116
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239
mom_eos::calculate_density
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:60