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
26 use mom_kappa_shear,
only : calc_kappa_shear_vertex, kappa_shear_at_vertex
40 implicit none ;
private
42 #include <MOM_memory.h>
44 public set_diffusivity
46 public set_diffusivity_init
47 public set_diffusivity_end
58 logical :: bulkmixedlayer
64 logical :: bottomdraglaw
66 logical :: bbl_mixing_as_max
70 logical :: use_lotw_bbl_diffusivity
71 logical :: lotw_bbl_use_omega
88 logical :: limit_dissipation
99 logical :: ml_radiation
112 real :: ml_rad_kd_max
114 real :: ml_rad_efold_coeff
118 logical :: ml_rad_bug
121 logical :: ml_rad_tke_decay
130 logical :: ml_use_omega
133 real :: ml_omega_frac
136 logical :: user_change_diff
137 logical :: usekappashear
139 logical :: vertex_shear
141 logical :: use_cvmix_shear
143 logical :: double_diffusion
144 logical :: use_cvmix_ddiff
145 logical :: simple_tke_to_kd
147 real :: max_rrho_salt_fingers
148 real :: max_salt_diff_salt_fingers
151 logical :: answers_2018
155 character(len=200) :: inputdir
165 integer :: id_maxtke = -1, id_tke_to_kd = -1, id_kd_user = -1
166 integer :: id_kd_layer = -1, id_kd_bbl = -1, id_n2 = -1
167 integer :: id_kd_work = -1, id_kt_extra = -1, id_ks_extra = -1
174 real,
pointer,
dimension(:,:,:) :: &
180 kt_extra => null(), &
182 real,
pointer,
dimension(:,:,:) :: tke_to_kd => null()
190 integer :: id_clock_kappashear, id_clock_cvmix_ddiff
205 subroutine set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt_in_T, &
206 G, GV, US, CS, Kd_lay, Kd_int)
210 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
212 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
214 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
216 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
218 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
222 type(
forcing),
intent(in) :: fluxes
223 type(optics_type),
pointer :: optics
227 real,
intent(in) :: dt_in_t
229 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
230 intent(out) :: kd_lay
231 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
232 optional,
intent(out) :: kd_int
235 real,
dimension(SZI_(G)) :: &
240 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
243 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
247 real,
dimension(SZI_(G),SZK_(G)) :: &
248 n2_lay, & !< squared buoyancy frequency associated with layers [T-2 ~> s-2]
249 maxtke, & !< energy required to entrain to h_max [m3 T-3]
254 real,
dimension(SZI_(G),SZK_(G)+1) :: &
255 n2_int, & !< squared buoyancy frequency associated at interfaces [T-2 ~> s-2]
256 drho_int, & !< locally ref potential density difference across interfaces [kg m-3]
257 kt_extra, & !< double difusion diffusivity of temperature [Z2 T-1 ~> m2 s-1]
265 integer :: kb(szi_(g))
267 logical :: showcalltree
269 integer :: i, j, k, is, ie, js, je, nz
270 integer :: isd, ied, jsd, jed
272 real :: kappa_dt_fill
274 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
275 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
276 showcalltree = calltree_showquery()
277 if (showcalltree)
call calltree_enter(
"set_diffusivity(), MOM_set_diffusivity.F90")
279 if (.not.
associated(cs))
call mom_error(fatal,
"set_diffusivity: "//&
280 "Module must be initialized before it is used.")
282 i_rho0 = 1.0 / gv%Rho0
284 if (cs%answers_2018)
then
285 kappa_dt_fill = us%m_to_Z**2 * 1.e-3 * 7200.
287 kappa_dt_fill = cs%Kd_smooth * dt_in_t
289 omega2 = cs%omega * cs%omega
291 use_eos =
associated(tv%eqn_of_state)
293 if ((cs%use_CVMix_ddiff .or. cs%double_diffusion) .and. .not. &
294 (
associated(visc%Kd_extra_T) .and.
associated(visc%Kd_extra_S))) &
295 call mom_error(fatal,
"set_diffusivity: both visc%Kd_extra_T and "//&
296 "visc%Kd_extra_S must be associated when USE_CVMIX_DDIFF or DOUBLE_DIFFUSION are true.")
300 kd_lay(:,:,:) = cs%Kd
301 kd_int(:,:,:) = cs%Kd
302 if (
associated(visc%Kv_slow)) visc%Kv_slow(:,:,:) = cs%Kv
306 if (cs%id_N2 > 0)
then
307 allocate(dd%N2_3d(isd:ied,jsd:jed,nz+1)) ; dd%N2_3d(:,:,:) = 0.0
309 if (cs%id_Kd_user > 0)
then
310 allocate(dd%Kd_user(isd:ied,jsd:jed,nz+1)) ; dd%Kd_user(:,:,:) = 0.0
312 if (cs%id_Kd_work > 0)
then
313 allocate(dd%Kd_work(isd:ied,jsd:jed,nz)) ; dd%Kd_work(:,:,:) = 0.0
315 if (cs%id_maxTKE > 0)
then
316 allocate(dd%maxTKE(isd:ied,jsd:jed,nz)) ; dd%maxTKE(:,:,:) = 0.0
318 if (cs%id_TKE_to_Kd > 0)
then
319 allocate(dd%TKE_to_Kd(isd:ied,jsd:jed,nz)) ; dd%TKE_to_Kd(:,:,:) = 0.0
321 if (cs%id_KT_extra > 0)
then
322 allocate(dd%KT_extra(isd:ied,jsd:jed,nz+1)) ; dd%KT_extra(:,:,:) = 0.0
324 if (cs%id_KS_extra > 0)
then
325 allocate(dd%KS_extra(isd:ied,jsd:jed,nz+1)) ; dd%KS_extra(:,:,:) = 0.0
327 if (cs%id_Kd_BBL > 0)
then
328 allocate(dd%Kd_BBL(isd:ied,jsd:jed,nz+1)) ; dd%Kd_BBL(:,:,:) = 0.0
332 call setup_tidal_diagnostics(g,cs%tm_csp)
337 call hchksum(tv%T,
"before vert_fill_TS tv%T",g%HI)
338 call hchksum(tv%S,
"before vert_fill_TS tv%S",g%HI)
339 call hchksum(h,
"before vert_fill_TS h",g%HI, scale=gv%H_to_m)
341 call vert_fill_ts(h, tv%T, tv%S, kappa_dt_fill, t_f, s_f, g, gv, larger_h_denom=.true.)
343 call hchksum(tv%T,
"after vert_fill_TS tv%T",g%HI)
344 call hchksum(tv%S,
"after vert_fill_TS tv%S",g%HI)
345 call hchksum(h,
"after vert_fill_TS h",g%HI, scale=gv%H_to_m)
349 if (cs%useKappaShear)
then
351 call hchksum(u_h,
"before calc_KS u_h",g%HI)
352 call hchksum(v_h,
"before calc_KS v_h",g%HI)
354 call cpu_clock_begin(id_clock_kappashear)
355 if (cs%Vertex_shear)
then
356 call full_convection(g, gv, h, tv, t_adj, s_adj, fluxes%p_surf, &
357 (gv%Z_to_H**2)*kappa_dt_fill, halo=1)
359 call calc_kappa_shear_vertex(u, v, h, t_adj, s_adj, tv, fluxes%p_surf, visc%Kd_shear, &
360 visc%TKE_turb, visc%Kv_shear_Bu, dt_in_t, g, gv, us, cs%kappaShear_CSp)
361 if (
associated(visc%Kv_shear)) visc%Kv_shear(:,:,:) = 0.0
363 call hchksum(visc%Kd_shear,
"after calc_KS_vert visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
364 call bchksum(visc%Kv_shear_Bu,
"after calc_KS_vert visc%Kv_shear_Bu", g%HI, scale=us%Z2_T_to_m2_s)
365 call bchksum(visc%TKE_turb,
"after calc_KS_vert visc%TKE_turb", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
369 call calculate_kappa_shear(u_h, v_h, h, tv, fluxes%p_surf, visc%Kd_shear, visc%TKE_turb, &
370 visc%Kv_shear, dt_in_t, g, gv, us, cs%kappaShear_CSp)
372 call hchksum(visc%Kd_shear,
"after calc_KS visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
373 call hchksum(visc%Kv_shear,
"after calc_KS visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
374 call hchksum(visc%TKE_turb,
"after calc_KS visc%TKE_turb", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
377 call cpu_clock_end(id_clock_kappashear)
378 if (showcalltree)
call calltree_waypoint(
"done with calculate_kappa_shear (set_diffusivity)")
379 elseif (cs%use_CVMix_shear)
then
381 call calculate_cvmix_shear(u_h, v_h, h, tv, visc%Kd_shear, visc%Kv_shear, g, gv, us, cs%CVMix_shear_CSp)
383 call hchksum(visc%Kd_shear,
"after CVMix_shear visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
384 call hchksum(visc%Kv_shear,
"after CVMix_shear visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
386 elseif (
associated(visc%Kv_shear))
then
387 visc%Kv_shear(:,:,:) = 0.0
395 call sfc_bkgnd_mixing(g, us, cs%bkgnd_mixing_csp)
402 call find_n2(h, tv, t_f, s_f, fluxes, j, g, gv, us, cs, drho_int, n2_lay, n2_int, n2_bot)
404 if (
associated(dd%N2_3d))
then
405 do k=1,nz+1 ;
do i=is,ie ; dd%N2_3d(i,j,k) = n2_int(i,k) ;
enddo ;
enddo
409 call calculate_bkgnd_mixing(h, tv, n2_lay, kd_lay, visc%Kv_slow, j, g, gv, us, cs%bkgnd_mixing_csp)
412 if (cs%double_diffusion)
then
413 call double_diffusion(tv, h, t_f, s_f, j, g, gv, us, cs, kt_extra, ks_extra)
414 do k=2,nz ;
do i=is,ie
415 if (ks_extra(i,k) > kt_extra(i,k))
then
416 kd_lay(i,j,k-1) = kd_lay(i,j,k-1) + 0.5 * kt_extra(i,k)
417 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * kt_extra(i,k)
418 visc%Kd_extra_S(i,j,k) = (ks_extra(i,k) - kt_extra(i,k))
419 visc%Kd_extra_T(i,j,k) = 0.0
420 elseif (kt_extra(i,k) > 0.0)
then
421 kd_lay(i,j,k-1) = kd_lay(i,j,k-1) + 0.5 * ks_extra(i,k)
422 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * ks_extra(i,k)
423 visc%Kd_extra_T(i,j,k) = (kt_extra(i,k) - ks_extra(i,k))
424 visc%Kd_extra_S(i,j,k) = 0.0
426 visc%Kd_extra_T(i,j,k) = 0.0
427 visc%Kd_extra_S(i,j,k) = 0.0
430 if (
associated(dd%KT_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
431 dd%KT_extra(i,j,k) = kt_extra(i,k)
432 enddo ;
enddo ;
endif
434 if (
associated(dd%KS_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
435 dd%KS_extra(i,j,k) = ks_extra(i,k)
436 enddo ;
enddo ;
endif
441 if (cs%use_CVMix_ddiff)
then
442 call cpu_clock_begin(id_clock_cvmix_ddiff)
443 call compute_ddiff_coeffs(h, tv, g, gv, us, j, visc%Kd_extra_T, visc%Kd_extra_S, cs%CVMix_ddiff_csp)
444 call cpu_clock_end(id_clock_cvmix_ddiff)
448 if (cs%useKappaShear .or. cs%use_CVMix_shear)
then
449 if (
present(kd_int))
then
450 do k=2,nz ;
do i=is,ie
451 kd_int(i,j,k) = visc%Kd_shear(i,j,k) + 0.5 * (kd_lay(i,j,k-1) + kd_lay(i,j,k))
454 kd_int(i,j,1) = visc%Kd_shear(i,j,1)
455 kd_int(i,j,nz+1) = 0.0
458 do k=1,nz ;
do i=is,ie
459 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * (visc%Kd_shear(i,j,k) + visc%Kd_shear(i,j,k+1))
462 if (
present(kd_int))
then
464 kd_int(i,j,1) = kd_lay(i,j,1) ; kd_int(i,j,nz+1) = 0.0
466 do k=2,nz ;
do i=is,ie
467 kd_int(i,j,k) = 0.5 * (kd_lay(i,j,k-1) + kd_lay(i,j,k))
472 call find_tke_to_kd(h, tv, drho_int, n2_lay, j, dt_in_t, g, gv, us, cs, tke_to_kd, &
474 if (
associated(dd%maxTKE))
then ;
do k=1,nz ;
do i=is,ie
475 dd%maxTKE(i,j,k) = maxtke(i,k)
476 enddo ;
enddo ;
endif
477 if (
associated(dd%TKE_to_Kd))
then ;
do k=1,nz ;
do i=is,ie
478 dd%TKE_to_Kd(i,j,k) = tke_to_kd(i,k)
479 enddo ;
enddo ;
endif
482 if (cs%ML_radiation) &
483 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, kd_lay, tke_to_kd, kd_int)
486 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tm_csp, &
487 n2_lay, n2_int, kd_lay, kd_int, cs%Kd_max, visc%Kv_slow)
491 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then
492 if (cs%use_LOTW_BBL_diffusivity)
then
493 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
494 kd_lay, kd_int, dd%Kd_BBL)
496 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
497 maxtke, kb, g, gv, us, cs, kd_lay, kd_int, dd%Kd_BBL)
501 if (cs%limit_dissipation)
then
507 do k=2,nz-1 ;
do i=is,ie
508 dissip = max( cs%dissip_min, &
509 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_lay(i,k)), &
510 cs%dissip_N2 * n2_lay(i,k))
511 kd_lay(i,j,k) = max(kd_lay(i,j,k) , &
512 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_lay(i,k) + omega2))))
515 if (
present(kd_int))
then ;
do k=2,nz ;
do i=is,ie
516 dissip = max( cs%dissip_min, &
517 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_int(i,k)), &
518 cs%dissip_N2 * n2_int(i,k))
519 kd_int(i,j,k) = max(kd_int(i,j,k) , &
520 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_int(i,k) + omega2))))
521 enddo ;
enddo ;
endif
524 if (
associated(dd%Kd_work))
then
525 do k=1,nz ;
do i=is,ie
526 dd%Kd_Work(i,j,k) = gv%Rho0 * kd_lay(i,j,k) * n2_lay(i,k) * &
533 call hchksum(kd_lay ,
"Kd_lay", g%HI, haloshift=0, &
534 scale=us%Z2_T_to_m2_s)
536 if (cs%useKappaShear)
call hchksum(visc%Kd_shear,
"Turbulent Kd", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
538 if (cs%use_CVMix_ddiff)
then
539 call hchksum(visc%Kd_extra_T,
"MOM_set_diffusivity: Kd_extra_T", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
540 call hchksum(visc%Kd_extra_S,
"MOM_set_diffusivity: Kd_extra_S", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
543 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v))
then
544 call uvchksum(
"BBL Kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, &
545 g%HI, 0, symmetric=.true., scale=us%Z2_T_to_m2_s)
548 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v))
then
549 call uvchksum(
"BBL bbl_thick_[uv]", visc%bbl_thick_u, &
550 visc%bbl_thick_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m)
553 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v))
then
554 call uvchksum(
"Ray_[uv]", visc%Ray_u, visc%Ray_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m*us%s_to_T)
559 if (cs%Kd_add > 0.0)
then
560 if (
present(kd_int))
then
562 do k=1,nz ;
do j=js,je ;
do i=is,ie
563 kd_int(i,j,k) = kd_int(i,j,k) + cs%Kd_add
564 kd_lay(i,j,k) = kd_lay(i,j,k) + cs%Kd_add
565 enddo ;
enddo ;
enddo
568 do k=1,nz ;
do j=js,je ;
do i=is,ie
569 kd_lay(i,j,k) = kd_lay(i,j,k) + cs%Kd_add
570 enddo ;
enddo ;
enddo
574 if (cs%user_change_diff)
then
575 call user_change_diff(h, tv, g, gv, cs%user_change_diff_CSp, kd_lay, kd_int, &
576 t_f, s_f, dd%Kd_user)
582 if (cs%bkgnd_mixing_csp%id_kd_bkgnd > 0) &
583 call post_data(cs%bkgnd_mixing_csp%id_kd_bkgnd, cs%bkgnd_mixing_csp%kd_bkgnd, cs%bkgnd_mixing_csp%diag)
584 if (cs%bkgnd_mixing_csp%id_kv_bkgnd > 0) &
585 call post_data(cs%bkgnd_mixing_csp%id_kv_bkgnd, cs%bkgnd_mixing_csp%kv_bkgnd, cs%bkgnd_mixing_csp%diag)
588 if (cs%CVMix_ddiff_csp%id_KT_extra > 0) &
589 call post_data(cs%CVMix_ddiff_csp%id_KT_extra, visc%Kd_extra_T, cs%CVMix_ddiff_csp%diag)
590 if (cs%CVMix_ddiff_csp%id_KS_extra > 0) &
591 call post_data(cs%CVMix_ddiff_csp%id_KS_extra, visc%Kd_extra_S, cs%CVMix_ddiff_csp%diag)
592 if (cs%CVMix_ddiff_csp%id_R_rho > 0) &
593 call post_data(cs%CVMix_ddiff_csp%id_R_rho, cs%CVMix_ddiff_csp%R_rho, cs%CVMix_ddiff_csp%diag)
595 if (cs%id_Kd_layer > 0)
call post_data(cs%id_Kd_layer, kd_lay, cs%diag)
598 call post_tidal_diagnostics(g,gv,h,cs%tm_csp)
600 if (cs%tm_csp%Int_tide_dissipation .or. cs%tm_csp%Lee_wave_dissipation .or. &
601 cs%tm_csp%Lowmode_itidal_dissipation)
then
603 if (cs%id_N2 > 0)
call post_data(cs%id_N2, dd%N2_3d, cs%diag)
604 if (cs%id_Kd_user > 0)
call post_data(cs%id_Kd_user, dd%Kd_user, cs%diag)
605 if (cs%id_Kd_Work > 0)
call post_data(cs%id_Kd_Work, dd%Kd_Work, cs%diag)
606 if (cs%id_maxTKE > 0)
call post_data(cs%id_maxTKE, dd%maxTKE, cs%diag)
607 if (cs%id_TKE_to_Kd > 0)
call post_data(cs%id_TKE_to_Kd, dd%TKE_to_Kd, cs%diag)
610 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, dd%KT_extra, cs%diag)
611 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, dd%KS_extra, cs%diag)
612 if (cs%id_Kd_BBL > 0)
call post_data(cs%id_Kd_BBL, dd%Kd_BBL, cs%diag)
614 if (
associated(dd%N2_3d))
deallocate(dd%N2_3d)
615 if (
associated(dd%Kd_work))
deallocate(dd%Kd_work)
616 if (
associated(dd%Kd_user))
deallocate(dd%Kd_user)
617 if (
associated(dd%maxTKE))
deallocate(dd%maxTKE)
618 if (
associated(dd%TKE_to_Kd))
deallocate(dd%TKE_to_Kd)
619 if (
associated(dd%KT_extra))
deallocate(dd%KT_extra)
620 if (
associated(dd%KS_extra))
deallocate(dd%KS_extra)
621 if (
associated(dd%Kd_BBL))
deallocate(dd%Kd_BBL)
623 if (showcalltree)
call calltree_leave(
"set_diffusivity()")
625 end subroutine set_diffusivity
628 subroutine find_tke_to_kd(h, tv, dRho_int, N2_lay, j, dt, G, GV, US, CS, &
629 TKE_to_Kd, maxTKE, kb)
633 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
637 real,
dimension(SZI_(G),SZK_(G)+1),
intent(in) :: dRho_int
639 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: N2_lay
641 integer,
intent(in) :: j
642 real,
intent(in) :: dt
644 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: TKE_to_Kd
649 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: maxTKE
651 integer,
dimension(SZI_(G)),
intent(out) :: kb
654 real,
dimension(SZI_(G),SZK_(G)) :: &
666 real,
dimension(SZI_(G)) :: &
686 logical :: do_i(SZI_(G))
688 integer :: i, k, is, ie, nz, i_rem, kmb, kb_min
689 is = g%isc ; ie = g%iec ; nz = g%ke
693 h_neglect = gv%H_subroundoff
694 g_rho0 = (us%L_to_Z**2 * gv%g_Earth) / gv%Rho0
695 if (cs%answers_2018)
then
696 i_rho0 = 1.0 / gv%Rho0
697 g_irho0 = (us%L_to_Z**2 * gv%g_Earth) * i_rho0
703 if (cs%simple_TKE_to_Kd)
then
704 do k=1,nz ;
do i=is,ie
705 hn2po2 = (gv%H_to_Z * h(i,j,k)) * (n2_lay(i,k) + omega2)
707 tke_to_kd(i,k) = 1.0 / hn2po2
708 else; tke_to_kd(i,k) = 0.;
endif
711 maxtke(i,k) = hn2po2 * cs%Kd_max
718 if (cs%bulkmixedlayer)
then
719 kmb = gv%nk_rho_varies
720 do i=is,ie ; p_0(i) = 0.0 ; p_ref(i) = tv%P_Ref ;
enddo
723 is, ie-is+1, tv%eqn_of_state)
726 is, ie-is+1, tv%eqn_of_state)
732 do k=kmb+1,nz-1 ;
if (rcv_kmb(i) <= gv%Rlay(k))
exit ;
enddo
737 do k=kb(i)-1,kmb+1,-1
738 if (rho_0(i,kmb) > rho_0(i,k))
exit
739 if (h(i,j,k)>2.0*gv%Angstrom_H) kb(i) = k
743 call set_density_ratios(h, tv, kb, g, gv, us, cs, j, ds_dsp1, rho_0)
746 do i=is,ie ; kb(i) = 1 ;
enddo
747 call set_density_ratios(h, tv, kb, g, gv, us, cs, j, ds_dsp1)
752 do k=2,nz-1 ;
do i=is,ie
753 dsp1_ds(i,k) = 1.0 / ds_dsp1(i,k)
755 do i=is,ie ; dsp1_ds(i,nz) = 0.0 ;
enddo
757 if (cs%bulkmixedlayer)
then
758 kmb = gv%nk_rho_varies
760 htot(i) = gv%H_to_Z*h(i,j,kmb)
763 mfkb(i) = ds_dsp1(i,kb(i)) * (gv%H_to_Z*(h(i,j,kmb) - gv%Angstrom_H))
765 do k=1,kmb-1 ;
do i=is,ie
766 htot(i) = htot(i) + gv%H_to_Z*h(i,j,k)
767 mfkb(i) = mfkb(i) + ds_dsp1(i,k+1)*(gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H))
771 maxent(i,1) = 0.0 ; htot(i) = gv%H_to_Z*(h(i,j,1) - gv%Angstrom_H)
774 do k=kb_min,nz-1 ;
do i=is,ie
776 maxent(i,kb(i)) = mfkb(i)
777 elseif (k > kb(i))
then
778 if (cs%answers_2018)
then
779 maxent(i,k) = (1.0/dsp1_ds(i,k))*(maxent(i,k-1) + htot(i))
781 maxent(i,k) = ds_dsp1(i,k)*(maxent(i,k-1) + htot(i))
783 htot(i) = htot(i) + gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H)
788 htot(i) = gv%H_to_Z*(h(i,j,nz) - gv%Angstrom_H) ; maxent(i,nz) = 0.0
789 do_i(i) = (g%mask2dT(i,j) > 0.5)
793 do i=is,ie ;
if (do_i(i))
then
794 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif
796 maxent(i,k) = min(maxent(i,k),dsp1_ds(i,k+1)*maxent(i,k+1) + htot(i))
797 htot(i) = htot(i) + gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H)
804 maxtke(i,1) = 0.0 ; tke_to_kd(i,1) = 0.0
805 maxtke(i,nz) = 0.0 ; tke_to_kd(i,nz) = 0.0
807 do k=2,kmb ;
do i=is,ie
809 tke_to_kd(i,k) = 1.0 / ((n2_lay(i,k) + omega2) * &
810 (gv%H_to_Z*(h(i,j,k) + h_neglect)))
812 do k=kmb+1,kb_min-1 ;
do i=is,ie
815 maxtke(i,k) = 0.0 ; tke_to_kd(i,k) = 0.0
817 do k=kb_min,nz-1 ;
do i=is,ie
827 dh_max = maxent(i,k) * (1.0 + dsp1_ds(i,k))
828 drho_lay = 0.5 * max(drho_int(i,k) + drho_int(i,k+1), 0.0)
829 maxtke(i,k) = i_dt * (g_irho0 * &
830 (0.5*max(drho_int(i,k+1) + dsp1_ds(i,k)*drho_int(i,k), 0.0))) * &
831 ((gv%H_to_Z*h(i,j,k) + dh_max) * maxent(i,k))
835 tke_to_kd(i,k) = 1.0 / (g_rho0 * drho_lay + &
836 cs%omega**2 * gv%H_to_Z*(h(i,j,k) + h_neglect))
840 end subroutine find_tke_to_kd
843 subroutine find_n2(h, tv, T_f, S_f, fluxes, j, G, GV, US, CS, dRho_int, &
844 N2_lay, N2_int, N2_bot)
848 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
852 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
855 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
858 type(
forcing),
intent(in) :: fluxes
859 integer,
intent(in) :: j
861 real,
dimension(SZI_(G),SZK_(G)+1), &
862 intent(out) :: dRho_int
864 real,
dimension(SZI_(G),SZK_(G)+1), &
865 intent(out) :: N2_int
866 real,
dimension(SZI_(G),SZK_(G)), &
867 intent(out) :: N2_lay
868 real,
dimension(SZI_(G)),
intent(out) :: N2_bot
870 real,
dimension(SZI_(G),SZK_(G)+1) :: &
875 real,
dimension(SZI_(G)) :: &
890 logical :: do_i(SZI_(G)), do_any
891 integer :: i, k, is, ie, nz
893 is = g%isc ; ie = g%iec ; nz = g%ke
894 g_rho0 = (us%L_to_Z**2 * gv%g_Earth) / gv%Rho0
895 h_neglect = gv%H_subroundoff
899 drho_int(i,1) = 0.0 ; drho_int(i,nz+1) = 0.0
900 drho_int_unfilt(i,1) = 0.0 ; drho_int_unfilt(i,nz+1) = 0.0
902 if (
associated(tv%eqn_of_state))
then
903 if (
associated(fluxes%p_surf))
then
904 do i=is,ie ; pres(i) = fluxes%p_surf(i,j) ;
enddo
906 do i=is,ie ; pres(i) = 0.0 ;
enddo
910 pres(i) = pres(i) + gv%H_to_Pa*h(i,j,k-1)
911 temp_int(i) = 0.5 * (t_f(i,j,k) + t_f(i,j,k-1))
912 salin_int(i) = 0.5 * (s_f(i,j,k) + s_f(i,j,k-1))
915 drho_dt(:,k), drho_ds(:,k), is, ie-is+1, tv%eqn_of_state)
917 drho_int(i,k) = max(drho_dt(i,k)*(t_f(i,j,k) - t_f(i,j,k-1)) + &
918 drho_ds(i,k)*(s_f(i,j,k) - s_f(i,j,k-1)), 0.0)
919 drho_int_unfilt(i,k) = max(drho_dt(i,k)*(tv%T(i,j,k) - tv%T(i,j,k-1)) + &
920 drho_ds(i,k)*(tv%S(i,j,k) - tv%S(i,j,k-1)), 0.0)
924 do k=2,nz ;
do i=is,ie
925 drho_int(i,k) = gv%Rlay(k) - gv%Rlay(k-1)
930 do k=1,nz ;
do i=is,ie
931 n2_lay(i,k) = g_rho0 * 0.5*(drho_int(i,k) + drho_int(i,k+1)) / &
932 (gv%H_to_Z*(h(i,j,k) + h_neglect))
934 do i=is,ie ; n2_int(i,1) = 0.0 ; n2_int(i,nz+1) = 0.0 ;
enddo
935 do k=2,nz ;
do i=is,ie
936 n2_int(i,k) = g_rho0 * drho_int(i,k) / &
937 (0.5*gv%H_to_Z*(h(i,j,k-1) + h(i,j,k) + h_neglect))
942 hb(i) = 0.0 ; drho_bot(i) = 0.0
943 z_from_bot(i) = 0.5*gv%H_to_Z*h(i,j,nz)
944 do_i(i) = (g%mask2dT(i,j) > 0.5)
946 if ( (cs%tm_csp%Int_tide_dissipation .or. cs%tm_csp%Lee_wave_dissipation) .and. &
947 .not. cs%tm_csp%use_CVMix_tidal )
then
948 h_amp(i) = sqrt(cs%tm_csp%h2(i,j))
956 do i=is,ie ;
if (do_i(i))
then
957 dz_int = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j,k-1))
958 z_from_bot(i) = z_from_bot(i) + dz_int
960 hb(i) = hb(i) + dz_int
961 drho_bot(i) = drho_bot(i) + drho_int(i,k)
963 if (z_from_bot(i) > h_amp(i))
then
966 hb(i) = hb(i) + 0.5*gv%H_to_Z*(h(i,j,k-1) + h(i,j,k-2))
967 drho_bot(i) = drho_bot(i) + drho_int(i,k-1)
974 if (.not.do_any)
exit
978 if (hb(i) > 0.0)
then
979 n2_bot(i) = (g_rho0 * drho_bot(i)) / hb(i)
980 else ; n2_bot(i) = 0.0 ;
endif
981 z_from_bot(i) = 0.5*gv%H_to_Z*h(i,j,nz)
982 do_i(i) = (g%mask2dT(i,j) > 0.5)
987 do i=is,ie ;
if (do_i(i))
then
988 dz_int = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j,k-1))
989 z_from_bot(i) = z_from_bot(i) + dz_int
991 n2_int(i,k) = n2_bot(i)
992 if (k>2) n2_lay(i,k-1) = n2_bot(i)
994 if (z_from_bot(i) > h_amp(i))
then
995 if (k>2) n2_int(i,k-1) = n2_bot(i)
1001 if (.not.do_any)
exit
1004 if (
associated(tv%eqn_of_state))
then
1005 do k=1,nz+1 ;
do i=is,ie
1006 drho_int(i,k) = drho_int_unfilt(i,k)
1010 end subroutine find_n2
1019 subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, US, CS, Kd_T_dd, Kd_S_dd)
1025 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1027 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1030 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1033 integer,
intent(in) :: j
1035 real,
dimension(SZI_(G),SZK_(G)+1), &
1036 intent(out) :: Kd_T_dd
1038 real,
dimension(SZI_(G),SZK_(G)+1), &
1039 intent(out) :: Kd_S_dd
1042 real,
dimension(SZI_(G)) :: &
1057 real,
parameter :: Rrho0 = 1.9
1059 integer :: i, k, is, ie, nz
1060 is = g%isc ; ie = g%iec ; nz = g%ke
1062 if (
associated(tv%eqn_of_state))
then
1064 pres(i) = 0.0 ; kd_t_dd(i,1) = 0.0 ; kd_s_dd(i,1) = 0.0
1065 kd_t_dd(i,nz+1) = 0.0 ; kd_s_dd(i,nz+1) = 0.0
1069 pres(i) = pres(i) + gv%H_to_Pa*h(i,j,k-1)
1070 temp_int(i) = 0.5 * (t_f(i,j,k-1) + t_f(i,j,k))
1071 salin_int(i) = 0.5 * (s_f(i,j,k-1) + s_f(i,j,k))
1074 drho_dt(:), drho_ds(:), is, ie-is+1, tv%eqn_of_state)
1077 alpha_dt = -1.0*drho_dt(i) * (t_f(i,j,k-1) - t_f(i,j,k))
1078 beta_ds = drho_ds(i) * (s_f(i,j,k-1) - s_f(i,j,k))
1080 if ((alpha_dt > beta_ds) .and. (beta_ds > 0.0))
then
1081 rrho = min(alpha_dt / beta_ds, rrho0)
1082 diff_dd = 1.0 - ((rrho-1.0)/(rrho0-1.0))
1083 kd_dd = cs%Max_salt_diff_salt_fingers * diff_dd*diff_dd*diff_dd
1084 kd_t_dd(i,k) = 0.7 * kd_dd
1085 kd_s_dd(i,k) = kd_dd
1086 elseif ((alpha_dt < 0.) .and. (beta_ds < 0.) .and. (alpha_dt > beta_ds))
then
1087 rrho = alpha_dt / beta_ds
1088 kd_dd = cs%Kv_molecular * 0.909 * exp(4.6 * exp(-0.54 * (1/rrho - 1)))
1090 if (rrho > 0.5) prandtl = (1.85-0.85/rrho)*rrho
1091 kd_t_dd(i,k) = kd_dd
1092 kd_s_dd(i,k) = prandtl * kd_dd
1094 kd_t_dd(i,k) = 0.0 ; kd_s_dd(i,k) = 0.0
1100 end subroutine double_diffusion
1103 subroutine add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, TKE_to_Kd, &
1104 maxTKE, kb, G, GV, US, CS, Kd_lay, Kd_int, Kd_BBL)
1108 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1110 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1112 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1116 type(
forcing),
intent(in) :: fluxes
1119 integer,
intent(in) :: j
1120 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd
1125 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: maxTKE
1127 integer,
dimension(SZI_(G)),
intent(in) :: kb
1130 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1131 intent(inout) :: Kd_lay
1133 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
1134 intent(inout) :: Kd_int
1136 real,
dimension(:,:,:),
pointer :: Kd_BBL
1140 real,
dimension(SZK_(G)+1) :: &
1142 real,
dimension(SZI_(G)) :: &
1153 real :: TKE_to_layer
1163 logical :: Rayleigh_drag
1167 logical :: domore, do_i(SZI_(G))
1168 logical :: do_diag_Kd_BBL
1170 integer :: i, k, is, ie, nz, i_rem, kb_min
1171 is = g%isc ; ie = g%iec ; nz = g%ke
1173 do_diag_kd_bbl =
associated(kd_bbl)
1175 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return
1177 cdrag_sqrt = sqrt(cs%cdrag)
1178 tke_ray = 0.0 ; rayleigh_drag = .false.
1179 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1181 i_rho0 = 1.0/gv%Rho0
1182 r0_g = gv%Rho0 / (us%L_to_Z**2 * gv%g_Earth)
1184 do k=2,nz ; rint(k) = 0.5*(gv%Rlay(k-1)+gv%Rlay(k)) ;
enddo
1186 kb_min = max(gv%nk_rho_varies+1,2)
1192 ustar_h = visc%ustar_BBL(i,j)
1193 if (
associated(fluxes%ustar_tidal)) &
1194 ustar_h = ustar_h + fluxes%ustar_tidal(i,j)
1195 absf = 0.25 * ((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1196 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1197 if ((ustar_h > 0.0) .and. (absf > 0.5*cs%IMax_decay*ustar_h))
then
1198 i2decay(i) = absf / ustar_h
1202 i2decay(i) = 0.5*cs%IMax_decay
1204 tke(i) = ((cs%BBL_effic * cdrag_sqrt) * exp(-i2decay(i)*(gv%H_to_Z*h(i,j,nz))) ) * &
1207 if (
associated(fluxes%TKE_tidal)) &
1208 tke(i) = tke(i) + (us%T_to_s**3 * us%m_to_Z**3 * fluxes%TKE_tidal(i,j)) * i_rho0 * &
1209 (cs%BBL_effic * exp(-i2decay(i)*(gv%H_to_Z*h(i,j,nz))))
1216 gh_sum_top(i) = r0_g * 400.0 * ustar_h**2
1218 do_i(i) = (g%mask2dT(i,j) > 0.5)
1219 htot(i) = gv%H_to_Z*h(i,j,nz)
1220 rho_htot(i) = gv%Rlay(nz)*(gv%H_to_Z*h(i,j,nz))
1221 rho_top(i) = gv%Rlay(1)
1222 if (cs%bulkmixedlayer .and. do_i(i)) rho_top(i) = gv%Rlay(kb(i)-1)
1225 do k=nz-1,2,-1 ; domore = .false.
1226 do i=is,ie ;
if (do_i(i))
then
1227 htot(i) = htot(i) + gv%H_to_Z*h(i,j,k)
1228 rho_htot(i) = rho_htot(i) + gv%Rlay(k)*(gv%H_to_Z*h(i,j,k))
1229 if (htot(i)*gv%Rlay(k-1) <= (rho_htot(i) - gh_sum_top(i)))
then
1231 rho_top(i) = (rho_htot(i) - gh_sum_top(i)) / htot(i)
1233 elseif (k <= kb(i))
then ; do_i(i) = .false.
1234 else ; domore = .true. ;
endif
1236 if (.not.domore)
exit
1239 do i=is,ie ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo
1242 do i=is,ie ;
if (do_i(i))
then
1243 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif
1247 tke(i) = tke(i) * exp(-i2decay(i) * (gv%H_to_Z*(h(i,j,k) + h(i,j,k+1))))
1250 if (maxtke(i,k) <= 0.0) cycle
1254 if (tke(i) > 0.0)
then
1255 if (rint(k) <= rho_top(i))
then
1256 tke_to_layer = tke(i)
1258 drl = rint(k+1) - rint(k) ; drbot = rint(k+1) - rho_top(i)
1259 tke_to_layer = tke(i) * drl * &
1260 (3.0*drbot*(rint(k) - rho_top(i)) + drl**2) / drbot**3
1262 else ; tke_to_layer = 0.0 ;
endif
1265 if (rayleigh_drag) tke_ray = 0.5*cs%BBL_effic * g%IareaT(i,j) * &
1266 us%m_to_Z**2 * us%T_to_s**2 * &
1267 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1268 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1269 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1270 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1272 if (tke_to_layer + tke_ray > 0.0)
then
1273 if (cs%BBL_mixing_as_max)
then
1274 if (tke_to_layer + tke_ray > maxtke(i,k)) &
1275 tke_to_layer = maxtke(i,k) - tke_ray
1277 tke(i) = tke(i) - tke_to_layer
1279 if (kd_lay(i,j,k) < (tke_to_layer + tke_ray) * tke_to_kd(i,k))
then
1280 delta_kd = (tke_to_layer + tke_ray) * tke_to_kd(i,k) - kd_lay(i,j,k)
1281 if ((cs%Kd_max >= 0.0) .and. (delta_kd > cs%Kd_max))
then
1282 delta_kd = cs%Kd_max
1283 kd_lay(i,j,k) = kd_lay(i,j,k) + delta_kd
1285 kd_lay(i,j,k) = (tke_to_layer + tke_ray) * tke_to_kd(i,k)
1287 kd_int(i,j,k) = kd_int(i,j,k) + 0.5 * delta_kd
1288 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5 * delta_kd
1289 if (do_diag_kd_bbl)
then
1290 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5 * delta_kd
1291 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5 * delta_kd
1295 if (kd_lay(i,j,k) >= maxtke(i,k) * tke_to_kd(i,k))
then
1297 tke(i) = tke(i) + tke_ray
1298 elseif (kd_lay(i,j,k) + (tke_to_layer + tke_ray) * tke_to_kd(i,k) > &
1299 maxtke(i,k) * tke_to_kd(i,k))
then
1300 tke_here = ((tke_to_layer + tke_ray) + kd_lay(i,j,k) / tke_to_kd(i,k)) - maxtke(i,k)
1301 tke(i) = (tke(i) - tke_here) + tke_ray
1303 tke_here = tke_to_layer + tke_ray
1304 tke(i) = tke(i) - tke_to_layer
1306 if (tke(i) < 0.0) tke(i) = 0.0
1308 if (tke_here > 0.0)
then
1309 delta_kd = tke_here * tke_to_kd(i,k)
1310 if (cs%Kd_max >= 0.0) delta_kd = min(delta_kd, cs%Kd_max)
1311 kd_lay(i,j,k) = kd_lay(i,j,k) + delta_kd
1312 kd_int(i,j,k) = kd_int(i,j,k) + 0.5 * delta_kd
1313 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5 * delta_kd
1314 if (do_diag_kd_bbl)
then
1315 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5 * delta_kd
1316 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5 * delta_kd
1326 if ((tke(i)<= 0.0) .and. (tke_ray == 0.0))
then
1327 do_i(i) = .false. ; i_rem = i_rem - 1
1331 if (i_rem == 0)
exit
1334 end subroutine add_drag_diffusivity
1339 subroutine add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, N2_int, &
1340 G, GV, US, CS, Kd_lay, Kd_int, Kd_BBL)
1344 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1346 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1348 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1352 type(
forcing),
intent(in) :: fluxes
1355 integer,
intent(in) :: j
1356 real,
dimension(SZI_(G),SZK_(G)+1), &
1357 intent(in) :: N2_int
1359 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1360 intent(inout) :: Kd_lay
1361 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
1362 intent(inout) :: Kd_int
1363 real,
dimension(:,:,:),
pointer :: Kd_BBL
1367 real :: TKE_remaining
1368 real :: TKE_consumed
1377 real :: total_thickness
1384 logical :: Rayleigh_drag
1386 integer :: i, k, km1
1387 real,
parameter :: von_karm = 0.41
1388 logical :: do_diag_Kd_BBL
1390 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return
1391 do_diag_kd_bbl =
associated(kd_bbl)
1394 if (cs%LOTW_BBL_use_omega) n2_min = cs%omega**2
1397 rayleigh_drag = .false.
1398 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1399 i_rho0 = 1.0/gv%Rho0
1400 cdrag_sqrt = sqrt(cs%cdrag)
1405 absf = 0.25 * ((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1406 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1409 ustar = visc%ustar_BBL(i,j)
1414 if (
associated(fluxes%ustar_tidal)) ustar = ustar + fluxes%ustar_tidal(i,j)
1418 idecay = cs%IMax_decay
1419 if ((ustar > 0.0) .and. (absf > cs%IMax_decay * ustar)) idecay = absf / ustar
1424 tke_column = cdrag_sqrt * visc%TKE_BBL(i,j)
1427 if (
associated(fluxes%TKE_tidal)) &
1428 tke_column = tke_column + us%m_to_Z**3*us%T_to_s**3 * fluxes%TKE_tidal(i,j) * i_rho0
1429 tke_column = cs%BBL_effic * tke_column
1431 tke_remaining = tke_column
1432 total_thickness = ( sum(h(i,j,:)) + gv%H_subroundoff )* gv%H_to_Z
1433 ustar_d = ustar * total_thickness
1440 dh = gv%H_to_Z * h(i,j,k)
1442 dhm1 = gv%H_to_Z * h(i,j,km1)
1445 if (rayleigh_drag) tke_remaining = tke_remaining + &
1446 us%m_to_Z**2 * us%T_to_s**2 * &
1447 0.5*cs%BBL_effic * g%IareaT(i,j) * &
1448 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1449 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1450 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1451 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1455 tke_remaining = exp(-idecay*dh) * tke_remaining
1457 z_bot = z_bot + h(i,j,k)*gv%H_to_Z
1458 d_minus_z = max(total_thickness - z_bot, 0.)
1462 if ( ustar_d + absf * ( z_bot * d_minus_z ) == 0.)
then
1465 kd_wall = ((von_karm * ustar2) * (z_bot * d_minus_z)) &
1466 / (ustar_d + absf * (z_bot * d_minus_z))
1471 tke_kd_wall = kd_wall * 0.5 * (dh + dhm1) * max(n2_int(i,k), n2_min)
1474 if (tke_kd_wall > 0.)
then
1475 tke_consumed = min(tke_kd_wall, tke_remaining)
1476 kd_wall = (tke_consumed / tke_kd_wall) * kd_wall
1479 if (tke_remaining > 0.)
then
1488 tke_remaining = tke_remaining - tke_consumed
1491 kd_int(i,j,k) = kd_int(i,j,k) + kd_wall
1492 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * (kd_wall + kd_lower)
1494 if (do_diag_kd_bbl) kd_bbl(i,j,k) = kd_wall
1498 end subroutine add_lotw_bbl_diffusivity
1501 subroutine add_mlrad_diffusivity(h, fluxes, j, G, GV, US, CS, Kd_lay, TKE_to_Kd, Kd_int)
1505 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1507 type(
forcing),
intent(in) :: fluxes
1509 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1510 intent(inout) :: Kd_lay
1511 integer,
intent(in) :: j
1512 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd
1517 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
1518 optional,
intent(inout) :: Kd_int
1523 real,
dimension(SZI_(G)) :: h_ml
1524 real,
dimension(SZI_(G)) :: TKE_ml_flux
1525 real,
dimension(SZI_(G)) :: I_decay
1526 real,
dimension(SZI_(G)) :: Kd_mlr_ml
1536 real :: I_decay_len2_TKE
1540 logical :: do_any, do_i(SZI_(G))
1541 integer :: i, k, is, ie, nz, kml
1542 is = g%isc ; ie = g%iec ; nz = g%ke
1544 omega2 = cs%omega**2
1547 h_neglect = gv%H_subroundoff*gv%H_to_Z
1549 if (.not.cs%ML_radiation)
return
1551 do i=is,ie ; h_ml(i) = 0.0 ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo
1552 do k=1,kml ;
do i=is,ie ; h_ml(i) = h_ml(i) + gv%H_to_Z*h(i,j,k) ;
enddo ;
enddo
1554 do i=is,ie ;
if (do_i(i))
then
1555 if (cs%ML_omega_frac >= 1.0)
then
1558 f_sq = 0.25 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1559 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
1560 if (cs%ML_omega_frac > 0.0) &
1561 f_sq = cs%ML_omega_frac * 4.0 * omega2 + (1.0 - cs%ML_omega_frac) * f_sq
1564 ustar_sq = max(fluxes%ustar(i,j), cs%ustar_min)**2
1566 tke_ml_flux(i) = (cs%mstar * cs%ML_rad_coeff) * (ustar_sq * (fluxes%ustar(i,j)))
1567 i_decay_len2_tke = cs%TKE_decay**2 * (f_sq / ustar_sq)
1569 if (cs%ML_rad_TKE_decay) &
1570 tke_ml_flux(i) = tke_ml_flux(i) * exp(-h_ml(i) * sqrt(i_decay_len2_tke))
1573 h_ml_sq = (cs%ML_rad_efold_coeff * (h_ml(i)+h_neglect))**2
1574 i_decay(i) = sqrt((i_decay_len2_tke * h_ml_sq + 1.0) / h_ml_sq)
1578 z1 = (gv%H_to_Z*h(i,j,kml+1)) * i_decay(i)
1580 kd_mlr = tke_ml_flux(i) * tke_to_kd(i,kml+1) * (1.0 - exp(-z1))
1582 kd_mlr = tke_ml_flux(i) * tke_to_kd(i,kml+1) * (z1 * (1.0 - z1 * (0.5 - c1_6 * z1)))
1584 kd_mlr_ml(i) = min(kd_mlr, cs%ML_rad_kd_max)
1585 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1588 do k=1,kml+1 ;
do i=is,ie ;
if (do_i(i))
then
1589 kd_lay(i,j,k) = kd_lay(i,j,k) + kd_mlr_ml(i)
1590 endif ;
enddo ;
enddo
1591 if (
present(kd_int))
then
1592 do k=2,kml+1 ;
do i=is,ie ;
if (do_i(i))
then
1593 kd_int(i,j,k) = kd_int(i,j,k) + kd_mlr_ml(i)
1594 endif ;
enddo ;
enddo
1595 if (kml<=nz-1)
then ;
do i=is,ie ;
if (do_i(i))
then
1596 kd_int(i,j,kml+2) = kd_int(i,j,kml+2) + 0.5 * kd_mlr_ml(i)
1597 endif ;
enddo ;
endif
1602 do i=is,ie ;
if (do_i(i))
then
1603 dzl = gv%H_to_Z*h(i,j,k) ; z1 = dzl*i_decay(i)
1604 if (cs%ML_Rad_bug)
then
1609 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1610 us%m_to_Z * ((1.0 - exp(-z1)) / dzl)
1612 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1613 us%m_to_Z * (i_decay(i) * (1.0 - z1 * (0.5 - c1_6*z1)))
1617 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * (1.0 - exp(-z1))
1619 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * (z1 * (1.0 - z1 * (0.5 - c1_6*z1)))
1622 kd_mlr = min(kd_mlr, cs%ML_rad_kd_max)
1623 kd_lay(i,j,k) = kd_lay(i,j,k) + kd_mlr
1624 if (
present(kd_int))
then
1625 kd_int(i,j,k) = kd_int(i,j,k) + 0.5 * kd_mlr
1626 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5 * kd_mlr
1629 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1630 if (tke_ml_flux(i) * i_decay(i) < 0.1 * cs%Kd_min * omega2)
then
1632 else ; do_any = .true. ;
endif
1634 if (.not.do_any)
exit
1637 end subroutine add_mlrad_diffusivity
1641 subroutine set_bbl_tke(u, v, h, fluxes, visc, G, GV, US, CS)
1645 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1647 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1649 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1651 type(
forcing),
intent(in) :: fluxes
1659 real,
dimension(SZI_(G)) :: &
1663 real,
dimension(SZIB_(G)) :: &
1668 real :: vhtot(szi_(g))
1670 real,
dimension(SZI_(G),SZJB_(G)) :: &
1677 logical :: domore, do_i(szi_(g))
1678 integer :: i, j, k, is, ie, js, je, nz
1679 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1681 if (.not.
associated(cs))
call mom_error(fatal,
"set_BBL_TKE: "//&
1682 "Module must be initialized before it is used.")
1684 if (.not.cs%bottomdraglaw .or. (cs%BBL_effic<=0.0))
then
1685 if (
associated(visc%ustar_BBL))
then
1686 do j=js,je ;
do i=is,ie ; visc%ustar_BBL(i,j) = 0.0 ;
enddo ;
enddo
1688 if (
associated(visc%TKE_BBL))
then
1689 do j=js,je ;
do i=is,ie ; visc%TKE_BBL(i,j) = 0.0 ;
enddo ;
enddo
1694 cdrag_sqrt = sqrt(cs%cdrag)
1704 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_v(i,j) > 0.0))
then
1705 do_i(i) = .true. ; vhtot(i) = 0.0 ; htot(i) = 0.0
1706 vstar(i,j) = visc%Kv_bbl_v(i,j) / (cdrag_sqrt*visc%bbl_thick_v(i,j))
1708 do_i(i) = .false. ; vstar(i,j) = 0.0 ; htot(i) = 0.0
1712 do i=is,ie ;
if (do_i(i))
then
1713 hvel = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j+1,k))
1714 if ((htot(i) + hvel) >= visc%bbl_thick_v(i,j))
then
1715 vhtot(i) = vhtot(i) + (visc%bbl_thick_v(i,j) - htot(i))*v(i,j,k)
1716 htot(i) = visc%bbl_thick_v(i,j)
1719 vhtot(i) = vhtot(i) + hvel*v(i,j,k)
1720 htot(i) = htot(i) + hvel
1724 if (.not.domore)
exit
1726 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (htot(i) > 0.0))
then
1727 v2_bbl(i,j) = (vhtot(i)*vhtot(i))/(htot(i)*htot(i))
1734 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_u(i,j) > 0.0))
then
1735 do_i(i) = .true. ; uhtot(i) = 0.0 ; htot(i) = 0.0
1736 ustar(i) = visc%Kv_bbl_u(i,j) / (cdrag_sqrt*visc%bbl_thick_u(i,j))
1738 do_i(i) = .false. ; ustar(i) = 0.0 ; htot(i) = 0.0
1740 do k=nz,1,-1 ; domore = .false.
1741 do i=is-1,ie ;
if (do_i(i))
then
1742 hvel = 0.5*gv%H_to_Z*(h(i,j,k) + h(i+1,j,k))
1743 if ((htot(i) + hvel) >= visc%bbl_thick_u(i,j))
then
1744 uhtot(i) = uhtot(i) + (visc%bbl_thick_u(i,j) - htot(i))*u(i,j,k)
1745 htot(i) = visc%bbl_thick_u(i,j)
1748 uhtot(i) = uhtot(i) + hvel*u(i,j,k)
1749 htot(i) = htot(i) + hvel
1753 if (.not.domore)
exit
1755 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (htot(i) > 0.0))
then
1756 u2_bbl(i) = (uhtot(i)*uhtot(i))/(htot(i)*htot(i))
1762 visc%ustar_BBL(i,j) = sqrt(0.5*g%IareaT(i,j) * &
1763 ((g%areaCu(i-1,j)*(ustar(i-1)*ustar(i-1)) + &
1764 g%areaCu(i,j)*(ustar(i)*ustar(i))) + &
1765 (g%areaCv(i,j-1)*(vstar(i,j-1)*vstar(i,j-1)) + &
1766 g%areaCv(i,j)*(vstar(i,j)*vstar(i,j))) ) )
1767 visc%TKE_BBL(i,j) = us%T_to_s**2 * us%m_to_Z**2 * &
1768 (((g%areaCu(i-1,j)*(ustar(i-1)*u2_bbl(i-1)) + &
1769 g%areaCu(i,j) * (ustar(i)*u2_bbl(i))) + &
1770 (g%areaCv(i,j-1)*(vstar(i,j-1)*v2_bbl(i,j-1)) + &
1771 g%areaCv(i,j) * (vstar(i,j)*v2_bbl(i,j))) )*g%IareaT(i,j))
1776 end subroutine set_bbl_tke
1778 subroutine set_density_ratios(h, tv, kb, G, GV, US, CS, j, ds_dsp1, rho_0)
1781 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1786 integer,
dimension(SZI_(G)),
intent(in) :: kb
1791 integer,
intent(in) :: j
1792 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: ds_dsp1
1796 real,
dimension(SZI_(G),SZK_(G)), &
1797 optional,
intent(in) :: rho_0
1803 real :: a(SZK_(G)), a_0(SZK_(G))
1804 real :: p_ref(SZI_(G))
1805 real :: Rcv(SZI_(G),SZK_(G))
1808 integer :: i, k, k3, is, ie, nz, kmb
1809 is = g%isc ; ie = g%iec ; nz = g%ke
1812 if (gv%g_prime(k+1) /= 0.0)
then
1814 ds_dsp1(i,k) = gv%g_prime(k) / gv%g_prime(k+1)
1823 if (cs%bulkmixedlayer)
then
1824 g_r0 = gv%g_Earth / gv%Rho0
1825 kmb = gv%nk_rho_varies
1827 do i=is,ie ; p_ref(i) = tv%P_Ref ;
enddo
1830 is, ie-is+1, tv%eqn_of_state)
1833 if (kb(i) <= nz-1)
then
1838 i_drho = g_r0 / gv%g_prime(k+1)
1841 a(k3+1) = (gv%Rlay(k) - rcv(i,k3)) * i_drho
1843 if ((
present(rho_0)) .and. (a(kmb+1) < 2.0*eps*ds_dsp1(i,k)))
then
1847 if ((rho_0(i,k) > rho_0(i,kmb)) .and. &
1848 (rho_0(i,k+1) > rho_0(i,k)))
then
1849 i_drho = 1.0 / (rho_0(i,k+1)-rho_0(i,k))
1850 a_0(kmb+1) = min((rho_0(i,k)-rho_0(i,kmb)) * i_drho, ds_dsp1(i,k))
1851 if (a_0(kmb+1) > a(kmb+1))
then
1853 a_0(k3) = a_0(kmb+1) + (rho_0(i,kmb)-rho_0(i,k3-1)) * i_drho
1855 if (a(kmb+1) <= eps*ds_dsp1(i,k))
then
1856 do k3=2,kmb+1 ; a(k3) = a_0(k3) ;
enddo
1859 tmp = a(kmb+1)/(eps*ds_dsp1(i,k)) - 1.0
1860 do k3=2,kmb+1 ; a(k3) = tmp*a(k3) + (1.0-tmp)*a_0(k3) ;
enddo
1866 ds_dsp1(i,k) = max(a(kmb+1),1e-5)
1875 ds_dsp1(i,k3) = max(a(k3),ds_dsp1(i,k))
1881 end subroutine set_density_ratios
1883 subroutine set_diffusivity_init(Time, G, GV, US, param_file, diag, CS, int_tide_CSp, &
1885 type(time_type),
intent(in) :: time
1891 type(
diag_ctrl),
target,
intent(inout) :: diag
1898 integer,
optional,
intent(out) :: halo_ts
1902 real :: decay_length
1903 logical :: ml_use_omega
1904 logical :: default_2018_answers
1906 # include "version_variable.h"
1907 character(len=40) :: mdl =
"MOM_set_diffusivity"
1908 real :: omega_frac_dflt
1909 integer :: i, j, is, ie, js, je
1910 integer :: isd, ied, jsd, jed
1912 if (
associated(cs))
then
1913 call mom_error(warning,
"diabatic_entrain_init called with an associated "// &
1914 "control structure.")
1919 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1920 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1923 if (
associated(int_tide_csp)) cs%int_tide_CSp => int_tide_csp
1924 if (
associated(tm_csp)) cs%tm_csp => tm_csp
1927 cs%BBL_mixing_as_max = .true.
1928 cs%cdrag = 0.003 ; cs%BBL_effic = 0.0
1929 cs%bulkmixedlayer = (gv%nkml > 0)
1934 call get_param(param_file, mdl,
"INPUTDIR", cs%inputdir, default=
".")
1935 cs%inputdir = slasher(cs%inputdir)
1936 call get_param(param_file, mdl,
"FLUX_RI_MAX", cs%FluxRi_max, &
1937 "The flux Richardson number where the stratification is "//&
1938 "large enough that N2 > omega2. The full expression for "//&
1939 "the Flux Richardson number is usually "//&
1940 "FLUX_RI_MAX*N2/(N2+OMEGA2).", default=0.2)
1941 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
1942 "The rotation rate of the earth.", units=
"s-1", &
1943 default=7.2921e-5, scale=us%T_to_s)
1945 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
1946 "This sets the default value for the various _2018_ANSWERS parameters.", &
1948 call get_param(param_file, mdl,
"SET_DIFF_2018_ANSWERS", cs%answers_2018, &
1949 "If true, use the order of arithmetic and expressions that recover the "//&
1950 "answers from the end of 2018. Otherwise, use updated and more robust "//&
1951 "forms of the same expressions.", default=default_2018_answers)
1953 call get_param(param_file, mdl,
"ML_RADIATION", cs%ML_radiation, &
1954 "If true, allow a fraction of TKE available from wind "//&
1955 "work to penetrate below the base of the mixed layer "//&
1956 "with a vertical decay scale determined by the minimum "//&
1957 "of: (1) The depth of the mixed layer, (2) an Ekman "//&
1958 "length scale.", default=.false.)
1959 if (cs%ML_radiation)
then
1961 cs%ustar_min = 2e-4 * cs%omega * (gv%Angstrom_Z + gv%H_subroundoff*gv%H_to_Z)
1963 call get_param(param_file, mdl,
"ML_RAD_EFOLD_COEFF", cs%ML_rad_efold_coeff, &
1964 "A coefficient that is used to scale the penetration "//&
1965 "depth for turbulence below the base of the mixed layer. "//&
1966 "This is only used if ML_RADIATION is true.", units=
"nondim", &
1968 call get_param(param_file, mdl,
"ML_RAD_BUG", cs%ML_rad_bug, &
1969 "If true use code with a bug that reduces the energy available "//&
1970 "in the transition layer by a factor of the inverse of the energy "//&
1971 "deposition lenthscale (in m).", default=.true.)
1972 call get_param(param_file, mdl,
"ML_RAD_KD_MAX", cs%ML_rad_kd_max, &
1973 "The maximum diapycnal diffusivity due to turbulence "//&
1974 "radiated from the base of the mixed layer. "//&
1975 "This is only used if ML_RADIATION is true.", &
1976 units=
"m2 s-1", default=1.0e-3, &
1977 scale=us%m2_s_to_Z2_T)
1978 call get_param(param_file, mdl,
"ML_RAD_COEFF", cs%ML_rad_coeff, &
1979 "The coefficient which scales MSTAR*USTAR^3 to obtain "//&
1980 "the energy available for mixing below the base of the "//&
1981 "mixed layer. This is only used if ML_RADIATION is true.", &
1982 units=
"nondim", default=0.2)
1983 call get_param(param_file, mdl,
"ML_RAD_APPLY_TKE_DECAY", cs%ML_rad_TKE_decay, &
1984 "If true, apply the same exponential decay to ML_rad as "//&
1985 "is applied to the other surface sources of TKE in the "//&
1986 "mixed layer code. This is only used if ML_RADIATION is true.", &
1988 call get_param(param_file, mdl,
"MSTAR", cs%mstar, &
1989 "The ratio of the friction velocity cubed to the TKE "//&
1990 "input to the mixed layer.",
"units=nondim", default=1.2)
1991 call get_param(param_file, mdl,
"TKE_DECAY", cs%TKE_decay, &
1992 "The ratio of the natural Ekman depth to the TKE decay scale.", &
1993 units=
"nondim", default=2.5)
1994 call get_param(param_file, mdl,
"ML_USE_OMEGA", ml_use_omega, &
1995 "If true, use the absolute rotation rate instead of the "//&
1996 "vertical component of rotation when setting the decay "//&
1997 "scale for turbulence.", default=.false., do_not_log=.true.)
1998 omega_frac_dflt = 0.0
1999 if (ml_use_omega)
then
2000 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
2001 omega_frac_dflt = 1.0
2003 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%ML_omega_frac, &
2004 "When setting the decay scale for turbulence, use this "//&
2005 "fraction of the absolute rotation rate blended with the "//&
2006 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
2007 units=
"nondim", default=omega_frac_dflt)
2010 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
2011 "If true, the bottom stress is calculated with a drag "//&
2012 "law of the form c_drag*|u|*u. The velocity magnitude "//&
2013 "may be an assumed value or it may be based on the "//&
2014 "actual velocity in the bottommost HBBL, depending on "//&
2015 "LINEAR_DRAG.", default=.true.)
2016 if (cs%bottomdraglaw)
then
2017 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
2018 "The drag coefficient relating the magnitude of the "//&
2019 "velocity field to the bottom stress. CDRAG is only used "//&
2020 "if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.003)
2021 call get_param(param_file, mdl,
"BBL_EFFIC", cs%BBL_effic, &
2022 "The efficiency with which the energy extracted by "//&
2023 "bottom drag drives BBL diffusion. This is only "//&
2024 "used if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.20)
2025 call get_param(param_file, mdl,
"BBL_MIXING_MAX_DECAY", decay_length, &
2026 "The maximum decay scale for the BBL diffusion, or 0 to allow the mixing "//&
2027 "to penetrate as far as stratification and rotation permit. The default "//&
2028 "for now is 200 m. This is only used if BOTTOMDRAGLAW is true.", &
2029 units=
"m", default=200.0, scale=us%m_to_Z)
2032 if (decay_length > 0.0) cs%IMax_decay = 1.0/decay_length
2033 call get_param(param_file, mdl,
"BBL_MIXING_AS_MAX", cs%BBL_mixing_as_max, &
2034 "If true, take the maximum of the diffusivity from the "//&
2035 "BBL mixing and the other diffusivities. Otherwise, "//&
2036 "diffusivity from the BBL_mixing is simply added.", &
2038 call get_param(param_file, mdl,
"USE_LOTW_BBL_DIFFUSIVITY", cs%use_LOTW_BBL_diffusivity, &
2039 "If true, uses a simple, imprecise but non-coordinate dependent, model "//&
2040 "of BBL mixing diffusivity based on Law of the Wall. Otherwise, uses "//&
2041 "the original BBL scheme.", default=.false.)
2042 if (cs%use_LOTW_BBL_diffusivity)
then
2043 call get_param(param_file, mdl,
"LOTW_BBL_USE_OMEGA", cs%LOTW_BBL_use_omega, &
2044 "If true, use the maximum of Omega and N for the TKE to diffusion "//&
2045 "calculation. Otherwise, N is N.", default=.true.)
2048 cs%use_LOTW_BBL_diffusivity = .false.
2050 cs%id_Kd_BBL = register_diag_field(
'ocean_model',
'Kd_BBL', diag%axesTi, time, &
2051 'Bottom Boundary Layer Diffusivity',
'm2 s-1', &
2052 conversion=us%Z2_T_to_m2_s)
2053 call get_param(param_file, mdl,
"SIMPLE_TKE_TO_KD", cs%simple_TKE_to_Kd, &
2054 "If true, uses a simple estimate of Kd/TKE that will "//&
2055 "work for arbitrary vertical coordinates. If false, "//&
2056 "calculates Kd/TKE and bounds based on exact energetics "//&
2057 "for an isopycnal layer-formulation.", &
2061 call bkgnd_mixing_init(time, g, gv, us, param_file, cs%diag, cs%bkgnd_mixing_csp)
2063 call get_param(param_file, mdl,
"KV", cs%Kv, &
2064 "The background kinematic viscosity in the interior. "//&
2065 "The molecular value, ~1e-6 m2 s-1, may be used.", &
2066 units=
"m2 s-1", scale=us%m2_s_to_Z2_T, &
2067 fail_if_missing=.true.)
2069 call get_param(param_file, mdl,
"KD", cs%Kd, &
2070 "The background diapycnal diffusivity of density in the "//&
2071 "interior. Zero or the molecular value, ~1e-7 m2 s-1, "//&
2072 "may be used.", units=
"m2 s-1", scale=us%m2_s_to_Z2_T, &
2073 fail_if_missing=.true.)
2074 call get_param(param_file, mdl,
"KD_MIN", cs%Kd_min, &
2075 "The minimum diapycnal diffusivity.", &
2076 units=
"m2 s-1", default=0.01*cs%Kd*us%Z2_T_to_m2_s, &
2077 scale=us%m2_s_to_Z2_T)
2078 call get_param(param_file, mdl,
"KD_MAX", cs%Kd_max, &
2079 "The maximum permitted increment for the diapycnal "//&
2080 "diffusivity from TKE-based parameterizations, or a "//&
2081 "negative value for no limit.", units=
"m2 s-1", default=-1.0, &
2082 scale=us%m2_s_to_Z2_T)
2083 if (cs%simple_TKE_to_Kd .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2084 "set_diffusivity_init: To use SIMPLE_TKE_TO_KD, KD_MAX must be set to >0.")
2085 call get_param(param_file, mdl,
"KD_ADD", cs%Kd_add, &
2086 "A uniform diapycnal diffusivity that is added "//&
2087 "everywhere without any filtering or scaling.", &
2088 units=
"m2 s-1", default=0.0, scale=us%m2_s_to_Z2_T)
2089 if (cs%use_LOTW_BBL_diffusivity .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2090 "set_diffusivity_init: KD_MAX must be set (positive) when "// &
2091 "USE_LOTW_BBL_DIFFUSIVITY=True.")
2092 call get_param(param_file, mdl,
"KD_SMOOTH", cs%Kd_smooth, &
2093 "A diapycnal diffusivity that is used to interpolate "//&
2094 "more sensible values of T & S into thin layers.", &
2095 default=1.0e-6, scale=us%m_to_Z**2*us%T_to_s)
2097 call get_param(param_file, mdl,
"DEBUG", cs%debug, &
2098 "If true, write out verbose debugging data.", &
2099 default=.false., debuggingparam=.true.)
2101 call get_param(param_file, mdl,
"USER_CHANGE_DIFFUSIVITY", cs%user_change_diff, &
2102 "If true, call user-defined code to change the diffusivity.", &
2105 call get_param(param_file, mdl,
"DISSIPATION_MIN", cs%dissip_min, &
2106 "The minimum dissipation by which to determine a lower "//&
2107 "bound of Kd (a floor).", units=
"W m-3", default=0.0, &
2108 scale=us%m2_s_to_Z2_T*(us%T_to_s**2))
2109 call get_param(param_file, mdl,
"DISSIPATION_N0", cs%dissip_N0, &
2110 "The intercept when N=0 of the N-dependent expression "//&
2111 "used to set a minimum dissipation by which to determine "//&
2112 "a lower bound of Kd (a floor): A in eps_min = A + B*N.", &
2113 units=
"W m-3", default=0.0, &
2114 scale=us%m2_s_to_Z2_T*(us%T_to_s**2))
2115 call get_param(param_file, mdl,
"DISSIPATION_N1", cs%dissip_N1, &
2116 "The coefficient multiplying N, following Gargett, used to "//&
2117 "set a minimum dissipation by which to determine a lower "//&
2118 "bound of Kd (a floor): B in eps_min = A + B*N", &
2119 units=
"J m-3", default=0.0, scale=us%m2_s_to_Z2_T*us%T_to_s)
2120 call get_param(param_file, mdl,
"DISSIPATION_KD_MIN", cs%dissip_Kd_min, &
2121 "The minimum vertical diffusivity applied as a floor.", &
2122 units=
"m2 s-1", default=0.0, scale=us%m2_s_to_Z2_T)
2124 cs%limit_dissipation = (cs%dissip_min>0.) .or. (cs%dissip_N1>0.) .or. &
2125 (cs%dissip_N0>0.) .or. (cs%dissip_Kd_min>0.)
2127 if (cs%FluxRi_max > 0.0) &
2128 cs%dissip_N2 = cs%dissip_Kd_min * gv%Rho0 / cs%FluxRi_max
2130 cs%id_Kd_layer = register_diag_field(
'ocean_model',
'Kd_layer', diag%axesTL, time, &
2131 'Diapycnal diffusivity of layers (as set)',
'm2 s-1', &
2132 conversion=us%Z2_T_to_m2_s)
2135 if (cs%tm_csp%Int_tide_dissipation .or. cs%tm_csp%Lee_wave_dissipation .or. &
2136 cs%tm_csp%Lowmode_itidal_dissipation)
then
2138 cs%id_Kd_Work = register_diag_field(
'ocean_model',
'Kd_Work', diag%axesTL, time, &
2139 'Work done by Diapycnal Mixing',
'W m-2', conversion=us%Z_to_m**3*us%s_to_T**3)
2140 cs%id_maxTKE = register_diag_field(
'ocean_model',
'maxTKE', diag%axesTL, time, &
2141 'Maximum layer TKE',
'm3 s-3', conversion=(us%Z_to_m**3*us%s_to_T**3))
2142 cs%id_TKE_to_Kd = register_diag_field(
'ocean_model',
'TKE_to_Kd', diag%axesTL, time, &
2143 'Convert TKE to Kd',
's2 m', &
2144 conversion=us%Z2_T_to_m2_s*(us%m_to_Z**3*us%T_to_s**3))
2145 cs%id_N2 = register_diag_field(
'ocean_model',
'N2', diag%axesTi, time, &
2146 'Buoyancy frequency squared',
's-2', cmor_field_name=
'obvfsq', &
2147 cmor_long_name=
'Square of seawater buoyancy frequency', &
2148 cmor_standard_name=
'square_of_brunt_vaisala_frequency_in_sea_water', &
2149 conversion=us%s_to_T**2)
2151 if (cs%user_change_diff) &
2152 cs%id_Kd_user = register_diag_field(
'ocean_model',
'Kd_user', diag%axesTi, time, &
2153 'User-specified Extra Diffusivity',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2156 call get_param(param_file, mdl,
"DOUBLE_DIFFUSION", cs%double_diffusion, &
2157 "If true, increase diffusivites for temperature or salt "//&
2158 "based on double-diffusive parameterization from MOM4/KPP.", &
2161 if (cs%double_diffusion)
then
2162 call get_param(param_file, mdl,
"MAX_RRHO_SALT_FINGERS", cs%Max_Rrho_salt_fingers, &
2163 "Maximum density ratio for salt fingering regime.", &
2164 default=2.55, units=
"nondim")
2165 call get_param(param_file, mdl,
"MAX_SALT_DIFF_SALT_FINGERS", cs%Max_salt_diff_salt_fingers, &
2166 "Maximum salt diffusivity for salt fingering regime.", &
2167 default=1.e-4, units=
"m2 s-1", scale=us%m2_s_to_Z2_T)
2168 call get_param(param_file, mdl,
"KV_MOLECULAR", cs%Kv_molecular, &
2169 "Molecular viscosity for calculation of fluxes under "//&
2170 "double-diffusive convection.", default=1.5e-6, units=
"m2 s-1", &
2171 scale=us%m2_s_to_Z2_T)
2174 cs%id_KT_extra = register_diag_field(
'ocean_model',
'KT_extra', diag%axesTi, time, &
2175 'Double-diffusive diffusivity for temperature',
'm2 s-1', &
2176 conversion=us%Z2_T_to_m2_s)
2178 cs%id_KS_extra = register_diag_field(
'ocean_model',
'KS_extra', diag%axesTi, time, &
2179 'Double-diffusive diffusivity for salinity',
'm2 s-1', &
2180 conversion=us%Z2_T_to_m2_s)
2183 if (cs%user_change_diff)
then
2184 call user_change_diff_init(time, g, gv, us, param_file, diag, cs%user_change_diff_CSp)
2187 if (cs%tm_csp%Int_tide_dissipation .and. cs%bkgnd_mixing_csp%Bryan_Lewis_diffusivity) &
2188 call mom_error(fatal,
"MOM_Set_Diffusivity: "// &
2189 "Bryan-Lewis and internal tidal dissipation are both enabled. Choose one.")
2191 cs%useKappaShear = kappa_shear_init(time, g, gv, us, param_file, cs%diag, cs%kappaShear_CSp)
2192 if (cs%useKappaShear) cs%Vertex_Shear = kappa_shear_at_vertex(param_file)
2194 if (cs%useKappaShear) &
2195 id_clock_kappashear = cpu_clock_id(
'(Ocean kappa_shear)', grain=clock_module)
2198 cs%use_CVMix_shear = cvmix_shear_init(time, g, gv, us, param_file, cs%diag, cs%CVMix_shear_csp)
2201 cs%use_CVMix_ddiff = cvmix_ddiff_init(time, g, gv, us, param_file, cs%diag, cs%CVMix_ddiff_csp)
2202 if (cs%use_CVMix_ddiff) &
2203 id_clock_cvmix_ddiff = cpu_clock_id(
'(Double diffusion via CVMix)', grain=clock_module)
2205 if (
present(halo_ts))
then
2207 if (cs%Vertex_Shear) halo_ts = 1
2210 end subroutine set_diffusivity_init
2213 subroutine set_diffusivity_end(CS)
2216 if (.not.
associated(cs))
return
2218 call bkgnd_mixing_end(cs%bkgnd_mixing_csp)
2220 if (cs%user_change_diff) &
2221 call user_change_diff_end(cs%user_change_diff_CSp)
2223 if (cs%use_CVMix_shear) &
2224 call cvmix_shear_end(cs%CVMix_shear_csp)
2226 if (cs%use_CVMix_ddiff) &
2227 call cvmix_ddiff_end(cs%CVMix_ddiff_csp)
2229 if (
associated(cs))
deallocate(cs)
2231 end subroutine set_diffusivity_end