MOM6
MOM_kappa_shear.F90
1 !> Shear-dependent mixing following Jackson et al. 2008.
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
7 use mom_cpu_clock, only : clock_module_driver, clock_module, clock_routine
8 use mom_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr
9 use mom_diag_mediator, only : diag_ctrl, time_type
10 use mom_debugging, only : hchksum, bchksum
11 use mom_error_handler, only : mom_error, is_root_pe, fatal, warning, note
13 use mom_grid, only : ocean_grid_type
18 
19 implicit none ; private
20 
21 #include <MOM_memory.h>
22 #ifdef use_netCDF
23 #include <netcdf.inc>
24 #endif
25 
26 public calculate_kappa_shear, calc_kappa_shear_vertex, kappa_shear_init
27 public kappa_shear_is_used, kappa_shear_at_vertex
28 
29 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
30 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
31 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
32 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
33 
34 !> This control structure holds the parameters that regulate shear mixing
35 type, public :: kappa_shear_cs ; private
36  real :: rino_crit !< The critical shear Richardson number for
37  !! shear-entrainment. The theoretical value is 0.25.
38  !! The values found by Jackson et al. are 0.25-0.35.
39  real :: shearmix_rate !< A nondimensional rate scale for shear-driven
40  !! entrainment. The value given by Jackson et al.
41  !! is 0.085-0.089.
42  real :: fri_curvature !< A constant giving the curvature of the function
43  !! of the Richardson number that relates shear to
44  !! sources in the kappa equation [nondim].
45  !! The values found by Jackson et al. are -0.97 - -0.89.
46  real :: c_n !< The coefficient for the decay of TKE due to
47  !! stratification (i.e. proportional to N*tke) [nondim].
48  !! The values found by Jackson et al. are 0.24-0.28.
49  real :: c_s !< The coefficient for the decay of TKE due to
50  !! shear (i.e. proportional to |S|*tke) [nondim].
51  !! The values found by Jackson et al. are 0.14-0.12.
52  real :: lambda !< The coefficient for the buoyancy length scale
53  !! in the kappa equation. Nondimensional.
54  !! The values found by Jackson et al. are 0.82-0.81.
55  real :: lambda2_n_s !< The square of the ratio of the coefficients of
56  !! the buoyancy and shear scales in the diffusivity
57  !! equation, 0 to eliminate the shear scale. Nondim.
58  real :: tke_bg !< The background level of TKE [Z2 T-2 ~> m2 s-2].
59  real :: kappa_0 !< The background diapycnal diffusivity [Z2 T-1 ~> m2 s-1].
60  real :: kappa_tol_err !< The fractional error in kappa that is tolerated.
61  real :: prandtl_turb !< Prandtl number used to convert Kd_shear into viscosity.
62  integer :: nkml !< The number of layers in the mixed layer, as
63  !! treated in this routine. If the pieces of the
64  !! mixed layer are not to be treated collectively,
65  !! nkml is set to 1.
66  integer :: max_rino_it !< The maximum number of iterations that may be used
67  !! to estimate the instantaneous shear-driven mixing.
68  integer :: max_ks_it !< The maximum number of iterations that may be used
69  !! to estimate the time-averaged diffusivity.
70  logical :: ks_at_vertex !< If true, do the calculations of the shear-driven mixing
71  !! at the cell vertices (i.e., the vorticity points).
72  logical :: eliminate_massless !< If true, massless layers are merged with neighboring
73  !! massive layers in this calculation.
74  ! I can think of no good reason why this should be false. - RWH
75  real :: vel_underflow !< Velocity components smaller than vel_underflow
76  !! are set to 0 [Z T-1 ~> m s-1].
77 ! logical :: layer_stagger = .false. ! If true, do the calculations centered at
78  ! layers, rather than the interfaces.
79  logical :: debug = .false. !< If true, write verbose debugging messages.
80  type(diag_ctrl), pointer :: diag => null() !< A structure that is used to
81  !! regulate the timing of diagnostic output.
82  !>@{ Diagnostic IDs
83  integer :: id_kd_shear = -1, id_tke = -1, id_ild2 = -1, id_dz_int = -1
84  !!@}
85 end type kappa_shear_cs
86 
87 ! integer :: id_clock_project, id_clock_KQ, id_clock_avg, id_clock_setup
88 
89 #undef DEBUG
90 #undef ADD_DIAGNOSTICS
91 
92 contains
93 
94 !> Subroutine for calculating shear-driven diffusivity and TKE in tracer columns
95 subroutine calculate_kappa_shear(u_in, v_in, h, tv, p_surf, kappa_io, tke_io, &
96  kv_io, dt, G, GV, US, CS, initialize_all)
97  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
98  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
99  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
100  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
101  intent(in) :: u_in !< Initial zonal velocity [m s-1]. (Intent in)
102  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
103  intent(in) :: v_in !< Initial meridional velocity [m s-1].
104  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
105  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2].
106  type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers to any
107  !! available thermodynamic fields. Absent fields
108  !! have NULL ptrs.
109  real, dimension(:,:), pointer :: p_surf !< The pressure at the ocean surface [Pa] (or NULL).
110  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
111  intent(inout) :: kappa_io !< The diapycnal diffusivity at each interface
112  !! (not layer!) [Z2 T-1 ~> m2 s-1]. Initially this is the
113  !! value from the previous timestep, which may
114  !! accelerate the iteration toward convergence.
115  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
116  intent(out) :: tke_io !< The turbulent kinetic energy per unit mass at
117  !! each interface (not layer!) [Z2 T-2 ~> m2 s-2].
118  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
119  intent(inout) :: kv_io !< The vertical viscosity at each interface
120  !! (not layer!) [Z2 T-1 ~> m2 s-1]. This discards any
121  !! previous value (i.e. it is intent out) and
122  !! simply sets Kv = Prandtl * Kd_shear
123  real, intent(in) :: dt !< Time increment [T ~> s].
124  type(kappa_shear_cs), pointer :: cs !< The control structure returned by a previous
125  !! call to kappa_shear_init.
126  logical, optional, intent(in) :: initialize_all !< If present and false, the previous
127  !! value of kappa is used to start the iterations
128 
129  ! Local variables
130  real, dimension(SZI_(G),SZK_(GV)) :: &
131  h_2d, & ! A 2-D version of h, but converted to [Z ~> m].
132  u_2d, v_2d, & ! 2-D versions of u_in and v_in, converted to [L T-1 ~> m s-1].
133  t_2d, s_2d, rho_2d ! 2-D versions of T, S, and rho.
134  real, dimension(SZI_(G),SZK_(GV)+1) :: &
135  kappa_2d, & ! 2-D version of kappa_io [Z2 T-1 ~> m2 s-1].
136  tke_2d ! 2-D version tke_io [Z2 T-2 ~> m2 s-2].
137  real, dimension(SZK_(GV)) :: &
138  idz, & ! The inverse of the distance between TKE points [Z-1 ~> m-1].
139  dz, & ! The layer thickness [Z ~> m].
140  u0xdz, & ! The initial zonal velocity times dz [Z L T-1 ~> m2 s-1].
141  v0xdz, & ! The initial meridional velocity times dz [Z L T-1 ~> m2 s-1].
142  t0xdz, & ! The initial temperature times dz [degC Z ~> degC m].
143  s0xdz ! The initial salinity times dz [ppt Z ~> ppt m].
144  real, dimension(SZK_(GV)+1) :: &
145  kappa, & ! The shear-driven diapycnal diffusivity at an interface [Z2 T-1 ~> m2 s-1].
146  tke, & ! The Turbulent Kinetic Energy per unit mass at an interface [Z2 T-2 ~> m2 s-2].
147  kappa_avg, & ! The time-weighted average of kappa [Z2 T-1 ~> m2 s-1].
148  tke_avg ! The time-weighted average of TKE [Z2 T-2 ~> m2 s-2].
149  real :: f2 ! The squared Coriolis parameter of each column [T-2 ~> s-2].
150  real :: surface_pres ! The top surface pressure [Pa].
151 
152  real :: dz_in_lay ! The running sum of the thickness in a layer [Z ~> m].
153  real :: k0dt ! The background diffusivity times the timestep [Z2 ~> m2].
154  real :: dz_massless ! A layer thickness that is considered massless [Z ~> m].
155  logical :: use_temperature ! If true, temperature and salinity have been
156  ! allocated and are being used as state variables.
157  logical :: new_kappa = .true. ! If true, ignore the value of kappa from the
158  ! last call to this subroutine.
159 
160  integer, dimension(SZK_(GV)+1) :: kc ! The index map between the original
161  ! interfaces and the interfaces with massless layers
162  ! merged into nearby massive layers.
163  real, dimension(SZK_(GV)+1) :: kf ! The fractional weight of interface kc+1 for
164  ! interpolating back to the original index space [nondim].
165  integer :: is, ie, js, je, i, j, k, nz, nzc
166 
167  ! Diagnostics that should be deleted?
168 #ifdef ADD_DIAGNOSTICS
169  real, dimension(SZK_(GV)+1) :: & ! Additional diagnostics.
170  i_ld2_1d, dz_int_1d
171  real, dimension(SZI_(G),SZK_(GV)+1) :: & ! 2-D versions of diagnostics.
172  i_ld2_2d, dz_int_2d
173  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: & ! 3-D versions of diagnostics.
174  i_ld2_3d, dz_int_3d
175 #endif
176  is = g%isc ; ie = g%iec; js = g%jsc ; je = g%jec ; nz = gv%ke
177 
178  use_temperature = .false. ; if (associated(tv%T)) use_temperature = .true.
179  new_kappa = .true. ; if (present(initialize_all)) new_kappa = initialize_all
180 
181  k0dt = dt*cs%kappa_0
182  dz_massless = 0.1*sqrt(k0dt)
183 
184  !$OMP parallel do default(private) shared(js,je,is,ie,nz,h,u_in,v_in,use_temperature,new_kappa, &
185 #ifdef ADD_DIAGNOSTICS
186  !$OMP I_Ld2_3d,dz_Int_3d, &
187 #endif
188  !$OMP tv,G,GV,US,CS,kappa_io,dz_massless,k0dt,p_surf,dt,tke_io,kv_io)
189  do j=js,je
190  do k=1,nz ; do i=is,ie
191  h_2d(i,k) = h(i,j,k)*gv%H_to_Z
192  u_2d(i,k) = u_in(i,j,k)*us%m_s_to_L_T ; v_2d(i,k) = v_in(i,j,k)*us%m_s_to_L_T
193  enddo ; enddo
194  if (use_temperature) then ; do k=1,nz ; do i=is,ie
195  t_2d(i,k) = tv%T(i,j,k) ; s_2d(i,k) = tv%S(i,j,k)
196  enddo ; enddo ; else ; do k=1,nz ; do i=is,ie
197  rho_2d(i,k) = gv%Rlay(k) ! Could be tv%Rho(i,j,k) ?
198  enddo ; enddo ; endif
199  if (.not.new_kappa) then ; do k=1,nz+1 ; do i=is,ie
200  kappa_2d(i,k) = kappa_io(i,j,k)
201  enddo ; enddo ; endif
202 
203 !---------------------------------------
204 ! Work on each column.
205 !---------------------------------------
206  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
207  ! call cpu_clock_begin(id_clock_setup)
208  ! Store a transposed version of the initial arrays.
209  ! Any elimination of massless layers would occur here.
210  if (cs%eliminate_massless) then
211  nzc = 1
212  do k=1,nz
213  ! Zero out the thicknesses of all layers, even if they are unused.
214  dz(k) = 0.0 ; u0xdz(k) = 0.0 ; v0xdz(k) = 0.0
215  t0xdz(k) = 0.0 ; s0xdz(k) = 0.0
216 
217  ! Add a new layer if this one has mass.
218 ! if ((dz(nzc) > 0.0) .and. (h_2d(i,k) > dz_massless)) nzc = nzc+1
219  if ((k>cs%nkml) .and. (dz(nzc) > 0.0) .and. &
220  (h_2d(i,k) > dz_massless)) nzc = nzc+1
221 
222  ! Only merge clusters of massless layers.
223 ! if ((dz(nzc) > dz_massless) .or. &
224 ! ((dz(nzc) > 0.0) .and. (h_2d(i,k) > dz_massless))) nzc = nzc+1
225 
226  kc(k) = nzc
227  dz(nzc) = dz(nzc) + h_2d(i,k)
228  u0xdz(nzc) = u0xdz(nzc) + u_2d(i,k)*h_2d(i,k)
229  v0xdz(nzc) = v0xdz(nzc) + v_2d(i,k)*h_2d(i,k)
230  if (use_temperature) then
231  t0xdz(nzc) = t0xdz(nzc) + t_2d(i,k)*h_2d(i,k)
232  s0xdz(nzc) = s0xdz(nzc) + s_2d(i,k)*h_2d(i,k)
233  else
234  t0xdz(nzc) = t0xdz(nzc) + rho_2d(i,k)*h_2d(i,k)
235  s0xdz(nzc) = s0xdz(nzc) + rho_2d(i,k)*h_2d(i,k)
236  endif
237  enddo
238  kc(nz+1) = nzc+1
239 
240  ! Set up Idz as the inverse of layer thicknesses.
241  do k=1,nzc ; idz(k) = 1.0 / dz(k) ; enddo
242 
243  ! Now determine kf, the fractional weight of interface kc when
244  ! interpolating between interfaces kc and kc+1.
245  kf(1) = 0.0 ; dz_in_lay = h_2d(i,1)
246  do k=2,nz
247  if (kc(k) > kc(k-1)) then
248  kf(k) = 0.0 ; dz_in_lay = h_2d(i,k)
249  else
250  kf(k) = dz_in_lay*idz(kc(k)) ; dz_in_lay = dz_in_lay + h_2d(i,k)
251  endif
252  enddo
253  kf(nz+1) = 0.0
254  else
255  do k=1,nz
256  dz(k) = h_2d(i,k)
257  u0xdz(k) = u_2d(i,k)*dz(k) ; v0xdz(k) = v_2d(i,k)*dz(k)
258  enddo
259  if (use_temperature) then
260  do k=1,nz
261  t0xdz(k) = t_2d(i,k)*dz(k) ; s0xdz(k) = s_2d(i,k)*dz(k)
262  enddo
263  else
264  do k=1,nz
265  t0xdz(k) = rho_2d(i,k)*dz(k) ; s0xdz(k) = rho_2d(i,k)*dz(k)
266  enddo
267  endif
268  nzc = nz
269  do k=1,nzc+1 ; kc(k) = k ; kf(k) = 0.0 ; enddo
270  endif
271  f2 = 0.25 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
272  (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
273  surface_pres = 0.0 ; if (associated(p_surf)) surface_pres = p_surf(i,j)
274 
275  ! ---------------------------------------------------- I_Ld2_1d, dz_Int_1d
276 
277  ! Set the initial guess for kappa, here defined at interfaces.
278  ! ----------------------------------------------------
279  if (new_kappa) then
280  do k=1,nzc+1 ; kappa(k) = us%m2_s_to_Z2_T*1.0 ; enddo
281  else
282  do k=1,nzc+1 ; kappa(k) = kappa_2d(i,k) ; enddo
283  endif
284 
285 #ifdef ADD_DIAGNOSTICS
286  call kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, &
287  dz, u0xdz, v0xdz, t0xdz, s0xdz, kappa_avg, &
288  tke_avg, tv, cs, gv, us, i_ld2_1d, dz_int_1d)
289 #else
290  call kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, &
291  dz, u0xdz, v0xdz, t0xdz, s0xdz, kappa_avg, &
292  tke_avg, tv, cs, gv, us)
293 #endif
294 
295  ! call cpu_clock_begin(id_clock_setup)
296  ! Extrapolate from the vertically reduced grid back to the original layers.
297  if (nz == nzc) then
298  do k=1,nz+1
299  kappa_2d(i,k) = kappa_avg(k)
300  !### Should this be tke_avg?
301  tke_2d(i,k) = tke(k)
302  enddo
303  else
304  do k=1,nz+1
305  if (kf(k) == 0.0) then
306  kappa_2d(i,k) = kappa_avg(kc(k))
307  tke_2d(i,k) = tke_avg(kc(k))
308  else
309  kappa_2d(i,k) = (1.0-kf(k)) * kappa_avg(kc(k)) + &
310  kf(k) * kappa_avg(kc(k)+1)
311  tke_2d(i,k) = (1.0-kf(k)) * tke_avg(kc(k)) + &
312  kf(k) * tke_avg(kc(k)+1)
313  endif
314  enddo
315  endif
316 #ifdef ADD_DIAGNOSTICS
317  do k=1,nz+1
318  i_ld2_2d(i,k) = i_ld2_1d(k) ; dz_int_2d(i,k) = dz_int_1d(k)
319  enddo
320 #endif
321  ! call cpu_clock_end(id_clock_setup)
322  else ! Land points, still inside the i-loop.
323  do k=1,nz+1
324  kappa_2d(i,k) = 0.0 ; tke_2d(i,k) = 0.0
325 #ifdef ADD_DIAGNOSTICS
326  i_ld2_2d(i,k) = 0.0 ; dz_int_2d(i,k) = 0.0
327 #endif
328  enddo
329  endif ; enddo ! i-loop
330 
331  do k=1,nz+1 ; do i=is,ie
332  kappa_io(i,j,k) = g%mask2dT(i,j) * kappa_2d(i,k)
333  tke_io(i,j,k) = g%mask2dT(i,j) * tke_2d(i,k)
334  kv_io(i,j,k) = ( g%mask2dT(i,j) * kappa_2d(i,k) ) * cs%Prandtl_turb
335 #ifdef ADD_DIAGNOSTICS
336  i_ld2_3d(i,j,k) = i_ld2_2d(i,k) ; dz_int_3d(i,j,k) = dz_int_2d(i,k)
337 #endif
338  enddo ; enddo
339 
340  enddo ! end of j-loop
341 
342  if (cs%debug) then
343  call hchksum(kappa_io, "kappa", g%HI, scale=us%Z2_T_to_m2_s)
344  call hchksum(tke_io, "tke", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
345  endif
346 
347  if (cs%id_Kd_shear > 0) call post_data(cs%id_Kd_shear, kappa_io, cs%diag)
348  if (cs%id_TKE > 0) call post_data(cs%id_TKE, tke_io, cs%diag)
349 #ifdef ADD_DIAGNOSTICS
350  if (cs%id_ILd2 > 0) call post_data(cs%id_ILd2, i_ld2_3d, cs%diag)
351  if (cs%id_dz_Int > 0) call post_data(cs%id_dz_Int, dz_int_3d, cs%diag)
352 #endif
353 
354 end subroutine calculate_kappa_shear
355 
356 
357 !> Subroutine for calculating shear-driven diffusivity and TKE in corner columns
358 subroutine calc_kappa_shear_vertex(u_in, v_in, h, T_in, S_in, tv, p_surf, kappa_io, tke_io, &
359  kv_io, dt, G, GV, US, CS, initialize_all)
360  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
361  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
362  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
363  real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
364  intent(in) :: u_in !< Initial zonal velocity [m s-1]. (Intent in)
365  real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
366  intent(in) :: v_in !< Initial meridional velocity [m s-1].
367  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
368  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2].
369  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
370  intent(in) :: t_in !< Layer potential temperatures [degC]
371  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
372  intent(in) :: s_in !< Layer salinities in ppt.
373  type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers to any
374  !! available thermodynamic fields. Absent fields
375  !! have NULL ptrs.
376  real, dimension(:,:), pointer :: p_surf !< The pressure at the ocean surface [Pa]
377  !! (or NULL).
378  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
379  intent(out) :: kappa_io !< The diapycnal diffusivity at each interface
380  !! (not layer!) [Z2 T-1 ~> m2 s-1].
381  real, dimension(SZIB_(G),SZJB_(G),SZK_(GV)+1), &
382  intent(out) :: tke_io !< The turbulent kinetic energy per unit mass at
383  !! each interface (not layer!) [Z2 T-2 ~> m2 s-2].
384  real, dimension(SZIB_(G),SZJB_(G),SZK_(GV)+1), &
385  intent(inout) :: kv_io !< The vertical viscosity at each interface [Z2 T-1 ~> m2 s-1].
386  !! The previous value is used to initialize kappa
387  !! in the vertex columes as Kappa = Kv/Prandtl
388  !! to accelerate the iteration toward covergence.
389  real, intent(in) :: dt !< Time increment [T ~> s].
390  type(kappa_shear_cs), pointer :: cs !< The control structure returned by a previous
391  !! call to kappa_shear_init.
392  logical, optional, intent(in) :: initialize_all !< If present and false, the previous
393  !! value of kappa is used to start the iterations
394 
395  ! Local variables
396  real, dimension(SZIB_(G),SZK_(GV)) :: &
397  h_2d, & ! A 2-D version of h, but converted to [Z ~> m].
398  u_2d, v_2d, & ! 2-D versions of u_in and v_in, converted to [L T-1 ~> m s-1].
399  t_2d, s_2d, rho_2d ! 2-D versions of T, S, and rho.
400  real, dimension(SZIB_(G),SZK_(GV)+1,2) :: &
401  kappa_2d ! Quasi 2-D versions of kappa_io [Z2 T-1 ~> m2 s-1].
402  real, dimension(SZIB_(G),SZK_(GV)+1) :: &
403  tke_2d ! 2-D version tke_io [Z2 T-2 ~> m2 s-2].
404  real, dimension(SZK_(GV)) :: &
405  idz, & ! The inverse of the distance between TKE points [Z-1 ~> m-1].
406  dz, & ! The layer thickness [Z ~> m].
407  u0xdz, & ! The initial zonal velocity times dz [L Z T-1 ~> m2 s-1].
408  v0xdz, & ! The initial meridional velocity times dz [L Z T-1 ~> m2 s-1].
409  t0xdz, & ! The initial temperature times dz [degC Z ~> degC m].
410  s0xdz ! The initial salinity times dz [ppt Z ~> ppt m].
411  real, dimension(SZK_(GV)+1) :: &
412  kappa, & ! The shear-driven diapycnal diffusivity at an interface [Z2 T-1 ~> m2 s-1].
413  tke, & ! The Turbulent Kinetic Energy per unit mass at an interface [Z2 T-2 ~> m2 s-2].
414  kappa_avg, & ! The time-weighted average of kappa [Z2 T-1 ~> m2 s-1].
415  tke_avg ! The time-weighted average of TKE [Z2 T-2 ~> m2 s-2].
416  real :: f2 ! The squared Coriolis parameter of each column [T-2 ~> s-2].
417  real :: surface_pres ! The top surface pressure [Pa].
418 
419  real :: dz_in_lay ! The running sum of the thickness in a layer [Z ~> m].
420  real :: k0dt ! The background diffusivity times the timestep [Z2 ~> m2].
421  real :: dz_massless ! A layer thickness that is considered massless [Z ~> m].
422  real :: i_hwt ! The inverse of the masked thickness weights [H-1 ~> m-1 or m2 kg-1].
423  real :: i_prandtl
424  logical :: use_temperature ! If true, temperature and salinity have been
425  ! allocated and are being used as state variables.
426  logical :: new_kappa = .true. ! If true, ignore the value of kappa from the
427  ! last call to this subroutine.
428  logical :: do_i ! If true, work on this column.
429 
430  integer, dimension(SZK_(GV)+1) :: kc ! The index map between the original
431  ! interfaces and the interfaces with massless layers
432  ! merged into nearby massive layers.
433  real, dimension(SZK_(GV)+1) :: kf ! The fractional weight of interface kc+1 for
434  ! interpolating back to the original index space [nondim].
435  integer :: isb, ieb, jsb, jeb, i, j, k, nz, nzc, j2, j2m1
436 
437  ! Diagnostics that should be deleted?
438 #ifdef ADD_DIAGNOSTICS
439  real, dimension(SZK_(GV)+1) :: & ! Additional diagnostics.
440  i_ld2_1d, dz_int_1d
441  real, dimension(SZI_(G),SZK_(GV)+1) :: & ! 2-D versions of diagnostics.
442  i_ld2_2d, dz_int_2d
443  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: & ! 3-D versions of diagnostics.
444  i_ld2_3d, dz_int_3d
445 #endif
446  isb = g%isc-1 ; ieb = g%iecB ; jsb = g%jsc-1 ; jeb = g%jecB ; nz = gv%ke
447 
448  use_temperature = .false. ; if (associated(tv%T)) use_temperature = .true.
449  new_kappa = .true. ; if (present(initialize_all)) new_kappa = initialize_all
450 
451  k0dt = dt*cs%kappa_0
452  dz_massless = 0.1*sqrt(k0dt)
453  i_prandtl = 0.0 ; if (cs%Prandtl_turb > 0.0) i_prandtl = 1.0 / cs%Prandtl_turb
454 
455  !$OMP parallel do default(private) shared(jsB,jeB,isB,ieB,nz,h,u_in,v_in,use_temperature,new_kappa, &
456 #ifdef ADD_DIAGNOSTICS
457  !$OMP I_Ld2_3d,dz_Int_3d, &
458 #endif
459  !$OMP tv,G,GV,US,CS,kappa_io,dz_massless,k0dt,p_surf,dt,tke_io,kv_io)
460  do j=jsb,jeb
461  j2 = mod(j,2)+1 ; j2m1 = 3-j2 ! = mod(J-1,2)+1
462 
463  ! Interpolate the various quantities to the corners, using masks.
464  do k=1,nz ; do i=isb,ieb
465  u_2d(i,k) = us%m_s_to_L_T * &
466  (u_in(i,j,k) * (g%mask2dCu(i,j) * (h(i,j,k) + h(i+1,j,k))) + &
467  u_in(i,j+1,k) * (g%mask2dCu(i,j+1) * (h(i,j+1,k) + h(i+1,j+1,k))) ) / &
468  ((g%mask2dCu(i,j) * (h(i,j,k) + h(i+1,j,k)) + &
469  g%mask2dCu(i,j+1) * (h(i,j+1,k) + h(i+1,j+1,k))) + gv%H_subroundoff)
470  v_2d(i,k) = us%m_s_to_L_T * &
471  (v_in(i,j,k) * (g%mask2dCv(i,j) * (h(i,j,k) + h(i,j+1,k))) + &
472  v_in(i+1,j,k) * (g%mask2dCv(i+1,j) * (h(i+1,j,k) + h(i+1,j+1,k))) ) / &
473  ((g%mask2dCv(i,j) * (h(i,j,k) + h(i,j+1,k)) + &
474  g%mask2dCv(i+1,j) * (h(i+1,j,k) + h(i+1,j+1,k))) + gv%H_subroundoff)
475  i_hwt = 1.0 / (((g%mask2dT(i,j) * h(i,j,k) + g%mask2dT(i+1,j+1) * h(i+1,j+1,k)) + &
476  (g%mask2dT(i+1,j) * h(i+1,j,k) + g%mask2dT(i,j+1) * h(i,j+1,k))) + &
477  gv%H_subroundoff)
478  if (use_temperature) then
479  t_2d(i,k) = ( ((g%mask2dT(i,j) * h(i,j,k)) * t_in(i,j,k) + &
480  (g%mask2dT(i+1,j+1) * h(i+1,j+1,k)) * t_in(i+1,j+1,k)) + &
481  ((g%mask2dT(i+1,j) * h(i+1,j,k)) * t_in(i+1,j,k) + &
482  (g%mask2dT(i,j+1) * h(i,j+1,k)) * t_in(i,j+1,k)) ) * i_hwt
483  s_2d(i,k) = ( ((g%mask2dT(i,j) * h(i,j,k)) * s_in(i,j,k) + &
484  (g%mask2dT(i+1,j+1) * h(i+1,j+1,k)) * s_in(i+1,j+1,k)) + &
485  ((g%mask2dT(i+1,j) * h(i+1,j,k)) * s_in(i+1,j,k) + &
486  (g%mask2dT(i,j+1) * h(i,j+1,k)) * s_in(i,j+1,k)) ) * i_hwt
487  endif
488  h_2d(i,k) = gv%H_to_Z * ((g%mask2dT(i,j) * h(i,j,k) + g%mask2dT(i+1,j+1) * h(i+1,j+1,k)) + &
489  (g%mask2dT(i+1,j) * h(i+1,j,k) + g%mask2dT(i,j+1) * h(i,j+1,k)) ) / &
490  ((g%mask2dT(i,j) + g%mask2dT(i+1,j+1)) + &
491  (g%mask2dT(i+1,j) + g%mask2dT(i,j+1)) + 1.0e-36 )
492 ! h_2d(I,k) = 0.25*((h(i,j,k) + h(i+1,j+1,k)) + (h(i+1,j,k) + h(i,j+1,k)))*GV%H_to_Z
493 ! h_2d(I,k) = ((h(i,j,k)**2 + h(i+1,j+1,k)**2) + &
494 ! (h(i+1,j,k)**2 + h(i,j+1,k)**2))*GV%H_to_Z * I_hwt
495  enddo ; enddo
496  if (.not.use_temperature) then ; do k=1,nz ; do i=isb,ieb
497  rho_2d(i,k) = gv%Rlay(k)
498  enddo ; enddo ; endif
499  if (.not.new_kappa) then ; do k=1,nz+1 ; do i=isb,ieb
500  kappa_2d(i,k,j2) = kv_io(i,j,k) * i_prandtl
501  enddo ; enddo ; endif
502 
503 !---------------------------------------
504 ! Work on each column.
505 !---------------------------------------
506  do i=isb,ieb ; if ((g%mask2dCu(i,j) + g%mask2dCu(i,j+1)) + &
507  (g%mask2dCv(i,j) + g%mask2dCv(i+1,j)) > 0.0) then
508  ! call cpu_clock_begin(Id_clock_setup)
509  ! Store a transposed version of the initial arrays.
510  ! Any elimination of massless layers would occur here.
511  if (cs%eliminate_massless) then
512  nzc = 1
513  do k=1,nz
514  ! Zero out the thicknesses of all layers, even if they are unused.
515  dz(k) = 0.0 ; u0xdz(k) = 0.0 ; v0xdz(k) = 0.0
516  t0xdz(k) = 0.0 ; s0xdz(k) = 0.0
517 
518  ! Add a new layer if this one has mass.
519 ! if ((dz(nzc) > 0.0) .and. (h_2d(I,k) > dz_massless)) nzc = nzc+1
520  if ((k>cs%nkml) .and. (dz(nzc) > 0.0) .and. &
521  (h_2d(i,k) > dz_massless)) nzc = nzc+1
522 
523  ! Only merge clusters of massless layers.
524 ! if ((dz(nzc) > dz_massless) .or. &
525 ! ((dz(nzc) > 0.0) .and. (h_2d(I,k) > dz_massless))) nzc = nzc+1
526 
527  kc(k) = nzc
528  dz(nzc) = dz(nzc) + h_2d(i,k)
529  u0xdz(nzc) = u0xdz(nzc) + u_2d(i,k)*h_2d(i,k)
530  v0xdz(nzc) = v0xdz(nzc) + v_2d(i,k)*h_2d(i,k)
531  if (use_temperature) then
532  t0xdz(nzc) = t0xdz(nzc) + t_2d(i,k)*h_2d(i,k)
533  s0xdz(nzc) = s0xdz(nzc) + s_2d(i,k)*h_2d(i,k)
534  else
535  t0xdz(nzc) = t0xdz(nzc) + rho_2d(i,k)*h_2d(i,k)
536  s0xdz(nzc) = s0xdz(nzc) + rho_2d(i,k)*h_2d(i,k)
537  endif
538  enddo
539  kc(nz+1) = nzc+1
540 
541  ! Set up Idz as the inverse of layer thicknesses.
542  do k=1,nzc ; idz(k) = 1.0 / dz(k) ; enddo
543 
544  ! Now determine kf, the fractional weight of interface kc when
545  ! interpolating between interfaces kc and kc+1.
546  kf(1) = 0.0 ; dz_in_lay = h_2d(i,1)
547  do k=2,nz
548  if (kc(k) > kc(k-1)) then
549  kf(k) = 0.0 ; dz_in_lay = h_2d(i,k)
550  else
551  kf(k) = dz_in_lay*idz(kc(k)) ; dz_in_lay = dz_in_lay + h_2d(i,k)
552  endif
553  enddo
554  kf(nz+1) = 0.0
555  else
556  do k=1,nz
557  dz(k) = h_2d(i,k)
558  u0xdz(k) = u_2d(i,k)*dz(k) ; v0xdz(k) = v_2d(i,k)*dz(k)
559  enddo
560  if (use_temperature) then
561  do k=1,nz
562  t0xdz(k) = t_2d(i,k)*dz(k) ; s0xdz(k) = s_2d(i,k)*dz(k)
563  enddo
564  else
565  do k=1,nz
566  t0xdz(k) = rho_2d(i,k)*dz(k) ; s0xdz(k) = rho_2d(i,k)*dz(k)
567  enddo
568  endif
569  nzc = nz
570  do k=1,nzc+1 ; kc(k) = k ; kf(k) = 0.0 ; enddo
571  endif
572  f2 = g%CoriolisBu(i,j)**2
573  surface_pres = 0.0 ; if (associated(p_surf)) &
574  surface_pres = 0.25 * ((p_surf(i,j) + p_surf(i+1,j+1)) + &
575  (p_surf(i+1,j) + p_surf(i,j+1)))
576 
577  ! ----------------------------------------------------
578  ! Set the initial guess for kappa, here defined at interfaces.
579  ! ----------------------------------------------------
580  if (new_kappa) then
581  do k=1,nzc+1 ; kappa(k) = us%m2_s_to_Z2_T*1.0 ; enddo
582  else
583  do k=1,nzc+1 ; kappa(k) = kappa_2d(i,k,j2) ; enddo
584  endif
585 
586 #ifdef ADD_DIAGNOSTICS
587  call kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, &
588  dz, u0xdz, v0xdz, t0xdz, s0xdz, kappa_avg, &
589  tke_avg, tv, cs, gv, us, i_ld2_1d, dz_int_1d)
590 #else
591  call kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, &
592  dz, u0xdz, v0xdz, t0xdz, s0xdz, kappa_avg, &
593  tke_avg, tv, cs, gv, us)
594 #endif
595  ! call cpu_clock_begin(Id_clock_setup)
596  ! Extrapolate from the vertically reduced grid back to the original layers.
597  if (nz == nzc) then
598  do k=1,nz+1
599  kappa_2d(i,k,j2) = kappa_avg(k)
600  !### Should this be tke_avg?
601  tke_2d(i,k) = tke(k)
602  enddo
603  else
604  do k=1,nz+1
605  if (kf(k) == 0.0) then
606  kappa_2d(i,k,j2) = kappa_avg(kc(k))
607  tke_2d(i,k) = tke_avg(kc(k))
608  else
609  kappa_2d(i,k,j2) = (1.0-kf(k)) * kappa_avg(kc(k)) + kf(k) * kappa_avg(kc(k)+1)
610  tke_2d(i,k) = (1.0-kf(k)) * tke_avg(kc(k)) + kf(k) * tke_avg(kc(k)+1)
611  endif
612  enddo
613  endif
614 #ifdef ADD_DIAGNOSTICS
615  do k=1,nz+1
616  i_ld2_2d(i,k) = i_ld2_1d(k) ; dz_int_2d(i,k) = dz_int_1d(k)
617  enddo
618 #endif
619  ! call cpu_clock_end(Id_clock_setup)
620  else ! Land points, still inside the i-loop.
621  do k=1,nz+1
622  kappa_2d(i,k,j2) = 0.0 ; tke_2d(i,k) = 0.0
623 #ifdef ADD_DIAGNOSTICS
624  i_ld2_2d(i,k) = 0.0 ; dz_int_2d(i,k) = 0.0
625 #endif
626  enddo
627  endif ; enddo ! i-loop
628 
629  do k=1,nz+1 ; do i=isb,ieb
630  tke_io(i,j,k) = g%mask2dBu(i,j) * tke_2d(i,k)
631  kv_io(i,j,k) = ( g%mask2dBu(i,j) * kappa_2d(i,k,j2) ) * cs%Prandtl_turb
632 #ifdef ADD_DIAGNOSTICS
633  i_ld2_3d(i,j,k) = i_ld2_2d(i,k) ; dz_int_3d(i,j,k) = dz_int_2d(i,k)
634 #endif
635  enddo ; enddo
636  if (j>=g%jsc) then ; do k=1,nz+1 ; do i=g%isc,g%iec
637  ! Set the diffusivities in tracer columns from the values at vertices.
638  kappa_io(i,j,k) = g%mask2dT(i,j) * 0.25 * &
639  ((kappa_2d(i-1,k,j2m1) + kappa_2d(i,k,j2)) + &
640  (kappa_2d(i-1,k,j2) + kappa_2d(i,k,j2m1)))
641  enddo ; enddo ; endif
642 
643  enddo ! end of J-loop
644 
645  if (cs%debug) then
646  call hchksum(kappa_io, "kappa", g%HI, scale=us%Z2_T_to_m2_s)
647  call bchksum(tke_io, "tke", g%HI)
648  endif
649 
650  if (cs%id_Kd_shear > 0) call post_data(cs%id_Kd_shear, kappa_io, cs%diag)
651  if (cs%id_TKE > 0) call post_data(cs%id_TKE, tke_io, cs%diag)
652 #ifdef ADD_DIAGNOSTICS
653  if (cs%id_ILd2 > 0) call post_data(cs%id_ILd2, i_ld2_3d, cs%diag)
654  if (cs%id_dz_Int > 0) call post_data(cs%id_dz_Int, dz_int_3d, cs%diag)
655 #endif
656 
657 end subroutine calc_kappa_shear_vertex
658 
659 
660 !> This subroutine calculates shear-driven diffusivity and TKE in a single column
661 subroutine kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, &
662  dz, u0xdz, v0xdz, T0xdz, S0xdz, kappa_avg, &
663  tke_avg, tv, CS, GV, US, I_Ld2_1d, dz_Int_1d)
664  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
665  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
666  real, dimension(SZK_(GV)+1), &
667  intent(inout) :: kappa !< The time-weighted average of kappa [Z2 T-1 ~> m2 s-1].
668  real, dimension(SZK_(GV)+1), &
669  intent(out) :: tke !< The Turbulent Kinetic Energy per unit mass at
670  !! an interface [Z2 T-2 ~> m2 s-2].
671  integer, intent(in) :: nzc !< The number of active layers in the column.
672  real, intent(in) :: f2 !< The square of the Coriolis parameter [T-2 ~> s-2].
673  real, intent(in) :: surface_pres !< The surface pressure [Pa].
674  real, dimension(SZK_(GV)), &
675  intent(in) :: dz !< The layer thickness [Z ~> m].
676  real, dimension(SZK_(GV)), &
677  intent(in) :: u0xdz !< The initial zonal velocity times dz [Z L T-1 ~> m2 s-1].
678  real, dimension(SZK_(GV)), &
679  intent(in) :: v0xdz !< The initial meridional velocity times dz [Z L T-1 ~> m2 s-1].
680  real, dimension(SZK_(GV)), &
681  intent(in) :: T0xdz !< The initial temperature times dz [degC Z ~> degC m].
682  real, dimension(SZK_(GV)), &
683  intent(in) :: S0xdz !< The initial salinity times dz [ppt Z ~> ppt m].
684  real, dimension(SZK_(GV)+1), &
685  intent(out) :: kappa_avg !< The time-weighted average of kappa [Z2 T-1 ~> m2 s-1].
686  real, dimension(SZK_(GV)+1), &
687  intent(out) :: tke_avg !< The time-weighted average of TKE [Z2 T-2 ~> m2 s-2].
688  real, intent(in) :: dt !< Time increment [T ~> s].
689  type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers to any
690  !! available thermodynamic fields. Absent fields
691  !! have NULL ptrs.
692  type(kappa_shear_cs), pointer :: CS !< The control structure returned by a previous
693  !! call to kappa_shear_init.
694  real, dimension(SZK_(GV)+1), &
695  optional, intent(out) :: I_Ld2_1d !< The inverse of the squared mixing length [Z-2 ~> m-2].
696  real, dimension(SZK_(GV)+1), &
697  optional, intent(out) :: dz_Int_1d !< The extent of a finite-volume space surrounding an interface,
698  !! as used in calculating kappa and TKE [Z ~> m].
699 
700  real, dimension(nzc) :: &
701  u, & ! The zonal velocity after a timestep of mixing [L T-1 ~> m s-1].
702  v, & ! The meridional velocity after a timestep of mixing [L T-1 ~> m s-1].
703  Idz, & ! The inverse of the distance between TKE points [Z-1 ~> m-1].
704  T, & ! The potential temperature after a timestep of mixing [degC].
705  Sal, & ! The salinity after a timestep of mixing [ppt].
706  u_test, v_test, & ! Temporary velocities [L T-1 ~> m s-1].
707  T_test, S_test ! Temporary temperatures [degC] and salinities [ppt].
708 
709  real, dimension(nzc+1) :: &
710  N2, & ! The squared buoyancy frequency at an interface [T-2 ~> s-2].
711  dz_Int, & ! The extent of a finite-volume space surrounding an interface,
712  ! as used in calculating kappa and TKE [Z ~> m].
713  i_dz_int, & ! The inverse of the distance between velocity & density points
714  ! above and below an interface [Z-1 ~> m-1]. This is used to
715  ! calculate N2, shear, and fluxes, and it might differ from
716  ! 1/dz_Int, as they have different uses.
717  s2, & ! The squared shear at an interface [T-2 ~> s-2].
718  a1, & ! a1 is the coupling between adjacent interfaces in the TKE,
719  ! velocity, and density equations [Z s-1 ~> m s-1] or [Z ~> m]
720  c1, & ! c1 is used in the tridiagonal (and similar) solvers.
721  k_src, & ! The shear-dependent source term in the kappa equation [T-1 ~> s-1].
722  kappa_src, & ! The shear-dependent source term in the kappa equation [T-1 ~> s-1].
723  kappa_out, & ! The kappa that results from the kappa equation [Z2 T-1 ~> m2 s-1].
724  kappa_mid, & ! The average of the initial and predictor estimates of kappa [Z2 T-1 ~> m2 s-1].
725  tke_pred, & ! The value of TKE from a predictor step [Z2 T-2 ~> m2 s-2].
726  kappa_pred, & ! The value of kappa from a predictor step [Z2 T-1 ~> m2 s-1].
727  pressure, & ! The pressure at an interface [Pa].
728  t_int, & ! The temperature interpolated to an interface [degC].
729  sal_int, & ! The salinity interpolated to an interface [ppt].
730  dbuoy_dt, & ! The partial derivatives of buoyancy with changes in temperature
731  dbuoy_ds, & ! and salinity, [Z T-2 degC-1 ~> m s-2 degC-1] and [Z T-2 ppt-1 ~> m s-2 ppt-1].
732  i_l2_bdry, & ! The inverse of the square of twice the harmonic mean
733  ! distance to the top and bottom boundaries [Z-2 ~> m-2].
734  k_q, & ! Diffusivity divided by TKE [Z2 m-2 s2 T-1 ~> s].
735  k_q_tmp, & ! A temporary copy of diffusivity divided by TKE [Z2 m-2 s2 T-1 ~> s].
736  local_src_avg, & ! The time-integral of the local source [nondim].
737  tol_min, & ! Minimum tolerated ksrc for the corrector step [T-1 ~> s-1].
738  tol_max, & ! Maximum tolerated ksrc for the corrector step [T-1 ~> s-1].
739  tol_chg, & ! The tolerated change integrated in time [s T-nondim].
740  dist_from_top, & ! The distance from the top surface [Z ~> m].
741  local_src ! The sum of all sources of kappa, including kappa_src and
742  ! sources from the elliptic term [T-1 ~> s-1].
743 
744  real :: dist_from_bot ! The distance from the bottom surface [Z ~> m].
745  real :: b1 ! The inverse of the pivot in the tridiagonal equations.
746  real :: bd1 ! A term in the denominator of b1.
747  real :: d1 ! 1 - c1 in the tridiagonal equations.
748  real :: gR0 ! A conversion factor from Z to Pa equal to Rho_0 times g
749  ! [kg m-1 Z-1 s-2 ~> kg m-2 s-2].
750  real :: g_R0 ! g_R0 is a rescaled version of g/Rho [Z m3 kg-1 T-2 ~> m4 kg-1 s-2].
751  real :: Norm ! A factor that normalizes two weights to 1 [Z-2 ~> m-2].
752  real :: tol_dksrc, tol2 ! ### Tolerances that need to be set better later.
753  real :: tol_dksrc_low ! The tolerance for the fractional decrease in ksrc
754  ! within an iteration. 0 < tol_dksrc_low < 1.
755  real :: Ri_crit ! The critical shear Richardson number for shear-
756  ! driven mixing. The theoretical value is 0.25.
757  real :: dt_rem ! The remaining time to advance the solution [T ~> s].
758  real :: dt_now ! The time step used in the current iteration [T ~> s].
759  real :: dt_wt ! The fractional weight of the current iteration [nondim].
760  real :: dt_test ! A time-step that is being tested for whether it
761  ! gives acceptably small changes in k_src [T ~> s].
762  real :: Idtt ! Idtt = 1 / dt_test [T-1 ~> s-1].
763  real :: dt_inc ! An increment to dt_test that is being tested [T ~> s].
764 
765  real :: k0dt ! The background diffusivity times the timestep [Z2 ~> m2].
766  logical :: valid_dt ! If true, all levels so far exhibit acceptably small
767  ! changes in k_src.
768  logical :: use_temperature ! If true, temperature and salinity have been
769  ! allocated and are being used as state variables.
770  integer :: ks_kappa, ke_kappa ! The k-range with nonzero kappas.
771  integer :: dt_halvings ! The number of times that the time-step is halved
772  ! in seeking an acceptable timestep. If none is
773  ! found, dt_rem*0.5^dt_halvings is used.
774  integer :: dt_refinements ! The number of 2-fold refinements that will be used
775  ! to estimate the maximum permitted time step. I.e.,
776  ! the resolution is 1/2^dt_refinements.
777  integer :: k, itt, itt_dt
778 #ifdef DEBUG
779  integer :: max_debug_itt ; parameter(max_debug_itt=20)
780  real :: wt(SZK_(GV)+1), wt_tot, I_wt_tot, wt_itt
781  real, dimension(SZK_(GV)+1) :: &
782  Ri_k, tke_prev, dtke, dkappa, dtke_norm, &
783  N2_debug, & ! A version of N2 for debugging [T-2 ~> s-2]
784  ksrc_av ! The average through the iterations of k_src [T-1 ~> s-1].
785  real, dimension(SZK_(GV)+1,0:max_debug_itt) :: &
786  tke_it1, N2_it1, Sh2_it1, ksrc_it1, kappa_it1, kprev_it1
787  real, dimension(SZK_(GV)+1,1:max_debug_itt) :: &
788  dkappa_it1, wt_it1, K_Q_it1, d_dkappa_it1, dkappa_norm
789  real, dimension(SZK_(GV),0:max_debug_itt) :: &
790  u_it1, v_it1, rho_it1, T_it1, S_it1
791  real, dimension(0:max_debug_itt) :: &
792  dk_wt_it1, dkpos_wt_it1, dkneg_wt_it1, k_mag
793  real, dimension(max_debug_itt) :: dt_it1
794 #endif
795 
796  ri_crit = cs%Rino_crit
797  gr0 = gv%z_to_H*gv%H_to_Pa
798  g_r0 = (us%L_to_Z**2 * gv%g_Earth) / gv%Rho0
799  k0dt = dt*cs%kappa_0
800  ! These are hard-coded for now. Perhaps these could be made dynamic later?
801  ! tol_dksrc = 0.5*tol_ksrc_chg ; tol_dksrc_low = 1.0 - 1.0/tol_ksrc_chg ?
802  tol_dksrc = 10.0 ; tol_dksrc_low = 0.95 ; tol2 = 2.0*cs%kappa_tol_err
803  dt_refinements = 5 ! Selected so that 1/2^dt_refinements < 1-tol_dksrc_low
804  use_temperature = .false. ; if (associated(tv%T)) use_temperature = .true.
805 
806 
807  ! Set up Idz as the inverse of layer thicknesses.
808  do k=1,nzc ; idz(k) = 1.0 / dz(k) ; enddo
809  ! Set up I_dz_int as the inverse of the distance between
810  ! adjacent layer centers.
811  i_dz_int(1) = 2.0 / dz(1)
812  dist_from_top(1) = 0.0
813  do k=2,nzc
814  i_dz_int(k) = 2.0 / (dz(k-1) + dz(k))
815  dist_from_top(k) = dist_from_top(k-1) + dz(k-1)
816  enddo
817  i_dz_int(nzc+1) = 2.0 / dz(nzc)
818 
819  ! Determine the velocities and thicknesses after eliminating massless
820  ! layers and applying a time-step of background diffusion.
821  if (nzc > 1) then
822  a1(2) = k0dt*i_dz_int(2)
823  b1 = 1.0 / (dz(1) + a1(2))
824  u(1) = b1 * u0xdz(1) ; v(1) = b1 * v0xdz(1)
825  t(1) = b1 * t0xdz(1) ; sal(1) = b1 * s0xdz(1)
826  c1(2) = a1(2) * b1 ; d1 = dz(1) * b1 ! = 1 - c1
827  do k=2,nzc-1
828  bd1 = dz(k) + d1*a1(k)
829  a1(k+1) = k0dt*i_dz_int(k+1)
830  b1 = 1.0 / (bd1 + a1(k+1))
831  u(k) = b1 * (u0xdz(k) + a1(k)*u(k-1))
832  v(k) = b1 * (v0xdz(k) + a1(k)*v(k-1))
833  t(k) = b1 * (t0xdz(k) + a1(k)*t(k-1))
834  sal(k) = b1 * (s0xdz(k) + a1(k)*sal(k-1))
835  c1(k+1) = a1(k+1) * b1 ; d1 = bd1 * b1 ! d1 = 1 - c1
836  enddo
837  ! rho or T and S have insulating boundary conditions, u & v use no-slip
838  ! bottom boundary conditions (if kappa0 > 0).
839  ! For no-slip bottom boundary conditions
840  b1 = 1.0 / ((dz(nzc) + d1*a1(nzc)) + k0dt*i_dz_int(nzc+1))
841  u(nzc) = b1 * (u0xdz(nzc) + a1(nzc)*u(nzc-1))
842  v(nzc) = b1 * (v0xdz(nzc) + a1(nzc)*v(nzc-1))
843  ! For insulating boundary conditions
844  b1 = 1.0 / (dz(nzc) + d1*a1(nzc))
845  t(nzc) = b1 * (t0xdz(nzc) + a1(nzc)*t(nzc-1))
846  sal(nzc) = b1 * (s0xdz(nzc) + a1(nzc)*sal(nzc-1))
847  do k=nzc-1,1,-1
848  u(k) = u(k) + c1(k+1)*u(k+1) ; v(k) = v(k) + c1(k+1)*v(k+1)
849  t(k) = t(k) + c1(k+1)*t(k+1) ; sal(k) = sal(k) + c1(k+1)*sal(k+1)
850  enddo
851  else
852  ! This is correct, but probably unnecessary.
853  b1 = 1.0 / (dz(1) + k0dt*i_dz_int(2))
854  u(1) = b1 * u0xdz(1) ; v(1) = b1 * v0xdz(1)
855  b1 = 1.0 / dz(1)
856  t(1) = b1 * t0xdz(1) ; sal(1) = b1 * s0xdz(1)
857  endif
858 
859  ! This uses half the harmonic mean of thicknesses to provide two estimates
860  ! of the boundary between cells, and the inverse of the harmonic mean to
861  ! weight the two estimates. The net effect is that interfaces around thin
862  ! layers have thin cells, and the total thickness adds up properly.
863  ! The top- and bottom- interfaces have zero thickness, consistent with
864  ! adding additional zero thickness layers.
865  dz_int(1) = 0.0 ; dz_int(2) = dz(1)
866  do k=2,nzc-1
867  norm = 1.0 / (dz(k)*(dz(k-1)+dz(k+1)) + 2.0*dz(k-1)*dz(k+1))
868  dz_int(k) = dz_int(k) + dz(k) * ( ((dz(k)+dz(k+1)) * dz(k-1)) * norm)
869  dz_int(k+1) = dz(k) * ( ((dz(k-1)+dz(k)) * dz(k+1)) * norm)
870  enddo
871  dz_int(nzc) = dz_int(nzc) + dz(nzc) ; dz_int(nzc+1) = 0.0
872 
873  dist_from_bot = 0.0
874  do k=nzc,2,-1
875  dist_from_bot = dist_from_bot + dz(k)
876  i_l2_bdry(k) = (dist_from_top(k) + dist_from_bot)**2 / &
877  (dist_from_top(k) * dist_from_bot)**2
878  enddo
879 
880  ! Calculate thermodynamic coefficients and an initial estimate of N2.
881  if (use_temperature) then
882  pressure(1) = surface_pres
883  do k=2,nzc
884  pressure(k) = pressure(k-1) + gr0*dz(k-1)
885  t_int(k) = 0.5*(t(k-1) + t(k))
886  sal_int(k) = 0.5*(sal(k-1) + sal(k))
887  enddo
888  call calculate_density_derivs(t_int, sal_int, pressure, dbuoy_dt, &
889  dbuoy_ds, 2, nzc-1, tv%eqn_of_state)
890  do k=2,nzc
891  dbuoy_dt(k) = -g_r0*dbuoy_dt(k)
892  dbuoy_ds(k) = -g_r0*dbuoy_ds(k)
893  enddo
894  else
895  do k=1,nzc+1 ; dbuoy_dt(k) = -g_r0 ; dbuoy_ds(k) = 0.0 ; enddo
896  endif
897 
898 #ifdef DEBUG
899  n2_debug(1) = 0.0 ; n2_debug(nzc+1) = 0.0
900  do k=2,nzc
901  n2_debug(k) = max((dbuoy_dt(k) * (t0xdz(k-1)*idz(k-1) - t0xdz(k)*idz(k)) + &
902  dbuoy_ds(k) * (s0xdz(k-1)*idz(k-1) - s0xdz(k)*idz(k))) * &
903  i_dz_int(k), 0.0)
904  enddo
905  do k=1,nzc
906  u_it1(k,0) = u0xdz(k)*idz(k) ; v_it1(k,0) = v0xdz(k)*idz(k)
907  t_it1(k,0) = t0xdz(k)*idz(k) ; s_it1(k,0) = s0xdz(k)*idz(k)
908  enddo
909  do k=1,nzc+1
910  kprev_it1(k,0) = kappa(k) ; kappa_it1(k,0) = kappa(k)
911  tke_it1(k,0) = 0.0
912  n2_it1(k,0) = n2_debug(k) ; sh2_it1(k,0) = s2(k) ; ksrc_it1(k,0) = k_src(k)
913  enddo
914  do k=nzc+1,gv%ke
915  u_it1(k,0) = 0.0 ; v_it1(k,0) = 0.0
916  t_it1(k,0) = 0.0 ; s_it1(k,0) = 0.0
917  kprev_it1(k+1,0) = 0.0 ; kappa_it1(k+1,0) = 0.0 ; tke_it1(k+1,0) = 0.0
918  n2_it1(k+1,0) = 0.0 ; sh2_it1(k+1,0) = 0.0 ; ksrc_it1(k+1,0) = 0.0
919  enddo
920  do itt=1,max_debug_itt
921  dt_it1(itt) = 0.0
922  do k=1,gv%ke
923  u_it1(k,itt) = 0.0 ; v_it1(k,itt) = 0.0
924  t_it1(k,itt) = 0.0 ; s_it1(k,itt) = 0.0
925  rho_it1(k,itt) = 0.0
926  enddo
927  do k=1,gv%ke+1
928  kprev_it1(k,itt) = 0.0 ; kappa_it1(k,itt) = 0.0 ; tke_it1(k,itt) = 0.0
929  n2_it1(k,itt) = 0.0 ; sh2_it1(k,itt) = 0.0
930  ksrc_it1(k,itt) = 0.0
931  dkappa_it1(k,itt) = 0.0 ; wt_it1(k,itt) = 0.0
932  k_q_it1(k,itt) = 0.0 ; d_dkappa_it1(k,itt) = 0.0
933  enddo
934  enddo
935  do k=1,gv%ke+1 ; ksrc_av(k) = 0.0 ; enddo
936 #endif
937 
938  ! This call just calculates N2 and S2.
939  call calculate_projected_state(kappa, u, v, t, sal, 0.0, nzc, dz, i_dz_int, &
940  dbuoy_dt, dbuoy_ds, u, v, t, sal, gv, us, &
941  n2=n2, s2=s2, vel_underflow=cs%vel_underflow)
942 ! ----------------------------------------------------
943 ! Iterate
944 ! ----------------------------------------------------
945  dt_rem = dt
946  do k=1,nzc+1
947  k_q(k) = 0.0
948  kappa_avg(k) = 0.0 ; tke_avg(k) = 0.0
949  local_src_avg(k) = 0.0
950  ! Use the grid spacings to scale errors in the source.
951  if ( dz_int(k) > 0.0 ) &
952  local_src_avg(k) = 0.1 * k0dt * i_dz_int(k) / dz_int(k)
953  enddo
954 
955 ! call cpu_clock_end(id_clock_setup)
956 
957 ! do itt=1,CS%max_RiNo_it
958  do itt=1,cs%max_KS_it
959 
960 ! ----------------------------------------------------
961 ! Calculate new values of u, v, rho, N^2 and S.
962 ! ----------------------------------------------------
963 #ifdef DEBUG
964  do k=1,nzc+1
965  ri_k(k) = 1e3 ; if (s2(k) > 1e-3*n2(k)) ri_k(k) = n2(k) / s2(k)
966  if (itt > 1) then ; tke_prev(k) = tke(k) ; else ; tke_prev(k) = 0.0 ; endif
967  enddo
968 #endif
969 
970  ! call cpu_clock_begin(id_clock_KQ)
971  call find_kappa_tke(n2, s2, kappa, idz, dz_int, i_l2_bdry, f2, &
972  nzc, cs, gv, us, k_q, tke, kappa_out, kappa_src, local_src)
973  ! call cpu_clock_end(id_clock_KQ)
974 
975  ! call cpu_clock_begin(id_clock_avg)
976  ! Determine the range of non-zero values of kappa_out.
977  ks_kappa = gv%ke+1 ; ke_kappa = 0
978  do k=2,nzc ; if (kappa_out(k) > 0.0) then
979  ks_kappa = k ; exit
980  endif ; enddo
981  do k=nzc,ks_kappa,-1 ; if (kappa_out(k) > 0.0) then
982  ke_kappa = k ; exit
983  endif ; enddo
984  if (ke_kappa == nzc) kappa_out(nzc+1) = 0.0
985  ! call cpu_clock_end(id_clock_avg)
986 
987  ! Determine how long to use this value of kappa (dt_now).
988 
989  ! call cpu_clock_begin(id_clock_project)
990  if ((ke_kappa < ks_kappa) .or. (itt==cs%max_RiNo_it)) then
991  dt_now = dt_rem
992  else
993  ! Limit dt_now so that |k_src(k)-kappa_src(k)| < tol * local_src(k)
994  dt_test = dt_rem
995  do k=2,nzc
996  tol_max(k) = kappa_src(k) + tol_dksrc * local_src(k)
997  tol_min(k) = kappa_src(k) - tol_dksrc_low * local_src(k)
998  tol_chg(k) = tol2 * local_src_avg(k)
999  enddo
1000 
1001  do itt_dt=1,(cs%max_KS_it+1-itt)/2
1002  ! The maximum number of times that the time-step is halved in
1003  ! seeking an acceptable timestep is reduced with each iteration,
1004  ! so that as the maximum number of iterations is approached, the
1005  ! whole remaining timestep is used. Typically, an acceptable
1006  ! timestep is found long before the minimum is reached, so the
1007  ! value of max_KS_it may be unimportant, especially if it is large
1008  ! enough.
1009  call calculate_projected_state(kappa_out, u, v, t, sal, 0.5*dt_test, nzc, dz, i_dz_int, &
1010  dbuoy_dt, dbuoy_ds, u_test, v_test, t_test, s_test, &
1011  gv, us, n2, s2, ks_int=ks_kappa, ke_int=ke_kappa, &
1012  vel_underflow=cs%vel_underflow)
1013  valid_dt = .true.
1014  idtt = 1.0 / dt_test
1015  do k=max(ks_kappa-1,2),min(ke_kappa+1,nzc)
1016  if (n2(k) < ri_crit * s2(k)) then ! Equivalent to Ri < Ri_crit.
1017  k_src(k) = (2.0 * cs%Shearmix_rate * sqrt(s2(k))) * &
1018  ((ri_crit*s2(k) - n2(k)) / (ri_crit*s2(k) + cs%FRi_curvature*n2(k)))
1019  if ((k_src(k) > max(tol_max(k), kappa_src(k) + idtt*tol_chg(k))) .or. &
1020  (k_src(k) < min(tol_min(k), kappa_src(k) - idtt*tol_chg(k)))) then
1021  valid_dt = .false. ; exit
1022  endif
1023  else
1024  if (0.0 < min(tol_min(k), kappa_src(k) - idtt*tol_chg(k))) then
1025  valid_dt = .false. ; k_src(k) = 0.0 ; exit
1026  endif
1027  endif
1028  enddo
1029 
1030  if (valid_dt) exit
1031  dt_test = 0.5*dt_test
1032  enddo
1033  if ((dt_test < dt_rem) .and. valid_dt) then
1034  dt_inc = 0.5*dt_test
1035  do itt_dt=1,dt_refinements
1036  call calculate_projected_state(kappa_out, u, v, t, sal, 0.5*(dt_test+dt_inc), &
1037  nzc, dz, i_dz_int, dbuoy_dt, dbuoy_ds, u_test, v_test, t_test, s_test, &
1038  gv, us, n2, s2, ks_int=ks_kappa, ke_int=ke_kappa, vel_underflow=cs%vel_underflow)
1039  valid_dt = .true.
1040  idtt = 1.0 / (dt_test+dt_inc)
1041  do k=max(ks_kappa-1,2),min(ke_kappa+1,nzc)
1042  if (n2(k) < ri_crit * s2(k)) then ! Equivalent to Ri < Ri_crit.
1043  k_src(k) = (2.0 * cs%Shearmix_rate * sqrt(s2(k))) * &
1044  ((ri_crit*s2(k) - n2(k)) / (ri_crit*s2(k) + cs%FRi_curvature*n2(k)))
1045  if ((k_src(k) > max(tol_max(k), kappa_src(k) + idtt*tol_chg(k))) .or. &
1046  (k_src(k) < min(tol_min(k), kappa_src(k) - idtt*tol_chg(k)))) then
1047  valid_dt = .false. ; exit
1048  endif
1049  else
1050  if (0.0 < min(tol_min(k), kappa_src(k) - idtt*tol_chg(k))) then
1051  valid_dt = .false. ; k_src(k) = 0.0 ; exit
1052  endif
1053  endif
1054  enddo
1055 
1056  if (valid_dt) dt_test = dt_test + dt_inc
1057  dt_inc = 0.5*dt_inc
1058  enddo
1059  else
1060  dt_inc = 0.0
1061  endif
1062 
1063  dt_now = min(dt_test*(1.0+cs%kappa_tol_err)+dt_inc, dt_rem)
1064  do k=2,nzc
1065  local_src_avg(k) = local_src_avg(k) + dt_now * local_src(k)
1066  enddo
1067  endif ! Are all the values of kappa_out 0?
1068  ! call cpu_clock_end(id_clock_project)
1069 
1070  ! The state has already been projected forward. Now find new values of kappa.
1071 
1072  if (ke_kappa < ks_kappa) then
1073  ! There is no mixing now, and will not be again.
1074  ! call cpu_clock_begin(id_clock_avg)
1075  dt_wt = dt_rem / dt ; dt_rem = 0.0
1076  do k=1,nzc+1
1077  kappa_mid(k) = 0.0
1078  ! This would be here but does nothing.
1079  ! kappa_avg(K) = kappa_avg(K) + kappa_mid(K)*dt_wt
1080  tke_avg(k) = tke_avg(k) + dt_wt*tke(k)
1081 #ifdef DEBUG
1082  tke_pred(k) = tke(k) ; kappa_pred(k) = 0.0 ; kappa(k) = 0.0
1083 #endif
1084  enddo
1085  ! call cpu_clock_end(id_clock_avg)
1086  else
1087  ! call cpu_clock_begin(id_clock_project)
1088  call calculate_projected_state(kappa_out, u, v, t, sal, dt_now, nzc, dz, i_dz_int, &
1089  dbuoy_dt, dbuoy_ds, u_test, v_test, t_test, s_test, &
1090  gv, us, n2=n2, s2=s2, ks_int=ks_kappa, ke_int=ke_kappa, &
1091  vel_underflow=cs%vel_underflow)
1092  ! call cpu_clock_end(id_clock_project)
1093 
1094  ! call cpu_clock_begin(id_clock_KQ)
1095  do k=1,nzc+1 ; k_q_tmp(k) = k_q(k) ; enddo
1096  call find_kappa_tke(n2, s2, kappa_out, idz, dz_int, i_l2_bdry, f2, &
1097  nzc, cs, gv, us, k_q_tmp, tke_pred, kappa_pred)
1098  ! call cpu_clock_end(id_clock_KQ)
1099 
1100  ks_kappa = gv%ke+1 ; ke_kappa = 0
1101  do k=1,nzc+1
1102  kappa_mid(k) = 0.5*(kappa_out(k) + kappa_pred(k))
1103  if ((kappa_mid(k) > 0.0) .and. (k<ks_kappa)) ks_kappa = k
1104  if (kappa_mid(k) > 0.0) ke_kappa = k
1105  enddo
1106 
1107  ! call cpu_clock_begin(id_clock_project)
1108  call calculate_projected_state(kappa_mid, u, v, t, sal, dt_now, nzc, dz, i_dz_int, &
1109  dbuoy_dt, dbuoy_ds, u_test, v_test, t_test, s_test, &
1110  gv, us, n2=n2, s2=s2, ks_int=ks_kappa, ke_int=ke_kappa, &
1111  vel_underflow=cs%vel_underflow)
1112  ! call cpu_clock_end(id_clock_project)
1113 
1114  ! call cpu_clock_begin(id_clock_KQ)
1115  call find_kappa_tke(n2, s2, kappa_out, idz, dz_int, i_l2_bdry, f2, &
1116  nzc, cs, gv, us, k_q, tke_pred, kappa_pred)
1117  ! call cpu_clock_end(id_clock_KQ)
1118 
1119  ! call cpu_clock_begin(id_clock_avg)
1120  dt_wt = dt_now / dt ; dt_rem = dt_rem - dt_now
1121  do k=1,nzc+1
1122  kappa_mid(k) = 0.5*(kappa_out(k) + kappa_pred(k))
1123  kappa_avg(k) = kappa_avg(k) + kappa_mid(k)*dt_wt
1124  tke_avg(k) = tke_avg(k) + dt_wt*0.5*(tke_pred(k) + tke(k))
1125  kappa(k) = kappa_pred(k) ! First guess for the next iteration.
1126  enddo
1127  ! call cpu_clock_end(id_clock_avg)
1128  endif
1129 
1130  if (dt_rem > 0.0) then
1131  ! Update the values of u, v, T, Sal, N2, and S2 for the next iteration.
1132  ! call cpu_clock_begin(id_clock_project)
1133  call calculate_projected_state(kappa_mid, u, v, t, sal, dt_now, nzc, &
1134  dz, i_dz_int, dbuoy_dt, dbuoy_ds, u, v, t, sal, &
1135  gv, us, n2, s2, vel_underflow=cs%vel_underflow)
1136  ! call cpu_clock_end(id_clock_project)
1137  endif
1138 
1139 #ifdef DEBUG
1140  if (itt <= max_debug_itt) then
1141  dt_it1(itt) = dt_now
1142  dk_wt_it1(itt) = 0.0 ; dkpos_wt_it1(itt) = 0.0 ; dkneg_wt_it1(itt) = 0.0
1143  k_mag(itt) = 0.0
1144  wt_itt = 1.0/real(itt) ; wt_tot = 0.0
1145  do k=1,nzc+1
1146  ksrc_av(k) = (1.0-wt_itt)*ksrc_av(k) + wt_itt*k_src(k)
1147  wt_tot = wt_tot + dz_int(k) * ksrc_av(k)
1148  enddo
1149  ! Use the 1/0=0 convention.
1150  i_wt_tot = 0.0 ; if (wt_tot > 0.0) i_wt_tot = 1.0/wt_tot
1151 
1152  do k=1,nzc+1
1153  wt(k) = (dz_int(k)*ksrc_av(k)) * i_wt_tot
1154  k_mag(itt) = k_mag(itt) + wt(k)*kappa_mid(k)
1155  dkappa_it1(k,itt) = kappa_pred(k) - kappa_out(k)
1156  dk_wt_it1(itt) = dk_wt_it1(itt) + wt(k)*dkappa_it1(k,itt)
1157  if (dkappa_it1(k,itt) > 0.0) then
1158  dkpos_wt_it1(itt) = dkpos_wt_it1(itt) + wt(k)*dkappa_it1(k,itt)
1159  else
1160  dkneg_wt_it1(itt) = dkneg_wt_it1(itt) + wt(k)*dkappa_it1(k,itt)
1161  endif
1162  wt_it1(k,itt) = wt(k)
1163  enddo
1164  endif
1165  do k=1,nzc+1
1166  ri_k(k) = 1e3 ; if (n2(k) < 1e3 * s2(k)) ri_k(k) = n2(k) / s2(k)
1167  dtke(k) = tke_pred(k) - tke(k)
1168  dtke_norm(k) = dtke(k) / (0.5*(tke(k) + tke_pred(k)))
1169  dkappa(k) = kappa_pred(k) - kappa_out(k)
1170  enddo
1171  if (itt <= max_debug_itt) then
1172  do k=1,nzc
1173  u_it1(k,itt) = u(k) ; v_it1(k,itt) = v(k)
1174  t_it1(k,itt) = t(k) ; s_it1(k,itt) = sal(k)
1175  enddo
1176  do k=1,nzc+1
1177  kprev_it1(k,itt) = kappa_out(k)
1178  kappa_it1(k,itt) = kappa_mid(k) ; tke_it1(k,itt) = 0.5*(tke(k)+tke_pred(k))
1179  n2_it1(k,itt)=n2(k) ; sh2_it1(k,itt)=s2(k)
1180  ksrc_it1(k,itt) = kappa_src(k)
1181  k_q_it1(k,itt) = kappa_out(k) / (tke(k))
1182  if (itt > 1) then
1183  if (abs(dkappa_it1(k,itt-1)) > 1e-20) &
1184  d_dkappa_it1(k,itt) = dkappa_it1(k,itt) / dkappa_it1(k,itt-1)
1185  endif
1186  dkappa_norm(k,itt) = dkappa(k) / max(0.5*(kappa_pred(k) + kappa_out(k)), us%m2_s_to_Z2_T*1e-100)
1187  enddo
1188  endif
1189 #endif
1190 
1191  if (dt_rem <= 0.0) exit
1192 
1193  enddo ! end itt loop
1194 
1195 #ifdef ADD_DIAGNOSTICS
1196  if (present(i_ld2_1d)) then
1197  do k=1,gv%ke+1 ; i_ld2_1d(k) = 0.0 ; enddo
1198  do k=2,nzc ; if (tke(k) > 0.0) &
1199  i_ld2_1d(k) = i_l2_bdry(k) + (n2(k) / cs%lambda**2 + f2) / tke(k)
1200  enddo
1201  endif
1202  if (present(dz_int_1d)) then
1203  do k=1,nzc+1 ; dz_int_1d(k) = dz_int(k) ; enddo
1204  do k=nzc+2,gv%ke ; dz_int_1d(k) = 0.0 ; enddo
1205  endif
1206 #endif
1207 
1208 end subroutine kappa_shear_column
1209 
1210 !> This subroutine calculates the velocities, temperature and salinity that
1211 !! the water column will have after mixing for dt with diffusivities kappa. It
1212 !! may also calculate the projected buoyancy frequency and shear.
1213 subroutine calculate_projected_state(kappa, u0, v0, T0, S0, dt, nz, &
1214  dz, I_dz_int, dbuoy_dT, dbuoy_dS, &
1215  u, v, T, Sal, GV, US, N2, S2, ks_int, ke_int, vel_underflow)
1216  integer, intent(in) :: nz !< The number of layers (after eliminating massless
1217  !! layers?).
1218  real, dimension(nz+1), intent(in) :: kappa !< The diapycnal diffusivity at interfaces,
1219  !! [Z2 T-1 ~> m2 s-1].
1220  real, dimension(nz), intent(in) :: u0 !< The initial zonal velocity [m s-1].
1221  real, dimension(nz), intent(in) :: v0 !< The initial meridional velocity [m s-1].
1222  real, dimension(nz), intent(in) :: T0 !< The initial temperature [degC].
1223  real, dimension(nz), intent(in) :: S0 !< The initial salinity [ppt].
1224  real, dimension(nz), intent(in) :: dz !< The grid spacing of layers [Z ~> m].
1225  real, dimension(nz+1), intent(in) :: I_dz_int !< The inverse of the layer's thicknesses
1226  !! [Z-1 ~> m-1].
1227  real, dimension(nz+1), intent(in) :: dbuoy_dT !< The partial derivative of buoyancy with
1228  !! temperature [Z T-2 degC-1 ~> m s-2 degC-1].
1229  real, dimension(nz+1), intent(in) :: dbuoy_dS !< The partial derivative of buoyancy with
1230  !! salinity [Z T-2 ppt-1 ~> m s-2 ppt-1].
1231  real, intent(in) :: dt !< The time step [T ~> s].
1232  real, dimension(nz), intent(inout) :: u !< The zonal velocity after dt [m s-1].
1233  real, dimension(nz), intent(inout) :: v !< The meridional velocity after dt [m s-1].
1234  real, dimension(nz), intent(inout) :: T !< The temperature after dt [degC].
1235  real, dimension(nz), intent(inout) :: Sal !< The salinity after dt [ppt].
1236  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
1237  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1238  real, dimension(nz+1), optional, &
1239  intent(inout) :: N2 !< The buoyancy frequency squared at interfaces [T-2 ~> s-2].
1240  real, dimension(nz+1), optional, &
1241  intent(inout) :: S2 !< The squared shear at interfaces [T-2 ~> s-2].
1242  integer, optional, intent(in) :: ks_int !< The topmost k-index with a non-zero diffusivity.
1243  integer, optional, intent(in) :: ke_int !< The bottommost k-index with a non-zero
1244  !! diffusivity.
1245  real, optional, intent(in) :: vel_underflow !< If present and true, any velocities that
1246  !! are smaller in magnitude than this value are
1247  !! set to 0 [m s-1].
1248 
1249  ! Local variables
1250  real, dimension(nz+1) :: c1
1251  real :: L2_to_Z2 ! A conversion factor from horizontal length units to vertical depth
1252  ! units squared [Z2 s2 T-2 m-2 ~> 1].
1253  real :: underflow_vel ! Velocities smaller in magnitude than underflow_vel are set to 0 [m s-1].
1254  real :: a_a, a_b, b1, d1, bd1, b1nz_0
1255  integer :: k, ks, ke
1256 
1257  ks = 1 ; ke = nz
1258  if (present(ks_int)) ks = max(ks_int-1,1)
1259  if (present(ke_int)) ke = min(ke_int,nz)
1260  underflow_vel = 0.0 ; if (present(vel_underflow)) underflow_vel = vel_underflow
1261 
1262  if (ks > ke) return
1263 
1264  if (dt > 0.0) then
1265  a_b = dt*(kappa(ks+1)*i_dz_int(ks+1))
1266  b1 = 1.0 / (dz(ks) + a_b)
1267  c1(ks+1) = a_b * b1 ; d1 = dz(ks) * b1 ! = 1 - c1
1268 
1269  u(ks) = (b1 * dz(ks))*u0(ks) ; v(ks) = (b1 * dz(ks))*v0(ks)
1270  t(ks) = (b1 * dz(ks))*t0(ks) ; sal(ks) = (b1 * dz(ks))*s0(ks)
1271  do k=ks+1,ke-1
1272  a_a = a_b
1273  a_b = dt*(kappa(k+1)*i_dz_int(k+1))
1274  bd1 = dz(k) + d1*a_a
1275  b1 = 1.0 / (bd1 + a_b)
1276  c1(k+1) = a_b * b1 ; d1 = bd1 * b1 ! d1 = 1 - c1
1277 
1278  u(k) = b1 * (dz(k)*u0(k) + a_a*u(k-1))
1279  v(k) = b1 * (dz(k)*v0(k) + a_a*v(k-1))
1280  t(k) = b1 * (dz(k)*t0(k) + a_a*t(k-1))
1281  sal(k) = b1 * (dz(k)*s0(k) + a_a*sal(k-1))
1282  enddo
1283  ! T and S have insulating boundary conditions, u & v use no-slip
1284  ! bottom boundary conditions at the solid bottom.
1285 
1286  ! For insulating boundary conditions or mixing simply stopping, use...
1287  a_a = a_b
1288  b1 = 1.0 / (dz(ke) + d1*a_a)
1289  t(ke) = b1 * (dz(ke)*t0(ke) + a_a*t(ke-1))
1290  sal(ke) = b1 * (dz(ke)*s0(ke) + a_a*sal(ke-1))
1291 
1292  ! There is no distinction between the effective boundary conditions for
1293  ! tracers and velocities if the mixing is separated from the bottom, but if
1294  ! the mixing goes all the way to the bottom, use no-slip BCs for velocities.
1295  if (ke == nz) then
1296  a_b = dt*(kappa(nz+1)*i_dz_int(nz+1))
1297  b1nz_0 = 1.0 / ((dz(nz) + d1*a_a) + a_b)
1298  else
1299  b1nz_0 = b1
1300  endif
1301  u(ke) = b1nz_0 * (dz(ke)*u0(ke) + a_a*u(ke-1))
1302  v(ke) = b1nz_0 * (dz(ke)*v0(ke) + a_a*v(ke-1))
1303  if (abs(u(ke)) < underflow_vel) u(ke) = 0.0
1304  if (abs(v(ke)) < underflow_vel) v(ke) = 0.0
1305 
1306  do k=ke-1,ks,-1
1307  u(k) = u(k) + c1(k+1)*u(k+1)
1308  v(k) = v(k) + c1(k+1)*v(k+1)
1309  if (abs(u(k)) < underflow_vel) u(k) = 0.0
1310  if (abs(v(k)) < underflow_vel) v(k) = 0.0
1311  t(k) = t(k) + c1(k+1)*t(k+1)
1312  sal(k) = sal(k) + c1(k+1)*sal(k+1)
1313  enddo
1314  else ! dt <= 0.0
1315  do k=1,nz
1316  u(k) = u0(k) ; v(k) = v0(k) ; t(k) = t0(k) ; sal(k) = s0(k)
1317  if (abs(u(k)) < underflow_vel) u(k) = 0.0
1318  if (abs(v(k)) < underflow_vel) v(k) = 0.0
1319  enddo
1320  endif
1321 
1322  if (present(s2)) then
1323  ! L2_to_Z2 = US%m_to_Z**2 * US%T_to_s**2
1324  l2_to_z2 = us%L_to_Z**2
1325  s2(1) = 0.0 ; s2(nz+1) = 0.0
1326  if (ks > 1) &
1327  s2(ks) = ((u(ks)-u0(ks-1))**2 + (v(ks)-v0(ks-1))**2) * (l2_to_z2*i_dz_int(ks)**2)
1328  do k=ks+1,ke
1329  s2(k) = ((u(k)-u(k-1))**2 + (v(k)-v(k-1))**2) * (l2_to_z2*i_dz_int(k)**2)
1330  enddo
1331  if (ke<nz) &
1332  s2(ke+1) = ((u0(ke+1)-u(ke))**2 + (v0(ke+1)-v(ke))**2) * (l2_to_z2*i_dz_int(ke+1)**2)
1333  endif
1334 
1335  if (present(n2)) then
1336  n2(1) = 0.0 ; n2(nz+1) = 0.0
1337  if (ks > 1) &
1338  n2(ks) = max(0.0, i_dz_int(ks) * &
1339  (dbuoy_dt(ks) * (t0(ks-1)-t(ks)) + dbuoy_ds(ks) * (s0(ks-1)-sal(ks))))
1340  do k=ks+1,ke
1341  n2(k) = max(0.0, i_dz_int(k) * &
1342  (dbuoy_dt(k) * (t(k-1)-t(k)) + dbuoy_ds(k) * (sal(k-1)-sal(k))))
1343  enddo
1344  if (ke<nz) &
1345  n2(ke+1) = max(0.0, i_dz_int(ke+1) * &
1346  (dbuoy_dt(ke+1) * (t(ke)-t0(ke+1)) + dbuoy_ds(ke+1) * (sal(ke)-s0(ke+1))))
1347  endif
1348 
1349 end subroutine calculate_projected_state
1350 
1351 !> This subroutine calculates new, consistent estimates of TKE and kappa.
1352 subroutine find_kappa_tke(N2, S2, kappa_in, Idz, dz_Int, I_L2_bdry, f2, &
1353  nz, CS, GV, US, K_Q, tke, kappa, kappa_src, local_src)
1354  integer, intent(in) :: nz !< The number of layers to work on.
1355  real, dimension(nz+1), intent(in) :: N2 !< The buoyancy frequency squared at interfaces [T-2 ~> s-2].
1356  real, dimension(nz+1), intent(in) :: S2 !< The squared shear at interfaces [T-2 ~> s-2].
1357  real, dimension(nz+1), intent(in) :: kappa_in !< The initial guess at the diffusivity
1358  !! [Z2 T-1 ~> m2 s-1].
1359  real, dimension(nz+1), intent(in) :: dz_Int !< The thicknesses associated with interfaces
1360  !! [Z-1 ~> m-1].
1361  real, dimension(nz+1), intent(in) :: I_L2_bdry !< The inverse of the squared distance to
1362  !! boundaries [Z-2 !> m-2].
1363  real, dimension(nz), intent(in) :: Idz !< The inverse grid spacing of layers [Z-1 ~> m-1].
1364  real, intent(in) :: f2 !< The squared Coriolis parameter [T-2 ~> s-2].
1365  type(kappa_shear_cs), pointer :: CS !< A pointer to this module's control structure.
1366  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
1367  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1368  real, dimension(nz+1), intent(inout) :: K_Q !< The shear-driven diapycnal diffusivity divided by
1369  !! the turbulent kinetic energy per unit mass at
1370  !! interfaces [Z2 m-2 s2 T-1 ~> s].
1371  real, dimension(nz+1), intent(out) :: tke !< The turbulent kinetic energy per unit mass at
1372  !! interfaces [Z2 T-2 ~> m2 s-2].
1373  real, dimension(nz+1), intent(out) :: kappa !< The diapycnal diffusivity at interfaces
1374  !! [Z2 T-1 ~> m2 s-1].
1375  real, dimension(nz+1), optional, &
1376  intent(out) :: kappa_src !< The source term for kappa [T-1].
1377  real, dimension(nz+1), optional, &
1378  intent(out) :: local_src !< The sum of all local sources for kappa,
1379  !! [T-1 ~> s-1].
1380 ! This subroutine calculates new, consistent estimates of TKE and kappa.
1381 
1382  ! Local variables
1383  real, dimension(nz) :: &
1384  aQ, & ! aQ is the coupling between adjacent interfaces in the TKE equations [Z T-1 ~> m s-1].
1385  dQdz ! Half the partial derivative of TKE with depth [Z T-2 ~> m s-2].
1386  real, dimension(nz+1) :: &
1387  dK, & ! The change in kappa [Z2 T-1 ~> m2 s-1].
1388  dQ, & ! The change in TKE [Z2 T-2 ~> m2 s-2].
1389  cQ, cK, & ! cQ and cK are the upward influences in the tridiagonal and
1390  ! hexadiagonal solvers for the TKE and kappa equations [nondim].
1391  i_ld2, & ! 1/Ld^2, where Ld is the effective decay length scale for kappa [Z-2 ~> m-2].
1392  tke_decay, & ! The local TKE decay rate [T-1 ~> s-1].
1393  k_src, & ! The source term in the kappa equation [T-1 ~> s-1].
1394  dqmdk, & ! With Newton's method the change in dQ(k-1) due to dK(k) [T ~> s].
1395  dkdq, & ! With Newton's method the change in dK(k) due to dQ(k) [T-1 ~> s-1].
1396  e1 ! The fractional change in a layer TKE due to a change in the
1397  ! TKE of the layer above when all the kappas below are 0.
1398  ! e1 is nondimensional, and 0 < e1 < 1.
1399  real :: tke_src ! The net source of TKE due to mixing against the shear
1400  ! and stratification [Z2 T-3 ~> m2 s-3]. (For convenience,
1401  ! a term involving the non-dissipation of q0 is also
1402  ! included here.)
1403  real :: bQ ! The inverse of the pivot in the tridiagonal equations [T Z-1 ~> s m-1].
1404  real :: bK ! The inverse of the pivot in the tridiagonal equations [Z-1 ~> m-1].
1405  real :: bQd1 ! A term in the denominator of bQ [Z T-1 ~> m s-1].
1406  real :: bKd1 ! A term in the denominator of bK [Z ~> m].
1407  real :: cQcomp, cKcomp ! 1 - cQ or 1 - cK in the tridiagonal equations.
1408  real :: c_s2 ! The coefficient for the decay of TKE due to
1409  ! shear (i.e. proportional to |S|*tke), nondimensional.
1410  real :: c_n2 ! The coefficient for the decay of TKE due to
1411  ! stratification (i.e. proportional to N*tke) [nondim].
1412  real :: Ri_crit ! The critical shear Richardson number for shear-
1413  ! driven mixing. The theoretical value is 0.25.
1414  real :: q0 ! The background level of TKE [Z2 T-2 ~> m2 s-2].
1415  real :: Ilambda2 ! 1.0 / CS%lambda**2 [nondim]
1416  real :: TKE_min ! The minimum value of shear-driven TKE that can be
1417  ! solved for [Z2 T-2 ~> m2 s-2].
1418  real :: kappa0 ! The background diapycnal diffusivity [Z2 T-1 ~> m2 s-1].
1419  real :: kappa_trunc ! Diffusivities smaller than this are rounded to 0 [Z2 T-1 ~> m2 s-1].
1420 
1421  real :: eden1, eden2, I_eden, ome ! Variables used in calculating e1.
1422  real :: diffusive_src ! The diffusive source in the kappa equation [Z T-1 ~> m s-1].
1423  real :: chg_by_k0 ! The value of k_src that leads to an increase of
1424  ! kappa_0 if only the diffusive term is a sink [T-1 ~> s-1].
1425 
1426  real :: kappa_mean ! A mean value of kappa [Z2 T-1 ~> m2 s-1].
1427  real :: Newton_test ! The value of relative error that will cause the next
1428  ! iteration to use Newton's method.
1429  ! Temporary variables used in the Newton's method iterations.
1430  real :: decay_term_k ! The decay term in the diffusivity equation
1431  real :: decay_term_Q ! The decay term in the TKE equation - proportional to [T-1 ~> s-1]
1432  real :: I_Q ! The inverse of TKE [s2 m-2]
1433  real :: kap_src
1434  real :: v1 ! A temporary variable proportional to [T-1 ~> s-1]
1435  real :: v2
1436  real :: tol_err ! The tolerance for max_err that determines when to
1437  ! stop iterating.
1438  real :: Newton_err ! The tolerance for max_err that determines when to
1439  ! start using Newton's method. Empirically, an initial
1440  ! value of about 0.2 seems to be most efficient.
1441  real, parameter :: roundoff = 1.0e-16 ! A negligible fractional change in TKE.
1442  ! This could be larger but performance gains are small.
1443 
1444  logical :: tke_noflux_bottom_BC = .false. ! Specify the boundary conditions
1445  logical :: tke_noflux_top_BC = .false. ! that are applied to the TKE eqns.
1446  logical :: do_Newton ! If .true., use Newton's method for the next iteration.
1447  logical :: abort_Newton ! If .true., an Newton's method has encountered a 0
1448  ! pivot, and should not have been used.
1449  logical :: was_Newton ! The value of do_Newton before checking convergence.
1450  logical :: within_tolerance ! If .true., all points are within tolerance to
1451  ! enable this subroutine to return.
1452  integer :: ks_src, ke_src ! The range indices that have nonzero k_src.
1453  integer :: ks_kappa, ke_kappa, ke_tke ! The ranges of k-indices that are or
1454  integer :: ks_kappa_prev, ke_kappa_prev ! were being worked on.
1455  integer :: itt, k, k2
1456 #ifdef DEBUG
1457  integer :: max_debug_itt ; parameter(max_debug_itt=20)
1458  real :: K_err_lin, Q_err_lin, TKE_src_norm
1459  real, dimension(nz+1) :: &
1460  I_Ld2_debug, & ! A separate version of I_Ld2 for debugging [Z-2 ~> m-2].
1461  kappa_prev, & ! The value of kappa at the start of the current iteration [Z2 T-1 ~> m2 s-1].
1462  TKE_prev ! The value of TKE at the start of the current iteration [Z2 T-2 ~> m2 s-2].
1463  real, dimension(nz+1,1:max_debug_itt) :: &
1464  tke_it1, kappa_it1, kprev_it1, & ! Various values from each iteration.
1465  dkappa_it1, K_Q_it1, d_dkappa_it1, dkappa_norm_it1
1466  integer :: it2
1467 #endif
1468 
1469  c_n2 = cs%C_N**2 ; c_s2 = cs%C_S**2
1470  q0 = cs%TKE_bg ; kappa0 = cs%kappa_0
1471  tke_min = max(cs%TKE_bg, 1.0e-20*us%m_to_Z**2*us%T_to_s**2)
1472  ri_crit = cs%Rino_crit
1473  ilambda2 = 1.0 / cs%lambda**2
1474  kappa_trunc = 0.01*kappa0 ! ### CHANGE THIS HARD-WIRING LATER?
1475  do_newton = .false. ; abort_newton = .false.
1476  tol_err = cs%kappa_tol_err
1477  newton_err = 0.2 ! This initial value may be automatically reduced later.
1478 
1479  ks_kappa = 2 ; ke_kappa = nz ; ks_kappa_prev = 2 ; ke_kappa_prev = nz
1480 
1481  ke_src = 0 ; ks_src = nz+1
1482  do k=2,nz
1483  if (n2(k) < ri_crit * s2(k)) then ! Equivalent to Ri < Ri_crit.
1484 ! Ri = N2(K) / S2(K)
1485 ! k_src(K) = (2.0 * CS%Shearmix_rate * sqrt(S2(K))) * &
1486 ! ((Ri_crit - Ri) / (Ri_crit + CS%FRi_curvature*Ri))
1487  k_src(k) = (2.0 * cs%Shearmix_rate * sqrt(s2(k))) * &
1488  ((ri_crit*s2(k) - n2(k)) / (ri_crit*s2(k) + cs%FRi_curvature*n2(k)))
1489  ke_src = k
1490  if (ks_src > k) ks_src = k
1491  else
1492  k_src(k) = 0.0
1493  endif
1494  enddo
1495 
1496  ! If there is no source anywhere, return kappa(K) = 0.
1497  if (ks_src > ke_src) then
1498  do k=1,nz+1
1499  kappa(k) = 0.0 ; k_q(k) = 0.0 ; tke(k) = tke_min
1500  enddo
1501  if (present(kappa_src)) then ; do k=1,nz+1 ; kappa_src(k) = 0.0 ; enddo ; endif
1502  if (present(local_src)) then ; do k=1,nz+1 ; local_src(k) = 0.0 ; enddo ; endif
1503  return
1504  endif
1505 
1506  do k=1,nz+1
1507  kappa(k) = kappa_in(k)
1508 ! TKE_decay(K) = c_n*sqrt(N2(K)) + c_s*sqrt(S2(K)) ! The expression in JHL.
1509  tke_decay(k) = sqrt(c_n2*n2(k) + c_s2*s2(k))
1510  if ((kappa(k) > 0.0) .and. (k_q(k) > 0.0)) then
1511  tke(k) = kappa(k) / k_q(k)
1512  else
1513  tke(k) = tke_min
1514  endif
1515  enddo
1516  ! Apply boundary conditions to kappa.
1517  kappa(1) = 0.0 ; kappa(nz+1) = 0.0
1518 
1519  ! Calculate the term (e1) that allows changes in TKE to be calculated quickly
1520  ! below the deepest nonzero value of kappa. If kappa = 0, below interface
1521  ! k-1, the final changes in TKE are related by dQ(K+1) = e1(K+1)*dQ(K).
1522  eden2 = kappa0 * idz(nz)
1523  if (tke_noflux_bottom_bc) then
1524  eden1 = dz_int(nz+1)*tke_decay(nz+1)
1525  i_eden = 1.0 / (eden2 + eden1)
1526  e1(nz+1) = eden2 * i_eden ; ome = eden1 * i_eden
1527  else
1528  e1(nz+1) = 0.0 ; ome = 1.0
1529  endif
1530  do k=nz,2,-1
1531  eden1 = dz_int(k)*tke_decay(k) + ome * eden2
1532  eden2 = kappa0 * idz(k-1)
1533  i_eden = 1.0 / (eden2 + eden1)
1534  e1(k) = eden2 * i_eden ; ome = eden1 * i_eden ! = 1-e1
1535  enddo
1536  e1(1) = 0.0
1537 
1538 
1539  ! Iterate here to convergence to within some tolerance of order tol_err.
1540  do itt=1,cs%max_RiNo_it
1541 
1542  ! ----------------------------------------------------
1543  ! Calculate TKE
1544  ! ----------------------------------------------------
1545 
1546 #ifdef DEBUG
1547  do k=1,nz+1 ; kappa_prev(k) = kappa(k) ; tke_prev(k) = tke(k) ; enddo
1548 #endif
1549 
1550  if (.not.do_newton) then
1551  ! Use separate steps of the TKE and kappa equations, that are
1552  ! explicit in the nonlinear source terms, implicit in a linearized
1553  ! version of the nonlinear sink terms, and implicit in the linear
1554  ! terms.
1555 
1556  ke_tke = max(ke_kappa,ke_kappa_prev)+1
1557  ! aQ is the coupling between adjacent interfaces [Z T-1 ~> m s-1].
1558  do k=1,min(ke_tke,nz)
1559  aq(k) = (0.5*(kappa(k)+kappa(k+1)) + kappa0) * idz(k)
1560  enddo
1561  dq(1) = -tke(1)
1562  if (tke_noflux_top_bc) then
1563  tke_src = kappa0*s2(1) + q0 * tke_decay(1) ! Uses that kappa(1) = 0
1564  bqd1 = dz_int(1) * tke_decay(1)
1565  bq = 1.0 / (bqd1 + aq(1))
1566  tke(1) = bq * (dz_int(1)*tke_src)
1567  cq(2) = aq(1) * bq ; cqcomp = bqd1 * bq ! = 1 - cQ
1568  else
1569  tke(1) = q0 ; cq(2) = 0.0 ; cqcomp = 1.0
1570  endif
1571  do k=2,ke_tke-1
1572  dq(k) = -tke(k)
1573  tke_src = (kappa(k) + kappa0)*s2(k) + q0*tke_decay(k)
1574  bqd1 = dz_int(k)*(tke_decay(k) + n2(k)*k_q(k)) + cqcomp*aq(k-1)
1575  bq = 1.0 / (bqd1 + aq(k))
1576  tke(k) = bq * (dz_int(k)*tke_src + aq(k-1)*tke(k-1))
1577  cq(k+1) = aq(k) * bq ; cqcomp = bqd1 * bq ! = 1 - cQ
1578  enddo
1579  if ((ke_tke == nz+1) .and. .not.(tke_noflux_bottom_bc)) then
1580  tke(nz+1) = tke_min
1581  dq(nz+1) = 0.0
1582  else
1583  k = ke_tke
1584  tke_src = kappa0*s2(k) + q0*tke_decay(k) ! Uses that kappa(ke_tke) = 0
1585  if (k == nz+1) then
1586  dq(k) = -tke(k)
1587  bq = 1.0 / (dz_int(k)*tke_decay(k) + cqcomp*aq(k-1))
1588  tke(k) = max(tke_min, bq * (dz_int(k)*tke_src + aq(k-1)*tke(k-1)))
1589  dq(k) = tke(k) + dq(k)
1590  else
1591  bq = 1.0 / ((dz_int(k)*tke_decay(k) + cqcomp*aq(k-1)) + aq(k))
1592  cq(k+1) = aq(k) * bq
1593  ! Account for all changes deeper in the water column.
1594  dq(k) = -tke(k)
1595  tke(k) = max((bq * (dz_int(k)*tke_src + aq(k-1)*tke(k-1)) + &
1596  cq(k+1)*(tke(k+1) - e1(k+1)*tke(k))) / (1.0 - cq(k+1)*e1(k+1)), tke_min)
1597  dq(k) = tke(k) + dq(k)
1598 
1599  ! Adjust TKE deeper in the water column in case ke_tke increases.
1600  ! This might not be strictly necessary?
1601  do k=ke_tke+1,nz+1
1602  dq(k) = e1(k)*dq(k-1)
1603  tke(k) = max(tke(k) + dq(k), tke_min)
1604  if (abs(dq(k)) < roundoff*tke(k)) exit
1605  enddo
1606  do k2=k+1,nz
1607  if (dq(k2) == 0.0) exit
1608  dq(k2) = 0.0
1609  enddo
1610  endif
1611  endif
1612  do k=ke_tke-1,1,-1
1613  tke(k) = max(tke(k) + cq(k+1)*tke(k+1), tke_min)
1614  dq(k) = tke(k) + dq(k)
1615  enddo
1616 
1617  ! ----------------------------------------------------
1618  ! Calculate kappa, here defined at interfaces.
1619  ! ----------------------------------------------------
1620 
1621  ke_kappa_prev = ke_kappa ; ks_kappa_prev = ks_kappa
1622 
1623  dk(1) = 0.0 ! kappa takes boundary values of 0.
1624  ck(2) = 0.0 ; ckcomp = 1.0
1625  if (itt == 1) then ; dO k=2,nz
1626  i_ld2(k) = (n2(k)*ilambda2 + f2) / tke(k) + i_l2_bdry(k)
1627  enddo ; endif
1628  do k=2,nz
1629  dk(k) = -kappa(k)
1630  if (itt>1) &
1631  i_ld2(k) = (n2(k)*ilambda2 + f2) / tke(k) + i_l2_bdry(k)
1632  bkd1 = dz_int(k)*i_ld2(k) + ckcomp*idz(k-1)
1633  bk = 1.0 / (bkd1 + idz(k))
1634 
1635  kappa(k) = bk * (idz(k-1)*kappa(k-1) + dz_int(k) * k_src(k))
1636  ck(k+1) = idz(k) * bk ; ckcomp = bkd1 * bk ! = 1 - cK(K+1)
1637 
1638  ! Neglect values that are smaller than kappa_trunc.
1639  if (kappa(k) < ckcomp*kappa_trunc) then
1640  kappa(k) = 0.0
1641  if (k > ke_src) then ; ke_kappa = k-1 ; k_q(k) = 0.0 ; exit ; endif
1642  elseif (kappa(k) < 2.0*ckcomp*kappa_trunc) then
1643  kappa(k) = 2.0 * (kappa(k) - ckcomp*kappa_trunc)
1644  endif
1645  enddo
1646  k_q(ke_kappa) = kappa(ke_kappa) / tke(ke_kappa)
1647  dk(ke_kappa) = dk(ke_kappa) + kappa(ke_kappa)
1648  do k=ke_kappa+2,ke_kappa_prev
1649  dk(k) = -kappa(k) ; kappa(k) = 0.0 ; k_q(k) = 0.0
1650  enddo
1651  do k=ke_kappa-1,2,-1
1652  kappa(k) = kappa(k) + ck(k+1)*kappa(k+1)
1653  ! Neglect values that are smaller than kappa_trunc.
1654  if (kappa(k) <= kappa_trunc) then
1655  kappa(k) = 0.0
1656  if (k < ks_src) then ; ks_kappa = k+1 ; k_q(k) = 0.0 ; exit ; endif
1657  elseif (kappa(k) < 2.0*kappa_trunc) then
1658  kappa(k) = 2.0 * (kappa(k) - kappa_trunc)
1659  endif
1660 
1661  dk(k) = dk(k) + kappa(k)
1662  k_q(k) = kappa(k) / tke(k)
1663  enddo
1664  do k=ks_kappa_prev,ks_kappa-2 ; kappa(k) = 0.0 ; k_q(k) = 0.0 ; enddo
1665 
1666  else ! do_Newton is .true.
1667 ! Once the solutions are close enough, use a Newton's method solver of the
1668 ! whole system to accelerate convergence.
1669  ks_kappa_prev = ks_kappa ; ke_kappa_prev = ke_kappa ; ke_kappa = nz
1670  ks_kappa = 2
1671  dk(1) = 0.0 ; ck(2) = 0.0 ; ckcomp = 1.0 ; dkdq(1) = 0.0
1672  aq(1) = (0.5*(kappa(1)+kappa(2))+kappa0) * idz(1)
1673  dqdz(1) = 0.5*(tke(1) - tke(2))*idz(1)
1674  if (tke_noflux_top_bc) then
1675  tke_src = dz_int(1) * (kappa0*s2(1) - (tke(1) - q0)*tke_decay(1)) - &
1676  aq(1) * (tke(1) - tke(2))
1677 
1678  bq = 1.0 / (aq(1) + dz_int(1)*tke_decay(1))
1679  cq(2) = aq(1) * bq
1680  cqcomp = (dz_int(1)*tke_decay(1)) * bq ! = 1 - cQ(2)
1681  dqmdk(2) = -dqdz(1) * bq
1682  dq(1) = bq * tke_src
1683  else
1684  dq(1) = 0.0 ; cq(2) = 0.0 ; cqcomp = 1.0 ; dqmdk(2) = 0.0
1685  endif
1686  do k=2,nz
1687  i_q = 1.0 / tke(k)
1688  i_ld2(k) = (n2(k)*ilambda2 + f2) * i_q + i_l2_bdry(k)
1689 
1690  kap_src = dz_int(k) * (k_src(k) - i_ld2(k)*kappa(k)) + &
1691  idz(k-1)*(kappa(k-1)-kappa(k)) - idz(k)*(kappa(k)-kappa(k+1))
1692 
1693  ! Ensure that the pivot is always positive, and that 0 <= cK <= 1.
1694  ! Otherwise do not use Newton's method.
1695  decay_term_k = -idz(k-1)*dqmdk(k)*dkdq(k-1) + dz_int(k)*i_ld2(k)
1696  if (decay_term_k < 0.0) then ; abort_newton = .true. ; exit ; endif
1697  bk = 1.0 / (idz(k) + idz(k-1)*ckcomp + decay_term_k)
1698 
1699  ck(k+1) = bk * idz(k)
1700  ckcomp = bk * (idz(k-1)*ckcomp + decay_term_k) ! = 1-cK(K+1)
1701  !### The following expression appears to be dimensionally inconsistent in length. -RWH
1702  dkdq(k) = bk * (idz(k-1)*dkdq(k-1)*cq(k) + &
1703  us%m_to_Z*(n2(k)*ilambda2 + f2) * i_q**2 * kappa(k) )
1704  ! I think that the second term needs to be multiplied by dz_Int(K):
1705  ! dz_Int(K)*(N2(K)*Ilambda2 + f2) * I_Q**2 * kappa(K) )
1706  dk(k) = bk * (kap_src + idz(k-1)*dk(k-1) + idz(k-1)*dkdq(k-1)*dq(k-1))
1707 
1708  ! Truncate away negligibly small values of kappa.
1709  if (dk(k) <= ckcomp*(kappa_trunc - kappa(k))) then
1710  dk(k) = -ckcomp*kappa(k)
1711 ! if (K > ke_src) then ; ke_kappa = k-1 ; K_Q(K) = 0.0 ; exit ; endif
1712  elseif (dk(k) < ckcomp*(2.0*kappa_trunc - kappa(k))) then
1713  dk(k) = 2.0 * dk(k) - ckcomp*(2.0*kappa_trunc - kappa(k))
1714  endif
1715 
1716  ! Solve for dQ(K)...
1717  aq(k) = (0.5*(kappa(k)+kappa(k+1))+kappa0) * idz(k)
1718  dqdz(k) = 0.5*(tke(k) - tke(k+1))*idz(k)
1719  tke_src = dz_int(k) * (((kappa(k) + kappa0)*s2(k) - kappa(k)*n2(k)) - &
1720  (tke(k) - q0)*tke_decay(k)) - &
1721  (aq(k) * (tke(k) - tke(k+1)) - aq(k-1) * (tke(k-1) - tke(k)))
1722  v1 = aq(k-1) + dqdz(k-1)*dkdq(k-1)
1723  v2 = (v1*dqmdk(k) + dqdz(k-1)*ck(k)) + &
1724  ((dqdz(k-1) - dqdz(k)) + dz_int(k)*(s2(k) - n2(k)))
1725 
1726  ! Ensure that the pivot is always positive, and that 0 <= cQ <= 1.
1727  ! Otherwise do not use Newton's method.
1728  decay_term_q = dz_int(k)*tke_decay(k) - dqdz(k-1)*dkdq(k-1)*cq(k) - v2*dkdq(k)
1729  if (decay_term_q < 0.0) then ; abort_newton = .true. ; exit ; endif
1730  bq = 1.0 / (aq(k) + (cqcomp*aq(k-1) + decay_term_q))
1731 
1732  cq(k+1) = aq(k) * bq
1733  cqcomp = (cqcomp*aq(k-1) + decay_term_q) * bq
1734  dqmdk(k+1) = (v2 * ck(k+1) - dqdz(k)) * bq
1735 
1736  ! Ensure that TKE+dQ will not drop below 0.5*TKE.
1737  dq(k) = max(bq * ((v1 * dq(k-1) + dqdz(k-1)*dk(k-1)) + &
1738  (v2 * dk(k) + tke_src)), cqcomp*(-0.5*tke(k)))
1739 
1740  ! Check whether the next layer will be affected by any nonzero kappas.
1741  if ((itt > 1) .and. (k > ke_src) .and. (dk(k) == 0.0) .and. &
1742  ((kappa(k) + kappa(k+1)) == 0.0)) then
1743  ! Could also do .and. (bQ*abs(tke_src) < roundoff*TKE(K)) then
1744  ke_kappa = k-1 ; exit
1745  endif
1746  enddo
1747  if ((ke_kappa == nz) .and. (.not. abort_newton)) then
1748  dk(nz+1) = 0.0 ; dkdq(nz+1) = 0.0
1749  if (tke_noflux_bottom_bc) then
1750  k = nz+1
1751  tke_src = dz_int(k) * (kappa0*s2(k) - (tke(k) - q0)*tke_decay(k)) + &
1752  aq(k-1) * (tke(k-1) - tke(k))
1753 
1754  v1 = aq(k-1) + dqdz(k-1)*dkdq(k-1)
1755  decay_term_q = max(0.0, dz_int(k)*tke_decay(k) - dqdz(k-1)*dkdq(k-1)*cq(k))
1756  if (decay_term_q < 0.0) then
1757  abort_newton = .true.
1758  else
1759  bq = 1.0 / (aq(k) + (cqcomp*aq(k-1) + decay_term_q))
1760  ! Ensure that TKE+dQ will not drop below 0.5*TKE.
1761  dq(k) = max(bq * ((v1 * dq(k-1) + dqdz(k-1)*dk(k-1)) + tke_src), -0.5*tke(k))
1762  tke(k) = max(tke(k) + dq(k), tke_min)
1763  endif
1764  else
1765  dq(nz+1) = 0.0
1766  endif
1767  elseif (.not. abort_newton) then
1768  ! Alter the first-guess determination of dQ(K).
1769  dq(ke_kappa+1) = dq(ke_kappa+1) / (1.0 - cq(ke_kappa+2)*e1(ke_kappa+2))
1770  tke(ke_kappa+1) = max(tke(ke_kappa+1) + dq(ke_kappa+1), tke_min)
1771  do k=ke_kappa+2,nz+1
1772 #ifdef DEBUG
1773  if (k < nz+1) then
1774  ! Ignore this source?
1775  aq(k) = (0.5*(kappa(k)+kappa(k+1))+kappa0) * idz(k)
1776  tke_src_norm = (dz_int(k) * (kappa0*s2(k) - (tke(k)-q0)*tke_decay(k)) - &
1777  (aq(k) * (tke(k) - tke(k+1)) - aq(k-1) * (tke(k-1) - tke(k))) ) / &
1778  (aq(k) + (aq(k-1) + dz_int(k)*tke_decay(k)))
1779  endif
1780 #endif
1781  dk(k) = 0.0
1782  ! Ensure that TKE+dQ will not drop below 0.5*TKE.
1783  dq(k) = max(e1(k)*dq(k-1),-0.5*tke(k))
1784  tke(k) = max(tke(k) + dq(k), tke_min)
1785  if (abs(dq(k)) < roundoff*tke(k)) exit
1786  enddo
1787 #ifdef DEBUG
1788  do k2=k+1,ke_kappa_prev+1 ; dq(k2) = 0.0 ; dk(k2) = 0.0 ; enddo
1789  do k=k2,nz+1 ; if (dq(k) == 0.0) exit ; dq(k) = 0.0 ; dk(k) = 0.0 ; enddo
1790 #endif
1791  endif
1792  if (.not. abort_newton) then
1793  do k=ke_kappa,2,-1
1794  ! Ensure that TKE+dQ will not drop below 0.5*TKE.
1795  dq(k) = max(dq(k) + (cq(k+1)*dq(k+1) + dqmdk(k+1) * dk(k+1)), -0.5*tke(k))
1796  tke(k) = max(tke(k) + dq(k), tke_min)
1797  dk(k) = dk(k) + (ck(k+1)*dk(k+1) + dkdq(k) * dq(k))
1798  ! Truncate away negligibly small values of kappa.
1799  if (dk(k) <= kappa_trunc - kappa(k)) then
1800  dk(k) = -kappa(k)
1801  kappa(k) = 0.0
1802  if ((k < ks_src) .and. (k+1 > ks_kappa)) ks_kappa = k+1
1803  elseif (dk(k) < 2.0*kappa_trunc - kappa(k)) then
1804  dk(k) = 2.0*dk(k) - (2.0*kappa_trunc - kappa(k))
1805  kappa(k) = max(kappa(k) + dk(k), 0.0) ! The max is for paranoia.
1806  if (k<=ks_kappa) ks_kappa = 2
1807  else
1808  kappa(k) = kappa(k) + dk(k)
1809  if (k<=ks_kappa) ks_kappa = 2
1810  endif
1811  enddo
1812  dq(1) = max(dq(1) + cq(2)*dq(2) + dqmdk(2) * dk(2), tke_min - tke(1))
1813  tke(1) = max(tke(1) + dq(1), tke_min)
1814  dk(1) = 0.0
1815  endif
1816 
1817 #ifdef DEBUG
1818  ! Check these solutions for consistency.
1819  ! The unit conversions here have not been carefully tested.
1820  do k=2,nz
1821  ! In these equations, K_err_lin and Q_err_lin should be at round-off levels
1822  ! compared with the dominant terms, perhaps, dz_Int*I_Ld2*kappa and
1823  ! dz_Int*TKE_decay*TKE. The exception is where, either 1) the decay term has been
1824  ! been increased to ensure a positive pivot, or 2) negative TKEs have been
1825  ! truncated, or 3) small or negative kappas have been rounded toward 0.
1826  i_q = 1.0 / tke(k)
1827  i_ld2_debug(k) = (n2(k)*ilambda2 + f2) * i_q + i_l2_bdry(k)
1828 
1829  kap_src = dz_int(k) * (k_src(k) - i_ld2(k)*kappa_prev(k)) + &
1830  (idz(k-1)*(kappa_prev(k-1)-kappa_prev(k)) - &
1831  idz(k)*(kappa_prev(k)-kappa_prev(k+1)))
1832  !### The last line of the following appears to be dimensionally inconsistent with the first two.
1833  ! I think that the term on the last line needs to be multiplied by dz_Int(K).
1834  k_err_lin = -idz(k-1)*(dk(k-1)-dk(k)) + idz(k)*(dk(k)-dk(k+1)) + &
1835  dz_int(k)*i_ld2_debug(k)*dk(k) - kap_src - &
1836  us%m_to_Z*(n2(k)*ilambda2 + f2)*i_q**2*kappa_prev(k) * dq(k)
1837 
1838  tke_src = dz_int(k) * ((kappa_prev(k) + kappa0)*s2(k) - &
1839  kappa_prev(k)*n2(k) - (tke_prev(k) - q0)*tke_decay(k)) - &
1840  (aq(k) * (tke_prev(k) - tke_prev(k+1)) - aq(k-1) * (tke_prev(k-1) - tke_prev(k)))
1841  q_err_lin = tke_src + (aq(k-1) * (dq(k-1)-dq(k)) - aq(k) * (dq(k)-dq(k+1))) - &
1842  0.5*(tke_prev(k)-tke_prev(k+1))*idz(k) * (dk(k) + dk(k+1)) - &
1843  0.5*(tke_prev(k)-tke_prev(k-1))*idz(k-1)* (dk(k-1) + dk(k)) + &
1844  dz_int(k) * (dk(k) * (s2(k) - n2(k)) - dq(k)*tke_decay(k))
1845  enddo
1846 #endif
1847  endif ! End of the Newton's method solver.
1848 
1849  ! Test kappa for convergence...
1850  if ((tol_err < newton_err) .and. (.not.abort_newton)) then
1851  ! A lower tolerance is used to switch to Newton's method than to switch back.
1852  newton_test = newton_err ; if (do_newton) newton_test = 2.0*newton_err
1853  was_newton = do_newton
1854  within_tolerance = .true. ; do_newton = .true.
1855  do k=min(ks_kappa,ks_kappa_prev),max(ke_kappa,ke_kappa_prev)
1856  kappa_mean = kappa0 + (kappa(k) - 0.5*dk(k))
1857  if (abs(dk(k)) > newton_test * kappa_mean) then
1858  if (do_newton) abort_newton = .true.
1859  within_tolerance = .false. ; do_newton = .false. ; exit
1860  elseif (abs(dk(k)) > tol_err * kappa_mean) then
1861  within_tolerance = .false. ; if (.not.do_newton) exit
1862  endif
1863  if (abs(dq(k)) > newton_test*(tke(k) - 0.5*dq(k))) then
1864  if (do_newton) abort_newton = .true.
1865  do_newton = .false. ; if (.not.within_tolerance) exit
1866  endif
1867  enddo
1868 
1869  else ! Newton's method will not be used again, so no need to check.
1870  within_tolerance = .true.
1871  do k=min(ks_kappa,ks_kappa_prev),max(ke_kappa,ke_kappa_prev)
1872  if (abs(dk(k)) > tol_err * (kappa0 + (kappa(k) - 0.5*dk(k)))) then
1873  within_tolerance = .false. ; exit
1874  endif
1875  enddo
1876  endif
1877 
1878  if (abort_newton) then
1879  do_newton = .false. ; abort_newton = .false.
1880  ! We went to Newton too quickly last time, so restrict the tolerance.
1881  newton_err = 0.5*newton_err
1882  ke_kappa_prev = nz
1883  do k=2,nz ; k_q(k) = kappa(k) / max(tke(k), tke_min) ; enddo
1884  endif
1885 
1886 #ifdef DEBUG
1887  if (itt <= max_debug_itt) then
1888  do k=1,nz+1
1889  kprev_it1(k,itt) = kappa_prev(k)
1890  kappa_it1(k,itt) = kappa(k) ; tke_it1(k,itt) = tke(k)
1891  dkappa_it1(k,itt) = kappa(k) - kappa_prev(k)
1892  dkappa_norm_it1(k,itt) = (kappa(k) - kappa_prev(k)) / &
1893  (kappa0 + 0.5*(kappa(k) + kappa_prev(k)))
1894  k_q_it1(k,itt) = kappa(k) / max(tke(k),tke_min)
1895  d_dkappa_it1(k,itt) = 0.0
1896  if (itt > 1) then ; if (abs(dkappa_it1(k,itt-1)) > 1e-20*us%m2_s_to_Z2_T) &
1897  d_dkappa_it1(k,itt) = dkappa_it1(k,itt) / dkappa_it1(k,itt-1)
1898  endif
1899  enddo
1900  endif
1901 #endif
1902 
1903  if (within_tolerance) exit
1904 
1905  enddo
1906 
1907 #ifdef DEBUG
1908  do it2=itt+1,max_debug_itt ; do k=1,nz+1
1909  kprev_it1(k,it2) = 0.0 ; kappa_it1(k,it2) = 0.0 ; tke_it1(k,it2) = 0.0
1910  dkappa_it1(k,it2) = 0.0 ; k_q_it1(k,it2) = 0.0 ; d_dkappa_it1(k,it2) = 0.0
1911  enddo ; enddo
1912 #endif
1913 
1914  if (do_newton) then ! K_Q needs to be calculated.
1915  do k=1,ks_kappa-1 ; k_q(k) = 0.0 ; enddo
1916  do k=ks_kappa,ke_kappa ; k_q(k) = kappa(k) / tke(k) ; enddo
1917  do k=ke_kappa+1,nz+1 ; k_q(k) = 0.0 ; enddo
1918  endif
1919 
1920  if (present(local_src)) then
1921  local_src(1) = 0.0 ; local_src(nz+1) = 0.0
1922  do k=2,nz
1923  diffusive_src = idz(k-1)*(kappa(k-1)-kappa(k)) + idz(k)*(kappa(k+1)-kappa(k))
1924  chg_by_k0 = kappa0 * ((idz(k-1)+idz(k)) / dz_int(k) + i_ld2(k))
1925  if (diffusive_src <= 0.0) then
1926  local_src(k) = k_src(k) + chg_by_k0
1927  else
1928  local_src(k) = (k_src(k) + chg_by_k0) + diffusive_src / dz_int(k)
1929  endif
1930  enddo
1931  endif
1932  if (present(kappa_src)) then
1933  kappa_src(1) = 0.0 ; kappa_src(nz+1) = 0.0
1934  do k=2,nz
1935  kappa_src(k) = k_src(k)
1936  enddo
1937  endif
1938 
1939 end subroutine find_kappa_tke
1940 
1941 !> This subroutineinitializesthe parameters that regulate shear-driven mixing
1942 function kappa_shear_init(Time, G, GV, US, param_file, diag, CS)
1943  type(time_type), intent(in) :: time !< The current model time.
1944  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
1945  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
1946  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
1947  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time
1948  !! parameters.
1949  type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to regulate diagnostic
1950  !! output.
1951  type(kappa_shear_cs), pointer :: cs !< A pointer that is set to point to the control
1952  !! structure for this module
1953  logical :: kappa_shear_init !< True if module is to be used, False otherwise
1954 
1955  ! Local variables
1956  logical :: merge_mixedlayer
1957 ! This include declares and sets the variable "version".
1958 #include "version_variable.h"
1959  character(len=40) :: mdl = "MOM_kappa_shear" ! This module's name.
1960  real :: kd_normal ! The KD of the main model, read here only as a parameter
1961  ! for setting the default of KD_SMOOTH
1962 
1963  if (associated(cs)) then
1964  call mom_error(warning, "kappa_shear_init called with an associated "// &
1965  "control structure.")
1966  return
1967  endif
1968  allocate(cs)
1969 
1970  ! The Jackson-Hallberg-Legg shear mixing parameterization uses the following
1971  ! 6 nondimensional coefficients. That paper gives 3 best fit parameter sets.
1972  ! Ri_Crit Rate FRi_Curv K_buoy TKE_N TKE_Shear
1973  ! p1: 0.25 0.089 -0.97 0.82 0.24 0.14
1974  ! p2: 0.30 0.085 -0.94 0.86 0.26 0.13
1975  ! p3: 0.35 0.088 -0.89 0.81 0.28 0.12
1976  ! Future research will reveal how these should be modified to take
1977  ! subgridscale inhomogeneity into account.
1978 
1979 ! Set default, read and log parameters
1980  call log_version(param_file, mdl, version, &
1981  "Parameterization of shear-driven turbulence following Jackson, Hallberg and Legg, JPO 2008")
1982  call get_param(param_file, mdl, "USE_JACKSON_PARAM", kappa_shear_init, &
1983  "If true, use the Jackson-Hallberg-Legg (JPO 2008) "//&
1984  "shear mixing parameterization.", default=.false.)
1985  call get_param(param_file, mdl, "VERTEX_SHEAR", cs%KS_at_vertex, &
1986  "If true, do the calculations of the shear-driven mixing "//&
1987  "at the cell vertices (i.e., the vorticity points).", &
1988  default=.false.)
1989  call get_param(param_file, mdl, "RINO_CRIT", cs%RiNo_crit, &
1990  "The critical Richardson number for shear mixing.", &
1991  units="nondim", default=0.25)
1992  call get_param(param_file, mdl, "SHEARMIX_RATE", cs%Shearmix_rate, &
1993  "A nondimensional rate scale for shear-driven entrainment. "//&
1994  "Jackson et al find values in the range of 0.085-0.089.", &
1995  units="nondim", default=0.089)
1996  call get_param(param_file, mdl, "MAX_RINO_IT", cs%max_RiNo_it, &
1997  "The maximum number of iterations that may be used to "//&
1998  "estimate the Richardson number driven mixing.", &
1999  units="nondim", default=50)
2000  call get_param(param_file, mdl, "KD", kd_normal, default=1.0e-7, do_not_log=.true.)
2001  call get_param(param_file, mdl, "KD_KAPPA_SHEAR_0", cs%kappa_0, &
2002  "The background diffusivity that is used to smooth the "//&
2003  "density and shear profiles before solving for the "//&
2004  "diffusivities. Defaults to value of KD.", &
2005  units="m2 s-1", default=kd_normal, scale=us%m2_s_to_Z2_T)
2006  call get_param(param_file, mdl, "FRI_CURVATURE", cs%FRi_curvature, &
2007  "The nondimensional curvature of the function of the "//&
2008  "Richardson number in the kappa source term in the "//&
2009  "Jackson et al. scheme.", units="nondim", default=-0.97)
2010  call get_param(param_file, mdl, "TKE_N_DECAY_CONST", cs%C_N, &
2011  "The coefficient for the decay of TKE due to "//&
2012  "stratification (i.e. proportional to N*tke). "//&
2013  "The values found by Jackson et al. are 0.24-0.28.", &
2014  units="nondim", default=0.24)
2015 ! call get_param(param_file, mdl, "LAYER_KAPPA_STAGGER", CS%layer_stagger, &
2016 ! default=.false.)
2017  call get_param(param_file, mdl, "TKE_SHEAR_DECAY_CONST", cs%C_S, &
2018  "The coefficient for the decay of TKE due to shear (i.e. "//&
2019  "proportional to |S|*tke). The values found by Jackson "//&
2020  "et al. are 0.14-0.12.", units="nondim", default=0.14)
2021  call get_param(param_file, mdl, "KAPPA_BUOY_SCALE_COEF", cs%lambda, &
2022  "The coefficient for the buoyancy length scale in the "//&
2023  "kappa equation. The values found by Jackson et al. are "//&
2024  "in the range of 0.81-0.86.", units="nondim", default=0.82)
2025  call get_param(param_file, mdl, "KAPPA_N_OVER_S_SCALE_COEF2", cs%lambda2_N_S, &
2026  "The square of the ratio of the coefficients of the "//&
2027  "buoyancy and shear scales in the diffusivity equation, "//&
2028  "Set this to 0 (the default) to eliminate the shear scale. "//&
2029  "This is only used if USE_JACKSON_PARAM is true.", &
2030  units="nondim", default=0.0)
2031  call get_param(param_file, mdl, "KAPPA_SHEAR_TOL_ERR", cs%kappa_tol_err, &
2032  "The fractional error in kappa that is tolerated. "//&
2033  "Iteration stops when changes between subsequent "//&
2034  "iterations are smaller than this everywhere in a "//&
2035  "column. The peak diffusivities usually converge most "//&
2036  "rapidly, and have much smaller errors than this.", &
2037  units="nondim", default=0.1)
2038  call get_param(param_file, mdl, "TKE_BACKGROUND", cs%TKE_bg, &
2039  "A background level of TKE used in the first iteration "//&
2040  "of the kappa equation. TKE_BACKGROUND could be 0.", &
2041  units="m2 s-2", default=0.0, scale=us%m_to_Z**2*us%T_to_s**2)
2042  call get_param(param_file, mdl, "KAPPA_SHEAR_ELIM_MASSLESS", cs%eliminate_massless, &
2043  "If true, massless layers are merged with neighboring "//&
2044  "massive layers in this calculation. The default is "//&
2045  "true and I can think of no good reason why it should "//&
2046  "be false. This is only used if USE_JACKSON_PARAM is true.", &
2047  default=.true.)
2048  call get_param(param_file, mdl, "MAX_KAPPA_SHEAR_IT", cs%max_KS_it, &
2049  "The maximum number of iterations that may be used to "//&
2050  "estimate the time-averaged diffusivity.", units="nondim", &
2051  default=13)
2052  call get_param(param_file, mdl, "PRANDTL_TURB", cs%Prandtl_turb, &
2053  "The turbulent Prandtl number applied to shear "//&
2054  "instability.", units="nondim", default=1.0, do_not_log=.true.)
2055  call get_param(param_file, mdl, "VEL_UNDERFLOW", cs%vel_underflow, &
2056  "A negligibly small velocity magnitude below which velocity "//&
2057  "components are set to 0. A reasonable value might be "//&
2058  "1e-30 m/s, which is less than an Angstrom divided by "//&
2059  "the age of the universe.", units="m s-1", default=0.0, scale=us%m_s_to_L_T)
2060  call get_param(param_file, mdl, "DEBUG_KAPPA_SHEAR", cs%debug, &
2061  "If true, write debugging data for the kappa-shear code. \n"//&
2062  "Caution: this option is _very_ verbose and should only "//&
2063  "be used in single-column mode!", &
2064  default=.false., debuggingparam=.true.)
2065 
2066 ! id_clock_KQ = cpu_clock_id('Ocean KS kappa_shear', grain=CLOCK_ROUTINE)
2067 ! id_clock_avg = cpu_clock_id('Ocean KS avg', grain=CLOCK_ROUTINE)
2068 ! id_clock_project = cpu_clock_id('Ocean KS project', grain=CLOCK_ROUTINE)
2069 ! id_clock_setup = cpu_clock_id('Ocean KS setup', grain=CLOCK_ROUTINE)
2070 
2071  cs%nkml = 1
2072  if (gv%nkml>0) then
2073  call get_param(param_file, mdl, "KAPPA_SHEAR_MERGE_ML",merge_mixedlayer, &
2074  "If true, combine the mixed layers together before "//&
2075  "solving the kappa-shear equations.", default=.true.)
2076  if (merge_mixedlayer) cs%nkml = gv%nkml
2077  endif
2078 
2079 ! Forego remainder of initialization if not using this scheme
2080  if (.not. kappa_shear_init) return
2081 
2082  cs%diag => diag
2083 
2084  cs%id_Kd_shear = register_diag_field('ocean_model','Kd_shear',diag%axesTi,time, &
2085  'Shear-driven Diapycnal Diffusivity', 'm2 s-1', conversion=us%Z2_T_to_m2_s)
2086  cs%id_TKE = register_diag_field('ocean_model','TKE_shear',diag%axesTi,time, &
2087  'Shear-driven Turbulent Kinetic Energy', 'm2 s-2', conversion=us%Z_to_m**2*us%s_to_T**2)
2088 #ifdef ADD_DIAGNOSTICS
2089  cs%id_ILd2 = register_diag_field('ocean_model','ILd2_shear',diag%axesTi,time, &
2090  'Inverse kappa decay scale at interfaces', 'm-2', conversion=us%m_to_Z**2)
2091  cs%id_dz_Int = register_diag_field('ocean_model','dz_Int_shear',diag%axesTi,time, &
2092  'Finite volume thickness of interfaces', 'm', conversion=us%Z_to_m)
2093 #endif
2094 
2095 end function kappa_shear_init
2096 
2097 !> This function indicates to other modules whether the Jackson et al shear mixing
2098 !! parameterization will be used without needing to duplicate the log entry.
2099 logical function kappa_shear_is_used(param_file)
2100  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
2101 ! Reads the parameter "USE_JACKSON_PARAM" and returns state.
2102  character(len=40) :: mdl = "MOM_kappa_shear" ! This module's name.
2103 
2104  call get_param(param_file, mdl, "USE_JACKSON_PARAM", kappa_shear_is_used, &
2105  default=.false., do_not_log=.true.)
2106 end function kappa_shear_is_used
2107 
2108 !> This function indicates to other modules whether the Jackson et al shear mixing
2109 !! parameterization will be used without needing to duplicate the log entry.
2110 logical function kappa_shear_at_vertex(param_file)
2111  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
2112 ! Reads the parameter "USE_JACKSON_PARAM" and returns state.
2113  character(len=40) :: mdl = "MOM_kappa_shear" ! This module's name.
2114 
2115  logical :: do_kappa_shear
2116 
2117  call get_param(param_file, mdl, "USE_JACKSON_PARAM", do_kappa_shear, &
2118  default=.false., do_not_log=.true.)
2119  kappa_shear_at_vertex = .false.
2120  if (do_kappa_shear) &
2121  call get_param(param_file, mdl, "VERTEX_SHEAR", kappa_shear_at_vertex, &
2122  "If true, do the calculations of the shear-driven mixing "//&
2123  "at the cell vertices (i.e., the vorticity points).", &
2124  default=.false., do_not_log=.true.)
2125 
2126 end function kappa_shear_at_vertex
2127 
2128 !> \namespace mom_kappa_shear
2129 !!
2130 !! By Laura Jackson and Robert Hallberg, 2006-2008
2131 !!
2132 !! This file contains the subroutines that determine the diapycnal
2133 !! diffusivity driven by resolved shears, as specified by the
2134 !! parameterizations described in Jackson and Hallberg (JPO, 2008).
2135 !!
2136 !! The technique by which the 6 equations (for kappa, TKE, u, v, T,
2137 !! and S) are solved simultaneously has been dramatically revised
2138 !! from the previous version. The previous version was not converging
2139 !! in some cases, especially near the surface mixed layer, while the
2140 !! revised version does. The revised version solves for kappa and
2141 !! TKE with shear and stratification fixed, then marches the density
2142 !! and velocities forward with an adaptive (and aggressive) time step
2143 !! in a predictor-corrector-corrector emulation of a trapezoidal
2144 !! scheme. Run-time-settable parameters determine the tolerence to
2145 !! which the kappa and TKE equations are solved and the minimum time
2146 !! step that can be taken.
2147 
2148 end module mom_kappa_shear
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_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_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_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_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_cpu_clock
Wraps the MPP cpu clock functions.
Definition: MOM_cpu_clock.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_eos::calculate_density_derivs
Calculate the derivatives of density with temperature and salinity from T, S, and P.
Definition: MOM_EOS.F90:70
mom_kappa_shear::kappa_shear_cs
This control structure holds the parameters that regulate shear mixing.
Definition: MOM_kappa_shear.F90:35
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
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_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_kappa_shear
Shear-dependent mixing following Jackson et al. 2008.
Definition: MOM_kappa_shear.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