8 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
9 use mom_cpu_clock, only : clock_module_driver, clock_module, clock_routine
16 use mom_debugging, only : hchksum, uvchksum, bchksum, hchksum_pair
30 use mom_kappa_shear, only : calc_kappa_shear_vertex, kappa_shear_at_vertex
32 use mom_open_boundary, only : obc_direction_e, obc_direction_w, obc_direction_n, obc_direction_s
43 implicit none ;
private 45 #include <MOM_memory.h> 47 public set_diffusivity
49 public set_diffusivity_init
50 public set_diffusivity_end
61 logical :: bulkmixedlayer
67 logical :: bottomdraglaw
69 logical :: bbl_mixing_as_max
73 logical :: use_lotw_bbl_diffusivity
74 logical :: lotw_bbl_use_omega
91 logical :: limit_dissipation
100 logical :: ml_radiation
113 real :: ml_rad_kd_max
115 real :: ml_rad_efold_coeff
119 logical :: ml_rad_bug
122 logical :: ml_rad_tke_decay
131 logical :: ml_use_omega
134 real :: ml_omega_frac
137 logical :: user_change_diff
138 logical :: usekappashear
140 logical :: vertex_shear
142 logical :: use_cvmix_shear
144 logical :: double_diffusion
145 logical :: use_cvmix_ddiff
146 logical :: use_tidal_mixing
147 logical :: simple_tke_to_kd
149 real :: max_rrho_salt_fingers
150 real :: max_salt_diff_salt_fingers
153 logical :: answers_2018
157 character(len=200) :: inputdir
167 integer :: id_maxtke = -1, id_tke_to_kd = -1, id_kd_user = -1
168 integer :: id_kd_layer = -1, id_kd_bbl = -1, id_n2 = -1
169 integer :: id_kd_work = -1, id_kt_extra = -1, id_ks_extra = -1, id_r_rho = -1
170 integer :: id_kd_bkgnd = -1, id_kv_bkgnd = -1
177 real,
pointer,
dimension(:,:,:) :: &
183 kd_bkgnd => null(), &
184 kv_bkgnd => null(), &
185 kt_extra => null(), &
186 ks_extra => null(), &
188 real,
pointer,
dimension(:,:,:) :: tke_to_kd => null()
196 integer :: id_clock_kappashear, id_clock_cvmix_ddiff
211 subroutine set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt, &
212 G, GV, US, CS, Kd_lay, Kd_int)
216 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
218 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
220 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
222 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
224 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
228 type(
forcing),
intent(in) :: fluxes
229 type(optics_type),
pointer :: optics
233 real,
intent(in) :: dt
235 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
236 optional,
intent(out) :: Kd_lay
237 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
238 optional,
intent(out) :: Kd_int
241 real,
dimension(SZI_(G)) :: &
246 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
250 real,
dimension(SZI_(G),SZK_(G)) :: &
251 N2_lay, & !< Squared buoyancy frequency associated with layers [T-2 ~> s-2]
252 Kd_lay_2d, & !< The layer diffusivities [Z2 T-1 ~> m2 s-1]
253 maxTKE, & !< Energy required to entrain to h_max [Z3 T-3 ~> m3 s-3]
258 real,
dimension(SZI_(G),SZK_(G)+1) :: &
259 N2_int, & !< squared buoyancy frequency associated at interfaces [T-2 ~> s-2]
260 Kd_int_2d, & !< The interface diffusivities [Z2 T-1 ~> m2 s-1]
261 Kv_bkgnd, & !< The background diffusion related interface viscosities [Z2 T-1 ~> m2 s-1]
262 dRho_int, & !< Locally referenced potential density difference across interfaces [R ~> kg m-3]
263 KT_extra, & !< Double difusion diffusivity of temperature [Z2 T-1 ~> m2 s-1]
270 logical :: TKE_to_Kd_used
271 integer :: kb(szi_(g))
273 logical :: showCallTree
275 integer :: i, j, k, is, ie, js, je, nz, isd, ied, jsd, jed
277 real :: kappa_dt_fill
279 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
280 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
281 showcalltree = calltree_showquery()
282 if (showcalltree)
call calltree_enter(
"set_diffusivity(), MOM_set_diffusivity.F90")
284 if (.not.
associated(cs))
call mom_error(fatal,
"set_diffusivity: "//&
285 "Module must be initialized before it is used.")
287 if (cs%answers_2018)
then 289 kappa_dt_fill = us%m_to_Z**2 * 1.e-3 * 7200.
291 kappa_dt_fill = cs%Kd_smooth * dt
293 omega2 = cs%omega * cs%omega
295 use_eos =
associated(tv%eqn_of_state)
297 if ((cs%use_CVMix_ddiff .or. cs%double_diffusion) .and. .not. &
298 (
associated(visc%Kd_extra_T) .and.
associated(visc%Kd_extra_S))) &
299 call mom_error(fatal,
"set_diffusivity: both visc%Kd_extra_T and "//&
300 "visc%Kd_extra_S must be associated when USE_CVMIX_DDIFF or DOUBLE_DIFFUSION are true.")
302 tke_to_kd_used = (cs%use_tidal_mixing .or. cs%ML_radiation .or. &
303 (cs%bottomdraglaw .and. .not.cs%use_LOTW_BBL_diffusivity))
306 if (
present(kd_lay)) kd_lay(:,:,:) = cs%Kd
307 if (
present(kd_int)) kd_int(:,:,:) = cs%Kd
308 if (
associated(visc%Kv_slow)) visc%Kv_slow(:,:,:) = cs%Kv
312 if (cs%id_N2 > 0)
then 313 allocate(dd%N2_3d(isd:ied,jsd:jed,nz+1)) ; dd%N2_3d(:,:,:) = 0.0
315 if (cs%id_Kd_user > 0)
then 316 allocate(dd%Kd_user(isd:ied,jsd:jed,nz+1)) ; dd%Kd_user(:,:,:) = 0.0
318 if (cs%id_Kd_work > 0)
then 319 allocate(dd%Kd_work(isd:ied,jsd:jed,nz)) ; dd%Kd_work(:,:,:) = 0.0
321 if (cs%id_maxTKE > 0)
then 322 allocate(dd%maxTKE(isd:ied,jsd:jed,nz)) ; dd%maxTKE(:,:,:) = 0.0
324 if (cs%id_TKE_to_Kd > 0)
then 325 allocate(dd%TKE_to_Kd(isd:ied,jsd:jed,nz)) ; dd%TKE_to_Kd(:,:,:) = 0.0
327 if ((cs%double_diffusion) .and. (cs%id_KT_extra > 0))
then 328 allocate(dd%KT_extra(isd:ied,jsd:jed,nz+1)) ; dd%KT_extra(:,:,:) = 0.0
330 if ((cs%double_diffusion) .and. (cs%id_KS_extra > 0))
then 331 allocate(dd%KS_extra(isd:ied,jsd:jed,nz+1)) ; dd%KS_extra(:,:,:) = 0.0
333 if (cs%id_R_rho > 0)
then 334 allocate(dd%drho_rat(isd:ied,jsd:jed,nz+1)) ; dd%drho_rat(:,:,:) = 0.0
336 if (cs%id_Kd_BBL > 0)
then 337 allocate(dd%Kd_BBL(isd:ied,jsd:jed,nz+1)) ; dd%Kd_BBL(:,:,:) = 0.0
340 if (cs%id_Kd_bkgnd > 0)
then 341 allocate(dd%Kd_bkgnd(isd:ied,jsd:jed,nz+1)) ; dd%Kd_bkgnd(:,:,:) = 0.
343 if (cs%id_Kv_bkgnd > 0)
then 344 allocate(dd%Kv_bkgnd(isd:ied,jsd:jed,nz+1)) ; dd%Kv_bkgnd(:,:,:) = 0.
348 call setup_tidal_diagnostics(g, cs%tidal_mixing_CSp)
350 if (cs%useKappaShear)
then 352 call hchksum_pair(
"before calc_KS [uv]_h", u_h, v_h, g%HI, scale=us%L_T_to_m_s)
354 call cpu_clock_begin(id_clock_kappashear)
355 if (cs%Vertex_shear)
then 356 call full_convection(g, gv, us, h, tv, t_f, s_f, fluxes%p_surf, &
357 (gv%Z_to_H**2)*kappa_dt_fill, halo=1)
359 call calc_kappa_shear_vertex(u, v, h, t_f, s_f, tv, fluxes%p_surf, visc%Kd_shear, &
360 visc%TKE_turb, visc%Kv_shear_Bu, dt, 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, 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
393 call hchksum(tv%T,
"before vert_fill_TS tv%T",g%HI)
394 call hchksum(tv%S,
"before vert_fill_TS tv%S",g%HI)
395 call hchksum(h,
"before vert_fill_TS h",g%HI, scale=gv%H_to_m)
397 call vert_fill_ts(h, tv%T, tv%S, kappa_dt_fill, t_f, s_f, g, gv, larger_h_denom=.true.)
399 call hchksum(tv%T,
"after vert_fill_TS tv%T",g%HI)
400 call hchksum(tv%S,
"after vert_fill_TS tv%S",g%HI)
401 call hchksum(h,
"after vert_fill_TS h",g%HI, scale=gv%H_to_m)
414 call find_n2(h, tv, t_f, s_f, fluxes, j, g, gv, us, cs, drho_int, n2_lay, n2_int, n2_bot)
416 if (
associated(dd%N2_3d))
then 417 do k=1,nz+1 ;
do i=is,ie ; dd%N2_3d(i,j,k) = n2_int(i,k) ;
enddo ;
enddo 421 call calculate_bkgnd_mixing(h, tv, n2_lay, kd_lay_2d, kd_int_2d, kv_bkgnd, j, g, gv, us, cs%bkgnd_mixing_csp)
423 if (
associated(visc%Kv_slow))
then ;
do k=1,nz+1 ;
do i=is,ie
424 visc%Kv_slow(i,j,k) = visc%Kv_slow(i,j,k) + kv_bkgnd(i,k)
425 enddo ;
enddo ;
endif 426 if (cs%id_Kv_bkgnd > 0)
then ;
do k=1,nz+1 ;
do i=is,ie
427 dd%Kv_bkgnd(i,j,k) = kv_bkgnd(i,k)
428 enddo ;
enddo ;
endif 429 if (cs%id_Kd_bkgnd > 0)
then ;
do k=1,nz+1 ;
do i=is,ie
430 dd%Kd_bkgnd(i,j,k) = kd_int_2d(i,k)
431 enddo ;
enddo ;
endif 434 if (cs%double_diffusion)
then 435 call double_diffusion(tv, h, t_f, s_f, j, g, gv, us, cs, kt_extra, ks_extra)
436 do k=2,nz ;
do i=is,ie
437 if (ks_extra(i,k) > kt_extra(i,k))
then 438 kd_lay_2d(i,k-1) = kd_lay_2d(i,k-1) + 0.5 * kt_extra(i,k)
439 kd_lay_2d(i,k) = kd_lay_2d(i,k) + 0.5 * kt_extra(i,k)
440 visc%Kd_extra_S(i,j,k) = (ks_extra(i,k) - kt_extra(i,k))
441 visc%Kd_extra_T(i,j,k) = 0.0
442 elseif (kt_extra(i,k) > 0.0)
then 443 kd_lay_2d(i,k-1) = kd_lay_2d(i,k-1) + 0.5 * ks_extra(i,k)
444 kd_lay_2d(i,k) = kd_lay_2d(i,k) + 0.5 * ks_extra(i,k)
445 visc%Kd_extra_T(i,j,k) = (kt_extra(i,k) - ks_extra(i,k))
446 visc%Kd_extra_S(i,j,k) = 0.0
448 visc%Kd_extra_T(i,j,k) = 0.0
449 visc%Kd_extra_S(i,j,k) = 0.0
452 if (
associated(dd%KT_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
453 dd%KT_extra(i,j,k) = kt_extra(i,k)
454 enddo ;
enddo ;
endif 456 if (
associated(dd%KS_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
457 dd%KS_extra(i,j,k) = ks_extra(i,k)
458 enddo ;
enddo ;
endif 463 if (cs%use_CVMix_ddiff)
then 464 call cpu_clock_begin(id_clock_cvmix_ddiff)
465 if (
associated(dd%drho_rat))
then 466 call compute_ddiff_coeffs(h, tv, g, gv, us, j, visc%Kd_extra_T, visc%Kd_extra_S, &
467 cs%CVMix_ddiff_csp, dd%drho_rat)
469 call compute_ddiff_coeffs(h, tv, g, gv, us, j, visc%Kd_extra_T, visc%Kd_extra_S, cs%CVMix_ddiff_csp)
471 call cpu_clock_end(id_clock_cvmix_ddiff)
475 if (tke_to_kd_used)
then 476 call find_tke_to_kd(h, tv, drho_int, n2_lay, j, dt, g, gv, us, cs, tke_to_kd, maxtke, kb)
477 if (
associated(dd%maxTKE))
then ;
do k=1,nz ;
do i=is,ie
478 dd%maxTKE(i,j,k) = maxtke(i,k)
479 enddo ;
enddo ;
endif 480 if (
associated(dd%TKE_to_Kd))
then ;
do k=1,nz ;
do i=is,ie
481 dd%TKE_to_Kd(i,j,k) = tke_to_kd(i,k)
482 enddo ;
enddo ;
endif 486 if (cs%useKappaShear .or. cs%use_CVMix_shear)
then 487 if (
present(kd_int))
then 488 do k=2,nz ;
do i=is,ie
489 kd_int_2d(i,k) = visc%Kd_shear(i,j,k) + 0.5 * (kd_lay_2d(i,k-1) + kd_lay_2d(i,k))
492 kd_int_2d(i,1) = visc%Kd_shear(i,j,1)
493 kd_int_2d(i,nz+1) = 0.0
496 do k=1,nz ;
do i=is,ie
497 kd_lay_2d(i,k) = kd_lay_2d(i,k) + 0.5 * (visc%Kd_shear(i,j,k) + visc%Kd_shear(i,j,k+1))
500 if (
present(kd_int))
then 502 kd_int_2d(i,1) = kd_lay_2d(i,1) ; kd_int_2d(i,nz+1) = 0.0
504 do k=2,nz ;
do i=is,ie
505 kd_int_2d(i,k) = 0.5 * (kd_lay_2d(i,k-1) + kd_lay_2d(i,k))
510 if (
present(kd_int))
then 512 if (cs%ML_radiation) &
513 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, tke_to_kd, kd_lay_2d, kd_int_2d)
516 if (cs%use_tidal_mixing) &
517 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tidal_mixing_CSp, &
518 n2_lay, n2_int, kd_lay_2d, kd_int_2d, cs%Kd_max, visc%Kv_slow)
521 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then 522 if (cs%use_LOTW_BBL_diffusivity)
then 523 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
524 dd%Kd_BBL, kd_lay_2d, kd_int_2d)
526 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
527 maxtke, kb, g, gv, us, cs, kd_lay_2d, kd_int_2d, dd%Kd_BBL)
531 if (cs%limit_dissipation)
then 537 do k=2,nz ;
do i=is,ie
538 dissip = max( cs%dissip_min, &
539 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_int(i,k)), &
540 cs%dissip_N2 * n2_int(i,k))
541 kd_int_2d(i,k) = max(kd_int_2d(i,k) , &
542 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_int(i,k) + omega2))))
547 if (cs%Kd_add > 0.0)
then ;
do k=1,nz+1 ;
do i=is,ie
548 kd_int_2d(i,k) = kd_int_2d(i,k) + cs%Kd_add
549 enddo ;
enddo ;
endif 552 do k=1,nz+1 ;
do i=is,ie
553 kd_int(i,j,k) = kd_int_2d(i,k)
559 if (cs%ML_radiation) &
560 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, tke_to_kd, kd_lay_2d)
563 if (cs%use_tidal_mixing) &
564 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tidal_mixing_CSp, &
565 n2_lay, n2_int, kd_lay_2d, kd_max=cs%Kd_max, kv=visc%Kv_slow)
568 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then 569 if (cs%use_LOTW_BBL_diffusivity)
then 570 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
571 dd%Kd_BBL, kd_lay_2d)
573 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
574 maxtke, kb, g, gv, us, cs, kd_lay_2d, kd_bbl=dd%Kd_BBL)
580 if (cs%limit_dissipation)
then 586 do k=2,nz-1 ;
do i=is,ie
587 dissip = max( cs%dissip_min, &
588 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_lay(i,k)), &
589 cs%dissip_N2 * n2_lay(i,k))
590 kd_lay_2d(i,k) = max(kd_lay_2d(i,k) , &
591 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_lay(i,k) + omega2))))
595 if (
associated(dd%Kd_work))
then 596 do k=1,nz ;
do i=is,ie
597 dd%Kd_Work(i,j,k) = gv%Rho0 * kd_lay_2d(i,k) * n2_lay(i,k) * &
603 if ((cs%Kd_add > 0.0) .and. (
present(kd_lay)))
then 604 do k=1,nz ;
do i=is,ie
605 kd_lay_2d(i,k) = kd_lay_2d(i,k) + cs%Kd_add
610 if (
present(kd_lay))
then ;
do k=1,nz ;
do i=is,ie
611 kd_lay(i,j,k) = kd_lay_2d(i,k)
612 enddo ;
enddo ;
endif 615 if (cs%user_change_diff)
then 616 call user_change_diff(h, tv, g, gv, us, cs%user_change_diff_CSp, kd_lay, kd_int, &
617 t_f, s_f, dd%Kd_user)
621 if (
present(kd_lay))
call hchksum(kd_lay,
"Kd_lay", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
623 if (cs%useKappaShear)
call hchksum(visc%Kd_shear,
"Turbulent Kd", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
625 if (cs%use_CVMix_ddiff)
then 626 call hchksum(visc%Kd_extra_T,
"MOM_set_diffusivity: Kd_extra_T", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
627 call hchksum(visc%Kd_extra_S,
"MOM_set_diffusivity: Kd_extra_S", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
630 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v))
then 631 call uvchksum(
"BBL Kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, g%HI, &
632 haloshift=0, symmetric=.true., scale=us%Z2_T_to_m2_s, &
636 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v))
then 637 call uvchksum(
"BBL bbl_thick_[uv]", visc%bbl_thick_u, visc%bbl_thick_v, &
638 g%HI, haloshift=0, symmetric=.true., scale=us%Z_to_m, &
642 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v))
then 643 call uvchksum(
"Ray_[uv]", visc%Ray_u, visc%Ray_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m*us%s_to_T)
649 if (
present(kd_lay) .and. (cs%id_Kd_layer > 0))
call post_data(cs%id_Kd_layer, kd_lay, cs%diag)
652 if (cs%id_Kd_bkgnd > 0)
call post_data(cs%id_Kd_bkgnd, dd%Kd_bkgnd, cs%diag)
653 if (cs%id_Kv_bkgnd > 0)
call post_data(cs%id_Kv_bkgnd, dd%Kv_bkgnd, cs%diag)
656 call post_tidal_diagnostics(g, gv, h, cs%tidal_mixing_CSp)
657 if (cs%id_N2 > 0)
call post_data(cs%id_N2, dd%N2_3d, cs%diag)
658 if (cs%id_Kd_Work > 0)
call post_data(cs%id_Kd_Work, dd%Kd_Work, cs%diag)
659 if (cs%id_maxTKE > 0)
call post_data(cs%id_maxTKE, dd%maxTKE, cs%diag)
660 if (cs%id_TKE_to_Kd > 0)
call post_data(cs%id_TKE_to_Kd, dd%TKE_to_Kd, cs%diag)
662 if (cs%id_Kd_user > 0)
call post_data(cs%id_Kd_user, dd%Kd_user, cs%diag)
665 if (cs%double_diffusion)
then 666 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, dd%KT_extra, cs%diag)
667 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, dd%KS_extra, cs%diag)
669 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, visc%Kd_extra_T, cs%diag)
670 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, visc%Kd_extra_S, cs%diag)
671 if (cs%id_R_rho > 0)
call post_data(cs%id_R_rho, dd%drho_rat, cs%diag)
673 if (cs%id_Kd_BBL > 0)
call post_data(cs%id_Kd_BBL, dd%Kd_BBL, cs%diag)
675 if (
associated(dd%N2_3d))
deallocate(dd%N2_3d)
676 if (
associated(dd%Kd_work))
deallocate(dd%Kd_work)
677 if (
associated(dd%Kd_user))
deallocate(dd%Kd_user)
678 if (
associated(dd%maxTKE))
deallocate(dd%maxTKE)
679 if (
associated(dd%TKE_to_Kd))
deallocate(dd%TKE_to_Kd)
680 if (
associated(dd%KT_extra))
deallocate(dd%KT_extra)
681 if (
associated(dd%KS_extra))
deallocate(dd%KS_extra)
682 if (
associated(dd%drho_rat))
deallocate(dd%drho_rat)
683 if (
associated(dd%Kd_BBL))
deallocate(dd%Kd_BBL)
685 if (showcalltree)
call calltree_leave(
"set_diffusivity()")
687 end subroutine set_diffusivity
690 subroutine find_tke_to_kd(h, tv, dRho_int, N2_lay, j, dt, G, GV, US, CS, &
691 TKE_to_Kd, maxTKE, kb)
695 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
699 real,
dimension(SZI_(G),SZK_(G)+1),
intent(in) :: dRho_int
701 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: N2_lay
703 integer,
intent(in) :: j
704 real,
intent(in) :: dt
706 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: TKE_to_Kd
711 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: maxTKE
713 integer,
dimension(SZI_(G)),
intent(out) :: kb
716 real,
dimension(SZI_(G),SZK_(G)) :: &
728 real,
dimension(SZI_(G)) :: &
747 logical :: do_i(szi_(g))
749 integer,
dimension(2) :: EOSdom
750 integer :: i, k, is, ie, nz, i_rem, kmb, kb_min
751 is = g%isc ; ie = g%iec ; nz = g%ke
755 h_neglect = gv%H_subroundoff
756 g_rho0 = (us%L_to_Z**2 * gv%g_Earth) / (gv%Rho0)
757 if (cs%answers_2018)
then 758 i_rho0 = 1.0 / (gv%Rho0)
759 g_irho0 = (us%L_to_Z**2 * gv%g_Earth) * i_rho0
765 if (cs%simple_TKE_to_Kd)
then 766 do k=1,nz ;
do i=is,ie
767 hn2po2 = (gv%H_to_Z * h(i,j,k)) * (n2_lay(i,k) + omega2)
769 tke_to_kd(i,k) = 1.0 / hn2po2
770 else; tke_to_kd(i,k) = 0.;
endif 773 maxtke(i,k) = hn2po2 * cs%Kd_max
780 if (cs%bulkmixedlayer)
then 781 kmb = gv%nk_rho_varies
782 do i=is,ie ; p_0(i) = 0.0 ; p_ref(i) = tv%P_Ref ;
enddo 783 eosdom(:) = eos_domain(g%HI)
785 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), p_0, rho_0(:,k), tv%eqn_of_state, eosdom)
787 call calculate_density(tv%T(:,j,kmb), tv%S(:,j,kmb), p_ref, rcv_kmb, tv%eqn_of_state, eosdom)
793 do k=kmb+1,nz-1 ;
if (rcv_kmb(i) <= gv%Rlay(k))
exit ;
enddo 798 do k=kb(i)-1,kmb+1,-1
799 if (rho_0(i,kmb) > rho_0(i,k))
exit 800 if (h(i,j,k)>2.0*gv%Angstrom_H) kb(i) = k
804 call set_density_ratios(h, tv, kb, g, gv, us, cs, j, ds_dsp1, rho_0)
807 do i=is,ie ; kb(i) = 1 ;
enddo 808 call set_density_ratios(h, tv, kb, g, gv, us, cs, j, ds_dsp1)
813 do k=2,nz-1 ;
do i=is,ie
814 dsp1_ds(i,k) = 1.0 / ds_dsp1(i,k)
816 do i=is,ie ; dsp1_ds(i,nz) = 0.0 ;
enddo 818 if (cs%bulkmixedlayer)
then 819 kmb = gv%nk_rho_varies
821 htot(i) = gv%H_to_Z*h(i,j,kmb)
824 mfkb(i) = ds_dsp1(i,kb(i)) * (gv%H_to_Z*(h(i,j,kmb) - gv%Angstrom_H))
826 do k=1,kmb-1 ;
do i=is,ie
827 htot(i) = htot(i) + gv%H_to_Z*h(i,j,k)
828 mfkb(i) = mfkb(i) + ds_dsp1(i,k+1)*(gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H))
832 maxent(i,1) = 0.0 ; htot(i) = gv%H_to_Z*(h(i,j,1) - gv%Angstrom_H)
835 do k=kb_min,nz-1 ;
do i=is,ie
837 maxent(i,kb(i)) = mfkb(i)
838 elseif (k > kb(i))
then 839 if (cs%answers_2018)
then 840 maxent(i,k) = (1.0/dsp1_ds(i,k))*(maxent(i,k-1) + htot(i))
842 maxent(i,k) = ds_dsp1(i,k)*(maxent(i,k-1) + htot(i))
844 htot(i) = htot(i) + gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H)
849 htot(i) = gv%H_to_Z*(h(i,j,nz) - gv%Angstrom_H) ; maxent(i,nz) = 0.0
850 do_i(i) = (g%mask2dT(i,j) > 0.5)
854 do i=is,ie ;
if (do_i(i))
then 855 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif 857 maxent(i,k) = min(maxent(i,k),dsp1_ds(i,k+1)*maxent(i,k+1) + htot(i))
858 htot(i) = htot(i) + gv%H_to_Z*(h(i,j,k) - gv%Angstrom_H)
865 maxtke(i,1) = 0.0 ; tke_to_kd(i,1) = 0.0
866 maxtke(i,nz) = 0.0 ; tke_to_kd(i,nz) = 0.0
868 do k=2,kmb ;
do i=is,ie
870 tke_to_kd(i,k) = 1.0 / ((n2_lay(i,k) + omega2) * &
871 (gv%H_to_Z*(h(i,j,k) + h_neglect)))
873 do k=kmb+1,kb_min-1 ;
do i=is,ie
876 maxtke(i,k) = 0.0 ; tke_to_kd(i,k) = 0.0
878 do k=kb_min,nz-1 ;
do i=is,ie
888 dh_max = maxent(i,k) * (1.0 + dsp1_ds(i,k))
889 drho_lay = 0.5 * max(drho_int(i,k) + drho_int(i,k+1), 0.0)
890 maxtke(i,k) = i_dt * (g_irho0 * &
891 (0.5*max(drho_int(i,k+1) + dsp1_ds(i,k)*drho_int(i,k), 0.0))) * &
892 ((gv%H_to_Z*h(i,j,k) + dh_max) * maxent(i,k))
896 tke_to_kd(i,k) = 1.0 / (g_rho0 * drho_lay + &
897 cs%omega**2 * gv%H_to_Z*(h(i,j,k) + h_neglect))
901 end subroutine find_tke_to_kd
904 subroutine find_n2(h, tv, T_f, S_f, fluxes, j, G, GV, US, CS, dRho_int, &
905 N2_lay, N2_int, N2_bot)
909 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
913 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
916 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
919 type(
forcing),
intent(in) :: fluxes
920 integer,
intent(in) :: j
922 real,
dimension(SZI_(G),SZK_(G)+1), &
923 intent(out) :: dRho_int
925 real,
dimension(SZI_(G),SZK_(G)+1), &
926 intent(out) :: N2_int
927 real,
dimension(SZI_(G),SZK_(G)), &
928 intent(out) :: N2_lay
929 real,
dimension(SZI_(G)),
intent(out) :: N2_bot
931 real,
dimension(SZI_(G),SZK_(G)+1) :: &
936 real,
dimension(SZI_(G)) :: &
951 logical :: do_i(szi_(g)), do_any
952 integer,
dimension(2) :: EOSdom
953 integer :: i, k, is, ie, nz
955 is = g%isc ; ie = g%iec ; nz = g%ke
956 g_rho0 = (us%L_to_Z**2 * gv%g_Earth) / (gv%Rho0)
957 h_neglect = gv%H_subroundoff
961 drho_int(i,1) = 0.0 ; drho_int(i,nz+1) = 0.0
962 drho_int_unfilt(i,1) = 0.0 ; drho_int_unfilt(i,nz+1) = 0.0
964 if (
associated(tv%eqn_of_state))
then 965 if (
associated(fluxes%p_surf))
then 966 do i=is,ie ; pres(i) = fluxes%p_surf(i,j) ;
enddo 968 do i=is,ie ; pres(i) = 0.0 ;
enddo 970 eosdom(:) = eos_domain(g%HI)
973 pres(i) = pres(i) + (gv%g_Earth*gv%H_to_RZ)*h(i,j,k-1)
974 temp_int(i) = 0.5 * (t_f(i,j,k) + t_f(i,j,k-1))
975 salin_int(i) = 0.5 * (s_f(i,j,k) + s_f(i,j,k-1))
978 tv%eqn_of_state, eosdom)
980 drho_int(i,k) = max(drho_dt(i,k)*(t_f(i,j,k) - t_f(i,j,k-1)) + &
981 drho_ds(i,k)*(s_f(i,j,k) - s_f(i,j,k-1)), 0.0)
982 drho_int_unfilt(i,k) = max(drho_dt(i,k)*(tv%T(i,j,k) - tv%T(i,j,k-1)) + &
983 drho_ds(i,k)*(tv%S(i,j,k) - tv%S(i,j,k-1)), 0.0)
987 do k=2,nz ;
do i=is,ie
988 drho_int(i,k) = gv%Rlay(k) - gv%Rlay(k-1)
993 do k=1,nz ;
do i=is,ie
994 n2_lay(i,k) = g_rho0 * 0.5*(drho_int(i,k) + drho_int(i,k+1)) / &
995 (gv%H_to_Z*(h(i,j,k) + h_neglect))
997 do i=is,ie ; n2_int(i,1) = 0.0 ; n2_int(i,nz+1) = 0.0 ;
enddo 998 do k=2,nz ;
do i=is,ie
999 n2_int(i,k) = g_rho0 * drho_int(i,k) / &
1000 (0.5*gv%H_to_Z*(h(i,j,k-1) + h(i,j,k) + h_neglect))
1005 hb(i) = 0.0 ; drho_bot(i) = 0.0 ; h_amp(i) = 0.0
1006 z_from_bot(i) = 0.5*gv%H_to_Z*h(i,j,nz)
1007 do_i(i) = (g%mask2dT(i,j) > 0.5)
1009 if (cs%use_tidal_mixing)
call tidal_mixing_h_amp(h_amp, g, j, cs%tidal_mixing_CSp)
1013 do i=is,ie ;
if (do_i(i))
then 1014 dz_int = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j,k-1))
1015 z_from_bot(i) = z_from_bot(i) + dz_int
1017 hb(i) = hb(i) + dz_int
1018 drho_bot(i) = drho_bot(i) + drho_int(i,k)
1020 if (z_from_bot(i) > h_amp(i))
then 1023 hb(i) = hb(i) + 0.5*gv%H_to_Z*(h(i,j,k-1) + h(i,j,k-2))
1024 drho_bot(i) = drho_bot(i) + drho_int(i,k-1)
1031 if (.not.do_any)
exit 1035 if (hb(i) > 0.0)
then 1036 n2_bot(i) = (g_rho0 * drho_bot(i)) / hb(i)
1037 else ; n2_bot(i) = 0.0 ;
endif 1038 z_from_bot(i) = 0.5*gv%H_to_Z*h(i,j,nz)
1039 do_i(i) = (g%mask2dT(i,j) > 0.5)
1044 do i=is,ie ;
if (do_i(i))
then 1045 dz_int = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j,k-1))
1046 z_from_bot(i) = z_from_bot(i) + dz_int
1048 n2_int(i,k) = n2_bot(i)
1049 if (k>2) n2_lay(i,k-1) = n2_bot(i)
1051 if (z_from_bot(i) > h_amp(i))
then 1052 if (k>2) n2_int(i,k-1) = n2_bot(i)
1058 if (.not.do_any)
exit 1061 if (
associated(tv%eqn_of_state))
then 1062 do k=1,nz+1 ;
do i=is,ie
1063 drho_int(i,k) = drho_int_unfilt(i,k)
1067 end subroutine find_n2
1076 subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, US, CS, Kd_T_dd, Kd_S_dd)
1082 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1084 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1087 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1090 integer,
intent(in) :: j
1092 real,
dimension(SZI_(G),SZK_(G)+1), &
1093 intent(out) :: Kd_T_dd
1095 real,
dimension(SZI_(G),SZK_(G)+1), &
1096 intent(out) :: Kd_S_dd
1099 real,
dimension(SZI_(G)) :: &
1114 real,
parameter :: Rrho0 = 1.9
1116 integer,
dimension(2) :: EOSdom
1117 integer :: i, k, is, ie, nz
1118 is = g%isc ; ie = g%iec ; nz = g%ke
1120 if (
associated(tv%eqn_of_state))
then 1122 pres(i) = 0.0 ; kd_t_dd(i,1) = 0.0 ; kd_s_dd(i,1) = 0.0
1123 kd_t_dd(i,nz+1) = 0.0 ; kd_s_dd(i,nz+1) = 0.0
1125 if (
associated(tv%p_surf))
then ;
do i=is,ie ; pres(i) = tv%p_surf(i,j) ;
enddo ;
endif 1126 eosdom(:) = eos_domain(g%HI)
1129 pres(i) = pres(i) + (gv%g_Earth*gv%H_to_RZ)*h(i,j,k-1)
1130 temp_int(i) = 0.5 * (t_f(i,j,k-1) + t_f(i,j,k))
1131 salin_int(i) = 0.5 * (s_f(i,j,k-1) + s_f(i,j,k))
1134 tv%eqn_of_state, eosdom)
1137 alpha_dt = -1.0*drho_dt(i) * (t_f(i,j,k-1) - t_f(i,j,k))
1138 beta_ds = drho_ds(i) * (s_f(i,j,k-1) - s_f(i,j,k))
1140 if ((alpha_dt > beta_ds) .and. (beta_ds > 0.0))
then 1141 rrho = min(alpha_dt / beta_ds, rrho0)
1142 diff_dd = 1.0 - ((rrho-1.0)/(rrho0-1.0))
1143 kd_dd = cs%Max_salt_diff_salt_fingers * diff_dd*diff_dd*diff_dd
1144 kd_t_dd(i,k) = 0.7 * kd_dd
1145 kd_s_dd(i,k) = kd_dd
1146 elseif ((alpha_dt < 0.) .and. (beta_ds < 0.) .and. (alpha_dt > beta_ds))
then 1147 rrho = alpha_dt / beta_ds
1148 kd_dd = cs%Kv_molecular * 0.909 * exp(4.6 * exp(-0.54 * (1/rrho - 1)))
1150 if (rrho > 0.5) prandtl = (1.85-0.85/rrho)*rrho
1151 kd_t_dd(i,k) = kd_dd
1152 kd_s_dd(i,k) = prandtl * kd_dd
1154 kd_t_dd(i,k) = 0.0 ; kd_s_dd(i,k) = 0.0
1160 end subroutine double_diffusion
1163 subroutine add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, TKE_to_Kd, &
1164 maxTKE, kb, G, GV, US, CS, Kd_lay, Kd_int, Kd_BBL)
1168 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1170 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1172 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1176 type(
forcing),
intent(in) :: fluxes
1179 integer,
intent(in) :: j
1180 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd
1185 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: maxTKE
1187 integer,
dimension(SZI_(G)),
intent(in) :: kb
1190 real,
dimension(SZI_(G),SZK_(G)),
intent(inout) :: Kd_lay
1192 real,
dimension(SZI_(G),SZK_(G)+1), &
1193 optional,
intent(inout) :: Kd_int
1195 real,
dimension(:,:,:),
pointer :: Kd_BBL
1199 real,
dimension(SZK_(G)+1) :: &
1201 real,
dimension(SZI_(G)) :: &
1212 real :: TKE_to_layer
1222 logical :: Rayleigh_drag
1226 logical :: domore, do_i(szi_(g))
1227 logical :: do_diag_Kd_BBL
1229 integer :: i, k, is, ie, nz, i_rem, kb_min
1230 is = g%isc ; ie = g%iec ; nz = g%ke
1232 do_diag_kd_bbl =
associated(kd_bbl)
1234 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return 1236 cdrag_sqrt = sqrt(cs%cdrag)
1237 tke_ray = 0.0 ; rayleigh_drag = .false.
1238 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1240 i_rho0 = 1.0 / (gv%Rho0)
1241 r0_g = gv%Rho0 / (us%L_to_Z**2 * gv%g_Earth)
1243 do k=2,nz ; rint(k) = 0.5*(gv%Rlay(k-1)+gv%Rlay(k)) ;
enddo 1245 kb_min = max(gv%nk_rho_varies+1,2)
1251 ustar_h = visc%ustar_BBL(i,j)
1252 if (
associated(fluxes%ustar_tidal)) &
1253 ustar_h = ustar_h + fluxes%ustar_tidal(i,j)
1254 absf = 0.25 * ((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1255 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1256 if ((ustar_h > 0.0) .and. (absf > 0.5*cs%IMax_decay*ustar_h))
then 1257 i2decay(i) = absf / ustar_h
1261 i2decay(i) = 0.5*cs%IMax_decay
1263 tke(i) = ((cs%BBL_effic * cdrag_sqrt) * exp(-i2decay(i)*(gv%H_to_Z*h(i,j,nz))) ) * &
1266 if (
associated(fluxes%TKE_tidal)) &
1267 tke(i) = tke(i) + fluxes%TKE_tidal(i,j) * i_rho0 * &
1268 (cs%BBL_effic * exp(-i2decay(i)*(gv%H_to_Z*h(i,j,nz))))
1275 gh_sum_top(i) = r0_g * 400.0 * ustar_h**2
1277 do_i(i) = (g%mask2dT(i,j) > 0.5)
1278 htot(i) = gv%H_to_Z*h(i,j,nz)
1279 rho_htot(i) = gv%Rlay(nz)*(gv%H_to_Z*h(i,j,nz))
1280 rho_top(i) = gv%Rlay(1)
1281 if (cs%bulkmixedlayer .and. do_i(i)) rho_top(i) = gv%Rlay(kb(i)-1)
1284 do k=nz-1,2,-1 ; domore = .false.
1285 do i=is,ie ;
if (do_i(i))
then 1286 htot(i) = htot(i) + gv%H_to_Z*h(i,j,k)
1287 rho_htot(i) = rho_htot(i) + gv%Rlay(k)*(gv%H_to_Z*h(i,j,k))
1288 if (htot(i)*gv%Rlay(k-1) <= (rho_htot(i) - gh_sum_top(i)))
then 1290 rho_top(i) = (rho_htot(i) - gh_sum_top(i)) / htot(i)
1292 elseif (k <= kb(i))
then ; do_i(i) = .false.
1293 else ; domore = .true. ;
endif 1295 if (.not.domore)
exit 1298 do i=is,ie ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo 1301 do i=is,ie ;
if (do_i(i))
then 1302 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif 1306 tke(i) = tke(i) * exp(-i2decay(i) * (gv%H_to_Z*(h(i,j,k) + h(i,j,k+1))))
1309 if (maxtke(i,k) <= 0.0) cycle
1313 if (tke(i) > 0.0)
then 1314 if (rint(k) <= rho_top(i))
then 1315 tke_to_layer = tke(i)
1317 drl = rint(k+1) - rint(k) ; drbot = rint(k+1) - rho_top(i)
1318 tke_to_layer = tke(i) * drl * &
1319 (3.0*drbot*(rint(k) - rho_top(i)) + drl**2) / (drbot**3)
1321 else ; tke_to_layer = 0.0 ;
endif 1324 if (rayleigh_drag) tke_ray = 0.5*cs%BBL_effic * us%L_to_Z**2 * g%IareaT(i,j) * &
1325 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1326 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1327 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1328 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1330 if (tke_to_layer + tke_ray > 0.0)
then 1331 if (cs%BBL_mixing_as_max)
then 1332 if (tke_to_layer + tke_ray > maxtke(i,k)) &
1333 tke_to_layer = maxtke(i,k) - tke_ray
1335 tke(i) = tke(i) - tke_to_layer
1337 if (kd_lay(i,k) < (tke_to_layer + tke_ray) * tke_to_kd(i,k))
then 1338 delta_kd = (tke_to_layer + tke_ray) * tke_to_kd(i,k) - kd_lay(i,k)
1339 if ((cs%Kd_max >= 0.0) .and. (delta_kd > cs%Kd_max))
then 1340 delta_kd = cs%Kd_max
1341 kd_lay(i,k) = kd_lay(i,k) + delta_kd
1343 kd_lay(i,k) = (tke_to_layer + tke_ray) * tke_to_kd(i,k)
1345 if (
present(kd_int))
then 1346 kd_int(i,k) = kd_int(i,k) + 0.5 * delta_kd
1347 kd_int(i,k+1) = kd_int(i,k+1) + 0.5 * delta_kd
1349 if (do_diag_kd_bbl)
then 1350 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5 * delta_kd
1351 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5 * delta_kd
1355 if (kd_lay(i,k) >= maxtke(i,k) * tke_to_kd(i,k))
then 1357 tke(i) = tke(i) + tke_ray
1358 elseif (kd_lay(i,k) + (tke_to_layer + tke_ray) * tke_to_kd(i,k) > &
1359 maxtke(i,k) * tke_to_kd(i,k))
then 1360 tke_here = ((tke_to_layer + tke_ray) + kd_lay(i,k) / tke_to_kd(i,k)) - maxtke(i,k)
1361 tke(i) = (tke(i) - tke_here) + tke_ray
1363 tke_here = tke_to_layer + tke_ray
1364 tke(i) = tke(i) - tke_to_layer
1366 if (tke(i) < 0.0) tke(i) = 0.0
1368 if (tke_here > 0.0)
then 1369 delta_kd = tke_here * tke_to_kd(i,k)
1370 if (cs%Kd_max >= 0.0) delta_kd = min(delta_kd, cs%Kd_max)
1371 kd_lay(i,k) = kd_lay(i,k) + delta_kd
1372 if (
present(kd_int))
then 1373 kd_int(i,k) = kd_int(i,k) + 0.5 * delta_kd
1374 kd_int(i,k+1) = kd_int(i,k+1) + 0.5 * delta_kd
1376 if (do_diag_kd_bbl)
then 1377 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5 * delta_kd
1378 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5 * delta_kd
1388 if ((tke(i)<= 0.0) .and. (tke_ray == 0.0))
then 1389 do_i(i) = .false. ; i_rem = i_rem - 1
1393 if (i_rem == 0)
exit 1396 end subroutine add_drag_diffusivity
1401 subroutine add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, N2_int, &
1402 G, GV, US, CS, Kd_BBL, Kd_lay, Kd_int)
1406 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1408 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1410 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1414 type(
forcing),
intent(in) :: fluxes
1417 integer,
intent(in) :: j
1418 real,
dimension(SZI_(G),SZK_(G)+1), &
1419 intent(in) :: N2_int
1421 real,
dimension(:,:,:),
pointer :: Kd_BBL
1422 real,
dimension(SZI_(G),SZK_(G)), &
1423 optional,
intent(inout) :: Kd_lay
1424 real,
dimension(SZI_(G),SZK_(G)+1), &
1425 optional,
intent(inout) :: Kd_int
1429 real :: TKE_remaining
1430 real :: TKE_consumed
1439 real :: total_thickness
1446 logical :: Rayleigh_drag
1448 integer :: i, k, km1
1449 real,
parameter :: von_karm = 0.41
1450 logical :: do_diag_Kd_BBL
1452 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return 1453 do_diag_kd_bbl =
associated(kd_bbl)
1456 if (cs%LOTW_BBL_use_omega) n2_min = cs%omega**2
1459 rayleigh_drag = .false.
1460 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1461 i_rho0 = 1.0 / (gv%Rho0)
1462 cdrag_sqrt = sqrt(cs%cdrag)
1467 absf = 0.25 * ((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1468 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1471 ustar = visc%ustar_BBL(i,j)
1476 if (
associated(fluxes%ustar_tidal)) ustar = ustar + fluxes%ustar_tidal(i,j)
1480 idecay = cs%IMax_decay
1481 if ((ustar > 0.0) .and. (absf > cs%IMax_decay * ustar)) idecay = absf / ustar
1486 tke_column = cdrag_sqrt * visc%TKE_BBL(i,j)
1489 if (
associated(fluxes%TKE_tidal)) &
1490 tke_column = tke_column + fluxes%TKE_tidal(i,j) * i_rho0
1491 tke_column = cs%BBL_effic * tke_column
1493 tke_remaining = tke_column
1494 total_thickness = ( sum(h(i,j,:)) + gv%H_subroundoff )* gv%H_to_Z
1495 ustar_d = ustar * total_thickness
1502 dh = gv%H_to_Z * h(i,j,k)
1504 dhm1 = gv%H_to_Z * h(i,j,km1)
1507 if (rayleigh_drag) tke_remaining = tke_remaining + &
1508 0.5*cs%BBL_effic * us%L_to_Z**2 * g%IareaT(i,j) * &
1509 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1510 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1511 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1512 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1516 tke_remaining = exp(-idecay*dh) * tke_remaining
1518 z_bot = z_bot + h(i,j,k)*gv%H_to_Z
1519 d_minus_z = max(total_thickness - z_bot, 0.)
1523 if ( ustar_d + absf * ( z_bot * d_minus_z ) == 0.)
then 1526 kd_wall = ((von_karm * ustar2) * (z_bot * d_minus_z)) &
1527 / (ustar_d + absf * (z_bot * d_minus_z))
1532 tke_kd_wall = kd_wall * 0.5 * (dh + dhm1) * max(n2_int(i,k), n2_min)
1535 if (tke_kd_wall > 0.)
then 1536 tke_consumed = min(tke_kd_wall, tke_remaining)
1537 kd_wall = (tke_consumed / tke_kd_wall) * kd_wall
1540 if (tke_remaining > 0.)
then 1549 tke_remaining = tke_remaining - tke_consumed
1552 if (
present(kd_int)) kd_int(i,k) = kd_int(i,k) + kd_wall
1553 if (
present(kd_lay)) kd_lay(i,k) = kd_lay(i,k) + 0.5 * (kd_wall + kd_lower)
1555 if (do_diag_kd_bbl) kd_bbl(i,j,k) = kd_wall
1559 end subroutine add_lotw_bbl_diffusivity
1562 subroutine add_mlrad_diffusivity(h, fluxes, j, G, GV, US, CS, TKE_to_Kd, Kd_lay, Kd_int)
1566 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1568 type(
forcing),
intent(in) :: fluxes
1569 integer,
intent(in) :: j
1571 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd
1576 real,
dimension(SZI_(G),SZK_(G)), &
1577 optional,
intent(inout) :: Kd_lay
1578 real,
dimension(SZI_(G),SZK_(G)+1), &
1579 optional,
intent(inout) :: Kd_int
1584 real,
dimension(SZI_(G)) :: h_ml
1585 real,
dimension(SZI_(G)) :: TKE_ml_flux
1586 real,
dimension(SZI_(G)) :: I_decay
1587 real,
dimension(SZI_(G)) :: Kd_mlr_ml
1597 real :: I_decay_len2_TKE
1601 logical :: do_any, do_i(szi_(g))
1602 integer :: i, k, is, ie, nz, kml
1603 is = g%isc ; ie = g%iec ; nz = g%ke
1605 omega2 = cs%omega**2
1608 h_neglect = gv%H_subroundoff*gv%H_to_Z
1610 if (.not.cs%ML_radiation)
return 1612 do i=is,ie ; h_ml(i) = 0.0 ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo 1613 do k=1,kml ;
do i=is,ie ; h_ml(i) = h_ml(i) + gv%H_to_Z*h(i,j,k) ;
enddo ;
enddo 1615 do i=is,ie ;
if (do_i(i))
then 1616 if (cs%ML_omega_frac >= 1.0)
then 1619 f_sq = 0.25 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1620 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
1621 if (cs%ML_omega_frac > 0.0) &
1622 f_sq = cs%ML_omega_frac * 4.0 * omega2 + (1.0 - cs%ML_omega_frac) * f_sq
1625 ustar_sq = max(fluxes%ustar(i,j), cs%ustar_min)**2
1627 tke_ml_flux(i) = (cs%mstar * cs%ML_rad_coeff) * (ustar_sq * (fluxes%ustar(i,j)))
1628 i_decay_len2_tke = cs%TKE_decay**2 * (f_sq / ustar_sq)
1630 if (cs%ML_rad_TKE_decay) &
1631 tke_ml_flux(i) = tke_ml_flux(i) * exp(-h_ml(i) * sqrt(i_decay_len2_tke))
1634 h_ml_sq = (cs%ML_rad_efold_coeff * (h_ml(i)+h_neglect))**2
1635 i_decay(i) = sqrt((i_decay_len2_tke * h_ml_sq + 1.0) / h_ml_sq)
1639 z1 = (gv%H_to_Z*h(i,j,kml+1)) * i_decay(i)
1641 kd_mlr = tke_ml_flux(i) * tke_to_kd(i,kml+1) * (1.0 - exp(-z1))
1643 kd_mlr = tke_ml_flux(i) * tke_to_kd(i,kml+1) * (z1 * (1.0 - z1 * (0.5 - c1_6 * z1)))
1645 kd_mlr_ml(i) = min(kd_mlr, cs%ML_rad_kd_max)
1646 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1649 if (
present(kd_lay))
then 1650 do k=1,kml+1 ;
do i=is,ie ;
if (do_i(i))
then 1651 kd_lay(i,k) = kd_lay(i,k) + kd_mlr_ml(i)
1652 endif ;
enddo ;
enddo 1654 if (
present(kd_int))
then 1655 do k=2,kml+1 ;
do i=is,ie ;
if (do_i(i))
then 1656 kd_int(i,k) = kd_int(i,k) + kd_mlr_ml(i)
1657 endif ;
enddo ;
enddo 1658 if (kml<=nz-1)
then ;
do i=is,ie ;
if (do_i(i))
then 1659 kd_int(i,kml+2) = kd_int(i,kml+2) + 0.5 * kd_mlr_ml(i)
1660 endif ;
enddo ;
endif 1665 do i=is,ie ;
if (do_i(i))
then 1666 dzl = gv%H_to_Z*h(i,j,k) ; z1 = dzl*i_decay(i)
1667 if (cs%ML_Rad_bug)
then 1672 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1673 us%m_to_Z * ((1.0 - exp(-z1)) / dzl)
1675 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1676 us%m_to_Z * (i_decay(i) * (1.0 - z1 * (0.5 - c1_6*z1)))
1680 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * (1.0 - exp(-z1))
1682 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * (z1 * (1.0 - z1 * (0.5 - c1_6*z1)))
1685 kd_mlr = min(kd_mlr, cs%ML_rad_kd_max)
1686 if (
present(kd_lay))
then 1687 kd_lay(i,k) = kd_lay(i,k) + kd_mlr
1689 if (
present(kd_int))
then 1690 kd_int(i,k) = kd_int(i,k) + 0.5 * kd_mlr
1691 kd_int(i,k+1) = kd_int(i,k+1) + 0.5 * kd_mlr
1694 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1695 if (tke_ml_flux(i) * i_decay(i) < 0.1 * cs%Kd_min * omega2)
then 1697 else ; do_any = .true. ;
endif 1699 if (.not.do_any)
exit 1702 end subroutine add_mlrad_diffusivity
1706 subroutine set_bbl_tke(u, v, h, fluxes, visc, G, GV, US, CS, OBC)
1710 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1712 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1714 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1716 type(
forcing),
intent(in) :: fluxes
1725 real,
dimension(SZI_(G)) :: &
1729 real,
dimension(SZIB_(G)) :: &
1734 real :: vhtot(szi_(g))
1736 real,
dimension(SZI_(G),SZJB_(G)) :: &
1743 logical :: domore, do_i(szi_(g))
1744 integer :: i, j, k, is, ie, js, je, nz
1746 logical :: local_open_u_BC, local_open_v_BC
1749 local_open_u_bc = .false.
1750 local_open_v_bc = .false.
1751 if (
present(obc))
then ;
if (
associated(obc))
then 1752 local_open_u_bc = obc%open_u_BCs_exist_globally
1753 local_open_v_bc = obc%open_v_BCs_exist_globally
1756 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1758 if (.not.
associated(cs))
call mom_error(fatal,
"set_BBL_TKE: "//&
1759 "Module must be initialized before it is used.")
1761 if (.not.cs%bottomdraglaw .or. (cs%BBL_effic<=0.0))
then 1762 if (
associated(visc%ustar_BBL))
then 1763 do j=js,je ;
do i=is,ie ; visc%ustar_BBL(i,j) = 0.0 ;
enddo ;
enddo 1765 if (
associated(visc%TKE_BBL))
then 1766 do j=js,je ;
do i=is,ie ; visc%TKE_BBL(i,j) = 0.0 ;
enddo ;
enddo 1771 cdrag_sqrt = sqrt(cs%cdrag)
1779 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_v(i,j) > 0.0))
then 1780 do_i(i) = .true. ; vhtot(i) = 0.0 ; htot(i) = 0.0
1781 vstar(i,j) = visc%Kv_bbl_v(i,j) / (cdrag_sqrt*visc%bbl_thick_v(i,j))
1783 do_i(i) = .false. ; vstar(i,j) = 0.0 ; htot(i) = 0.0
1787 do i=is,ie ;
if (do_i(i))
then 1790 if (local_open_v_bc)
then 1791 l_seg = obc%segnum_v(i,j)
1792 if (l_seg /= obc_none)
then 1793 has_obc = obc%segment(l_seg)%open
1799 if (obc%segment(l_seg)%direction == obc_direction_n)
then 1800 hvel = gv%H_to_Z*h(i,j,k)
1802 hvel = gv%H_to_Z*h(i,j+1,k)
1805 hvel = 0.5*gv%H_to_Z*(h(i,j,k) + h(i,j+1,k))
1808 if ((htot(i) + hvel) >= visc%bbl_thick_v(i,j))
then 1809 vhtot(i) = vhtot(i) + (visc%bbl_thick_v(i,j) - htot(i))*v(i,j,k)
1810 htot(i) = visc%bbl_thick_v(i,j)
1813 vhtot(i) = vhtot(i) + hvel*v(i,j,k)
1814 htot(i) = htot(i) + hvel
1818 if (.not.domore)
exit 1820 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (htot(i) > 0.0))
then 1821 v2_bbl(i,j) = (vhtot(i)*vhtot(i))/(htot(i)*htot(i))
1828 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_u(i,j) > 0.0))
then 1829 do_i(i) = .true. ; uhtot(i) = 0.0 ; htot(i) = 0.0
1830 ustar(i) = visc%Kv_bbl_u(i,j) / (cdrag_sqrt*visc%bbl_thick_u(i,j))
1832 do_i(i) = .false. ; ustar(i) = 0.0 ; htot(i) = 0.0
1834 do k=nz,1,-1 ; domore = .false.
1835 do i=is-1,ie ;
if (do_i(i))
then 1838 if (local_open_u_bc)
then 1839 l_seg = obc%segnum_u(i,j)
1840 if (l_seg /= obc_none)
then 1841 has_obc = obc%segment(l_seg)%open
1847 if (obc%segment(l_seg)%direction == obc_direction_e)
then 1848 hvel = gv%H_to_Z*h(i,j,k)
1850 hvel = gv%H_to_Z*h(i+1,j,k)
1853 hvel = 0.5*gv%H_to_Z*(h(i,j,k) + h(i+1,j,k))
1856 if ((htot(i) + hvel) >= visc%bbl_thick_u(i,j))
then 1857 uhtot(i) = uhtot(i) + (visc%bbl_thick_u(i,j) - htot(i))*u(i,j,k)
1858 htot(i) = visc%bbl_thick_u(i,j)
1861 uhtot(i) = uhtot(i) + hvel*u(i,j,k)
1862 htot(i) = htot(i) + hvel
1866 if (.not.domore)
exit 1868 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (htot(i) > 0.0))
then 1869 u2_bbl(i) = (uhtot(i)*uhtot(i))/(htot(i)*htot(i))
1875 visc%ustar_BBL(i,j) = sqrt(0.5*g%IareaT(i,j) * &
1876 ((g%areaCu(i-1,j)*(ustar(i-1)*ustar(i-1)) + &
1877 g%areaCu(i,j)*(ustar(i)*ustar(i))) + &
1878 (g%areaCv(i,j-1)*(vstar(i,j-1)*vstar(i,j-1)) + &
1879 g%areaCv(i,j)*(vstar(i,j)*vstar(i,j))) ) )
1880 visc%TKE_BBL(i,j) = us%L_to_Z**2 * &
1881 (((g%areaCu(i-1,j)*(ustar(i-1)*u2_bbl(i-1)) + &
1882 g%areaCu(i,j) * (ustar(i)*u2_bbl(i))) + &
1883 (g%areaCv(i,j-1)*(vstar(i,j-1)*v2_bbl(i,j-1)) + &
1884 g%areaCv(i,j) * (vstar(i,j)*v2_bbl(i,j))) )*g%IareaT(i,j))
1889 end subroutine set_bbl_tke
1891 subroutine set_density_ratios(h, tv, kb, G, GV, US, CS, j, ds_dsp1, rho_0)
1894 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1899 integer,
dimension(SZI_(G)),
intent(in) :: kb
1904 integer,
intent(in) :: j
1905 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: ds_dsp1
1909 real,
dimension(SZI_(G),SZK_(G)), &
1910 optional,
intent(in) :: rho_0
1916 real :: a(szk_(g)), a_0(szk_(g))
1917 real :: p_ref(szi_(g))
1918 real :: Rcv(szi_(g),szk_(g))
1921 integer,
dimension(2) :: EOSdom
1922 integer :: i, k, k3, is, ie, nz, kmb
1923 is = g%isc ; ie = g%iec ; nz = g%ke
1926 if (gv%g_prime(k+1) /= 0.0)
then 1928 ds_dsp1(i,k) = gv%g_prime(k) / gv%g_prime(k+1)
1937 if (cs%bulkmixedlayer)
then 1938 g_r0 = gv%g_Earth / (gv%Rho0)
1939 kmb = gv%nk_rho_varies
1941 do i=is,ie ; p_ref(i) = tv%P_Ref ;
enddo 1942 eosdom(:) = eos_domain(g%HI)
1944 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), p_ref, rcv(:,k), tv%eqn_of_state, eosdom)
1947 if (kb(i) <= nz-1)
then 1952 i_drho = g_r0 / gv%g_prime(k+1)
1955 a(k3+1) = (gv%Rlay(k) - rcv(i,k3)) * i_drho
1957 if ((
present(rho_0)) .and. (a(kmb+1) < 2.0*eps*ds_dsp1(i,k)))
then 1961 if ((rho_0(i,k) > rho_0(i,kmb)) .and. &
1962 (rho_0(i,k+1) > rho_0(i,k)))
then 1963 i_drho = 1.0 / (rho_0(i,k+1)-rho_0(i,k))
1964 a_0(kmb+1) = min((rho_0(i,k)-rho_0(i,kmb)) * i_drho, ds_dsp1(i,k))
1965 if (a_0(kmb+1) > a(kmb+1))
then 1967 a_0(k3) = a_0(kmb+1) + (rho_0(i,kmb)-rho_0(i,k3-1)) * i_drho
1969 if (a(kmb+1) <= eps*ds_dsp1(i,k))
then 1970 do k3=2,kmb+1 ; a(k3) = a_0(k3) ;
enddo 1973 tmp = a(kmb+1)/(eps*ds_dsp1(i,k)) - 1.0
1974 do k3=2,kmb+1 ; a(k3) = tmp*a(k3) + (1.0-tmp)*a_0(k3) ;
enddo 1980 ds_dsp1(i,k) = max(a(kmb+1),1e-5)
1989 ds_dsp1(i,k3) = max(a(k3),ds_dsp1(i,k))
1995 end subroutine set_density_ratios
1997 subroutine set_diffusivity_init(Time, G, GV, US, param_file, diag, CS, int_tide_CSp, halo_TS)
1998 type(time_type),
intent(in) :: Time
2004 type(
diag_ctrl),
target,
intent(inout) :: diag
2009 integer,
optional,
intent(out) :: halo_TS
2013 real :: decay_length
2014 logical :: ML_use_omega
2015 logical :: default_2018_answers
2017 # include "version_variable.h" 2018 character(len=40) :: mdl =
"MOM_set_diffusivity" 2019 real :: omega_frac_dflt
2020 logical :: Bryan_Lewis_diffusivity
2022 integer :: i, j, is, ie, js, je
2023 integer :: isd, ied, jsd, jed
2025 if (
associated(cs))
then 2026 call mom_error(warning,
"diabatic_entrain_init called with an associated "// &
2027 "control structure.")
2032 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2033 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2036 if (
associated(int_tide_csp)) cs%int_tide_CSp => int_tide_csp
2039 cs%BBL_mixing_as_max = .true.
2040 cs%cdrag = 0.003 ; cs%BBL_effic = 0.0
2041 cs%bulkmixedlayer = (gv%nkml > 0)
2046 call get_param(param_file, mdl,
"INPUTDIR", cs%inputdir, default=
".")
2047 cs%inputdir = slasher(cs%inputdir)
2048 call get_param(param_file, mdl,
"FLUX_RI_MAX", cs%FluxRi_max, &
2049 "The flux Richardson number where the stratification is "//&
2050 "large enough that N2 > omega2. The full expression for "//&
2051 "the Flux Richardson number is usually "//&
2052 "FLUX_RI_MAX*N2/(N2+OMEGA2).", units=
"nondim", default=0.2)
2053 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
2054 "The rotation rate of the earth.", units=
"s-1", default=7.2921e-5, scale=us%T_to_s)
2056 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
2057 "This sets the default value for the various _2018_ANSWERS parameters.", &
2059 call get_param(param_file, mdl,
"SET_DIFF_2018_ANSWERS", cs%answers_2018, &
2060 "If true, use the order of arithmetic and expressions that recover the "//&
2061 "answers from the end of 2018. Otherwise, use updated and more robust "//&
2062 "forms of the same expressions.", default=default_2018_answers)
2065 cs%use_tidal_mixing = tidal_mixing_init(time, g, gv, us, param_file, diag, &
2066 cs%tidal_mixing_CSp)
2068 call get_param(param_file, mdl,
"ML_RADIATION", cs%ML_radiation, &
2069 "If true, allow a fraction of TKE available from wind "//&
2070 "work to penetrate below the base of the mixed layer "//&
2071 "with a vertical decay scale determined by the minimum "//&
2072 "of: (1) The depth of the mixed layer, (2) an Ekman "//&
2073 "length scale.", default=.false.)
2074 if (cs%ML_radiation)
then 2076 cs%ustar_min = 2e-4 * cs%omega * (gv%Angstrom_Z + gv%H_subroundoff*gv%H_to_Z)
2078 call get_param(param_file, mdl,
"ML_RAD_EFOLD_COEFF", cs%ML_rad_efold_coeff, &
2079 "A coefficient that is used to scale the penetration "//&
2080 "depth for turbulence below the base of the mixed layer. "//&
2081 "This is only used if ML_RADIATION is true.", units=
"nondim", default=0.2)
2082 call get_param(param_file, mdl,
"ML_RAD_BUG", cs%ML_rad_bug, &
2083 "If true use code with a bug that reduces the energy available "//&
2084 "in the transition layer by a factor of the inverse of the energy "//&
2085 "deposition lenthscale (in m).", default=.false.)
2086 call get_param(param_file, mdl,
"ML_RAD_KD_MAX", cs%ML_rad_kd_max, &
2087 "The maximum diapycnal diffusivity due to turbulence "//&
2088 "radiated from the base of the mixed layer. "//&
2089 "This is only used if ML_RADIATION is true.", &
2090 units=
"m2 s-1", default=1.0e-3, scale=us%m2_s_to_Z2_T)
2091 call get_param(param_file, mdl,
"ML_RAD_COEFF", cs%ML_rad_coeff, &
2092 "The coefficient which scales MSTAR*USTAR^3 to obtain "//&
2093 "the energy available for mixing below the base of the "//&
2094 "mixed layer. This is only used if ML_RADIATION is true.", &
2095 units=
"nondim", default=0.2)
2096 call get_param(param_file, mdl,
"ML_RAD_APPLY_TKE_DECAY", cs%ML_rad_TKE_decay, &
2097 "If true, apply the same exponential decay to ML_rad as "//&
2098 "is applied to the other surface sources of TKE in the "//&
2099 "mixed layer code. This is only used if ML_RADIATION is true.", default=.true.)
2100 call get_param(param_file, mdl,
"MSTAR", cs%mstar, &
2101 "The ratio of the friction velocity cubed to the TKE "//&
2102 "input to the mixed layer.", units=
"nondim", default=1.2)
2103 call get_param(param_file, mdl,
"TKE_DECAY", cs%TKE_decay, &
2104 "The ratio of the natural Ekman depth to the TKE decay scale.", &
2105 units=
"nondim", default=2.5)
2106 call get_param(param_file, mdl,
"ML_USE_OMEGA", ml_use_omega, &
2107 "If true, use the absolute rotation rate instead of the "//&
2108 "vertical component of rotation when setting the decay "//&
2109 "scale for turbulence.", default=.false., do_not_log=.true.)
2110 omega_frac_dflt = 0.0
2111 if (ml_use_omega)
then 2112 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
2113 omega_frac_dflt = 1.0
2115 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%ML_omega_frac, &
2116 "When setting the decay scale for turbulence, use this "//&
2117 "fraction of the absolute rotation rate blended with the "//&
2118 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
2119 units=
"nondim", default=omega_frac_dflt)
2122 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
2123 "If true, the bottom stress is calculated with a drag "//&
2124 "law of the form c_drag*|u|*u. The velocity magnitude "//&
2125 "may be an assumed value or it may be based on the actual "//&
2126 "velocity in the bottommost HBBL, depending on LINEAR_DRAG.", default=.true.)
2127 if (cs%bottomdraglaw)
then 2128 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
2129 "The drag coefficient relating the magnitude of the "//&
2130 "velocity field to the bottom stress. CDRAG is only used "//&
2131 "if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.003)
2132 call get_param(param_file, mdl,
"BBL_EFFIC", cs%BBL_effic, &
2133 "The efficiency with which the energy extracted by "//&
2134 "bottom drag drives BBL diffusion. This is only "//&
2135 "used if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.20)
2136 call get_param(param_file, mdl,
"BBL_MIXING_MAX_DECAY", decay_length, &
2137 "The maximum decay scale for the BBL diffusion, or 0 to allow the mixing "//&
2138 "to penetrate as far as stratification and rotation permit. The default "//&
2139 "for now is 200 m. This is only used if BOTTOMDRAGLAW is true.", &
2140 units=
"m", default=200.0, scale=us%m_to_Z)
2143 if (decay_length > 0.0) cs%IMax_decay = 1.0/decay_length
2144 call get_param(param_file, mdl,
"BBL_MIXING_AS_MAX", cs%BBL_mixing_as_max, &
2145 "If true, take the maximum of the diffusivity from the "//&
2146 "BBL mixing and the other diffusivities. Otherwise, "//&
2147 "diffusivity from the BBL_mixing is simply added.", &
2149 call get_param(param_file, mdl,
"USE_LOTW_BBL_DIFFUSIVITY", cs%use_LOTW_BBL_diffusivity, &
2150 "If true, uses a simple, imprecise but non-coordinate dependent, model "//&
2151 "of BBL mixing diffusivity based on Law of the Wall. Otherwise, uses "//&
2152 "the original BBL scheme.", default=.false.)
2153 if (cs%use_LOTW_BBL_diffusivity)
then 2154 call get_param(param_file, mdl,
"LOTW_BBL_USE_OMEGA", cs%LOTW_BBL_use_omega, &
2155 "If true, use the maximum of Omega and N for the TKE to diffusion "//&
2156 "calculation. Otherwise, N is N.", default=.true.)
2159 cs%use_LOTW_BBL_diffusivity = .false.
2161 cs%id_Kd_BBL = register_diag_field(
'ocean_model',
'Kd_BBL', diag%axesTi, time, &
2162 'Bottom Boundary Layer Diffusivity',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2163 call get_param(param_file, mdl,
"SIMPLE_TKE_TO_KD", cs%simple_TKE_to_Kd, &
2164 "If true, uses a simple estimate of Kd/TKE that will "//&
2165 "work for arbitrary vertical coordinates. If false, "//&
2166 "calculates Kd/TKE and bounds based on exact energetics "//&
2167 "for an isopycnal layer-formulation.", default=.false.)
2170 call bkgnd_mixing_init(time, g, gv, us, param_file, cs%diag, cs%bkgnd_mixing_csp)
2172 call get_param(param_file, mdl,
"KV", cs%Kv, &
2173 "The background kinematic viscosity in the interior. "//&
2174 "The molecular value, ~1e-6 m2 s-1, may be used.", &
2175 units=
"m2 s-1", scale=us%m2_s_to_Z2_T, fail_if_missing=.true.)
2177 call get_param(param_file, mdl,
"KD", cs%Kd, &
2178 "The background diapycnal diffusivity of density in the "//&
2179 "interior. Zero or the molecular value, ~1e-7 m2 s-1, "//&
2180 "may be used.", default=0.0, units=
"m2 s-1", scale=us%m2_s_to_Z2_T)
2181 call get_param(param_file, mdl,
"KD_MIN", cs%Kd_min, &
2182 "The minimum diapycnal diffusivity.", &
2183 units=
"m2 s-1", default=0.01*cs%Kd*us%Z2_T_to_m2_s, scale=us%m2_s_to_Z2_T)
2184 call get_param(param_file, mdl,
"KD_MAX", cs%Kd_max, &
2185 "The maximum permitted increment for the diapycnal "//&
2186 "diffusivity from TKE-based parameterizations, or a negative "//&
2187 "value for no limit.", units=
"m2 s-1", default=-1.0, scale=us%m2_s_to_Z2_T)
2188 if (cs%simple_TKE_to_Kd .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2189 "set_diffusivity_init: To use SIMPLE_TKE_TO_KD, KD_MAX must be set to >0.")
2190 call get_param(param_file, mdl,
"KD_ADD", cs%Kd_add, &
2191 "A uniform diapycnal diffusivity that is added "//&
2192 "everywhere without any filtering or scaling.", &
2193 units=
"m2 s-1", default=0.0, scale=us%m2_s_to_Z2_T)
2194 if (cs%use_LOTW_BBL_diffusivity .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2195 "set_diffusivity_init: KD_MAX must be set (positive) when "// &
2196 "USE_LOTW_BBL_DIFFUSIVITY=True.")
2197 call get_param(param_file, mdl,
"KD_SMOOTH", cs%Kd_smooth, &
2198 "A diapycnal diffusivity that is used to interpolate "//&
2199 "more sensible values of T & S into thin layers.", &
2200 units=
"m2 s-1", default=1.0e-6, scale=us%m2_s_to_Z2_T)
2202 call get_param(param_file, mdl,
"DEBUG", cs%debug, &
2203 "If true, write out verbose debugging data.", &
2204 default=.false., debuggingparam=.true.)
2206 call get_param(param_file, mdl,
"USER_CHANGE_DIFFUSIVITY", cs%user_change_diff, &
2207 "If true, call user-defined code to change the diffusivity.", default=.false.)
2209 call get_param(param_file, mdl,
"DISSIPATION_MIN", cs%dissip_min, &
2210 "The minimum dissipation by which to determine a lower "//&
2211 "bound of Kd (a floor).", &
2212 units=
"W m-3", default=0.0, scale=us%W_m2_to_RZ3_T3*us%Z_to_m)
2213 call get_param(param_file, mdl,
"DISSIPATION_N0", cs%dissip_N0, &
2214 "The intercept when N=0 of the N-dependent expression "//&
2215 "used to set a minimum dissipation by which to determine "//&
2216 "a lower bound of Kd (a floor): A in eps_min = A + B*N.", &
2217 units=
"W m-3", default=0.0, scale=us%W_m2_to_RZ3_T3*us%Z_to_m)
2218 call get_param(param_file, mdl,
"DISSIPATION_N1", cs%dissip_N1, &
2219 "The coefficient multiplying N, following Gargett, used to "//&
2220 "set a minimum dissipation by which to determine a lower "//&
2221 "bound of Kd (a floor): B in eps_min = A + B*N", &
2222 units=
"J m-3", default=0.0, scale=us%W_m2_to_RZ3_T3*us%Z_to_m*us%s_to_T)
2223 call get_param(param_file, mdl,
"DISSIPATION_KD_MIN", cs%dissip_Kd_min, &
2224 "The minimum vertical diffusivity applied as a floor.", &
2225 units=
"m2 s-1", default=0.0, scale=us%m2_s_to_Z2_T)
2227 cs%limit_dissipation = (cs%dissip_min>0.) .or. (cs%dissip_N1>0.) .or. &
2228 (cs%dissip_N0>0.) .or. (cs%dissip_Kd_min>0.)
2230 if (cs%FluxRi_max > 0.0) &
2231 cs%dissip_N2 = cs%dissip_Kd_min * gv%Rho0 / cs%FluxRi_max
2233 cs%id_Kd_bkgnd = register_diag_field(
'ocean_model',
'Kd_bkgnd', diag%axesTi, time, &
2234 'Background diffusivity added by MOM_bkgnd_mixing module',
'm2/s', conversion=us%Z2_T_to_m2_s)
2235 cs%id_Kv_bkgnd = register_diag_field(
'ocean_model',
'Kv_bkgnd', diag%axesTi, time, &
2236 'Background viscosity added by MOM_bkgnd_mixing module',
'm2/s', conversion=us%Z2_T_to_m2_s)
2238 cs%id_Kd_layer = register_diag_field(
'ocean_model',
'Kd_layer', diag%axesTL, time, &
2239 'Diapycnal diffusivity of layers (as set)',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2241 if (cs%use_tidal_mixing)
then 2242 cs%id_Kd_Work = register_diag_field(
'ocean_model',
'Kd_Work', diag%axesTL, time, &
2243 'Work done by Diapycnal Mixing',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2244 cs%id_maxTKE = register_diag_field(
'ocean_model',
'maxTKE', diag%axesTL, time, &
2245 'Maximum layer TKE',
'm3 s-3', conversion=(us%Z_to_m**3*us%s_to_T**3))
2246 cs%id_TKE_to_Kd = register_diag_field(
'ocean_model',
'TKE_to_Kd', diag%axesTL, time, &
2247 'Convert TKE to Kd',
's2 m', conversion=us%Z2_T_to_m2_s*(us%m_to_Z**3*us%T_to_s**3))
2248 cs%id_N2 = register_diag_field(
'ocean_model',
'N2', diag%axesTi, time, &
2249 'Buoyancy frequency squared',
's-2', conversion=us%s_to_T**2, cmor_field_name=
'obvfsq', &
2250 cmor_long_name=
'Square of seawater buoyancy frequency', &
2251 cmor_standard_name=
'square_of_brunt_vaisala_frequency_in_sea_water')
2254 if (cs%user_change_diff) &
2255 cs%id_Kd_user = register_diag_field(
'ocean_model',
'Kd_user', diag%axesTi, time, &
2256 'User-specified Extra Diffusivity',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2258 call get_param(param_file, mdl,
"DOUBLE_DIFFUSION", cs%double_diffusion, &
2259 "If true, increase diffusivites for temperature or salt "//&
2260 "based on double-diffusive parameterization from MOM4/KPP.", &
2263 if (cs%double_diffusion)
then 2264 call get_param(param_file, mdl,
"MAX_RRHO_SALT_FINGERS", cs%Max_Rrho_salt_fingers, &
2265 "Maximum density ratio for salt fingering regime.", &
2266 default=2.55, units=
"nondim")
2267 call get_param(param_file, mdl,
"MAX_SALT_DIFF_SALT_FINGERS", cs%Max_salt_diff_salt_fingers, &
2268 "Maximum salt diffusivity for salt fingering regime.", &
2269 default=1.e-4, units=
"m2 s-1", scale=us%m2_s_to_Z2_T)
2270 call get_param(param_file, mdl,
"KV_MOLECULAR", cs%Kv_molecular, &
2271 "Molecular viscosity for calculation of fluxes under double-diffusive "//&
2272 "convection.", default=1.5e-6, units=
"m2 s-1", scale=us%m2_s_to_Z2_T)
2276 if (cs%user_change_diff)
then 2277 call user_change_diff_init(time, g, gv, us, param_file, diag, cs%user_change_diff_CSp)
2280 call get_param(param_file, mdl,
"BRYAN_LEWIS_DIFFUSIVITY", bryan_lewis_diffusivity, &
2281 "If true, use a Bryan & Lewis (JGR 1979) like tanh "//&
2282 "profile of background diapycnal diffusivity with depth. "//&
2283 "This is done via CVMix.", default=.false., do_not_log=.true.)
2284 if (cs%use_tidal_mixing .and. bryan_lewis_diffusivity) &
2285 call mom_error(fatal,
"MOM_Set_Diffusivity: "// &
2286 "Bryan-Lewis and internal tidal dissipation are both enabled. Choose one.")
2288 cs%useKappaShear = kappa_shear_init(time, g, gv, us, param_file, cs%diag, cs%kappaShear_CSp)
2289 cs%Vertex_Shear = kappa_shear_at_vertex(param_file)
2291 if (cs%useKappaShear) &
2292 id_clock_kappashear = cpu_clock_id(
'(Ocean kappa_shear)', grain=clock_module)
2295 cs%use_CVMix_shear = cvmix_shear_init(time, g, gv, us, param_file, cs%diag, cs%CVMix_shear_csp)
2298 cs%use_CVMix_ddiff = cvmix_ddiff_init(time, g, gv, us, param_file, cs%diag, cs%CVMix_ddiff_csp)
2299 if (cs%use_CVMix_ddiff) &
2300 id_clock_cvmix_ddiff = cpu_clock_id(
'(Double diffusion via CVMix)', grain=clock_module)
2302 if (cs%double_diffusion .or. cs%use_CVMix_ddiff)
then 2303 cs%id_KT_extra = register_diag_field(
'ocean_model',
'KT_extra', diag%axesTi, time, &
2304 'Double-diffusive diffusivity for temperature',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2305 cs%id_KS_extra = register_diag_field(
'ocean_model',
'KS_extra', diag%axesTi, time, &
2306 'Double-diffusive diffusivity for salinity',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2308 if (cs%use_CVMix_ddiff)
then 2309 cs%id_R_rho = register_diag_field(
'ocean_model',
'R_rho', diag%axesTi, time, &
2310 'Double-diffusion density ratio',
'nondim')
2313 if (
present(halo_ts))
then 2315 if (cs%Vertex_Shear) halo_ts = 1
2318 end subroutine set_diffusivity_init
2321 subroutine set_diffusivity_end(CS)
2324 if (.not.
associated(cs))
return 2326 call bkgnd_mixing_end(cs%bkgnd_mixing_csp)
2328 if (cs%use_tidal_mixing)
call tidal_mixing_end(cs%tidal_mixing_CSp)
2330 if (cs%user_change_diff)
call user_change_diff_end(cs%user_change_diff_CSp)
2332 if (cs%use_CVMix_shear)
call cvmix_shear_end(cs%CVMix_shear_csp)
2334 if (cs%use_CVMix_ddiff)
call cvmix_ddiff_end(cs%CVMix_ddiff_csp)
2336 if (
associated(cs))
deallocate(cs)
2338 end subroutine set_diffusivity_end
Control structure including parameters for CVMix double diffusion.
This module implements boundary forcing for MOM6.
Control structure including parameters for CVMix interior shear schemes.
Interface to CVMix interior shear schemes.
This control structure has parameters for the MOM_internal_tides module.
Control structure with parameters for the tidal mixing module.
Ocean grid type. See mom_grid for details.
Shear-dependent mixing following Jackson et al. 2008.
Calculates density of sea water from T, S and P.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Open boundary segment data structure.
Vertical viscosities, drag coefficients, and related fields.
Interface to background mixing schemes, including the Bryan and Lewis (1979) which is applied via CVM...
Wraps the MPP cpu clock functions.
This control structure contains parameters for MOM_set_diffusivity.
This module contains I/O framework code.
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
A module with intrinsic functions that are used by MOM but are not supported by some compilers...
This control structure holds the parameters that regulate shear mixing.
Control structure for user_change_diffusivity.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Subroutines that use the ray-tracing equations to propagate the internal tide energy density...
Routines for error handling and I/O management.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Provides subroutines for quantities specific to the equation of state.
An overloaded interface to log version information about modules.
Control structure including parameters for this module.
Describes the vertical ocean grid, including unit conversion factors.
Does full convective adjustment of unstable regions via a strong diffusivity.
Interface to vertical tidal mixing schemes including CVMix tidal mixing.
Interface to CVMix double diffusion scheme.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Calculate vertical diffusivity from all mixing processes.
Controls where open boundary conditions are applied.
Handy functions for manipulating strings.
Increments the diapycnal diffusivity in a specified band of latitudes and densities.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
Read a data field from a file.
This structure has memory for used in calculating diagnostics of diffusivity.
Calculations of isoneutral slopes and stratification.
An overloaded interface to read and log the values of various types of parameters.
Provides checksumming functions for debugging.
A structure for creating arrays of pointers to 3D arrays.