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
241 real,
dimension(SZI_(G)) :: &
244 type(diffusivity_diags) :: dd
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()")