MOM6
MOM_lateral_mixing_coeffs.F90
Go to the documentation of this file.
1 !> Variable mixing coefficients
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_debugging, only : hchksum, uvchksum
7 use mom_error_handler, only : mom_error, fatal, warning, mom_mesg
8 use mom_diag_mediator, only : register_diag_field, safe_alloc_ptr, post_data
11 use mom_domains, only : group_pass_type, pass_var
15 use mom_grid, only : ocean_grid_type
19 
20 implicit none ; private
21 
22 #include <MOM_memory.h>
23 
24 !> Variable mixing coefficients
25 type, public :: varmix_cs ;
26  logical :: use_variable_mixing !< If true, use the variable mixing.
27  logical :: resoln_scaled_kh !< If true, scale away the Laplacian viscosity
28  !! when the deformation radius is well resolved.
29  logical :: resoln_scaled_khth !< If true, scale away the thickness diffusivity
30  !! when the deformation radius is well resolved.
31  logical :: resoln_scaled_khtr !< If true, scale away the tracer diffusivity
32  !! when the deformation radius is well resolved.
33  logical :: interpolate_res_fn !< If true, interpolate the resolution function
34  !! to the velocity points from the thickness
35  !! points; otherwise interpolate the wave
36  !! speed and calculate the resolution function
37  !! independently at each point.
38  logical :: use_stored_slopes !< If true, stores isopycnal slopes in this structure.
39  logical :: resoln_use_ebt !< If true, uses the equivalent barotropic wave speed instead
40  !! of first baroclinic wave for calculating the resolution fn.
41  logical :: khth_use_ebt_struct !< If true, uses the equivalent barotropic structure
42  !! as the vertical structure of thickness diffusivity.
43  logical :: use_visbeck_slope_bug !< If true, then retain a legacy bug in the calculation of weights
44  !! applied to isoneutral slopes. There was an erroneous k-indexing
45  !! for layer thicknesses. In addition, masking at coastlines was not
46  !! used which introduced potential restart issues. This flag will be
47  !! deprecated in a future release.
48  logical :: calculate_cg1 !< If true, calls wave_speed() to calculate the first
49  !! baroclinic wave speed and populate CS%cg1.
50  !! This parameter is set depending on other parameters.
51  logical :: calculate_rd_dx !< If true, calculates Rd/dx and populate CS%Rd_dx_h.
52  !! This parameter is set depending on other parameters.
53  logical :: calculate_res_fns !< If true, calculate all the resolution factors.
54  !! This parameter is set depending on other parameters.
55  logical :: calculate_eady_growth_rate !< If true, calculate all the Eady growth rate.
56  !! This parameter is set depending on other parameters.
57  real, dimension(:,:), pointer :: &
58  sn_u => null(), & !< S*N at u-points (s^-1)
59  sn_v => null(), & !< S*N at v-points (s^-1)
60  l2u => null(), & !< Length scale^2 at u-points (m^2)
61  l2v => null(), & !< Length scale^2 at v-points (m^2)
62  cg1 => null(), & !< The first baroclinic gravity wave speed in m s-1.
63  res_fn_h => null(), & !< Non-dimensional function of the ratio the first baroclinic
64  !! deformation radius to the grid spacing at h points.
65  res_fn_q => null(), & !< Non-dimensional function of the ratio the first baroclinic
66  !! deformation radius to the grid spacing at q points.
67  res_fn_u => null(), & !< Non-dimensional function of the ratio the first baroclinic
68  !! deformation radius to the grid spacing at u points.
69  res_fn_v => null(), & !< Non-dimensional function of the ratio the first baroclinic
70  !! deformation radius to the grid spacing at v points.
71  beta_dx2_h => null(), & !< The magnitude of the gradient of the Coriolis parameter
72  !! times the grid spacing squared at h points.
73  beta_dx2_q => null(), & !< The magnitude of the gradient of the Coriolis parameter
74  !! times the grid spacing squared at q points.
75  beta_dx2_u => null(), & !< The magnitude of the gradient of the Coriolis parameter
76  !! times the grid spacing squared at u points.
77  beta_dx2_v => null(), & !< The magnitude of the gradient of the Coriolis parameter
78  !! times the grid spacing squared at v points.
79  f2_dx2_h => null(), & !< The Coriolis parameter squared times the grid
80  !! spacing squared at h, in m2 s-2.
81  f2_dx2_q => null(), & !< The Coriolis parameter squared times the grid
82  !! spacing squared at q, in m2 s-2.
83  f2_dx2_u => null(), & !< The Coriolis parameter squared times the grid
84  !! spacing squared at u, in m2 s-2.
85  f2_dx2_v => null(), & !< The Coriolis parameter squared times the grid
86  !! spacing squared at v, in m2 s-2.
87  rd_dx_h => null() !< Deformation radius over grid spacing (non-dim.)
88 
89  real, dimension(:,:,:), pointer :: &
90  slope_x => null(), & !< Zonal isopycnal slope (non-dimensional)
91  slope_y => null(), & !< Meridional isopycnal slope (non-dimensional)
92  ebt_struct => null() !< Vertical structure function to scale diffusivities with (non-dim)
93 
94  ! Parameters
95  integer :: varmix_ktop !< Top layer to start downward integrals
96  real :: visbeck_l_scale !< Fixed length scale in Visbeck formula
97  real :: res_coef_khth !< A non-dimensional number that determines the function
98  !! of resolution, used for thickness and tracer mixing, as:
99  !! F = 1 / (1 + (Res_coef_khth*Ld/dx)^Res_fn_power)
100  real :: res_coef_visc !< A non-dimensional number that determines the function
101  !! of resolution, used for lateral viscosity, as:
102  !! F = 1 / (1 + (Res_coef_visc*Ld/dx)^Res_fn_power)
103  real :: kappa_smooth !< A diffusivity for smoothing T/S in vanished layers (m2/s)
104  integer :: res_fn_power_khth !< The power of dx/Ld in the KhTh resolution function. Any
105  !! positive integer power may be used, but even powers
106  !! and especially 2 are coded to be more efficient.
107  integer :: res_fn_power_visc !< The power of dx/Ld in the Kh resolution function. Any
108  !! positive integer power may be used, but even powers
109  !! and especially 2 are coded to be more efficient.
110  real :: visbeck_s_max !< Upper bound on slope used in Eady growth rate (nondim).
111 
112  ! Diagnostics
113  !>@{
114  !! Diagnostic identifier
115  integer :: id_sn_u=-1, id_sn_v=-1, id_l2u=-1, id_l2v=-1, id_res_fn = -1
116  integer :: id_n2_u=-1, id_n2_v=-1, id_s2_u=-1, id_s2_v=-1
117  integer :: id_rd_dx=-1
118  type(diag_ctrl), pointer :: diag !< A structure that is used to regulate the
119  !! timing of diagnostic output.
120  !>@}
121 
122  type(wave_speed_cs), pointer :: wave_speed_csp => null() !< Wave speed control structure
123  type(group_pass_type) :: pass_cg1 !< For group halo pass
124  logical :: debug !< If true, write out checksums of data for debugging
125 end type varmix_cs
126 
128 
129 contains
130 
131 !> Calculates and stores the non-dimensional resolution functions
132 subroutine calc_resoln_function(h, tv, G, GV, CS)
133  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
134  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness (m or kg/m2)
135  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
136  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure
137  type(varmix_cs), pointer :: CS !< Variable mixing coefficients
138  ! Local variables
139  real :: cg1_q ! The gravity wave speed interpolated to q points, in m s-1.
140  real :: cg1_u ! The gravity wave speed interpolated to u points, in m s-1.
141  real :: cg1_v ! The gravity wave speed interpolated to v points, in m s-1.
142  real :: dx_term
143  integer :: power_2
144  integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
145  integer :: i, j, k
146  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
147  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
148 
149  if (.not. ASSOCIATED(cs)) call mom_error(fatal, "calc_resoln_function:"// &
150  "Module must be initialized before it is used.")
151  if (cs%calculate_cg1) then
152  if (.not. ASSOCIATED(cs%cg1)) call mom_error(fatal, &
153  "calc_resoln_function: %cg1 is not associated with Resoln_scaled_Kh.")
154  if (cs%khth_use_ebt_struct) then
155  if (.not. ASSOCIATED(cs%ebt_struct)) call mom_error(fatal, &
156  "calc_resoln_function: %ebt_struct is not associated with RESOLN_USE_EBT.")
157  if (cs%Resoln_use_ebt) then
158  ! Both resolution fn and vertical structure are using EBT
159  call wave_speed(h, tv, g, gv, cs%cg1, cs%wave_speed_CSp, modal_structure=cs%ebt_struct)
160  else
161  ! Use EBT to get vertical structure first and then re-calculate cg1 using first baroclinic mode
162  call wave_speed(h, tv, g, gv, cs%cg1, cs%wave_speed_CSp, modal_structure=cs%ebt_struct, use_ebt_mode=.true.)
163  call wave_speed(h, tv, g, gv, cs%cg1, cs%wave_speed_CSp)
164  endif
165  call pass_var(cs%ebt_struct, g%Domain)
166  else
167  call wave_speed(h, tv, g, gv, cs%cg1, cs%wave_speed_CSp)
168  endif
169 
170  call create_group_pass(cs%pass_cg1, cs%cg1, g%Domain)
171  call do_group_pass(cs%pass_cg1, g%Domain)
172  endif
173 
174  ! Calculate and store the ratio between deformation radius and grid-spacing
175  ! at h-points (non-dimensional).
176  if (cs%calculate_rd_dx) then
177  if (.not. ASSOCIATED(cs%Rd_dx_h)) call mom_error(fatal, &
178  "calc_resoln_function: %Rd_dx_h is not associated with calculate_rd_dx.")
179 !$OMP parallel default(none) shared(is,ie,js,je,CS)
180 !$OMP do
181  do j=js-1,je+1 ; do i=is-1,ie+1
182  cs%Rd_dx_h(i,j) = cs%cg1(i,j) / &
183  (sqrt(cs%f2_dx2_h(i,j) + cs%cg1(i,j)*cs%beta_dx2_h(i,j)))
184  enddo ; enddo
185 !$OMP end parallel
186  if (query_averaging_enabled(cs%diag)) then
187  if (cs%id_Rd_dx > 0) call post_data(cs%id_Rd_dx, cs%Rd_dx_h, cs%diag)
188  endif
189  endif
190 
191  if (.not. cs%calculate_res_fns) return
192 
193  if (.not. ASSOCIATED(cs%Res_fn_h)) call mom_error(fatal, &
194  "calc_resoln_function: %Res_fn_h is not associated with Resoln_scaled_Kh.")
195  if (.not. ASSOCIATED(cs%Res_fn_q)) call mom_error(fatal, &
196  "calc_resoln_function: %Res_fn_q is not associated with Resoln_scaled_Kh.")
197  if (.not. ASSOCIATED(cs%Res_fn_u)) call mom_error(fatal, &
198  "calc_resoln_function: %Res_fn_u is not associated with Resoln_scaled_Kh.")
199  if (.not. ASSOCIATED(cs%Res_fn_v)) call mom_error(fatal, &
200  "calc_resoln_function: %Res_fn_v is not associated with Resoln_scaled_Kh.")
201  if (.not. ASSOCIATED(cs%f2_dx2_h)) call mom_error(fatal, &
202  "calc_resoln_function: %f2_dx2_h is not associated with Resoln_scaled_Kh.")
203  if (.not. ASSOCIATED(cs%f2_dx2_q)) call mom_error(fatal, &
204  "calc_resoln_function: %f2_dx2_q is not associated with Resoln_scaled_Kh.")
205  if (.not. ASSOCIATED(cs%f2_dx2_u)) call mom_error(fatal, &
206  "calc_resoln_function: %f2_dx2_u is not associated with Resoln_scaled_Kh.")
207  if (.not. ASSOCIATED(cs%f2_dx2_v)) call mom_error(fatal, &
208  "calc_resoln_function: %f2_dx2_v is not associated with Resoln_scaled_Kh.")
209  if (.not. ASSOCIATED(cs%beta_dx2_h)) call mom_error(fatal, &
210  "calc_resoln_function: %beta_dx2_h is not associated with Resoln_scaled_Kh.")
211  if (.not. ASSOCIATED(cs%beta_dx2_q)) call mom_error(fatal, &
212  "calc_resoln_function: %beta_dx2_q is not associated with Resoln_scaled_Kh.")
213  if (.not. ASSOCIATED(cs%beta_dx2_u)) call mom_error(fatal, &
214  "calc_resoln_function: %beta_dx2_u is not associated with Resoln_scaled_Kh.")
215  if (.not. ASSOCIATED(cs%beta_dx2_v)) call mom_error(fatal, &
216  "calc_resoln_function: %beta_dx2_v is not associated with Resoln_scaled_Kh.")
217 
218  ! Do this calculation on the extent used in MOM_hor_visc.F90, and
219  ! MOM_tracer.F90 so that no halo update is needed.
220 
221 !$OMP parallel default(none) shared(is,ie,js,je,Ieq,Jeq,CS) &
222 !$OMP private(dx_term,cg1_q,power_2,cg1_u,cg1_v)
223  if (cs%Res_fn_power_visc >= 100) then
224 !$OMP do
225  do j=js-1,je+1 ; do i=is-1,ie+1
226  dx_term = cs%f2_dx2_h(i,j) + cs%cg1(i,j)*cs%beta_dx2_h(i,j)
227  if ((cs%Res_coef_visc * cs%cg1(i,j))**2 > dx_term) then
228  cs%Res_fn_h(i,j) = 0.0
229  else
230  cs%Res_fn_h(i,j) = 1.0
231  endif
232  enddo ; enddo
233 !$OMP do
234  do j=js-1,jeq ; do i=is-1,ieq
235  cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
236  (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
237  dx_term = cs%f2_dx2_q(i,j) + cg1_q * cs%beta_dx2_q(i,j)
238  if ((cs%Res_coef_visc * cg1_q)**2 > dx_term) then
239  cs%Res_fn_q(i,j) = 0.0
240  else
241  cs%Res_fn_q(i,j) = 1.0
242  endif
243  enddo ; enddo
244  elseif (cs%Res_fn_power_visc == 2) then
245 !$OMP do
246  do j=js-1,je+1 ; do i=is-1,ie+1
247  dx_term = cs%f2_dx2_h(i,j) + cs%cg1(i,j)*cs%beta_dx2_h(i,j)
248  cs%Res_fn_h(i,j) = dx_term / (dx_term + (cs%Res_coef_visc * cs%cg1(i,j))**2)
249  enddo ; enddo
250 !$OMP do
251  do j=js-1,jeq ; do i=is-1,ieq
252  cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
253  (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
254  dx_term = cs%f2_dx2_q(i,j) + cg1_q * cs%beta_dx2_q(i,j)
255  cs%Res_fn_q(i,j) = dx_term / (dx_term + (cs%Res_coef_visc * cg1_q)**2)
256  enddo ; enddo
257  elseif (mod(cs%Res_fn_power_visc, 2) == 0) then
258  power_2 = cs%Res_fn_power_visc / 2
259 !$OMP do
260  do j=js-1,je+1 ; do i=is-1,ie+1
261  dx_term = (cs%f2_dx2_h(i,j) + cs%cg1(i,j)*cs%beta_dx2_h(i,j))**power_2
262  cs%Res_fn_h(i,j) = dx_term / &
263  (dx_term + (cs%Res_coef_visc * cs%cg1(i,j))**cs%Res_fn_power_visc)
264  enddo ; enddo
265 !$OMP do
266  do j=js-1,jeq ; do i=is-1,ieq
267  cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
268  (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
269  dx_term = (cs%f2_dx2_q(i,j) + cg1_q * cs%beta_dx2_q(i,j))**power_2
270  cs%Res_fn_q(i,j) = dx_term / &
271  (dx_term + (cs%Res_coef_visc * cg1_q)**cs%Res_fn_power_visc)
272  enddo ; enddo
273  else
274 !$OMP do
275  do j=js-1,je+1 ; do i=is-1,ie+1
276  dx_term = (sqrt(cs%f2_dx2_h(i,j) + &
277  cs%cg1(i,j)*cs%beta_dx2_h(i,j)))**cs%Res_fn_power_visc
278  cs%Res_fn_h(i,j) = dx_term / &
279  (dx_term + (cs%Res_coef_visc * cs%cg1(i,j))**cs%Res_fn_power_visc)
280  enddo ; enddo
281 !$OMP do
282  do j=js-1,jeq ; do i=is-1,ieq
283  cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
284  (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
285  dx_term = (sqrt(cs%f2_dx2_q(i,j) + &
286  cg1_q * cs%beta_dx2_q(i,j)))**cs%Res_fn_power_visc
287  cs%Res_fn_q(i,j) = dx_term / &
288  (dx_term + (cs%Res_coef_visc * cg1_q)**cs%Res_fn_power_visc)
289  enddo ; enddo
290  endif
291 
292  if (cs%interpolate_Res_fn) then
293  do j=js,je ; do i=is-1,ieq
294  cs%Res_fn_u(i,j) = 0.5*(cs%Res_fn_h(i,j) + cs%Res_fn_h(i+1,j))
295  enddo ; enddo
296  do j=js-1,jeq ; do i=is,ie
297  cs%Res_fn_v(i,j) = 0.5*(cs%Res_fn_h(i,j) + cs%Res_fn_h(i,j+1))
298  enddo ; enddo
299  else ! .not.CS%interpolate_Res_fn
300  if (cs%Res_fn_power_khth >= 100) then
301 !$OMP do
302  do j=js,je ; do i=is-1,ieq
303  cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
304  dx_term = cs%f2_dx2_u(i,j) + cg1_u * cs%beta_dx2_u(i,j)
305  if ((cs%Res_coef_khth * cg1_u)**2 > dx_term) then
306  cs%Res_fn_u(i,j) = 0.0
307  else
308  cs%Res_fn_u(i,j) = 1.0
309  endif
310  enddo ; enddo
311 !$OMP do
312  do j=js-1,jeq ; do i=is,ie
313  cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
314  dx_term = cs%f2_dx2_v(i,j) + cg1_v * cs%beta_dx2_v(i,j)
315  if ((cs%Res_coef_khth * cg1_v)**2 > dx_term) then
316  cs%Res_fn_v(i,j) = 0.0
317  else
318  cs%Res_fn_v(i,j) = 1.0
319  endif
320  enddo ; enddo
321  elseif (cs%Res_fn_power_khth == 2) then
322 !$OMP do
323  do j=js,je ; do i=is-1,ieq
324  cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
325  dx_term = cs%f2_dx2_u(i,j) + cg1_u * cs%beta_dx2_u(i,j)
326  cs%Res_fn_u(i,j) = dx_term / (dx_term + (cs%Res_coef_khth * cg1_u)**2)
327  enddo ; enddo
328 !$OMP do
329  do j=js-1,jeq ; do i=is,ie
330  cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
331  dx_term = cs%f2_dx2_v(i,j) + cg1_v * cs%beta_dx2_v(i,j)
332  cs%Res_fn_v(i,j) = dx_term / (dx_term + (cs%Res_coef_khth * cg1_v)**2)
333  enddo ; enddo
334  elseif (mod(cs%Res_fn_power_khth, 2) == 0) then
335  power_2 = cs%Res_fn_power_khth / 2
336 !$OMP do
337  do j=js,je ; do i=is-1,ieq
338  cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
339  dx_term = (cs%f2_dx2_u(i,j) + cg1_u * cs%beta_dx2_u(i,j))**power_2
340  cs%Res_fn_u(i,j) = dx_term / &
341  (dx_term + (cs%Res_coef_khth * cg1_u)**cs%Res_fn_power_khth)
342  enddo ; enddo
343 !$OMP do
344  do j=js-1,jeq ; do i=is,ie
345  cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
346  dx_term = (cs%f2_dx2_v(i,j) + cg1_v * cs%beta_dx2_v(i,j))**power_2
347  cs%Res_fn_v(i,j) = dx_term / &
348  (dx_term + (cs%Res_coef_khth * cg1_v)**cs%Res_fn_power_khth)
349  enddo ; enddo
350  else
351 !$OMP do
352  do j=js,je ; do i=is-1,ieq
353  cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
354  dx_term = (sqrt(cs%f2_dx2_u(i,j) + &
355  cg1_u * cs%beta_dx2_u(i,j)))**cs%Res_fn_power_khth
356  cs%Res_fn_u(i,j) = dx_term / &
357  (dx_term + (cs%Res_coef_khth * cg1_u)**cs%Res_fn_power_khth)
358  enddo ; enddo
359 !$OMP do
360  do j=js-1,jeq ; do i=is,ie
361  cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
362  dx_term = (sqrt(cs%f2_dx2_v(i,j) + &
363  cg1_v * cs%beta_dx2_v(i,j)))**cs%Res_fn_power_khth
364  cs%Res_fn_v(i,j) = dx_term / &
365  (dx_term + (cs%Res_coef_khth * cg1_v)**cs%Res_fn_power_khth)
366  enddo ; enddo
367  endif
368  endif
369 !$OMP end parallel
370 
371  if (query_averaging_enabled(cs%diag)) then
372  if (cs%id_Res_fn > 0) call post_data(cs%id_Res_fn, cs%Res_fn_h, cs%diag)
373  endif
374 
375 end subroutine calc_resoln_function
376 
377 !> Calculates and stores functions of isopycnal slopes, e.g. Sx, Sy, S*N, mostly used in the Visbeck et al.
378 !! style scaling of diffusivity
379 subroutine calc_slope_functions(h, tv, dt, G, GV, CS)
380  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
381  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure
382  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness (m or kg/m2)
383  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
384  real, intent(in) :: dt !< Time increment (s)
385  type(varmix_cs), pointer :: CS !< Variable mixing coefficients
386  ! Local variables
387  real, dimension(SZI_(G), SZJ_(G), SZK_(G)+1) :: &
388  e ! The interface heights relative to mean sea level, in m.
389  real, dimension(SZIB_(G), SZJ_(G), SZK_(G)+1) :: N2_u ! Square of Brunt-Vaisala freq at u-points
390  real, dimension(SZI_(G), SZJB_(G), SZK_(G)+1) :: N2_v ! Square of Brunt-Vaisala freq at u-points
391 
392  if (.not. ASSOCIATED(cs)) call mom_error(fatal, "MOM_lateral_mixing_coeffs.F90, calc_slope_functions:"//&
393  "Module must be initialized before it is used.")
394 
395  if (cs%calculate_Eady_growth_rate) then
396  call find_eta(h, tv, gv%g_Earth, g, gv, e, halo_size=2)
397  if (cs%use_stored_slopes) then
398  call calc_isoneutral_slopes(g, gv, h, e, tv, dt*cs%kappa_smooth, &
399  cs%slope_x, cs%slope_y, n2_u, n2_v, 1)
400  call calc_visbeck_coeffs(h, e, cs%slope_x, cs%slope_y, n2_u, n2_v, g, gv, cs)
401 ! call calc_slope_functions_using_just_e(h, G, CS, e, .false.)
402  else
403  !call calc_isoneutral_slopes(G, GV, h, e, tv, dt*CS%kappa_smooth, CS%slope_x, CS%slope_y)
404  call calc_slope_functions_using_just_e(h, g, gv, cs, e, .true.)
405  endif
406  endif
407 
408  if (query_averaging_enabled(cs%diag)) then
409  if (cs%id_SN_u > 0) call post_data(cs%id_SN_u, cs%SN_u, cs%diag)
410  if (cs%id_SN_v > 0) call post_data(cs%id_SN_v, cs%SN_v, cs%diag)
411  if (cs%id_L2u > 0) call post_data(cs%id_L2u, cs%L2u, cs%diag)
412  if (cs%id_L2v > 0) call post_data(cs%id_L2v, cs%L2v, cs%diag)
413  if (cs%id_N2_u > 0) call post_data(cs%id_N2_u, n2_u, cs%diag)
414  if (cs%id_N2_v > 0) call post_data(cs%id_N2_v, n2_v, cs%diag)
415  endif
416 
417 end subroutine calc_slope_functions
418 
419 !> Calculates factors used when setting diffusivity coefficients similar to Visbeck et al.
420 subroutine calc_visbeck_coeffs(h, e, slope_x, slope_y, N2_u, N2_v, G, GV, CS)
421  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
422  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure
423  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness (m or kg/m2)
424  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), intent(in) :: e !< Interface position (m)
425  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)+1), intent(in) :: slope_x !< Zonal isoneutral slope
426  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)+1), intent(in) :: N2_u !< Brunt-Vaisala frequency at u-points (1/s2)
427  real, dimension(SZI_(G),SZJB_(G),SZK_(G)+1), intent(in) :: slope_y !< Meridional isoneutral slope
428  real, dimension(SZI_(G),SZJB_(G),SZK_(G)+1), intent(in) :: N2_v !< Brunt-Vaisala frequency at v-points (1/s2)
429  type(varmix_cs), pointer :: CS !< Variable mixing coefficients
430  ! Local variables
431  real :: E_x(szib_(g), szj_(g)) ! X-slope of interface at u points (for diagnostics)
432  real :: E_y(szi_(g), szjb_(g)) ! Y-slope of interface at u points (for diagnostics)
433  real :: Khth_Loc ! Locally calculated thickness mixing coefficient (m2/s)
434  real :: S2 ! Interface slope squared (non-dim)
435  real :: N2 ! Brunt-Vaisala frequency (1/s)
436  real :: Hup, Hdn ! Thickness from above, below (m or kg m-2)
437  real :: H_geom ! The geometric mean of Hup*Hdn, in m or kg m-2.
438  integer :: is, ie, js, je, nz
439  integer :: i, j, k, kb_max
440  real :: S2max, wNE, wSE, wSW, wNW
441  real :: SN_u_local(szib_(g), szj_(g),szk_(g))
442  real :: SN_v_local(szi_(g), szjb_(g),szk_(g))
443  real :: H_u(szib_(g)), H_v(szi_(g))
444  real :: S2_u(szib_(g), szj_(g))
445  real :: S2_v(szi_(g), szjb_(g))
446 
447  if (.not. ASSOCIATED(cs)) call mom_error(fatal, "calc_slope_function:"// &
448  "Module must be initialized before it is used.")
449  if (.not. cs%calculate_Eady_growth_rate) return
450  if (.not. ASSOCIATED(cs%SN_u)) call mom_error(fatal, "calc_slope_function:"// &
451  "%SN_u is not associated with use_variable_mixing.")
452  if (.not. ASSOCIATED(cs%SN_v)) call mom_error(fatal, "calc_slope_function:"// &
453  "%SN_v is not associated with use_variable_mixing.")
454 
455  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
456 
457  s2max = cs%Visbeck_S_max**2
458 
459 !$OMP parallel default(none) shared(is,ie,js,je,CS,nz,e,G,GV,h, &
460 !$OMP S2_u,S2_v,slope_x,slope_y, &
461 !$OMP SN_u_local,SN_v_local,N2_u,N2_v, S2max) &
462 !$OMP private(E_x,E_y,S2,H_u,H_v,Hdn,Hup,H_geom,N2, &
463 !$OMP wNE, wSE, wSW, wNW)
464 !$OMP do
465  do j=js-1,je+1 ; do i=is-1,ie+1
466  cs%SN_u(i,j) = 0.0
467  cs%SN_v(i,j) = 0.0
468  enddo ; enddo
469 
470  ! To set the length scale based on the deformation radius, use wave_speed to
471  ! calculate the first-mode gravity wave speed and then blend the equatorial
472  ! and midlatitude deformation radii, using calc_resoln_function as a template.
473 
474 !$OMP do
475  do j = js,je
476  do i=is-1,ie
477  cs%SN_u(i,j) = 0. ; h_u(i) = 0. ; s2_u(i,j) = 0.
478  enddo
479  do k=2,nz ; do i=is-1,ie
480  hdn = sqrt( h(i,j,k) * h(i+1,j,k) )
481  hup = sqrt( h(i,j,k-1) * h(i+1,j,k-1) )
482  h_geom = sqrt( hdn * hup )
483  !H_geom = H_geom * sqrt(N2) ! WKB-ish
484  !H_geom = H_geom * N2 ! WKB-ish
485  if (cs%use_Visbeck_slope_bug) then
486  wse = h(i+1,j,k)*h(i+1,j-1,k) * h(i+1,j,k)*h(i+1,j-1,k-1)
487  wnw = h(i ,j,k)*h(i ,j+1,k) * h(i ,j,k)*h(i ,j+1,k-1)
488  wne = h(i+1,j,k)*h(i+1,j+1,k) * h(i+1,j,k)*h(i+1,j+1,k-1)
489  wsw = h(i ,j,k)*h(i ,j-1,k) * h(i ,j,k)*h(i ,j-1,k-1)
490  s2 = slope_x(i,j,k)**2 + ( &
491  (wnw*slope_y(i,j,k)**2+wse*slope_y(i+1,j-1,k)**2) &
492  +(wne*slope_y(i+1,j,k)**2+wsw*slope_y(i,j-1,k)**2) ) / &
493  ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**2 ) !### This should be **4 for consistent units.
494  else
495  wse = g%mask2dCv(i+1,j-1) * ( (h(i+1,j,k)*h(i+1,j-1,k)) * (h(i+1,j,k-1)*h(i+1,j-1,k-1)) )
496  wnw = g%mask2dCv(i ,j ) * ( (h(i ,j,k)*h(i ,j+1,k)) * (h(i ,j,k-1)*h(i ,j+1,k-1)) )
497  wne = g%mask2dCv(i+1,j ) * ( (h(i+1,j,k)*h(i+1,j+1,k)) * (h(i+1,j,k-1)*h(i+1,j+1,k-1)) )
498  wsw = g%mask2dCv(i ,j-1) * ( (h(i ,j,k)*h(i ,j-1,k)) * (h(i ,j,k-1)*h(i ,j-1,k-1)) )
499  s2 = slope_x(i,j,k)**2 + ( &
500  (wnw*slope_y(i,j,k)**2+wse*slope_y(i+1,j-1,k)**2) &
501  +(wne*slope_y(i+1,j,k)**2+wsw*slope_y(i,j-1,k)**2) ) / &
502  ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**4 )
503  endif
504  if (s2max>0.) s2 = s2 * s2max / (s2 + s2max) ! Limit S2
505  n2 = max(0., n2_u(i,j,k))
506  cs%SN_u(i,j) = cs%SN_u(i,j) + sqrt( s2*n2 )*h_geom
507  s2_u(i,j) = s2_u(i,j) + s2*h_geom
508  h_u(i) = h_u(i) + h_geom
509  enddo ; enddo
510  do i=is-1,ie
511  if (h_u(i)>0.) then
512  cs%SN_u(i,j) = g%mask2dCu(i,j) * cs%SN_u(i,j) / h_u(i)
513  s2_u(i,j) = g%mask2dCu(i,j) * s2_u(i,j) / h_u(i)
514  else
515  cs%SN_u(i,j) = 0.
516  endif
517  enddo
518  enddo
519 
520 !$OMP do
521  do j = js-1,je
522  do i=is,ie
523  cs%SN_v(i,j) = 0. ; h_v(i) = 0. ; s2_v(i,j) = 0.
524  enddo
525  do k=2,nz ; do i=is,ie
526  hdn = sqrt( h(i,j,k) * h(i,j+1,k) )
527  hup = sqrt( h(i,j,k-1) * h(i,j+1,k-1) )
528  h_geom = sqrt( hdn * hup )
529  !H_geom = H_geom * sqrt(N2) ! WKB-ish
530  !H_geom = H_geom * N2 ! WKB-ish
531  if (cs%use_Visbeck_slope_bug) then
532  wse = h(i,j ,k)*h(i+1,j ,k) * h(i,j ,k)*h(i+1,j ,k-1)
533  wnw = h(i,j+1,k)*h(i-1,j+1,k) * h(i,j+1,k)*h(i-1,j+1,k-1)
534  wne = h(i,j+1,k)*h(i+1,j+1,k) * h(i,j+1,k)*h(i+1,j+1,k-1)
535  wsw = h(i,j ,k)*h(i-1,j ,k) * h(i,j ,k)*h(i-1,j ,k-1)
536  s2 = slope_y(i,j,k)**2 + ( &
537  (wse*slope_x(i,j,k)**2+wnw*slope_x(i-1,j+1,k)**2) &
538  +(wne*slope_x(i,j+1,k)**2+wsw*slope_x(i-1,j,k)**2) ) / &
539  ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**2 ) !### This should be **4 for consistent units.
540  else
541  wse = g%mask2dCu(i,j) * ( (h(i,j ,k)*h(i+1,j ,k)) * (h(i,j ,k-1)*h(i+1,j ,k-1)) )
542  wnw = g%mask2dCu(i-1,j+1) * ( (h(i,j+1,k)*h(i-1,j+1,k)) * (h(i,j+1,k-1)*h(i-1,j+1,k-1)) )
543  wne = g%mask2dCu(i,j+1) * ( (h(i,j+1,k)*h(i+1,j+1,k)) * (h(i,j+1,k-1)*h(i+1,j+1,k-1)) )
544  wsw = g%mask2dCu(i-1,j) * ( (h(i,j ,k)*h(i-1,j ,k)) * (h(i,j ,k-1)*h(i-1,j ,k-1)) )
545  s2 = slope_y(i,j,k)**2 + ( &
546  (wse*slope_x(i,j,k)**2+wnw*slope_x(i-1,j+1,k)**2) &
547  +(wne*slope_x(i,j+1,k)**2+wsw*slope_x(i-1,j,k)**2) ) / &
548  ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**4 ) !### This should be **4 for consistent units.
549  endif
550  if (s2max>0.) s2 = s2 * s2max / (s2 + s2max) ! Limit S2
551  n2 = max(0., n2_v(i,j,k))
552  cs%SN_v(i,j) = cs%SN_v(i,j) + sqrt( s2*n2 )*h_geom
553  s2_v(i,j) = s2_v(i,j) + s2*h_geom
554  h_v(i) = h_v(i) + h_geom
555  enddo ; enddo
556  do i=is,ie
557  if (h_v(i)>0.) then
558  cs%SN_v(i,j) = g%mask2dCv(i,j) * cs%SN_v(i,j) / h_v(i)
559  s2_v(i,j) = g%mask2dCv(i,j) * s2_v(i,j) / h_v(i)
560  else
561  cs%SN_v(i,j) = 0.
562  endif
563  enddo
564  enddo
565 
566 !$OMP end parallel
567 
568 ! Offer diagnostic fields for averaging.
569  if (query_averaging_enabled(cs%diag)) then
570  if (cs%id_S2_u > 0) call post_data(cs%id_S2_u, s2_u, cs%diag)
571  if (cs%id_S2_v > 0) call post_data(cs%id_S2_v, s2_v, cs%diag)
572  endif
573 
574  if (cs%debug) then
575  call uvchksum("calc_Visbeck_coeffs slope_[xy]", slope_x, slope_y, g%HI, haloshift=1)
576  call uvchksum("calc_Visbeck_coeffs N2_u, N2_v", n2_u, n2_v, g%HI)
577  call uvchksum("calc_Visbeck_coeffs SN_[uv]", cs%SN_u, cs%SN_v, g%HI)
578  endif
579 
580 end subroutine calc_visbeck_coeffs
581 
582 !> The original calc_slope_function() that calculated slopes using
583 !! interface positions only, not accounting for density variations.
584 subroutine calc_slope_functions_using_just_e(h, G, GV, CS, e, calculate_slopes)
585  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
586  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness (m or kg/m2)
587  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure
588  type(varmix_cs), pointer :: CS !< Variable mixing coefficients
589  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), intent(in) :: e !< Interface position (m)
590  logical, intent(in) :: calculate_slopes !< If true, calculate slopes internally
591  !! otherwise use slopes stored in CS
592  ! Local variables
593  real :: E_x(szib_(g), szj_(g)) ! X-slope of interface at u points (for diagnostics)
594  real :: E_y(szi_(g), szjb_(g)) ! Y-slope of interface at u points (for diagnostics)
595  real :: Khth_Loc ! Locally calculated thickness mixing coefficient (m2/s)
596  real :: H_cutoff ! Local estimate of a minimum thickness for masking (m)
597  real :: h_neglect ! A thickness that is so small it is usually lost
598  ! in roundoff and can be neglected, in H.
599  real :: S2 ! Interface slope squared (non-dim)
600  real :: N2 ! Brunt-Vaisala frequency (1/s)
601  real :: Hup, Hdn ! Thickness from above, below (m or kg m-2)
602  real :: H_geom ! The geometric mean of Hup*Hdn, in m or kg m-2.
603  real :: one_meter ! One meter in thickness units of m or kg m-2.
604  integer :: is, ie, js, je, nz
605  integer :: i, j, k, kb_max
606  real :: SN_u_local(szib_(g), szj_(g),szk_(g))
607  real :: SN_v_local(szi_(g), szjb_(g),szk_(g))
608 
609  if (.not. ASSOCIATED(cs)) call mom_error(fatal, "calc_slope_function:"// &
610  "Module must be initialized before it is used.")
611  if (.not. cs%calculate_Eady_growth_rate) return
612  if (.not. ASSOCIATED(cs%SN_u)) call mom_error(fatal, "calc_slope_function:"// &
613  "%SN_u is not associated with use_variable_mixing.")
614  if (.not. ASSOCIATED(cs%SN_v)) call mom_error(fatal, "calc_slope_function:"// &
615  "%SN_v is not associated with use_variable_mixing.")
616 
617  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
618 
619  one_meter = 1.0 * gv%m_to_H
620  h_neglect = gv%H_subroundoff
621  h_cutoff = real(2*nz) * (gv%angstrom + h_neglect)
622 
623 !$OMP parallel default(none) shared(is,ie,js,je,CS,nz,e,G,GV,h,H_cutoff,h_neglect, &
624 !$OMP one_meter,SN_u_local,SN_v_local,calculate_slopes) &
625 !$OMP private(E_x,E_y,S2,Hdn,Hup,H_geom,N2)
626 !$OMP do
627  do j=js-1,je+1 ; do i=is-1,ie+1
628  cs%SN_u(i,j) = 0.0
629  cs%SN_v(i,j) = 0.0
630  enddo ; enddo
631 
632  ! To set the length scale based on the deformation radius, use wave_speed to
633  ! calculate the first-mode gravity wave speed and then blend the equatorial
634  ! and midlatitude deformation radii, using calc_resoln_function as a template.
635 
636 !$OMP do
637  do k=nz,cs%VarMix_Ktop,-1
638 
639  if (calculate_slopes) then
640  ! Calculate the interface slopes E_x and E_y and u- and v- points respectively
641  do j=js-1,je+1 ; do i=is-1,ie
642  e_x(i,j) = (e(i+1,j,k)-e(i,j,k))*g%IdxCu(i,j)
643  ! Mask slopes where interface intersects topography
644  if (min(h(i,j,k),h(i+1,j,k)) < h_cutoff) e_x(i,j) = 0.
645  enddo ; enddo
646  do j=js-1,je ; do i=is-1,ie+1
647  e_y(i,j) = (e(i,j+1,k)-e(i,j,k))*g%IdyCv(i,j)
648  ! Mask slopes where interface intersects topography
649  if (min(h(i,j,k),h(i,j+1,k)) < h_cutoff) e_y(i,j) = 0.
650  enddo ; enddo
651  else
652  do j=js-1,je+1 ; do i=is-1,ie
653  e_x(i,j) = cs%slope_x(i,j,k)
654  if (min(h(i,j,k),h(i+1,j,k)) < h_cutoff) e_x(i,j) = 0.
655  enddo ; enddo
656  do j=js-1,je ; do i=is-1,ie+1
657  e_y(i,j) = cs%slope_y(i,j,k)
658  if (min(h(i,j,k),h(i,j+1,k)) < h_cutoff) e_y(i,j) = 0.
659  enddo ; enddo
660  endif
661 
662  ! Calculate N*S*h from this layer and add to the sum
663  do j=js,je ; do i=is-1,ie
664  s2 = ( e_x(i,j)**2 + 0.25*( &
665  (e_y(i,j)**2+e_y(i+1,j-1)**2)+(e_y(i+1,j)**2+e_y(i,j-1)**2) ) )
666  hdn = 2.*h(i,j,k)*h(i,j,k-1) / (h(i,j,k) + h(i,j,k-1) + h_neglect)
667  hup = 2.*h(i+1,j,k)*h(i+1,j,k-1) / (h(i+1,j,k) + h(i+1,j,k-1) + h_neglect)
668  h_geom = sqrt(hdn*hup)
669  n2 = gv%g_prime(k) / (gv%H_to_m * max(hdn,hup,one_meter))
670  if (min(h(i,j,k-1), h(i+1,j,k-1), h(i,j,k), h(i+1,j,k)) < h_cutoff) &
671  s2 = 0.0
672  sn_u_local(i,j,k) = (h_geom * gv%H_to_m) * s2 * n2
673  enddo ; enddo
674  do j=js-1,je ; do i=is,ie
675  s2 = ( e_y(i,j)**2 + 0.25*( &
676  (e_x(i,j)**2+e_x(i-1,j+1)**2)+(e_x(i,j+1)**2+e_x(i-1,j)**2) ) )
677  hdn = 2.*h(i,j,k)*h(i,j,k-1) / (h(i,j,k) + h(i,j,k-1) + h_neglect)
678  hup = 2.*h(i,j+1,k)*h(i,j+1,k-1) / (h(i,j+1,k) + h(i,j+1,k-1) + h_neglect)
679  h_geom = sqrt(hdn*hup)
680  n2 = gv%g_prime(k) / (gv%H_to_m * max(hdn,hup,one_meter))
681  if (min(h(i,j,k-1), h(i,j+1,k-1), h(i,j,k), h(i,j+1,k)) < h_cutoff) &
682  s2 = 0.0
683  sn_v_local(i,j,k) = (h_geom * gv%H_to_m) * s2 * n2
684  enddo ; enddo
685 
686  enddo ! k
687 !$OMP do
688  do j = js,je;
689  do k=nz,cs%VarMix_Ktop,-1 ; do i=is-1,ie
690  cs%SN_u(i,j) = cs%SN_u(i,j) + sn_u_local(i,j,k)
691  enddo ; enddo
692  ! SN above contains S^2*N^2*H, convert to vertical average of S*N
693  do i=is-1,ie
694  !SN_u(I,j) = sqrt( SN_u(I,j) / ( max(G%bathyT(I,j), G%bathyT(I+1,j)) + GV%Angstrom ) )
695  !The code below behaves better than the line above. Not sure why? AJA
696  if ( min(g%bathyT(i,j), g%bathyT(i+1,j)) > h_cutoff ) then
697  cs%SN_u(i,j) = g%mask2dCu(i,j) * sqrt( cs%SN_u(i,j) / max(g%bathyT(i,j), g%bathyT(i+1,j)) )
698  else
699  cs%SN_u(i,j) = 0.0
700  endif
701  enddo
702  enddo
703 !$OMP do
704  do j=js-1,je
705  do k=nz,cs%VarMix_Ktop,-1 ; do i=is,ie
706  cs%SN_v(i,j) = cs%SN_v(i,j) + sn_v_local(i,j,k)
707  enddo ; enddo
708  do i=is,ie
709  !SN_v(i,J) = sqrt( SN_v(i,J) / ( max(G%bathyT(i,J), G%bathyT(i,J+1)) + GV%Angstrom ) )
710  !The code below behaves better than the line above. Not sure why? AJA
711  if ( min(g%bathyT(i,j), g%bathyT(i+1,j)) > h_cutoff ) then
712  cs%SN_v(i,j) = g%mask2dCv(i,j) * sqrt( cs%SN_v(i,j) / max(g%bathyT(i,j), g%bathyT(i,j+1)) )
713  else
714  cs%SN_v(i,j) = 0.0
715  endif
716  enddo
717  enddo
718 !$OMP end parallel
719 
721 
722 !> Initializes the variables mixing coefficients container
723 subroutine varmix_init(Time, G, param_file, diag, CS)
724  type(time_type), intent(in) :: Time !< Current model time
725  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
726  type(param_file_type), intent(in) :: param_file !< Parameter file handles
727  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure
728  type(varmix_cs), pointer :: CS !< Variable mixing coefficients
729  ! Local variables
730  real :: KhTr_Slope_Cff, KhTh_Slope_Cff, oneOrTwo, N2_filter_depth
731  real :: KhTr_passivity_coeff
732  real, parameter :: absurdly_small_freq2 = 1e-34 ! A miniscule frequency
733  ! squared that is used to avoid division by 0, in s-2. This
734  ! value is roughly (pi / (the age of the universe) )^2.
735  logical :: Gill_equatorial_Ld, use_FGNV_streamfn, use_MEKE, in_use
736  real :: MLE_front_length
737 ! This include declares and sets the variable "version".
738 #include "version_variable.h"
739  character(len=40) :: mdl = "MOM_lateral_mixing_coeffs" ! This module's name.
740  integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, i, j
741  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
742  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
743  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
744  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
745  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
746 
747  if (associated(cs)) then
748  call mom_error(warning, "VarMix_init called with an associated "// &
749  "control structure.")
750  return
751  endif
752 
753  allocate(cs)
754  in_use = .false. ! Set to true to avoid deallocating
755  cs%diag => diag ! Diagnostics pointer
756  cs%calculate_cg1 = .false.
757  cs%calculate_Rd_dx = .false.
758  cs%calculate_res_fns = .false.
759  cs%calculate_Eady_growth_rate = .false.
760 
761  ! Read all relevant parameters and write them to the model log.
762  call log_version(param_file, mdl, version, "")
763  call get_param(param_file, mdl, "USE_VARIABLE_MIXING", cs%use_variable_mixing,&
764  "If true, the variable mixing code will be called. This \n"//&
765  "allows diagnostics to be created even if the scheme is \n"//&
766  "not used. If KHTR_SLOPE_CFF>0 or KhTh_Slope_Cff>0, \n"//&
767  "this is set to true regardless of what is in the \n"//&
768  "parameter file.", default=.false.)
769  call get_param(param_file, mdl, "RESOLN_SCALED_KH", cs%Resoln_scaled_Kh, &
770  "If true, the Laplacian lateral viscosity is scaled away \n"//&
771  "when the first baroclinic deformation radius is well \n"//&
772  "resolved.", default=.false.)
773  call get_param(param_file, mdl, "RESOLN_SCALED_KHTH", cs%Resoln_scaled_KhTh, &
774  "If true, the interface depth diffusivity is scaled away \n"//&
775  "when the first baroclinic deformation radius is well \n"//&
776  "resolved.", default=.false.)
777  call get_param(param_file, mdl, "RESOLN_SCALED_KHTR", cs%Resoln_scaled_KhTr, &
778  "If true, the epipycnal tracer diffusivity is scaled \n"//&
779  "away when the first baroclinic deformation radius is \n"//&
780  "well resolved.", default=.false.)
781  call get_param(param_file, mdl, "RESOLN_USE_EBT", cs%Resoln_use_ebt, &
782  "If true, uses the equivalent barotropic wave speed instead\n"//&
783  "of first baroclinic wave for calculating the resolution fn.",&
784  default=.false.)
785  call get_param(param_file, mdl, "KHTH_USE_EBT_STRUCT", cs%khth_use_ebt_struct, &
786  "If true, uses the equivalent barotropic structure\n"//&
787  "as the vertical structure of thickness diffusivity.",&
788  default=.false.)
789  call get_param(param_file, mdl, "KHTH_SLOPE_CFF", khth_slope_cff, &
790  "The nondimensional coefficient in the Visbeck formula \n"//&
791  "for the interface depth diffusivity", units="nondim", &
792  default=0.0)
793  call get_param(param_file, mdl, "KHTR_SLOPE_CFF", khtr_slope_cff, &
794  "The nondimensional coefficient in the Visbeck formula \n"//&
795  "for the epipycnal tracer diffusivity", units="nondim", &
796  default=0.0)
797  call get_param(param_file, mdl, "USE_STORED_SLOPES", cs%use_stored_slopes,&
798  "If true, the isopycnal slopes are calculated once and\n"//&
799  "stored for re-use. This uses more memory but avoids calling\n"//&
800  "the equation of state more times than should be necessary.", &
801  default=.false.)
802  call get_param(param_file, mdl, "KHTH_USE_FGNV_STREAMFUNCTION", use_fgnv_streamfn, &
803  default=.false., do_not_log=.true.)
804  cs%calculate_cg1 = cs%calculate_cg1 .or. use_fgnv_streamfn
805  call get_param(param_file, mdl, "USE_MEKE", use_meke, &
806  default=.false., do_not_log=.true.)
807  cs%calculate_Eady_growth_rate = cs%calculate_Eady_growth_rate .or. use_meke
808  call get_param(param_file, mdl, "KHTR_PASSIVITY_COEFF", khtr_passivity_coeff, &
809  default=0., do_not_log=.true.)
810  cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (khtr_passivity_coeff>0.)
811  call get_param(param_file, mdl, "MLE_FRONT_LENGTH", mle_front_length, &
812  default=0., do_not_log=.true.)
813  cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (mle_front_length>0.)
814 
815  call get_param(param_file, mdl, "DEBUG", cs%debug, default=.false., do_not_log=.true.)
816 
817  if (cs%Resoln_use_ebt .or. cs%khth_use_ebt_struct) then
818  in_use = .true.
819  call get_param(param_file, mdl, "RESOLN_N2_FILTER_DEPTH", n2_filter_depth, &
820  "The depth below which N2 is monotonized to avoid stratification\n"//&
821  "artifacts from altering the equivalent barotropic mode structure.",&
822  units='m', default=2000.)
823  allocate(cs%ebt_struct(isd:ied,jsd:jed,g%ke)) ; cs%ebt_struct(:,:,:) = 0.0
824  endif
825 
826  if (khtr_slope_cff>0. .or. khth_slope_cff>0.) then
827  cs%calculate_Eady_growth_rate = .true.
828  call get_param(param_file, mdl, "VISBECK_MAX_SLOPE", cs%Visbeck_S_max, &
829  "If non-zero, is an upper bound on slopes used in the\n"// &
830  "Visbeck formula for diffusivity. This does not affect the\n"// &
831  "isopycnal slope calculation used within thickness diffusion.", &
832  units="nondim", default=0.0)
833  endif
834 
835  if (cs%use_stored_slopes) then
836  in_use = .true.
837  allocate(cs%slope_x(isdb:iedb,jsd:jed,g%ke+1)) ; cs%slope_x(:,:,:) = 0.0
838  allocate(cs%slope_y(isd:ied,jsdb:jedb,g%ke+1)) ; cs%slope_y(:,:,:) = 0.0
839  call get_param(param_file, mdl, "KD_SMOOTH", cs%kappa_smooth, &
840  "A diapycnal diffusivity that is used to interpolate \n"//&
841  "more sensible values of T & S into thin layers.", &
842  default=1.0e-6)
843  endif
844 
845  if (cs%calculate_Eady_growth_rate) then
846  in_use = .true.
847  allocate(cs%SN_u(isdb:iedb,jsd:jed)) ; cs%SN_u(:,:) = 0.0
848  allocate(cs%SN_v(isd:ied,jsdb:jedb)) ; cs%SN_v(:,:) = 0.0
849  cs%id_SN_u = register_diag_field('ocean_model', 'SN_u', diag%axesCu1, time, &
850  'Inverse eddy time-scale, S*N, at u-points', 's^-1')
851  cs%id_SN_v = register_diag_field('ocean_model', 'SN_v', diag%axesCv1, time, &
852  'Inverse eddy time-scale, S*N, at v-points', 's^-1')
853  call get_param(param_file, mdl, "VARMIX_KTOP", cs%VarMix_Ktop, &
854  "The layer number at which to start vertical integration \n"//&
855  "of S*N for purposes of finding the Eady growth rate.", &
856  units="nondim", default=2)
857  endif
858 
859  if (khtr_slope_cff>0. .or. khth_slope_cff>0.) then
860  in_use = .true.
861  call get_param(param_file, mdl, "VISBECK_L_SCALE", cs%Visbeck_L_scale, &
862  "The fixed length scale in the Visbeck formula.", units="m", &
863  default=0.0)
864  allocate(cs%L2u(isdb:iedb,jsd:jed)) ; cs%L2u(:,:) = cs%Visbeck_L_scale**2
865  allocate(cs%L2v(isd:ied,jsdb:jedb)) ; cs%L2v(:,:) = cs%Visbeck_L_scale**2
866 
867  cs%id_L2u = register_diag_field('ocean_model', 'L2u', diag%axesCu1, time, &
868  'Length scale squared for mixing coefficient, at u-points', 'm^2')
869  cs%id_L2v = register_diag_field('ocean_model', 'L2v', diag%axesCv1, time, &
870  'Length scale squared for mixing coefficient, at v-points', 'm^2')
871  endif
872 
873  if (cs%use_stored_slopes) then
874  cs%id_N2_u = register_diag_field('ocean_model', 'N2_u', diag%axesCui, time, &
875  'Square of Brunt-Vaisala frequency, N^2, at u-points, as used in Visbeck et al.', 's^-2')
876  cs%id_N2_v = register_diag_field('ocean_model', 'N2_v', diag%axesCvi, time, &
877  'Square of Brunt-Vaisala frequency, N^2, at v-points, as used in Visbeck et al.', 's^-2')
878  cs%id_S2_u = register_diag_field('ocean_model', 'S2_u', diag%axesCu1, time, &
879  'Depth average square of slope magnitude, S^2, at u-points, as used in Visbeck et al.', 's^-2')
880  cs%id_S2_v = register_diag_field('ocean_model', 'S2_v', diag%axesCv1, time, &
881  'Depth average square of slope magnitude, S^2, at v-points, as used in Visbeck et al.', 's^-2')
882  endif
883 
884  if (cs%Resoln_scaled_Kh .or. cs%Resoln_scaled_KhTh .or. cs%Resoln_scaled_KhTr) then
885  cs%calculate_Rd_dx = .true.
886  cs%calculate_res_fns = .true.
887  allocate(cs%Res_fn_h(isd:ied,jsd:jed)) ; cs%Res_fn_h(:,:) = 0.0
888  allocate(cs%Res_fn_q(isdb:iedb,jsdb:jedb)) ; cs%Res_fn_q(:,:) = 0.0
889  allocate(cs%Res_fn_u(isdb:iedb,jsd:jed)) ; cs%Res_fn_u(:,:) = 0.0
890  allocate(cs%Res_fn_v(isd:ied,jsdb:jedb)) ; cs%Res_fn_v(:,:) = 0.0
891  allocate(cs%beta_dx2_q(isdb:iedb,jsdb:jedb)) ; cs%beta_dx2_q(:,:) = 0.0
892  allocate(cs%beta_dx2_u(isdb:iedb,jsd:jed)) ; cs%beta_dx2_u(:,:) = 0.0
893  allocate(cs%beta_dx2_v(isd:ied,jsdb:jedb)) ; cs%beta_dx2_v(:,:) = 0.0
894  allocate(cs%f2_dx2_q(isdb:iedb,jsdb:jedb)) ; cs%f2_dx2_q(:,:) = 0.0
895  allocate(cs%f2_dx2_u(isdb:iedb,jsd:jed)) ; cs%f2_dx2_u(:,:) = 0.0
896  allocate(cs%f2_dx2_v(isd:ied,jsdb:jedb)) ; cs%f2_dx2_v(:,:) = 0.0
897 
898  cs%id_Res_fn = register_diag_field('ocean_model', 'Res_fn', diag%axesT1, time, &
899  'Resolution function for scaling diffusivities', 'Nondim')
900 
901  call get_param(param_file, mdl, "KH_RES_SCALE_COEF", cs%Res_coef_khth, &
902  "A coefficient that determines how KhTh is scaled away if \n"//&
903  "RESOLN_SCALED_... is true, as \n"//&
904  "F = 1 / (1 + (KH_RES_SCALE_COEF*Rd/dx)^KH_RES_FN_POWER).", &
905  units="nondim", default=1.0)
906  call get_param(param_file, mdl, "KH_RES_FN_POWER", cs%Res_fn_power_khth, &
907  "The power of dx/Ld in the Kh resolution function. Any \n"//&
908  "positive integer may be used, although even integers \n"//&
909  "are more efficient to calculate. Setting this greater \n"//&
910  "than 100 results in a step-function being used.", &
911  units="nondim", default=2)
912  call get_param(param_file, mdl, "VISC_RES_SCALE_COEF", cs%Res_coef_visc, &
913  "A coefficient that determines how Kh is scaled away if \n"//&
914  "RESOLN_SCALED_... is true, as \n"//&
915  "F = 1 / (1 + (KH_RES_SCALE_COEF*Rd/dx)^KH_RES_FN_POWER).\n"//&
916  "This function affects lateral viscosity, Kh, and not KhTh.", &
917  units="nondim", default=cs%Res_coef_khth)
918  call get_param(param_file, mdl, "VISC_RES_FN_POWER", cs%Res_fn_power_visc, &
919  "The power of dx/Ld in the Kh resolution function. Any \n"//&
920  "positive integer may be used, although even integers \n"//&
921  "are more efficient to calculate. Setting this greater \n"//&
922  "than 100 results in a step-function being used.\n"//&
923  "This function affects lateral viscosity, Kh, and not KhTh.", &
924  units="nondim", default=cs%Res_fn_power_khth)
925  call get_param(param_file, mdl, "INTERPOLATE_RES_FN", cs%interpolate_Res_fn, &
926  "If true, interpolate the resolution function to the \n"//&
927  "velocity points from the thickness points; otherwise \n"//&
928  "interpolate the wave speed and calculate the resolution \n"//&
929  "function independently at each point.", default=.true.)
930  call get_param(param_file, mdl, "USE_VISBECK_SLOPE_BUG", cs%use_Visbeck_slope_bug, &
931  "If true, then retain a legacy bug in the calculation of weights \n"//&
932  "applied to isoneutral slopes. There was an erroneous k-indexing \n"//&
933  "for layer thicknesses. In addition, masking at coastlines was not \n"//&
934  "used which introduced potential restart issues. This flag will be \n"//&
935  "deprecated in a future release.", default=.false.)
936  if (cs%interpolate_Res_fn) then
937  if (cs%Res_coef_visc .ne. cs%Res_coef_khth) call mom_error(fatal, &
938  "MOM_lateral_mixing_coeffs.F90, VarMix_init:"//&
939  "When INTERPOLATE_RES_FN=True, VISC_RES_FN_POWER must equal KH_RES_SCALE_COEF.")
940  if (cs%Res_fn_power_visc .ne. cs%Res_fn_power_khth) call mom_error(fatal, &
941  "MOM_lateral_mixing_coeffs.F90, VarMix_init:"//&
942  "When INTERPOLATE_RES_FN=True, VISC_RES_FN_POWER must equal KH_RES_FN_POWER.")
943  endif
944  call get_param(param_file, mdl, "GILL_EQUATORIAL_LD", gill_equatorial_ld, &
945  "If true, uses Gill's definition of the baroclinic\n"//&
946  "equatorial deformation radius, otherwise, if false, use\n"//&
947  "Pedlosky's definition. These definitions differ by a factor\n"//&
948  "of 2 infront of the beta term in the denominator. Gill's"//&
949  "is the more appropriate definition.\n", default=.false.)
950  if (gill_equatorial_ld) then
951  oneortwo = 2.0
952  else
953  oneortwo = 1.0
954  endif
955 
956  do j=js-1,jeq ; do i=is-1,ieq
957  cs%f2_dx2_q(i,j) = (g%dxBu(i,j)**2 + g%dyBu(i,j)**2) * &
958  max(g%CoriolisBu(i,j)**2, absurdly_small_freq2)
959  cs%beta_dx2_q(i,j) = oneortwo * (g%dxBu(i,j)**2 + g%dyBu(i,j)**2) * (sqrt(0.5 * &
960  ( (((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
961  ((g%CoriolisBu(i+1,j)-g%CoriolisBu(i,j)) * g%IdxCv(i+1,j))**2) + &
962  (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
963  ((g%CoriolisBu(i,j+1)-g%CoriolisBu(i,j)) * g%IdyCu(i,j+1))**2) ) ))
964  enddo ; enddo
965 
966  do j=js,je ; do i=is-1,ieq
967  cs%f2_dx2_u(i,j) = (g%dxCu(i,j)**2 + g%dyCu(i,j)**2) * &
968  max(0.5*(g%CoriolisBu(i,j)**2+g%CoriolisBu(i,j-1)**2), absurdly_small_freq2)
969  cs%beta_dx2_u(i,j) = oneortwo * (g%dxCu(i,j)**2 + g%dyCu(i,j)**2) * (sqrt( &
970  0.25*( (((g%CoriolisBu(i,j-1)-g%CoriolisBu(i-1,j-1)) * g%IdxCv(i,j-1))**2 + &
971  ((g%CoriolisBu(i+1,j)-g%CoriolisBu(i,j)) * g%IdxCv(i+1,j))**2) + &
972  (((g%CoriolisBu(i+1,j-1)-g%CoriolisBu(i,j-1)) * g%IdxCv(i+1,j-1))**2 + &
973  ((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2) ) + &
974  ((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 ))
975  enddo ; enddo
976 
977  do j=js-1,jeq ; do i=is,ie
978  cs%f2_dx2_v(i,j) = (g%dxCv(i,j)**2 + g%dyCv(i,j)**2) * &
979  max(0.5*(g%CoriolisBu(i,j)**2+g%CoriolisBu(i-1,j)**2), absurdly_small_freq2)
980  cs%beta_dx2_v(i,j) = oneortwo * (g%dxCv(i,j)**2 + g%dyCv(i,j)**2) * (sqrt( &
981  ((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
982  0.25*( (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
983  ((g%CoriolisBu(i-1,j+1)-g%CoriolisBu(i-1,j)) * g%IdyCu(i-1,j+1))**2) + &
984  (((g%CoriolisBu(i,j+1)-g%CoriolisBu(i,j)) * g%IdyCu(i,j+1))**2 + &
985  ((g%CoriolisBu(i-1,j)-g%CoriolisBu(i-1,j-1)) * g%IdyCu(i-1,j))**2) ) ))
986  enddo ; enddo
987 
988  endif
989 
990  ! Resolution %Rd_dx_h
991  cs%id_Rd_dx = register_diag_field('ocean_model', 'Rd_dx', diag%axesT1, time, &
992  'Ratio between deformation radius and grid spacing', 'Nondim')
993  cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (cs%id_Rd_dx>0)
994 
995  if (cs%calculate_Rd_dx) then
996  cs%calculate_cg1 = .true. ! We will need %cg1
997  allocate(cs%Rd_dx_h(isd:ied,jsd:jed)) ; cs%Rd_dx_h(:,:) = 0.0
998  allocate(cs%beta_dx2_h(isd:ied,jsd:jed)); cs%beta_dx2_h(:,:) = 0.0
999  allocate(cs%f2_dx2_h(isd:ied,jsd:jed)) ; cs%f2_dx2_h(:,:) = 0.0
1000  do j=js-1,je+1 ; do i=is-1,ie+1
1001  cs%f2_dx2_h(i,j) = (g%dxT(i,j)**2 + g%dyT(i,j)**2) * &
1002  max(0.25 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1003  (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2)), &
1004  absurdly_small_freq2)
1005  cs%beta_dx2_h(i,j) = oneortwo * (g%dxT(i,j)**2 + g%dyT(i,j)**2) * (sqrt(0.5 * &
1006  ( (((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
1007  ((g%CoriolisBu(i,j-1)-g%CoriolisBu(i-1,j-1)) * g%IdxCv(i,j-1))**2) + &
1008  (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
1009  ((g%CoriolisBu(i-1,j)-g%CoriolisBu(i-1,j-1)) * g%IdyCu(i-1,j))**2) ) ))
1010  enddo ; enddo
1011  endif
1012 
1013  if (cs%calculate_cg1) then
1014  in_use = .true.
1015  allocate(cs%cg1(isd:ied,jsd:jed)); cs%cg1(:,:) = 0.0
1016  call wave_speed_init(cs%wave_speed_CSp, use_ebt_mode=cs%Resoln_use_ebt, mono_n2_depth=n2_filter_depth)
1017  endif
1018 
1019  ! If nothing is being stored in this class then deallocate
1020  if (in_use) then
1021  cs%use_variable_mixing = .true.
1022  else
1023  deallocate(cs)
1024  return
1025  endif
1026 
1027 end subroutine varmix_init
1028 
1029 !> \namespace mom_lateral_mixing_coeffs
1030 !!
1031 !! This module provides a container for various factors used in prescribing diffusivities, that are
1032 !! a function of the state (in particular the stratification and isoneutral slopes).
1033 !!
1034 !! \section section_Resolution_Function The resolution function
1035 !!
1036 !! The resolution function is expressed in terms of the ratio of grid-spacing to deformation radius.
1037 !! The square of the resolution parameter is
1038 !!
1039 !! \f[
1040 !! R^2 = \frac{L_d^2}{\Delta^2} = \frac{ c_g^2 }{ f^2 \Delta^2 + c_g \beta \Delta^2 }
1041 !! \f]
1042 !!
1043 !! where the grid spacing is calculated as
1044 !!
1045 !! \f[
1046 !! \Delta^2 = \Delta x^2 + \Delta y^2 .
1047 !! \f]
1048 !!
1049 !! \todo Check this reference to Bob on/off paper.
1050 !! The resolution function used in scaling diffusivities (Hallberg, 2010) is
1051 !!
1052 !! \f[
1053 !! r(\Delta,L_d) = \frac{1}{1+(\alpha R)^p}
1054 !! \f]
1055 !!
1056 !! The resolution function can be applied independently to thickness diffusion (module mom_thickness_diffuse), tracer diffusion (mom_tracer_hordiff)
1057 !! lateral viscosity (mom_hor_visc).
1058 !!
1059 !! Robert Hallberg, 2013: Using a resolution function to regulate parameterizations of oceanic mesoscale eddy effects.
1060 !! Ocean Modelling, 71, pp 92-103. http://dx.doi.org/10.1016/j.ocemod.2013.08.007
1061 !!
1062 !! | Symbol | Module parameter |
1063 !! | ------ | --------------- |
1064 !! | - | <code>USE_VARIABLE_MIXING</code> |
1065 !! | - | <code>RESOLN_SCALED_KH</code> |
1066 !! | - | <code>RESOLN_SCALED_KHTH</code> |
1067 !! | - | <code>RESOLN_SCALED_KHTR</code> |
1068 !! | \f$ \alpha \f$ | <code>KH_RES_SCALE_COEF</code> (for thickness and tracer diffusivity) |
1069 !! | \f$ p \f$ | <code>KH_RES_FN_POWER</code> (for thickness and tracer diffusivity) |
1070 !! | \f$ \alpha \f$ | <code>VISC_RES_SCALE_COEF</code> (for lateral viscosity) |
1071 !! | \f$ p \f$ | <code>VISC_RES_FN_POWER</code> (for lateral viscosity) |
1072 !! | - | <code>GILL_EQUATORIAL_LD</code> |
1073 !!
1074 !!
1075 !!
1076 !! \section section_Vicbeck Visbeck diffusivity
1077 !!
1078 !! This module also calculates factors used in setting the thickness diffusivity similar to a Visbeck et al., 1997, scheme.
1079 !! The factors are combined in mom_thickness_diffuse::thickness_diffuse() but calculated in this module.
1080 !!
1081 !! \f[
1082 !! \kappa_h = \alpha_s L_s^2 S N
1083 !! \f]
1084 !!
1085 !! where \f$S\f$ is the magnitude of the isoneutral slope and \f$N\f$ is the Brunt-Vaisala frequency.
1086 !!
1087 !! Visbeck, Marshall, Haine and Spall, 1997: Specification of Eddy Transfer Coefficients in Coarse-Resolution
1088 !! Ocean Circulation Models. J. Phys. Oceanogr. http://dx.doi.org/10.1175/1520-0485(1997)027%3C0381:SOETCI%3E2.0.CO;2
1089 !!
1090 !! | Symbol | Module parameter |
1091 !! | ------ | --------------- |
1092 !! | - | <code>USE_VARIABLE_MIXING</code> |
1093 !! | \f$ \alpha_s \f$ | <code>KHTH_SLOPE_CFF</code> (for mom_thickness_diffuse module)|
1094 !! | \f$ \alpha_s \f$ | <code>KHTR_SLOPE_CFF</code> (for mom_tracer_hordiff module)|
1095 !! | \f$ L_{s} \f$ | <code>VISBECK_L_SCALE</code> |
1096 !! | \f$ S_{max} \f$ | <code>VISBECK_MAX_SLOPE</code> |
1097 !!
1098 !!
1099 !! \section section_vertical_structure_khth Vertical structure function for KhTh
1100 !!
1101 !! The thickness diffusivity can be prescribed a vertical distribution with the shape of the equivalent barotropic velocity mode.
1102 !! The structure function is stored in the control structure for thie module (varmix_cs) but is calculated use subroutines in
1103 !! mom_wave_speed.
1104 !!
1105 !! | Symbol | Module parameter |
1106 !! | ------ | --------------- |
1107 !! | - | <code>KHTH_USE_EBT_STRUCT</code> |
1108 
1109 end module mom_lateral_mixing_coeffs
Control structure for MOM_wave_speed.
subroutine calc_slope_functions_using_just_e(h, G, GV, CS, e, calculate_slopes)
The original calc_slope_function() that calculated slopes using interface positions only...
subroutine, public wave_speed_init(CS, use_ebt_mode, mono_N2_column_fraction, mono_N2_depth)
Initialize control structure for MOM_wave_speed.
The module calculates interface heights, including free surface height.
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Provides the ocean grid type.
Definition: MOM_grid.F90:2
subroutine, public do_group_pass(group, MOM_dom)
Routines for calculating baroclinic wave speeds.
subroutine calc_visbeck_coeffs(h, e, slope_x, slope_y, N2_u, N2_v, G, GV, CS)
Calculates factors used when setting diffusivity coefficients similar to Visbeck et al...
subroutine, public calc_isoneutral_slopes(G, GV, h, e, tv, dt_kappa_smooth, slope_x, slope_y, N2_u, N2_v, halo)
Variable mixing coefficients.
subroutine, public varmix_init(Time, G, param_file, diag, CS)
Initializes the variables mixing coefficients container.
logical function, public query_averaging_enabled(diag_cs, time_int, time_end)
subroutine, public calc_resoln_function(h, tv, G, GV, CS)
Calculates and stores the non-dimensional resolution functions.
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 ...
subroutine, public mom_mesg(message, verb, all_print)
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine, public wave_speed(h, tv, G, GV, cg1, CS, full_halos, use_ebt_mode, mono_N2_column_fraction, mono_N2_depth, modal_structure)
Calculates the wave speed of the first baroclinic mode.
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)
Calculations of isoneutral slopes and stratification.