21 implicit none ;
private
23 #include <MOM_memory.h>
27 logical :: use_variable_mixing
28 logical :: resoln_scaled_kh
30 logical :: resoln_scaled_khth
32 logical :: resoln_scaled_khtr
34 logical :: interpolate_res_fn
39 logical :: use_stored_slopes
40 logical :: resoln_use_ebt
42 logical :: khth_use_ebt_struct
44 logical :: calculate_cg1
47 logical :: calculate_rd_dx
49 logical :: calculate_res_fns
51 logical :: calculate_eady_growth_rate
53 real,
dimension(:,:),
pointer :: &
67 beta_dx2_h => null(), &
69 beta_dx2_q => null(), &
71 beta_dx2_u => null(), &
73 beta_dx2_v => null(), &
85 real,
dimension(:,:,:),
pointer :: &
91 real allocable_,
dimension(NIMEMB_PTR_,NJMEM_) :: &
94 real allocable_,
dimension(NIMEM_,NJMEMB_PTR_) :: &
97 real allocable_,
dimension(NIMEMB_PTR_,NJMEM_,NKMEM_) :: &
100 real allocable_,
dimension(NIMEM_,NJMEMB_PTR_,NKMEM_) :: &
104 logical :: use_visbeck
105 integer :: varmix_ktop
106 real :: visbeck_l_scale
107 real :: res_coef_khth
110 real :: res_coef_visc
114 integer :: res_fn_power_khth
117 integer :: res_fn_power_visc
120 real :: visbeck_s_max
123 logical :: use_qg_leith_gm
124 logical :: use_beta_in_qg_leith
129 integer :: id_sn_u=-1, id_sn_v=-1, id_l2u=-1, id_l2v=-1, id_res_fn = -1
130 integer :: id_n2_u=-1, id_n2_v=-1, id_s2_u=-1, id_s2_v=-1
131 integer :: id_rd_dx=-1, id_kh_u_qg = -1, id_kh_v_qg = -1
137 type(group_pass_type) :: pass_cg1
141 public varmix_init, calc_slope_functions, calc_resoln_function
142 public calc_qg_leith_viscosity
147 subroutine calc_resoln_function(h, tv, G, GV, US, CS)
149 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
163 integer :: is, ie, js, je, isq, ieq, jsq, jeq, nz
165 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
166 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
168 if (.not.
associated(cs))
call mom_error(fatal,
"calc_resoln_function:"// &
169 "Module must be initialized before it is used.")
170 if (cs%calculate_cg1)
then
171 if (.not.
associated(cs%cg1))
call mom_error(fatal, &
172 "calc_resoln_function: %cg1 is not associated with Resoln_scaled_Kh.")
173 if (cs%khth_use_ebt_struct)
then
174 if (.not.
associated(cs%ebt_struct))
call mom_error(fatal, &
175 "calc_resoln_function: %ebt_struct is not associated with RESOLN_USE_EBT.")
176 if (cs%Resoln_use_ebt)
then
178 call wave_speed(h, tv, g, gv, us, cs%cg1, cs%wave_speed_CSp, modal_structure=cs%ebt_struct)
181 call wave_speed(h, tv, g, gv, us, cs%cg1, cs%wave_speed_CSp, modal_structure=cs%ebt_struct, &
183 call wave_speed(h, tv, g, gv, us, cs%cg1, cs%wave_speed_CSp)
185 call pass_var(cs%ebt_struct, g%Domain)
187 call wave_speed(h, tv, g, gv, us, cs%cg1, cs%wave_speed_CSp)
191 call do_group_pass(cs%pass_cg1, g%Domain)
196 if (cs%calculate_rd_dx)
then
197 if (.not.
associated(cs%Rd_dx_h))
call mom_error(fatal, &
198 "calc_resoln_function: %Rd_dx_h is not associated with calculate_rd_dx.")
201 do j=js-1,je+1 ;
do i=is-1,ie+1
202 cs%Rd_dx_h(i,j) = us%T_to_s*cs%cg1(i,j) / &
203 (sqrt(cs%f2_dx2_h(i,j) + us%T_to_s*cs%cg1(i,j)*cs%beta_dx2_h(i,j)))
206 if (query_averaging_enabled(cs%diag))
then
207 if (cs%id_Rd_dx > 0)
call post_data(cs%id_Rd_dx, cs%Rd_dx_h, cs%diag)
211 if (.not. cs%calculate_res_fns)
return
213 if (.not.
associated(cs%Res_fn_h))
call mom_error(fatal, &
214 "calc_resoln_function: %Res_fn_h is not associated with Resoln_scaled_Kh.")
215 if (.not.
associated(cs%Res_fn_q))
call mom_error(fatal, &
216 "calc_resoln_function: %Res_fn_q is not associated with Resoln_scaled_Kh.")
217 if (.not.
associated(cs%Res_fn_u))
call mom_error(fatal, &
218 "calc_resoln_function: %Res_fn_u is not associated with Resoln_scaled_Kh.")
219 if (.not.
associated(cs%Res_fn_v))
call mom_error(fatal, &
220 "calc_resoln_function: %Res_fn_v is not associated with Resoln_scaled_Kh.")
221 if (.not.
associated(cs%f2_dx2_h))
call mom_error(fatal, &
222 "calc_resoln_function: %f2_dx2_h is not associated with Resoln_scaled_Kh.")
223 if (.not.
associated(cs%f2_dx2_q))
call mom_error(fatal, &
224 "calc_resoln_function: %f2_dx2_q is not associated with Resoln_scaled_Kh.")
225 if (.not.
associated(cs%f2_dx2_u))
call mom_error(fatal, &
226 "calc_resoln_function: %f2_dx2_u is not associated with Resoln_scaled_Kh.")
227 if (.not.
associated(cs%f2_dx2_v))
call mom_error(fatal, &
228 "calc_resoln_function: %f2_dx2_v is not associated with Resoln_scaled_Kh.")
229 if (.not.
associated(cs%beta_dx2_h))
call mom_error(fatal, &
230 "calc_resoln_function: %beta_dx2_h is not associated with Resoln_scaled_Kh.")
231 if (.not.
associated(cs%beta_dx2_q))
call mom_error(fatal, &
232 "calc_resoln_function: %beta_dx2_q is not associated with Resoln_scaled_Kh.")
233 if (.not.
associated(cs%beta_dx2_u))
call mom_error(fatal, &
234 "calc_resoln_function: %beta_dx2_u is not associated with Resoln_scaled_Kh.")
235 if (.not.
associated(cs%beta_dx2_v))
call mom_error(fatal, &
236 "calc_resoln_function: %beta_dx2_v is not associated with Resoln_scaled_Kh.")
243 if (cs%Res_fn_power_visc >= 100)
then
245 do j=js-1,je+1 ;
do i=is-1,ie+1
246 dx_term = cs%f2_dx2_h(i,j) + us%T_to_s*cs%cg1(i,j)*cs%beta_dx2_h(i,j)
247 if ((cs%Res_coef_visc * us%T_to_s*cs%cg1(i,j))**2 > dx_term)
then
248 cs%Res_fn_h(i,j) = 0.0
250 cs%Res_fn_h(i,j) = 1.0
254 do j=js-1,jeq ;
do i=is-1,ieq
255 cg1_q = us%T_to_s * 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
256 (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
257 dx_term = cs%f2_dx2_q(i,j) + cg1_q * cs%beta_dx2_q(i,j)
258 if ((cs%Res_coef_visc * cg1_q)**2 > dx_term)
then
259 cs%Res_fn_q(i,j) = 0.0
261 cs%Res_fn_q(i,j) = 1.0
264 elseif (cs%Res_fn_power_visc == 2)
then
266 do j=js-1,je+1 ;
do i=is-1,ie+1
267 dx_term = cs%f2_dx2_h(i,j) + us%T_to_s*cs%cg1(i,j)*cs%beta_dx2_h(i,j)
268 cs%Res_fn_h(i,j) = dx_term / (dx_term + (cs%Res_coef_visc * us%T_to_s*cs%cg1(i,j))**2)
271 do j=js-1,jeq ;
do i=is-1,ieq
272 cg1_q = us%T_to_s * 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
273 (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
274 dx_term = cs%f2_dx2_q(i,j) + cg1_q * cs%beta_dx2_q(i,j)
275 cs%Res_fn_q(i,j) = dx_term / (dx_term + (cs%Res_coef_visc * cg1_q)**2)
277 elseif (mod(cs%Res_fn_power_visc, 2) == 0)
then
278 power_2 = cs%Res_fn_power_visc / 2
280 do j=js-1,je+1 ;
do i=is-1,ie+1
281 dx_term = (us%s_to_T**2*cs%f2_dx2_h(i,j) + cs%cg1(i,j)*us%s_to_T*cs%beta_dx2_h(i,j))**power_2
282 cs%Res_fn_h(i,j) = dx_term / &
283 (dx_term + (cs%Res_coef_visc * cs%cg1(i,j))**cs%Res_fn_power_visc)
286 do j=js-1,jeq ;
do i=is-1,ieq
287 cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
288 (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
289 dx_term = (us%s_to_T**2*cs%f2_dx2_q(i,j) + cg1_q * us%s_to_T*cs%beta_dx2_q(i,j))**power_2
290 cs%Res_fn_q(i,j) = dx_term / &
291 (dx_term + (cs%Res_coef_visc * cg1_q)**cs%Res_fn_power_visc)
295 do j=js-1,je+1 ;
do i=is-1,ie+1
296 dx_term = (us%s_to_T*sqrt(cs%f2_dx2_h(i,j) + &
297 us%T_to_s*cs%cg1(i,j)*cs%beta_dx2_h(i,j)))**cs%Res_fn_power_visc
298 cs%Res_fn_h(i,j) = dx_term / &
299 (dx_term + (cs%Res_coef_visc * cs%cg1(i,j))**cs%Res_fn_power_visc)
302 do j=js-1,jeq ;
do i=is-1,ieq
303 cg1_q = 0.25 * ((cs%cg1(i,j) + cs%cg1(i+1,j+1)) + &
304 (cs%cg1(i+1,j) + cs%cg1(i,j+1)))
305 dx_term = (us%s_to_T*sqrt(cs%f2_dx2_q(i,j) + &
306 us%T_to_s*cg1_q * cs%beta_dx2_q(i,j)))**cs%Res_fn_power_visc
307 cs%Res_fn_q(i,j) = dx_term / &
308 (dx_term + (cs%Res_coef_visc * cg1_q)**cs%Res_fn_power_visc)
312 if (cs%interpolate_Res_fn)
then
313 do j=js,je ;
do i=is-1,ieq
314 cs%Res_fn_u(i,j) = 0.5*(cs%Res_fn_h(i,j) + cs%Res_fn_h(i+1,j))
316 do j=js-1,jeq ;
do i=is,ie
317 cs%Res_fn_v(i,j) = 0.5*(cs%Res_fn_h(i,j) + cs%Res_fn_h(i,j+1))
320 if (cs%Res_fn_power_khth >= 100)
then
322 do j=js,je ;
do i=is-1,ieq
323 cg1_u = 0.5 * us%T_to_s * (cs%cg1(i,j) + cs%cg1(i+1,j))
324 dx_term = cs%f2_dx2_u(i,j) + cg1_u * cs%beta_dx2_u(i,j)
325 if ((cs%Res_coef_khth * cg1_u)**2 > dx_term)
then
326 cs%Res_fn_u(i,j) = 0.0
328 cs%Res_fn_u(i,j) = 1.0
332 do j=js-1,jeq ;
do i=is,ie
333 cg1_v = 0.5 * us%T_to_s * (cs%cg1(i,j) + cs%cg1(i,j+1))
334 dx_term = cs%f2_dx2_v(i,j) + cg1_v * cs%beta_dx2_v(i,j)
335 if ((cs%Res_coef_khth * cg1_v)**2 > dx_term)
then
336 cs%Res_fn_v(i,j) = 0.0
338 cs%Res_fn_v(i,j) = 1.0
341 elseif (cs%Res_fn_power_khth == 2)
then
343 do j=js,je ;
do i=is-1,ieq
344 cg1_u = 0.5 * us%T_to_s * (cs%cg1(i,j) + cs%cg1(i+1,j))
345 dx_term = cs%f2_dx2_u(i,j) + cg1_u * cs%beta_dx2_u(i,j)
346 cs%Res_fn_u(i,j) = dx_term / (dx_term + (cs%Res_coef_khth * cg1_u)**2)
349 do j=js-1,jeq ;
do i=is,ie
350 cg1_v = 0.5 * us%T_to_s * (cs%cg1(i,j) + cs%cg1(i,j+1))
351 dx_term = cs%f2_dx2_v(i,j) + cg1_v * cs%beta_dx2_v(i,j)
352 cs%Res_fn_v(i,j) = dx_term / (dx_term + (cs%Res_coef_khth * cg1_v)**2)
354 elseif (mod(cs%Res_fn_power_khth, 2) == 0)
then
355 power_2 = cs%Res_fn_power_khth / 2
357 do j=js,je ;
do i=is-1,ieq
358 cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
359 dx_term = (us%s_to_T**2*cs%f2_dx2_u(i,j) + cg1_u * us%s_to_T*cs%beta_dx2_u(i,j))**power_2
360 cs%Res_fn_u(i,j) = dx_term / &
361 (dx_term + (cs%Res_coef_khth * cg1_u)**cs%Res_fn_power_khth)
364 do j=js-1,jeq ;
do i=is,ie
365 cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
366 dx_term = (us%s_to_T**2*cs%f2_dx2_v(i,j) + cg1_v * us%s_to_T*cs%beta_dx2_v(i,j))**power_2
367 cs%Res_fn_v(i,j) = dx_term / &
368 (dx_term + (cs%Res_coef_khth * cg1_v)**cs%Res_fn_power_khth)
372 do j=js,je ;
do i=is-1,ieq
373 cg1_u = 0.5 * (cs%cg1(i,j) + cs%cg1(i+1,j))
374 dx_term = (us%s_to_T*sqrt(cs%f2_dx2_u(i,j) + &
375 us%T_to_s*cg1_u * cs%beta_dx2_u(i,j)))**cs%Res_fn_power_khth
376 cs%Res_fn_u(i,j) = dx_term / &
377 (dx_term + (cs%Res_coef_khth * cg1_u)**cs%Res_fn_power_khth)
380 do j=js-1,jeq ;
do i=is,ie
381 cg1_v = 0.5 * (cs%cg1(i,j) + cs%cg1(i,j+1))
382 dx_term = (us%s_to_T*sqrt(cs%f2_dx2_v(i,j) + &
383 us%T_to_s*cg1_v * cs%beta_dx2_v(i,j)))**cs%Res_fn_power_khth
384 cs%Res_fn_v(i,j) = dx_term / &
385 (dx_term + (cs%Res_coef_khth * cg1_v)**cs%Res_fn_power_khth)
391 if (query_averaging_enabled(cs%diag))
then
392 if (cs%id_Res_fn > 0)
call post_data(cs%id_Res_fn, cs%Res_fn_h, cs%diag)
395 end subroutine calc_resoln_function
399 subroutine calc_slope_functions(h, tv, dt, G, GV, US, CS)
403 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
405 real,
intent(in) :: dt
408 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)+1) :: &
410 real,
dimension(SZIB_(G), SZJ_(G), SZK_(G)+1) :: n2_u
411 real,
dimension(SZI_(G), SZJB_(G), SZK_(G)+1) :: n2_v
413 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_lateral_mixing_coeffs.F90, calc_slope_functions:"//&
414 "Module must be initialized before it is used.")
416 if (cs%calculate_Eady_growth_rate)
then
417 call find_eta(h, tv, g, gv, us, e, halo_size=2)
418 if (cs%use_stored_slopes)
then
419 call calc_isoneutral_slopes(g, gv, us, h, e, tv, dt*cs%kappa_smooth, &
420 cs%slope_x, cs%slope_y, n2_u, n2_v, 1)
421 call calc_visbeck_coeffs(h, cs%slope_x, cs%slope_y, n2_u, n2_v, g, gv, cs)
425 call calc_slope_functions_using_just_e(h, g, gv, us, cs, e, .true.)
429 if (query_averaging_enabled(cs%diag))
then
430 if (cs%id_SN_u > 0)
call post_data(cs%id_SN_u, cs%SN_u, cs%diag)
431 if (cs%id_SN_v > 0)
call post_data(cs%id_SN_v, cs%SN_v, cs%diag)
432 if (cs%id_L2u > 0)
call post_data(cs%id_L2u, cs%L2u, cs%diag)
433 if (cs%id_L2v > 0)
call post_data(cs%id_L2v, cs%L2v, cs%diag)
434 if (cs%id_N2_u > 0)
call post_data(cs%id_N2_u, cs%N2_u, cs%diag)
435 if (cs%id_N2_v > 0)
call post_data(cs%id_N2_v, cs%N2_v, cs%diag)
438 end subroutine calc_slope_functions
441 subroutine calc_visbeck_coeffs(h, slope_x, slope_y, N2_u, N2_v, G, GV, CS)
444 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
445 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: slope_x
446 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: N2_u
447 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(in) :: slope_y
448 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(in) :: N2_v
456 integer :: is, ie, js, je, nz
457 integer :: i, j, k, kb_max
458 real :: S2max, wNE, wSE, wSW, wNW
459 real :: H_u(SZIB_(G)), H_v(SZI_(G))
460 real :: S2_u(SZIB_(G), SZJ_(G))
461 real :: S2_v(SZI_(G), SZJB_(G))
463 if (.not.
associated(cs))
call mom_error(fatal,
"calc_slope_function:"// &
464 "Module must be initialized before it is used.")
465 if (.not. cs%calculate_Eady_growth_rate)
return
466 if (.not.
associated(cs%SN_u))
call mom_error(fatal,
"calc_slope_function:"// &
467 "%SN_u is not associated with use_variable_mixing.")
468 if (.not.
associated(cs%SN_v))
call mom_error(fatal,
"calc_slope_function:"// &
469 "%SN_v is not associated with use_variable_mixing.")
471 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
473 s2max = cs%Visbeck_S_max**2
476 do j=js-1,je+1 ;
do i=is-1,ie+1
488 cs%SN_u(i,j) = 0. ; h_u(i) = 0. ; s2_u(i,j) = 0.
490 do k=2,nz ;
do i=is-1,ie
491 hdn = sqrt( h(i,j,k) * h(i+1,j,k) )
492 hup = sqrt( h(i,j,k-1) * h(i+1,j,k-1) )
493 h_geom = sqrt( hdn * hup )
496 wse = g%mask2dCv(i+1,j-1) * ( (h(i+1,j,k)*h(i+1,j-1,k)) * (h(i+1,j,k-1)*h(i+1,j-1,k-1)) )
497 wnw = g%mask2dCv(i ,j ) * ( (h(i ,j,k)*h(i ,j+1,k)) * (h(i ,j,k-1)*h(i ,j+1,k-1)) )
498 wne = g%mask2dCv(i+1,j ) * ( (h(i+1,j,k)*h(i+1,j+1,k)) * (h(i+1,j,k-1)*h(i+1,j+1,k-1)) )
499 wsw = g%mask2dCv(i ,j-1) * ( (h(i ,j,k)*h(i ,j-1,k)) * (h(i ,j,k-1)*h(i ,j-1,k-1)) )
500 s2 = slope_x(i,j,k)**2 + &
501 ((wnw*slope_y(i,j,k)**2 + wse*slope_y(i+1,j-1,k)**2) + &
502 (wne*slope_y(i+1,j,k)**2 + wsw*slope_y(i,j-1,k)**2) ) / &
503 ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**4 )
504 if (s2max>0.) s2 = s2 * s2max / (s2 + s2max)
506 n2 = max(0., n2_u(i,j,k))
507 cs%SN_u(i,j) = cs%SN_u(i,j) + sqrt( s2*n2 )*h_geom
508 s2_u(i,j) = s2_u(i,j) + s2*h_geom
509 h_u(i) = h_u(i) + h_geom
513 cs%SN_u(i,j) = g%mask2dCu(i,j) * cs%SN_u(i,j) / h_u(i)
514 s2_u(i,j) = g%mask2dCu(i,j) * s2_u(i,j) / h_u(i)
524 cs%SN_v(i,j) = 0. ; h_v(i) = 0. ; s2_v(i,j) = 0.
526 do k=2,nz ;
do i=is,ie
527 hdn = sqrt( h(i,j,k) * h(i,j+1,k) )
528 hup = sqrt( h(i,j,k-1) * h(i,j+1,k-1) )
529 h_geom = sqrt( hdn * hup )
532 wse = g%mask2dCu(i,j) * ( (h(i,j ,k)*h(i+1,j ,k)) * (h(i,j ,k-1)*h(i+1,j ,k-1)) )
533 wnw = g%mask2dCu(i-1,j+1) * ( (h(i,j+1,k)*h(i-1,j+1,k)) * (h(i,j+1,k-1)*h(i-1,j+1,k-1)) )
534 wne = g%mask2dCu(i,j+1) * ( (h(i,j+1,k)*h(i+1,j+1,k)) * (h(i,j+1,k-1)*h(i+1,j+1,k-1)) )
535 wsw = g%mask2dCu(i-1,j) * ( (h(i,j ,k)*h(i-1,j ,k)) * (h(i,j ,k-1)*h(i-1,j ,k-1)) )
536 s2 = slope_y(i,j,k)**2 + &
537 ((wse*slope_x(i,j,k)**2 + wnw*slope_x(i-1,j+1,k)**2) + &
538 (wne*slope_x(i,j+1,k)**2 + wsw*slope_x(i-1,j,k)**2) ) / &
539 ( ((wse+wnw) + (wne+wsw)) + gv%H_subroundoff**4 )
540 if (s2max>0.) s2 = s2 * s2max / (s2 + s2max)
542 n2 = max(0., n2_v(i,j,k))
543 cs%SN_v(i,j) = cs%SN_v(i,j) + sqrt( s2*n2 )*h_geom
544 s2_v(i,j) = s2_v(i,j) + s2*h_geom
545 h_v(i) = h_v(i) + h_geom
549 cs%SN_v(i,j) = g%mask2dCv(i,j) * cs%SN_v(i,j) / h_v(i)
550 s2_v(i,j) = g%mask2dCv(i,j) * s2_v(i,j) / h_v(i)
558 if (query_averaging_enabled(cs%diag))
then
559 if (cs%id_S2_u > 0)
call post_data(cs%id_S2_u, s2_u, cs%diag)
560 if (cs%id_S2_v > 0)
call post_data(cs%id_S2_v, s2_v, cs%diag)
564 call uvchksum(
"calc_Visbeck_coeffs slope_[xy]", slope_x, slope_y, g%HI, haloshift=1)
565 call uvchksum(
"calc_Visbeck_coeffs N2_u, N2_v", n2_u, n2_v, g%HI)
566 call uvchksum(
"calc_Visbeck_coeffs SN_[uv]", cs%SN_u, cs%SN_v, g%HI)
569 end subroutine calc_visbeck_coeffs
573 subroutine calc_slope_functions_using_just_e(h, G, GV, US, CS, e, calculate_slopes)
575 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
579 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: e
580 logical,
intent(in) :: calculate_slopes
583 real :: E_x(SZIB_(G), SZJ_(G))
584 real :: E_y(SZI_(G), SZJB_(G))
595 integer :: is, ie, js, je, nz
596 integer :: i, j, k, kb_max
597 real :: S2N2_u_local(SZIB_(G), SZJ_(G),SZK_(G))
598 real :: S2N2_v_local(SZI_(G), SZJB_(G),SZK_(G))
600 if (.not.
associated(cs))
call mom_error(fatal,
"calc_slope_function:"// &
601 "Module must be initialized before it is used.")
602 if (.not. cs%calculate_Eady_growth_rate)
return
603 if (.not.
associated(cs%SN_u))
call mom_error(fatal,
"calc_slope_function:"// &
604 "%SN_u is not associated with use_variable_mixing.")
605 if (.not.
associated(cs%SN_v))
call mom_error(fatal,
"calc_slope_function:"// &
606 "%SN_v is not associated with use_variable_mixing.")
608 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
610 one_meter = 1.0 * gv%m_to_H
611 h_neglect = gv%H_subroundoff
612 h_cutoff = real(2*nz) * (gv%Angstrom_H + h_neglect)
620 do k=nz,cs%VarMix_Ktop,-1
622 if (calculate_slopes)
then
624 do j=js-1,je+1 ;
do i=is-1,ie
625 e_x(i,j) = z_to_l*(e(i+1,j,k)-e(i,j,k))*g%IdxCu(i,j)
627 if (min(h(i,j,k),h(i+1,j,k)) < h_cutoff) e_x(i,j) = 0.
629 do j=js-1,je ;
do i=is-1,ie+1
630 e_y(i,j) = z_to_l*(e(i,j+1,k)-e(i,j,k))*g%IdyCv(i,j)
632 if (min(h(i,j,k),h(i,j+1,k)) < h_cutoff) e_y(i,j) = 0.
635 do j=js-1,je+1 ;
do i=is-1,ie
636 e_x(i,j) = cs%slope_x(i,j,k)
637 if (min(h(i,j,k),h(i+1,j,k)) < h_cutoff) e_x(i,j) = 0.
639 do j=js-1,je ;
do i=is-1,ie+1
640 e_y(i,j) = cs%slope_y(i,j,k)
641 if (min(h(i,j,k),h(i,j+1,k)) < h_cutoff) e_y(i,j) = 0.
646 do j=js,je ;
do i=is-1,ie
647 s2 = ( e_x(i,j)**2 + 0.25*( &
648 (e_y(i,j)**2+e_y(i+1,j-1)**2)+(e_y(i+1,j)**2+e_y(i,j-1)**2) ) )
649 hdn = 2.*h(i,j,k)*h(i,j,k-1) / (h(i,j,k) + h(i,j,k-1) + h_neglect)
650 hup = 2.*h(i+1,j,k)*h(i+1,j,k-1) / (h(i+1,j,k) + h(i+1,j,k-1) + h_neglect)
651 h_geom = sqrt(hdn*hup)
652 n2 = gv%g_prime(k)*us%L_to_Z**2 / (gv%H_to_Z * max(hdn,hup,one_meter))
653 if (min(h(i,j,k-1), h(i+1,j,k-1), h(i,j,k), h(i+1,j,k)) < h_cutoff) &
655 s2n2_u_local(i,j,k) = (h_geom * gv%H_to_Z) * s2 * n2
657 do j=js-1,je ;
do i=is,ie
658 s2 = ( e_y(i,j)**2 + 0.25*( &
659 (e_x(i,j)**2+e_x(i-1,j+1)**2)+(e_x(i,j+1)**2+e_x(i-1,j)**2) ) )
660 hdn = 2.*h(i,j,k)*h(i,j,k-1) / (h(i,j,k) + h(i,j,k-1) + h_neglect)
661 hup = 2.*h(i,j+1,k)*h(i,j+1,k-1) / (h(i,j+1,k) + h(i,j+1,k-1) + h_neglect)
662 h_geom = sqrt(hdn*hup)
663 n2 = gv%g_prime(k)*us%L_to_Z**2 / (gv%H_to_Z * max(hdn,hup,one_meter))
664 if (min(h(i,j,k-1), h(i,j+1,k-1), h(i,j,k), h(i,j+1,k)) < h_cutoff) &
666 s2n2_v_local(i,j,k) = (h_geom * gv%H_to_Z) * s2 * n2
672 do i=is-1,ie ; cs%SN_u(i,j) = 0.0 ;
enddo
673 do k=nz,cs%VarMix_Ktop,-1 ;
do i=is-1,ie
674 cs%SN_u(i,j) = cs%SN_u(i,j) + s2n2_u_local(i,j,k)
680 if ( min(g%bathyT(i,j), g%bathyT(i+1,j)) > h_cutoff*gv%H_to_Z )
then
681 cs%SN_u(i,j) = g%mask2dCu(i,j) * us%s_to_T * sqrt( cs%SN_u(i,j) / &
682 (max(g%bathyT(i,j), g%bathyT(i+1,j))) )
690 do i=is,ie ; cs%SN_v(i,j) = 0.0 ;
enddo
691 do k=nz,cs%VarMix_Ktop,-1 ;
do i=is,ie
692 cs%SN_v(i,j) = cs%SN_v(i,j) + s2n2_v_local(i,j,k)
697 if ( min(g%bathyT(i,j), g%bathyT(i+1,j)) > h_cutoff*gv%H_to_Z )
then
698 cs%SN_v(i,j) = g%mask2dCv(i,j) * us%s_to_T * sqrt( cs%SN_v(i,j) / &
699 (max(g%bathyT(i,j), g%bathyT(i,j+1))) )
706 end subroutine calc_slope_functions_using_just_e
709 subroutine calc_qg_leith_viscosity(CS, G, GV, h, k, div_xx_dx, div_xx_dy, vort_xy_dx, vort_xy_dy)
715 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
716 integer,
intent(in) :: k
717 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: div_xx_dx
719 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: div_xx_dy
721 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: vort_xy_dx
723 real,
dimension(SZIB_(G),SZJ_(G)),
intent(inout) :: vort_xy_dy
738 real,
dimension(SZI_(G),SZJB_(G)) :: &
747 real,
dimension(SZIB_(G),SZJ_(G)) :: &
757 real :: h_at_slope_above, h_at_slope_below, ih, f
758 integer :: i, j, is, ie, js, je, isq, ieq, jsq, jeq,nz
761 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
762 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
765 inv_pi3 = 1.0/((4.0*atan(1.0))**3)
770 if ((k > 1) .and. (k < nz))
then
776 do j=js-2,jeq+2 ;
do i=is-2,ieq+1
777 h_at_slope_above = 2. * ( h(i,j,k-1) * h(i+1,j,k-1) ) * ( h(i,j,k) * h(i+1,j,k) ) / &
778 ( ( h(i,j,k-1) * h(i+1,j,k-1) ) * ( h(i,j,k) + h(i+1,j,k) ) &
779 + ( h(i,j,k) * h(i+1,j,k) ) * ( h(i,j,k-1) + h(i+1,j,k-1) ) + gv%H_subroundoff )
780 h_at_slope_below = 2. * ( h(i,j,k) * h(i+1,j,k) ) * ( h(i,j,k+1) * h(i+1,j,k+1) ) / &
781 ( ( h(i,j,k) * h(i+1,j,k) ) * ( h(i,j,k+1) + h(i+1,j,k+1) ) &
782 + ( h(i,j,k+1) * h(i+1,j,k+1) ) * ( h(i,j,k) + h(i+1,j,k) ) + gv%H_subroundoff )
783 ih = 1./ ( ( h_at_slope_above + h_at_slope_below + gv%H_subroundoff ) * gv%H_to_m )
784 dslopex_dz(i,j) = 2. * ( cs%slope_x(i,j,k) - cs%slope_x(i,j,k+1) ) * ih
785 h_at_u(i,j) = 2. * ( h_at_slope_above * h_at_slope_below ) * ih
789 do j=js-2,jeq+1 ;
do i=is-2,ieq+2
790 h_at_slope_above = 2. * ( h(i,j,k-1) * h(i,j+1,k-1) ) * ( h(i,j,k) * h(i,j+1,k) ) / &
791 ( ( h(i,j,k-1) * h(i,j+1,k-1) ) * ( h(i,j,k) + h(i,j+1,k) ) &
792 + ( h(i,j,k) * h(i,j+1,k) ) * ( h(i,j,k-1) + h(i,j+1,k-1) ) + gv%H_subroundoff )
793 h_at_slope_below = 2. * ( h(i,j,k) * h(i,j+1,k) ) * ( h(i,j,k+1) * h(i,j+1,k+1) ) / &
794 ( ( h(i,j,k) * h(i,j+1,k) ) * ( h(i,j,k+1) + h(i,j+1,k+1) ) &
795 + ( h(i,j,k+1) * h(i,j+1,k+1) ) * ( h(i,j,k) + h(i,j+1,k) ) + gv%H_subroundoff )
796 ih = 1./ ( ( h_at_slope_above + h_at_slope_below + gv%H_subroundoff ) * gv%H_to_m )
797 dslopey_dz(i,j) = 2. * ( cs%slope_y(i,j,k) - cs%slope_y(i,j,k+1) ) * ih
798 h_at_v(i,j) = 2. * ( h_at_slope_above * h_at_slope_below ) * ih
802 do j=js-2,jeq+1 ;
do i=is-1,ieq+1
803 f = 0.5 * ( g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j) )
804 vort_xy_dx(i,j) = vort_xy_dx(i,j) - f * &
805 ( ( h_at_u(i,j) * dslopex_dz(i,j) + h_at_u(i-1,j+1) * dslopex_dz(i-1,j+1) ) &
806 + ( h_at_u(i-1,j) * dslopex_dz(i-1,j) + h_at_u(i,j+1) * dslopex_dz(i,j+1) ) ) / &
807 ( ( h_at_u(i,j) + h_at_u(i-1,j+1) ) + ( h_at_u(i-1,j) + h_at_u(i,j+1) ) + gv%H_subroundoff)
811 do j=js-1,jeq+1 ;
do i=is-2,ieq+1
812 f = 0.5 * ( g%CoriolisBu(i,j) + g%CoriolisBu(i,j-1) )
814 vort_xy_dy(i,j) = vort_xy_dx(i,j) - f * &
815 ( ( h_at_v(i,j) * dslopey_dz(i,j) + h_at_v(i+1,j-1) * dslopey_dz(i+1,j-1) ) &
816 + ( h_at_v(i,j-1) * dslopey_dz(i,j-1) + h_at_v(i+1,j) * dslopey_dz(i+1,j) ) ) / &
817 ( ( h_at_v(i,j) + h_at_v(i+1,j-1) ) + ( h_at_v(i,j-1) + h_at_v(i+1,j) ) + gv%H_subroundoff)
824 if (cs%use_QG_Leith_GM)
then
826 do j=js,je ;
do i=is-1,ieq
827 grad_vort_mag_u(i,j) = sqrt(vort_xy_dy(i,j)**2 + (0.25*(vort_xy_dx(i,j) + vort_xy_dx(i+1,j) &
828 + vort_xy_dx(i,j-1) + vort_xy_dx(i+1,j-1)))**2)
829 grad_div_mag_u(i,j) = sqrt(div_xx_dx(i,j)**2 + (0.25*(div_xx_dy(i,j) + div_xx_dy(i+1,j) &
830 + div_xx_dy(i,j-1) + div_xx_dy(i+1,j-1)))**2)
831 if (cs%use_beta_in_QG_Leith)
then
832 beta_u(i,j) = sqrt( (0.5*(g%dF_dx(i,j)+g%dF_dx(i+1,j))**2) + &
833 (0.5*(g%dF_dy(i,j)+g%dF_dy(i+1,j))**2) )
834 cs%KH_u_QG(i,j,k) = min(grad_vort_mag_u(i,j) + grad_div_mag_u(i,j), beta_u(i,j)*3) &
835 * cs%Laplac3_const_u(i,j) * inv_pi3
837 cs%KH_u_QG(i,j,k) = (grad_vort_mag_u(i,j) + grad_div_mag_u(i,j)) &
838 * cs%Laplac3_const_u(i,j) * inv_pi3
842 do j=js-1,jeq ;
do i=is,ie
843 grad_vort_mag_v(i,j) = sqrt(vort_xy_dx(i,j)**2 + (0.25*(vort_xy_dy(i,j) + vort_xy_dy(i-1,j) &
844 + vort_xy_dy(i,j+1) + vort_xy_dy(i-1,j+1)))**2)
845 grad_div_mag_v(i,j) = sqrt(div_xx_dy(i,j)**2 + (0.25*(div_xx_dx(i,j) + div_xx_dx(i-1,j) &
846 + div_xx_dx(i,j+1) + div_xx_dx(i-1,j+1)))**2)
847 if (cs%use_beta_in_QG_Leith)
then
848 beta_v(i,j) = sqrt( (0.5*(g%dF_dx(i,j)+g%dF_dx(i,j+1))**2) + &
849 (0.5*(g%dF_dy(i,j)+g%dF_dy(i,j+1))**2) )
850 cs%KH_v_QG(i,j,k) = min(grad_vort_mag_v(i,j) + grad_div_mag_v(i,j), beta_v(i,j)*3) &
851 * cs%Laplac3_const_v(i,j) * inv_pi3
853 cs%KH_v_QG(i,j,k) = (grad_vort_mag_v(i,j) + grad_div_mag_v(i,j)) &
854 * cs%Laplac3_const_v(i,j) * inv_pi3
860 if (cs%id_KH_v_QG > 0)
call post_data(cs%id_KH_v_QG, cs%KH_v_QG, cs%diag)
861 if (cs%id_KH_u_QG > 0)
call post_data(cs%id_KH_u_QG, cs%KH_u_QG, cs%diag)
865 end subroutine calc_qg_leith_viscosity
868 subroutine varmix_init(Time, G, GV, US, param_file, diag, CS)
869 type(time_type),
intent(in) :: time
874 type(
diag_ctrl),
target,
intent(inout) :: diag
877 real :: khtr_slope_cff, khth_slope_cff, oneortwo, n2_filter_depth
878 real :: khtr_passivity_coeff
879 real :: absurdly_small_freq
881 logical :: gill_equatorial_ld, use_fgnv_streamfn, use_meke, in_use
882 real :: mle_front_length
883 real :: leith_lap_const
884 real :: grid_sp_u2, grid_sp_u3
885 real :: grid_sp_v2, grid_sp_v3
887 #include "version_variable.h"
888 character(len=40) :: mdl =
"MOM_lateral_mixing_coeffs"
889 integer :: is, ie, js, je, isq, ieq, jsq, jeq, i, j
890 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb
891 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
892 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
893 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
894 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
896 if (
associated(cs))
then
897 call mom_error(warning,
"VarMix_init called with an associated "// &
898 "control structure.")
905 cs%calculate_cg1 = .false.
906 cs%calculate_Rd_dx = .false.
907 cs%calculate_res_fns = .false.
908 cs%calculate_Eady_growth_rate = .false.
912 call get_param(param_file, mdl,
"USE_VARIABLE_MIXING", cs%use_variable_mixing,&
913 "If true, the variable mixing code will be called. This "//&
914 "allows diagnostics to be created even if the scheme is "//&
915 "not used. If KHTR_SLOPE_CFF>0 or KhTh_Slope_Cff>0, "//&
916 "this is set to true regardless of what is in the "//&
917 "parameter file.", default=.false.)
918 call get_param(param_file, mdl,
"USE_VISBECK", cs%use_Visbeck,&
919 "If true, use the Visbeck et al. (1997) formulation for \n"//&
920 "thickness diffusivity.", default=.false.)
921 call get_param(param_file, mdl,
"RESOLN_SCALED_KH", cs%Resoln_scaled_Kh, &
922 "If true, the Laplacian lateral viscosity is scaled away "//&
923 "when the first baroclinic deformation radius is well "//&
924 "resolved.", default=.false.)
925 call get_param(param_file, mdl,
"RESOLN_SCALED_KHTH", cs%Resoln_scaled_KhTh, &
926 "If true, the interface depth diffusivity is scaled away "//&
927 "when the first baroclinic deformation radius is well "//&
928 "resolved.", default=.false.)
929 call get_param(param_file, mdl,
"RESOLN_SCALED_KHTR", cs%Resoln_scaled_KhTr, &
930 "If true, the epipycnal tracer diffusivity is scaled "//&
931 "away when the first baroclinic deformation radius is "//&
932 "well resolved.", default=.false.)
933 call get_param(param_file, mdl,
"RESOLN_USE_EBT", cs%Resoln_use_ebt, &
934 "If true, uses the equivalent barotropic wave speed instead "//&
935 "of first baroclinic wave for calculating the resolution fn.",&
937 call get_param(param_file, mdl,
"KHTH_USE_EBT_STRUCT", cs%khth_use_ebt_struct, &
938 "If true, uses the equivalent barotropic structure "//&
939 "as the vertical structure of thickness diffusivity.",&
941 call get_param(param_file, mdl,
"KHTH_SLOPE_CFF", khth_slope_cff, &
942 "The nondimensional coefficient in the Visbeck formula "//&
943 "for the interface depth diffusivity", units=
"nondim", &
945 call get_param(param_file, mdl,
"KHTR_SLOPE_CFF", khtr_slope_cff, &
946 "The nondimensional coefficient in the Visbeck formula "//&
947 "for the epipycnal tracer diffusivity", units=
"nondim", &
949 call get_param(param_file, mdl,
"USE_STORED_SLOPES", cs%use_stored_slopes,&
950 "If true, the isopycnal slopes are calculated once and "//&
951 "stored for re-use. This uses more memory but avoids calling "//&
952 "the equation of state more times than should be necessary.", &
954 call get_param(param_file, mdl,
"VERY_SMALL_FREQUENCY", absurdly_small_freq, &
955 "A miniscule frequency that is used to avoid division by 0. The default "//&
956 "value is roughly (pi / (the age of the universe)).", &
957 default=1.0e-17, units=
"s-1", scale=us%T_to_s)
958 call get_param(param_file, mdl,
"KHTH_USE_FGNV_STREAMFUNCTION", use_fgnv_streamfn, &
959 default=.false., do_not_log=.true.)
960 cs%calculate_cg1 = cs%calculate_cg1 .or. use_fgnv_streamfn
961 call get_param(param_file, mdl,
"USE_MEKE", use_meke, &
962 default=.false., do_not_log=.true.)
963 cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. use_meke
964 cs%calculate_Eady_growth_rate = cs%calculate_Eady_growth_rate .or. use_meke
965 call get_param(param_file, mdl,
"KHTR_PASSIVITY_COEFF", khtr_passivity_coeff, &
966 default=0., do_not_log=.true.)
967 cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (khtr_passivity_coeff>0.)
968 call get_param(param_file, mdl,
"MLE_FRONT_LENGTH", mle_front_length, &
969 default=0., do_not_log=.true.)
970 cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (mle_front_length>0.)
972 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false., do_not_log=.true.)
974 if (cs%Resoln_use_ebt .or. cs%khth_use_ebt_struct)
then
976 call get_param(param_file, mdl,
"RESOLN_N2_FILTER_DEPTH", n2_filter_depth, &
977 "The depth below which N2 is monotonized to avoid stratification "//&
978 "artifacts from altering the equivalent barotropic mode structure.",&
979 units=
"m", default=2000.)
980 allocate(cs%ebt_struct(isd:ied,jsd:jed,g%ke)) ; cs%ebt_struct(:,:,:) = 0.0
983 if (khtr_slope_cff>0. .or. khth_slope_cff>0.)
then
984 cs%calculate_Eady_growth_rate = .true.
985 call get_param(param_file, mdl,
"VISBECK_MAX_SLOPE", cs%Visbeck_S_max, &
986 "If non-zero, is an upper bound on slopes used in the "//&
987 "Visbeck formula for diffusivity. This does not affect the "//&
988 "isopycnal slope calculation used within thickness diffusion.", &
989 units=
"nondim", default=0.0)
992 if (cs%use_stored_slopes)
then
994 allocate(cs%slope_x(isdb:iedb,jsd:jed,g%ke+1)) ; cs%slope_x(:,:,:) = 0.0
995 allocate(cs%slope_y(isd:ied,jsdb:jedb,g%ke+1)) ; cs%slope_y(:,:,:) = 0.0
996 allocate(cs%N2_u(isdb:iedb,jsd:jed,g%ke+1)) ; cs%N2_u(:,:,:) = 0.0
997 allocate(cs%N2_v(isd:ied,jsdb:jedb,g%ke+1)) ; cs%N2_v(:,:,:) = 0.0
998 call get_param(param_file, mdl,
"KD_SMOOTH", cs%kappa_smooth, &
999 "A diapycnal diffusivity that is used to interpolate "//&
1000 "more sensible values of T & S into thin layers.", &
1001 units=
"m2 s-1", default=1.0e-6, scale=us%m_to_Z**2)
1004 if (cs%calculate_Eady_growth_rate)
then
1006 allocate(cs%SN_u(isdb:iedb,jsd:jed)) ; cs%SN_u(:,:) = 0.0
1007 allocate(cs%SN_v(isd:ied,jsdb:jedb)) ; cs%SN_v(:,:) = 0.0
1008 cs%id_SN_u = register_diag_field(
'ocean_model',
'SN_u', diag%axesCu1, time, &
1009 'Inverse eddy time-scale, S*N, at u-points',
's-1')
1010 cs%id_SN_v = register_diag_field(
'ocean_model',
'SN_v', diag%axesCv1, time, &
1011 'Inverse eddy time-scale, S*N, at v-points',
's-1')
1012 call get_param(param_file, mdl,
"VARMIX_KTOP", cs%VarMix_Ktop, &
1013 "The layer number at which to start vertical integration "//&
1014 "of S*N for purposes of finding the Eady growth rate.", &
1015 units=
"nondim", default=2)
1018 if (khtr_slope_cff>0. .or. khth_slope_cff>0.)
then
1020 call get_param(param_file, mdl,
"VISBECK_L_SCALE", cs%Visbeck_L_scale, &
1021 "The fixed length scale in the Visbeck formula.", units=
"m", &
1023 allocate(cs%L2u(isdb:iedb,jsd:jed)) ; cs%L2u(:,:) = 0.0
1024 allocate(cs%L2v(isd:ied,jsdb:jedb)) ; cs%L2v(:,:) = 0.0
1025 if (cs%Visbeck_L_scale<0)
then
1026 do j=js,je ;
do i=is-1,ieq
1027 cs%L2u(i,j) = cs%Visbeck_L_scale**2*g%areaCu(i,j)
1029 do j=js-1,jeq ;
do i=is,ie
1030 cs%L2v(i,j) = cs%Visbeck_L_scale**2*g%areaCv(i,j)
1033 cs%L2u(:,:) = cs%Visbeck_L_scale**2
1034 cs%L2v(:,:) = cs%Visbeck_L_scale**2
1037 cs%id_L2u = register_diag_field(
'ocean_model',
'L2u', diag%axesCu1, time, &
1038 'Length scale squared for mixing coefficient, at u-points',
'm2')
1039 cs%id_L2v = register_diag_field(
'ocean_model',
'L2v', diag%axesCv1, time, &
1040 'Length scale squared for mixing coefficient, at v-points',
'm2')
1043 if (cs%use_stored_slopes)
then
1044 cs%id_N2_u = register_diag_field(
'ocean_model',
'N2_u', diag%axesCui, time, &
1045 'Square of Brunt-Vaisala frequency, N^2, at u-points, as used in Visbeck et al.',
's-2')
1046 cs%id_N2_v = register_diag_field(
'ocean_model',
'N2_v', diag%axesCvi, time, &
1047 'Square of Brunt-Vaisala frequency, N^2, at v-points, as used in Visbeck et al.',
's-2')
1048 cs%id_S2_u = register_diag_field(
'ocean_model',
'S2_u', diag%axesCu1, time, &
1049 'Depth average square of slope magnitude, S^2, at u-points, as used in Visbeck et al.',
's-2')
1050 cs%id_S2_v = register_diag_field(
'ocean_model',
'S2_v', diag%axesCv1, time, &
1051 'Depth average square of slope magnitude, S^2, at v-points, as used in Visbeck et al.',
's-2')
1055 if (cs%Resoln_scaled_Kh .or. cs%Resoln_scaled_KhTh .or. cs%Resoln_scaled_KhTr)
then
1056 cs%calculate_Rd_dx = .true.
1057 cs%calculate_res_fns = .true.
1058 allocate(cs%Res_fn_h(isd:ied,jsd:jed)) ; cs%Res_fn_h(:,:) = 0.0
1059 allocate(cs%Res_fn_q(isdb:iedb,jsdb:jedb)) ; cs%Res_fn_q(:,:) = 0.0
1060 allocate(cs%Res_fn_u(isdb:iedb,jsd:jed)) ; cs%Res_fn_u(:,:) = 0.0
1061 allocate(cs%Res_fn_v(isd:ied,jsdb:jedb)) ; cs%Res_fn_v(:,:) = 0.0
1062 allocate(cs%beta_dx2_q(isdb:iedb,jsdb:jedb)) ; cs%beta_dx2_q(:,:) = 0.0
1063 allocate(cs%beta_dx2_u(isdb:iedb,jsd:jed)) ; cs%beta_dx2_u(:,:) = 0.0
1064 allocate(cs%beta_dx2_v(isd:ied,jsdb:jedb)) ; cs%beta_dx2_v(:,:) = 0.0
1065 allocate(cs%f2_dx2_q(isdb:iedb,jsdb:jedb)) ; cs%f2_dx2_q(:,:) = 0.0
1066 allocate(cs%f2_dx2_u(isdb:iedb,jsd:jed)) ; cs%f2_dx2_u(:,:) = 0.0
1067 allocate(cs%f2_dx2_v(isd:ied,jsdb:jedb)) ; cs%f2_dx2_v(:,:) = 0.0
1069 cs%id_Res_fn = register_diag_field(
'ocean_model',
'Res_fn', diag%axesT1, time, &
1070 'Resolution function for scaling diffusivities',
'nondim')
1072 call get_param(param_file, mdl,
"KH_RES_SCALE_COEF", cs%Res_coef_khth, &
1073 "A coefficient that determines how KhTh is scaled away if "//&
1074 "RESOLN_SCALED_... is true, as "//&
1075 "F = 1 / (1 + (KH_RES_SCALE_COEF*Rd/dx)^KH_RES_FN_POWER).", &
1076 units=
"nondim", default=1.0)
1077 call get_param(param_file, mdl,
"KH_RES_FN_POWER", cs%Res_fn_power_khth, &
1078 "The power of dx/Ld in the Kh resolution function. Any "//&
1079 "positive integer may be used, although even integers "//&
1080 "are more efficient to calculate. Setting this greater "//&
1081 "than 100 results in a step-function being used.", &
1082 units=
"nondim", default=2)
1083 call get_param(param_file, mdl,
"VISC_RES_SCALE_COEF", cs%Res_coef_visc, &
1084 "A coefficient that determines how Kh is scaled away if "//&
1085 "RESOLN_SCALED_... is true, as "//&
1086 "F = 1 / (1 + (KH_RES_SCALE_COEF*Rd/dx)^KH_RES_FN_POWER). "//&
1087 "This function affects lateral viscosity, Kh, and not KhTh.", &
1088 units=
"nondim", default=cs%Res_coef_khth)
1089 call get_param(param_file, mdl,
"VISC_RES_FN_POWER", cs%Res_fn_power_visc, &
1090 "The power of dx/Ld in the Kh resolution function. Any "//&
1091 "positive integer may be used, although even integers "//&
1092 "are more efficient to calculate. Setting this greater "//&
1093 "than 100 results in a step-function being used. "//&
1094 "This function affects lateral viscosity, Kh, and not KhTh.", &
1095 units=
"nondim", default=cs%Res_fn_power_khth)
1096 call get_param(param_file, mdl,
"INTERPOLATE_RES_FN", cs%interpolate_Res_fn, &
1097 "If true, interpolate the resolution function to the "//&
1098 "velocity points from the thickness points; otherwise "//&
1099 "interpolate the wave speed and calculate the resolution "//&
1100 "function independently at each point.", default=.true.)
1101 if (cs%interpolate_Res_fn)
then
1102 if (cs%Res_coef_visc /= cs%Res_coef_khth)
call mom_error(fatal, &
1103 "MOM_lateral_mixing_coeffs.F90, VarMix_init:"//&
1104 "When INTERPOLATE_RES_FN=True, VISC_RES_FN_POWER must equal KH_RES_SCALE_COEF.")
1105 if (cs%Res_fn_power_visc /= cs%Res_fn_power_khth)
call mom_error(fatal, &
1106 "MOM_lateral_mixing_coeffs.F90, VarMix_init:"//&
1107 "When INTERPOLATE_RES_FN=True, VISC_RES_FN_POWER must equal KH_RES_FN_POWER.")
1110 call get_param(param_file, mdl,
"GILL_EQUATORIAL_LD", gill_equatorial_ld, &
1111 "If true, uses Gill's definition of the baroclinic "//&
1112 "equatorial deformation radius, otherwise, if false, use "//&
1113 "Pedlosky's definition. These definitions differ by a factor "//&
1114 "of 2 in front of the beta term in the denominator. Gill's "//&
1115 "is the more appropriate definition.", default=.false.)
1116 if (gill_equatorial_ld)
then
1120 do j=js-1,jeq ;
do i=is-1,ieq
1121 cs%f2_dx2_q(i,j) = (g%dxBu(i,j)**2 + g%dyBu(i,j)**2) * &
1122 max(g%CoriolisBu(i,j)**2, absurdly_small_freq**2)
1123 cs%beta_dx2_q(i,j) = oneortwo * (g%dxBu(i,j)**2 + g%dyBu(i,j)**2) * (sqrt(0.5 * &
1124 ( (((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
1125 ((g%CoriolisBu(i+1,j)-g%CoriolisBu(i,j)) * g%IdxCv(i+1,j))**2) + &
1126 (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
1127 ((g%CoriolisBu(i,j+1)-g%CoriolisBu(i,j)) * g%IdyCu(i,j+1))**2) ) ))
1130 do j=js,je ;
do i=is-1,ieq
1131 cs%f2_dx2_u(i,j) = (g%dxCu(i,j)**2 + g%dyCu(i,j)**2) * &
1132 max(0.5* (g%CoriolisBu(i,j)**2+g%CoriolisBu(i,j-1)**2), absurdly_small_freq**2)
1133 cs%beta_dx2_u(i,j) = oneortwo * (g%dxCu(i,j)**2 + g%dyCu(i,j)**2) * (sqrt( &
1134 0.25*( (((g%CoriolisBu(i,j-1)-g%CoriolisBu(i-1,j-1)) * g%IdxCv(i,j-1))**2 + &
1135 ((g%CoriolisBu(i+1,j)-g%CoriolisBu(i,j)) * g%IdxCv(i+1,j))**2) + &
1136 (((g%CoriolisBu(i+1,j-1)-g%CoriolisBu(i,j-1)) * g%IdxCv(i+1,j-1))**2 + &
1137 ((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2) ) + &
1138 ((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 ))
1141 do j=js-1,jeq ;
do i=is,ie
1142 cs%f2_dx2_v(i,j) = (g%dxCv(i,j)**2 + g%dyCv(i,j)**2) * &
1143 max(0.5*(g%CoriolisBu(i,j)**2+g%CoriolisBu(i-1,j)**2), absurdly_small_freq**2)
1144 cs%beta_dx2_v(i,j) = oneortwo * (g%dxCv(i,j)**2 + g%dyCv(i,j)**2) * (sqrt( &
1145 ((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
1146 0.25*( (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
1147 ((g%CoriolisBu(i-1,j+1)-g%CoriolisBu(i-1,j)) * g%IdyCu(i-1,j+1))**2) + &
1148 (((g%CoriolisBu(i,j+1)-g%CoriolisBu(i,j)) * g%IdyCu(i,j+1))**2 + &
1149 ((g%CoriolisBu(i-1,j)-g%CoriolisBu(i-1,j-1)) * g%IdyCu(i-1,j))**2) ) ))
1155 cs%id_Rd_dx = register_diag_field(
'ocean_model',
'Rd_dx', diag%axesT1, time, &
1156 'Ratio between deformation radius and grid spacing',
'm m-1')
1157 cs%calculate_Rd_dx = cs%calculate_Rd_dx .or. (cs%id_Rd_dx>0)
1159 if (cs%calculate_Rd_dx)
then
1160 cs%calculate_cg1 = .true.
1161 allocate(cs%Rd_dx_h(isd:ied,jsd:jed)) ; cs%Rd_dx_h(:,:) = 0.0
1162 allocate(cs%beta_dx2_h(isd:ied,jsd:jed)); cs%beta_dx2_h(:,:) = 0.0
1163 allocate(cs%f2_dx2_h(isd:ied,jsd:jed)) ; cs%f2_dx2_h(:,:) = 0.0
1164 do j=js-1,je+1 ;
do i=is-1,ie+1
1165 cs%f2_dx2_h(i,j) = (g%dxT(i,j)**2 + g%dyT(i,j)**2) * &
1166 max(0.25 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1167 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2)), &
1168 absurdly_small_freq**2)
1169 cs%beta_dx2_h(i,j) = oneortwo * (g%dxT(i,j)**2 + g%dyT(i,j)**2) * (sqrt(0.5 * &
1170 ( (((g%CoriolisBu(i,j)-g%CoriolisBu(i-1,j)) * g%IdxCv(i,j))**2 + &
1171 ((g%CoriolisBu(i,j-1)-g%CoriolisBu(i-1,j-1)) * g%IdxCv(i,j-1))**2) + &
1172 (((g%CoriolisBu(i,j)-g%CoriolisBu(i,j-1)) * g%IdyCu(i,j))**2 + &
1173 ((g%CoriolisBu(i-1,j)-g%CoriolisBu(i-1,j-1)) * g%IdyCu(i-1,j))**2) ) ))
1177 if (cs%calculate_cg1)
then
1179 allocate(cs%cg1(isd:ied,jsd:jed)); cs%cg1(:,:) = 0.0
1180 call wave_speed_init(cs%wave_speed_CSp, use_ebt_mode=cs%Resoln_use_ebt, mono_n2_depth=n2_filter_depth)
1184 call get_param(param_file, mdl,
"USE_QG_LEITH_GM", cs%use_QG_Leith_GM, &
1185 "If true, use the QG Leith viscosity as the GM coefficient.", &
1188 if (cs%Use_QG_Leith_GM)
then
1189 call get_param(param_file, mdl,
"LEITH_LAP_CONST", leith_lap_const, &
1190 "The nondimensional Laplacian Leith constant, \n"//&
1191 "often set to 1.0", units=
"nondim", default=0.0)
1193 call get_param(param_file, mdl,
"USE_BETA_IN_LEITH", cs%use_beta_in_QG_Leith, &
1194 "If true, include the beta term in the Leith nonlinear eddy viscosity.", &
1197 alloc_(cs%Laplac3_const_u(isdb:iedb,jsd:jed)) ; cs%Laplac3_const_u(:,:) = 0.0
1198 alloc_(cs%Laplac3_const_v(isd:ied,jsdb:jedb)) ; cs%Laplac3_const_v(:,:) = 0.0
1199 alloc_(cs%KH_u_QG(isdb:iedb,jsd:jed,g%ke)) ; cs%KH_u_QG(:,:,:) = 0.0
1200 alloc_(cs%KH_v_QG(isd:ied,jsdb:jedb,g%ke)) ; cs%KH_v_QG(:,:,:) = 0.0
1203 cs%id_KH_u_QG = register_diag_field(
'ocean_model',
'KH_u_QG', diag%axesCuL, time, &
1204 'Horizontal viscosity from Leith QG, at u-points',
'm2 s-1')
1205 cs%id_KH_v_QG = register_diag_field(
'ocean_model',
'KH_v_QG', diag%axesCvL, time, &
1206 'Horizontal viscosity from Leith QG, at v-points',
'm2 s-1')
1208 do j=jsq,jeq+1 ;
do i=is-1,ieq
1210 grid_sp_u2 = g%dyCu(i,j)*g%dxCu(i,j)
1211 grid_sp_u3 = grid_sp_u2*sqrt(grid_sp_u2)
1212 cs%Laplac3_const_u(i,j) = leith_lap_const * grid_sp_u3
1214 do j=js-1,jeq ;
do i=isq,ieq+1
1216 grid_sp_v2 = g%dyCv(i,j)*g%dxCu(i,j)
1217 grid_sp_v3 = grid_sp_v2*sqrt(grid_sp_v2)
1218 cs%Laplac3_const_v(i,j) = leith_lap_const * grid_sp_v3
1221 if (.not. cs%use_stored_slopes)
call mom_error(fatal, &
1222 "MOM_lateral_mixing_coeffs.F90, VarMix_init:"//&
1223 "USE_STORED_SLOPES must be True when using QG Leith.")
1228 cs%use_variable_mixing = .true.
1234 end subroutine varmix_init