213 type(ocean_grid_type),
intent(in) :: G
214 type(verticalGrid_type),
intent(in) :: GV
215 type(unit_scale_type),
intent(in) :: US
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)), &
226 type(thermo_var_ptrs),
intent(inout) :: tv
228 type(forcing),
intent(in) :: fluxes
229 type(optics_type),
pointer :: optics
231 type(vertvisc_type),
intent(inout) :: visc
233 real,
intent(in) :: dt
234 type(set_diffusivity_CS),
pointer :: CS
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
239 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
240 optional,
intent(out) :: Kd_extra_T
243 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
244 optional,
intent(out) :: Kd_extra_S
249 real,
dimension(SZI_(G)) :: &
252 type(diffusivity_diags) :: dd
254 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
258 real,
dimension(SZI_(G),SZK_(G)) :: &
259 N2_lay, & !< Squared buoyancy frequency associated with layers [T-2 ~> s-2]
260 Kd_lay_2d, & !< The layer diffusivities [Z2 T-1 ~> m2 s-1]
261 maxTKE, & !< Energy required to entrain to h_max [Z3 T-3 ~> m3 s-3]
266 real,
dimension(SZI_(G),SZK_(G)+1) :: &
267 N2_int, & !< squared buoyancy frequency associated at interfaces [T-2 ~> s-2]
268 Kd_int_2d, & !< The interface diffusivities [Z2 T-1 ~> m2 s-1]
269 Kv_bkgnd, & !< The background diffusion related interface viscosities [Z2 T-1 ~> m2 s-1]
270 dRho_int, & !< Locally referenced potential density difference across interfaces [R ~> kg m-3]
271 KT_extra, & !< Double difusion diffusivity of temperature [Z2 T-1 ~> m2 s-1]
278 logical :: TKE_to_Kd_used
279 integer :: kb(SZI_(G))
281 logical :: showCallTree
283 integer :: i, j, k, is, ie, js, je, nz, isd, ied, jsd, jed
285 real :: kappa_dt_fill
287 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
288 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
289 showcalltree = calltree_showquery()
290 if (showcalltree)
call calltree_enter(
"set_diffusivity(), MOM_set_diffusivity.F90")
292 if (.not.
associated(cs))
call mom_error(fatal,
"set_diffusivity: "//&
293 "Module must be initialized before it is used.")
295 if (cs%answers_2018)
then 297 kappa_dt_fill = us%m_to_Z**2 * 1.e-3 * 7200.
299 kappa_dt_fill = cs%Kd_smooth * dt
301 omega2 = cs%omega * cs%omega
303 use_eos =
associated(tv%eqn_of_state)
305 if ((cs%use_CVMix_ddiff .or. cs%double_diffusion) .and. &
306 .not.(
present(kd_extra_t) .and.
present(kd_extra_s))) &
307 call mom_error(fatal,
"set_diffusivity: both Kd_extra_T and Kd_extra_S must be present "//&
308 "when USE_CVMIX_DDIFF or DOUBLE_DIFFUSION are true.")
310 tke_to_kd_used = (cs%use_tidal_mixing .or. cs%ML_radiation .or. &
311 (cs%bottomdraglaw .and. .not.cs%use_LOTW_BBL_diffusivity))
314 if (
present(kd_lay)) kd_lay(:,:,:) = cs%Kd
315 if (
present(kd_int)) kd_int(:,:,:) = cs%Kd
316 if (
present(kd_extra_t)) kd_extra_t(:,:,:) = 0.0
317 if (
present(kd_extra_s)) kd_extra_s(:,:,:) = 0.0
318 if (
associated(visc%Kv_slow)) visc%Kv_slow(:,:,:) = cs%Kv
322 if (cs%id_N2 > 0)
then 323 allocate(dd%N2_3d(isd:ied,jsd:jed,nz+1)) ; dd%N2_3d(:,:,:) = 0.0
325 if (cs%id_Kd_user > 0)
then 326 allocate(dd%Kd_user(isd:ied,jsd:jed,nz+1)) ; dd%Kd_user(:,:,:) = 0.0
328 if (cs%id_Kd_work > 0)
then 329 allocate(dd%Kd_work(isd:ied,jsd:jed,nz)) ; dd%Kd_work(:,:,:) = 0.0
331 if (cs%id_maxTKE > 0)
then 332 allocate(dd%maxTKE(isd:ied,jsd:jed,nz)) ; dd%maxTKE(:,:,:) = 0.0
334 if (cs%id_TKE_to_Kd > 0)
then 335 allocate(dd%TKE_to_Kd(isd:ied,jsd:jed,nz)) ; dd%TKE_to_Kd(:,:,:) = 0.0
337 if ((cs%double_diffusion) .and. (cs%id_KT_extra > 0))
then 338 allocate(dd%KT_extra(isd:ied,jsd:jed,nz+1)) ; dd%KT_extra(:,:,:) = 0.0
340 if ((cs%double_diffusion) .and. (cs%id_KS_extra > 0))
then 341 allocate(dd%KS_extra(isd:ied,jsd:jed,nz+1)) ; dd%KS_extra(:,:,:) = 0.0
343 if (cs%id_R_rho > 0)
then 344 allocate(dd%drho_rat(isd:ied,jsd:jed,nz+1)) ; dd%drho_rat(:,:,:) = 0.0
346 if (cs%id_Kd_BBL > 0)
then 347 allocate(dd%Kd_BBL(isd:ied,jsd:jed,nz+1)) ; dd%Kd_BBL(:,:,:) = 0.0
350 if (cs%id_Kd_bkgnd > 0)
then 351 allocate(dd%Kd_bkgnd(isd:ied,jsd:jed,nz+1)) ; dd%Kd_bkgnd(:,:,:) = 0.
353 if (cs%id_Kv_bkgnd > 0)
then 354 allocate(dd%Kv_bkgnd(isd:ied,jsd:jed,nz+1)) ; dd%Kv_bkgnd(:,:,:) = 0.
358 call setup_tidal_diagnostics(g, cs%tidal_mixing_CSp)
360 if (cs%useKappaShear)
then 362 call hchksum_pair(
"before calc_KS [uv]_h", u_h, v_h, g%HI, scale=us%L_T_to_m_s)
364 call cpu_clock_begin(id_clock_kappashear)
365 if (cs%Vertex_shear)
then 366 call full_convection(g, gv, us, h, tv, t_f, s_f, fluxes%p_surf, &
367 (gv%Z_to_H**2)*kappa_dt_fill, halo=1)
369 call calc_kappa_shear_vertex(u, v, h, t_f, s_f, tv, fluxes%p_surf, visc%Kd_shear, &
370 visc%TKE_turb, visc%Kv_shear_Bu, dt, g, gv, us, cs%kappaShear_CSp)
371 if (
associated(visc%Kv_shear)) visc%Kv_shear(:,:,:) = 0.0
373 call hchksum(visc%Kd_shear,
"after calc_KS_vert visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
374 call bchksum(visc%Kv_shear_Bu,
"after calc_KS_vert visc%Kv_shear_Bu", g%HI, scale=us%Z2_T_to_m2_s)
375 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)
379 call calculate_kappa_shear(u_h, v_h, h, tv, fluxes%p_surf, visc%Kd_shear, visc%TKE_turb, &
380 visc%Kv_shear, dt, g, gv, us, cs%kappaShear_CSp)
382 call hchksum(visc%Kd_shear,
"after calc_KS visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
383 call hchksum(visc%Kv_shear,
"after calc_KS visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
384 call hchksum(visc%TKE_turb,
"after calc_KS visc%TKE_turb", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
387 call cpu_clock_end(id_clock_kappashear)
388 if (showcalltree)
call calltree_waypoint(
"done with calculate_kappa_shear (set_diffusivity)")
389 elseif (cs%use_CVMix_shear)
then 391 call calculate_cvmix_shear(u_h, v_h, h, tv, visc%Kd_shear, visc%Kv_shear, g, gv, us, cs%CVMix_shear_CSp)
393 call hchksum(visc%Kd_shear,
"after CVMix_shear visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
394 call hchksum(visc%Kv_shear,
"after CVMix_shear visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
396 elseif (
associated(visc%Kv_shear))
then 397 visc%Kv_shear(:,:,:) = 0.0
403 call hchksum(tv%T,
"before vert_fill_TS tv%T",g%HI)
404 call hchksum(tv%S,
"before vert_fill_TS tv%S",g%HI)
405 call hchksum(h,
"before vert_fill_TS h",g%HI, scale=gv%H_to_m)
407 call vert_fill_ts(h, tv%T, tv%S, kappa_dt_fill, t_f, s_f, g, gv, larger_h_denom=.true.)
409 call hchksum(tv%T,
"after vert_fill_TS tv%T",g%HI)
410 call hchksum(tv%S,
"after vert_fill_TS tv%S",g%HI)
411 call hchksum(h,
"after vert_fill_TS h",g%HI, scale=gv%H_to_m)
424 call find_n2(h, tv, t_f, s_f, fluxes, j, g, gv, us, cs, drho_int, n2_lay, n2_int, n2_bot)
426 if (
associated(dd%N2_3d))
then 427 do k=1,nz+1 ;
do i=is,ie ; dd%N2_3d(i,j,k) = n2_int(i,k) ;
enddo ;
enddo 431 call calculate_bkgnd_mixing(h, tv, n2_lay, kd_lay_2d, kd_int_2d, kv_bkgnd, j, g, gv, us, cs%bkgnd_mixing_csp)
433 if (
associated(visc%Kv_slow))
then ;
do k=1,nz+1 ;
do i=is,ie
434 visc%Kv_slow(i,j,k) = visc%Kv_slow(i,j,k) + kv_bkgnd(i,k)
435 enddo ;
enddo ;
endif 436 if (cs%id_Kv_bkgnd > 0)
then ;
do k=1,nz+1 ;
do i=is,ie
437 dd%Kv_bkgnd(i,j,k) = kv_bkgnd(i,k)
438 enddo ;
enddo ;
endif 439 if (cs%id_Kd_bkgnd > 0)
then ;
do k=1,nz+1 ;
do i=is,ie
440 dd%Kd_bkgnd(i,j,k) = kd_int_2d(i,k)
441 enddo ;
enddo ;
endif 444 if (cs%double_diffusion)
then 445 call double_diffusion(tv, h, t_f, s_f, j, g, gv, us, cs, kt_extra, ks_extra)
448 do k=2,nz ;
do i=is,ie
449 if (ks_extra(i,k) > kt_extra(i,k))
then 450 kd_lay_2d(i,k-1) = kd_lay_2d(i,k-1) + 0.5 * kt_extra(i,k)
451 kd_lay_2d(i,k) = kd_lay_2d(i,k) + 0.5 * kt_extra(i,k)
452 kd_extra_s(i,j,k) = (ks_extra(i,k) - kt_extra(i,k))
453 kd_extra_t(i,j,k) = 0.0
454 elseif (kt_extra(i,k) > 0.0)
then 455 kd_lay_2d(i,k-1) = kd_lay_2d(i,k-1) + 0.5 * ks_extra(i,k)
456 kd_lay_2d(i,k) = kd_lay_2d(i,k) + 0.5 * ks_extra(i,k)
457 kd_extra_t(i,j,k) = (kt_extra(i,k) - ks_extra(i,k))
458 kd_extra_s(i,j,k) = 0.0
460 kd_extra_t(i,j,k) = 0.0
461 kd_extra_s(i,j,k) = 0.0
464 if (
associated(dd%KT_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
465 dd%KT_extra(i,j,k) = kt_extra(i,k)
466 enddo ;
enddo ;
endif 468 if (
associated(dd%KS_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
469 dd%KS_extra(i,j,k) = ks_extra(i,k)
470 enddo ;
enddo ;
endif 475 if (cs%use_CVMix_ddiff)
then 476 call cpu_clock_begin(id_clock_cvmix_ddiff)
477 if (
associated(dd%drho_rat))
then 478 call compute_ddiff_coeffs(h, tv, g, gv, us, j, kd_extra_t, kd_extra_s, &
479 cs%CVMix_ddiff_csp, dd%drho_rat)
481 call compute_ddiff_coeffs(h, tv, g, gv, us, j, kd_extra_t, kd_extra_s, cs%CVMix_ddiff_csp)
483 call cpu_clock_end(id_clock_cvmix_ddiff)
487 if (tke_to_kd_used)
then 488 call find_tke_to_kd(h, tv, drho_int, n2_lay, j, dt, g, gv, us, cs, tke_to_kd, maxtke, kb)
489 if (
associated(dd%maxTKE))
then ;
do k=1,nz ;
do i=is,ie
490 dd%maxTKE(i,j,k) = maxtke(i,k)
491 enddo ;
enddo ;
endif 492 if (
associated(dd%TKE_to_Kd))
then ;
do k=1,nz ;
do i=is,ie
493 dd%TKE_to_Kd(i,j,k) = tke_to_kd(i,k)
494 enddo ;
enddo ;
endif 498 if (cs%useKappaShear .or. cs%use_CVMix_shear)
then 499 if (
present(kd_int))
then 500 do k=2,nz ;
do i=is,ie
501 kd_int_2d(i,k) = visc%Kd_shear(i,j,k) + 0.5 * (kd_lay_2d(i,k-1) + kd_lay_2d(i,k))
504 kd_int_2d(i,1) = visc%Kd_shear(i,j,1)
505 kd_int_2d(i,nz+1) = 0.0
508 do k=1,nz ;
do i=is,ie
509 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))
512 if (
present(kd_int))
then 514 kd_int_2d(i,1) = kd_lay_2d(i,1) ; kd_int_2d(i,nz+1) = 0.0
516 do k=2,nz ;
do i=is,ie
517 kd_int_2d(i,k) = 0.5 * (kd_lay_2d(i,k-1) + kd_lay_2d(i,k))
522 if (
present(kd_int))
then 524 if (cs%ML_radiation) &
525 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, tke_to_kd, kd_lay_2d, kd_int_2d)
528 if (cs%use_tidal_mixing) &
529 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tidal_mixing_CSp, &
530 n2_lay, n2_int, kd_lay_2d, kd_int_2d, cs%Kd_max, visc%Kv_slow)
533 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then 534 if (cs%use_LOTW_BBL_diffusivity)
then 535 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
536 dd%Kd_BBL, kd_lay_2d, kd_int_2d)
538 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
539 maxtke, kb, g, gv, us, cs, kd_lay_2d, kd_int_2d, dd%Kd_BBL)
543 if (cs%limit_dissipation)
then 549 do k=2,nz ;
do i=is,ie
550 dissip = max( cs%dissip_min, &
551 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_int(i,k)), &
552 cs%dissip_N2 * n2_int(i,k))
553 kd_int_2d(i,k) = max(kd_int_2d(i,k) , &
554 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_int(i,k) + omega2))))
559 if (cs%Kd_add > 0.0)
then ;
do k=1,nz+1 ;
do i=is,ie
560 kd_int_2d(i,k) = kd_int_2d(i,k) + cs%Kd_add
561 enddo ;
enddo ;
endif 564 do k=1,nz+1 ;
do i=is,ie
565 kd_int(i,j,k) = kd_int_2d(i,k)
571 if (cs%ML_radiation) &
572 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, tke_to_kd, kd_lay_2d)
575 if (cs%use_tidal_mixing) &
576 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tidal_mixing_CSp, &
577 n2_lay, n2_int, kd_lay_2d, kd_max=cs%Kd_max, kv=visc%Kv_slow)
580 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then 581 if (cs%use_LOTW_BBL_diffusivity)
then 582 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
583 dd%Kd_BBL, kd_lay_2d)
585 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
586 maxtke, kb, g, gv, us, cs, kd_lay_2d, kd_bbl=dd%Kd_BBL)
592 if (cs%limit_dissipation)
then 598 do k=2,nz-1 ;
do i=is,ie
599 dissip = max( cs%dissip_min, &
600 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_lay(i,k)), &
601 cs%dissip_N2 * n2_lay(i,k))
602 kd_lay_2d(i,k) = max(kd_lay_2d(i,k) , &
603 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_lay(i,k) + omega2))))
607 if (
associated(dd%Kd_work))
then 608 do k=1,nz ;
do i=is,ie
609 dd%Kd_Work(i,j,k) = gv%Rho0 * kd_lay_2d(i,k) * n2_lay(i,k) * &
615 if ((cs%Kd_add > 0.0) .and. (
present(kd_lay)))
then 616 do k=1,nz ;
do i=is,ie
617 kd_lay_2d(i,k) = kd_lay_2d(i,k) + cs%Kd_add
622 if (
present(kd_lay))
then ;
do k=1,nz ;
do i=is,ie
623 kd_lay(i,j,k) = kd_lay_2d(i,k)
624 enddo ;
enddo ;
endif 627 if (cs%user_change_diff)
then 628 call user_change_diff(h, tv, g, gv, us, cs%user_change_diff_CSp, kd_lay, kd_int, &
629 t_f, s_f, dd%Kd_user)
633 if (
present(kd_lay))
call hchksum(kd_lay,
"Kd_lay", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
635 if (cs%useKappaShear)
call hchksum(visc%Kd_shear,
"Turbulent Kd", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
637 if (cs%use_CVMix_ddiff)
then 638 call hchksum(kd_extra_t,
"MOM_set_diffusivity: Kd_extra_T", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
639 call hchksum(kd_extra_s,
"MOM_set_diffusivity: Kd_extra_S", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
642 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v))
then 643 call uvchksum(
"BBL Kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, g%HI, &
644 haloshift=0, symmetric=.true., scale=us%Z2_T_to_m2_s, &
648 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v))
then 649 call uvchksum(
"BBL bbl_thick_[uv]", visc%bbl_thick_u, visc%bbl_thick_v, &
650 g%HI, haloshift=0, symmetric=.true., scale=us%Z_to_m, &
654 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v))
then 655 call uvchksum(
"Ray_[uv]", visc%Ray_u, visc%Ray_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m*us%s_to_T)
661 if (
present(kd_lay) .and. (cs%id_Kd_layer > 0))
call post_data(cs%id_Kd_layer, kd_lay, cs%diag)
664 if (cs%id_Kd_bkgnd > 0)
call post_data(cs%id_Kd_bkgnd, dd%Kd_bkgnd, cs%diag)
665 if (cs%id_Kv_bkgnd > 0)
call post_data(cs%id_Kv_bkgnd, dd%Kv_bkgnd, cs%diag)
668 call post_tidal_diagnostics(g, gv, h, cs%tidal_mixing_CSp)
669 if (cs%id_N2 > 0)
call post_data(cs%id_N2, dd%N2_3d, cs%diag)
670 if (cs%id_Kd_Work > 0)
call post_data(cs%id_Kd_Work, dd%Kd_Work, cs%diag)
671 if (cs%id_maxTKE > 0)
call post_data(cs%id_maxTKE, dd%maxTKE, cs%diag)
672 if (cs%id_TKE_to_Kd > 0)
call post_data(cs%id_TKE_to_Kd, dd%TKE_to_Kd, cs%diag)
674 if (cs%id_Kd_user > 0)
call post_data(cs%id_Kd_user, dd%Kd_user, cs%diag)
677 if (cs%double_diffusion)
then 678 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, dd%KT_extra, cs%diag)
679 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, dd%KS_extra, cs%diag)
680 elseif (cs%use_CVMix_ddiff)
then 681 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, kd_extra_t, cs%diag)
682 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, kd_extra_s, cs%diag)
683 if (cs%id_R_rho > 0)
call post_data(cs%id_R_rho, dd%drho_rat, cs%diag)
685 if (cs%id_Kd_BBL > 0)
call post_data(cs%id_Kd_BBL, dd%Kd_BBL, cs%diag)
687 if (
associated(dd%N2_3d))
deallocate(dd%N2_3d)
688 if (
associated(dd%Kd_work))
deallocate(dd%Kd_work)
689 if (
associated(dd%Kd_user))
deallocate(dd%Kd_user)
690 if (
associated(dd%maxTKE))
deallocate(dd%maxTKE)
691 if (
associated(dd%TKE_to_Kd))
deallocate(dd%TKE_to_Kd)
692 if (
associated(dd%KT_extra))
deallocate(dd%KT_extra)
693 if (
associated(dd%KS_extra))
deallocate(dd%KS_extra)
694 if (
associated(dd%drho_rat))
deallocate(dd%drho_rat)
695 if (
associated(dd%Kd_BBL))
deallocate(dd%Kd_BBL)
697 if (showcalltree)
call calltree_leave(
"set_diffusivity()")