207 type(ocean_grid_type),
intent(in) :: G
208 type(verticalGrid_type),
intent(in) :: GV
209 type(unit_scale_type),
intent(in) :: US
210 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
212 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
214 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
216 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
218 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
220 type(thermo_var_ptrs),
intent(inout) :: tv
222 type(forcing),
intent(in) :: fluxes
223 type(optics_type),
pointer :: optics
225 type(vertvisc_type),
intent(inout) :: visc
227 real,
intent(in) :: dt_in_T
228 type(set_diffusivity_CS),
pointer :: CS
229 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
230 intent(out) :: Kd_lay
231 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
232 optional,
intent(out) :: Kd_int
235 real,
dimension(SZI_(G)) :: &
238 type(diffusivity_diags) :: dd
240 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
243 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
247 real,
dimension(SZI_(G),SZK_(G)) :: &
248 N2_lay, & !< squared buoyancy frequency associated with layers [T-2 ~> s-2]
249 maxTKE, & !< energy required to entrain to h_max [m3 T-3]
254 real,
dimension(SZI_(G),SZK_(G)+1) :: &
255 N2_int, & !< squared buoyancy frequency associated at interfaces [T-2 ~> s-2]
256 dRho_int, & !< locally ref potential density difference across interfaces [kg m-3]
257 KT_extra, & !< double difusion diffusivity of temperature [Z2 T-1 ~> m2 s-1]
265 integer :: kb(SZI_(G))
267 logical :: showCallTree
269 integer :: i, j, k, is, ie, js, je, nz
270 integer :: isd, ied, jsd, jed
272 real :: kappa_dt_fill
274 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
275 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
276 showcalltree = calltree_showquery()
277 if (showcalltree)
call calltree_enter(
"set_diffusivity(), MOM_set_diffusivity.F90")
279 if (.not.
associated(cs))
call mom_error(fatal,
"set_diffusivity: "//&
280 "Module must be initialized before it is used.")
282 i_rho0 = 1.0 / gv%Rho0
284 if (cs%answers_2018)
then
285 kappa_dt_fill = us%m_to_Z**2 * 1.e-3 * 7200.
287 kappa_dt_fill = cs%Kd_smooth * dt_in_t
289 omega2 = cs%omega * cs%omega
291 use_eos =
associated(tv%eqn_of_state)
293 if ((cs%use_CVMix_ddiff .or. cs%double_diffusion) .and. .not. &
294 (
associated(visc%Kd_extra_T) .and.
associated(visc%Kd_extra_S))) &
295 call mom_error(fatal,
"set_diffusivity: both visc%Kd_extra_T and "//&
296 "visc%Kd_extra_S must be associated when USE_CVMIX_DDIFF or DOUBLE_DIFFUSION are true.")
300 kd_lay(:,:,:) = cs%Kd
301 kd_int(:,:,:) = cs%Kd
302 if (
associated(visc%Kv_slow)) visc%Kv_slow(:,:,:) = cs%Kv
306 if (cs%id_N2 > 0)
then
307 allocate(dd%N2_3d(isd:ied,jsd:jed,nz+1)) ; dd%N2_3d(:,:,:) = 0.0
309 if (cs%id_Kd_user > 0)
then
310 allocate(dd%Kd_user(isd:ied,jsd:jed,nz+1)) ; dd%Kd_user(:,:,:) = 0.0
312 if (cs%id_Kd_work > 0)
then
313 allocate(dd%Kd_work(isd:ied,jsd:jed,nz)) ; dd%Kd_work(:,:,:) = 0.0
315 if (cs%id_maxTKE > 0)
then
316 allocate(dd%maxTKE(isd:ied,jsd:jed,nz)) ; dd%maxTKE(:,:,:) = 0.0
318 if (cs%id_TKE_to_Kd > 0)
then
319 allocate(dd%TKE_to_Kd(isd:ied,jsd:jed,nz)) ; dd%TKE_to_Kd(:,:,:) = 0.0
321 if (cs%id_KT_extra > 0)
then
322 allocate(dd%KT_extra(isd:ied,jsd:jed,nz+1)) ; dd%KT_extra(:,:,:) = 0.0
324 if (cs%id_KS_extra > 0)
then
325 allocate(dd%KS_extra(isd:ied,jsd:jed,nz+1)) ; dd%KS_extra(:,:,:) = 0.0
327 if (cs%id_Kd_BBL > 0)
then
328 allocate(dd%Kd_BBL(isd:ied,jsd:jed,nz+1)) ; dd%Kd_BBL(:,:,:) = 0.0
332 call setup_tidal_diagnostics(g,cs%tm_csp)
337 call hchksum(tv%T,
"before vert_fill_TS tv%T",g%HI)
338 call hchksum(tv%S,
"before vert_fill_TS tv%S",g%HI)
339 call hchksum(h,
"before vert_fill_TS h",g%HI, scale=gv%H_to_m)
341 call vert_fill_ts(h, tv%T, tv%S, kappa_dt_fill, t_f, s_f, g, gv, larger_h_denom=.true.)
343 call hchksum(tv%T,
"after vert_fill_TS tv%T",g%HI)
344 call hchksum(tv%S,
"after vert_fill_TS tv%S",g%HI)
345 call hchksum(h,
"after vert_fill_TS h",g%HI, scale=gv%H_to_m)
349 if (cs%useKappaShear)
then
351 call hchksum(u_h,
"before calc_KS u_h",g%HI)
352 call hchksum(v_h,
"before calc_KS v_h",g%HI)
354 call cpu_clock_begin(id_clock_kappashear)
355 if (cs%Vertex_shear)
then
356 call full_convection(g, gv, h, tv, t_adj, s_adj, fluxes%p_surf, &
357 (gv%Z_to_H**2)*kappa_dt_fill, halo=1)
359 call calc_kappa_shear_vertex(u, v, h, t_adj, s_adj, tv, fluxes%p_surf, visc%Kd_shear, &
360 visc%TKE_turb, visc%Kv_shear_Bu, dt_in_t, g, gv, us, cs%kappaShear_CSp)
361 if (
associated(visc%Kv_shear)) visc%Kv_shear(:,:,:) = 0.0
363 call hchksum(visc%Kd_shear,
"after calc_KS_vert visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
364 call bchksum(visc%Kv_shear_Bu,
"after calc_KS_vert visc%Kv_shear_Bu", g%HI, scale=us%Z2_T_to_m2_s)
365 call bchksum(visc%TKE_turb,
"after calc_KS_vert visc%TKE_turb", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
369 call calculate_kappa_shear(u_h, v_h, h, tv, fluxes%p_surf, visc%Kd_shear, visc%TKE_turb, &
370 visc%Kv_shear, dt_in_t, g, gv, us, cs%kappaShear_CSp)
372 call hchksum(visc%Kd_shear,
"after calc_KS visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
373 call hchksum(visc%Kv_shear,
"after calc_KS visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
374 call hchksum(visc%TKE_turb,
"after calc_KS visc%TKE_turb", g%HI, scale=us%Z_to_m**2*us%s_to_T**2)
377 call cpu_clock_end(id_clock_kappashear)
378 if (showcalltree)
call calltree_waypoint(
"done with calculate_kappa_shear (set_diffusivity)")
379 elseif (cs%use_CVMix_shear)
then
381 call calculate_cvmix_shear(u_h, v_h, h, tv, visc%Kd_shear, visc%Kv_shear, g, gv, us, cs%CVMix_shear_CSp)
383 call hchksum(visc%Kd_shear,
"after CVMix_shear visc%Kd_shear", g%HI, scale=us%Z2_T_to_m2_s)
384 call hchksum(visc%Kv_shear,
"after CVMix_shear visc%Kv_shear", g%HI, scale=us%Z2_T_to_m2_s)
386 elseif (
associated(visc%Kv_shear))
then
387 visc%Kv_shear(:,:,:) = 0.0
395 call sfc_bkgnd_mixing(g, us, cs%bkgnd_mixing_csp)
402 call find_n2(h, tv, t_f, s_f, fluxes, j, g, gv, us, cs, drho_int, n2_lay, n2_int, n2_bot)
404 if (
associated(dd%N2_3d))
then
405 do k=1,nz+1 ;
do i=is,ie ; dd%N2_3d(i,j,k) = n2_int(i,k) ;
enddo ;
enddo
409 call calculate_bkgnd_mixing(h, tv, n2_lay, kd_lay, visc%Kv_slow, j, g, gv, us, cs%bkgnd_mixing_csp)
412 if (cs%double_diffusion)
then
413 call double_diffusion(tv, h, t_f, s_f, j, g, gv, us, cs, kt_extra, ks_extra)
414 do k=2,nz ;
do i=is,ie
415 if (ks_extra(i,k) > kt_extra(i,k))
then
416 kd_lay(i,j,k-1) = kd_lay(i,j,k-1) + 0.5 * kt_extra(i,k)
417 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * kt_extra(i,k)
418 visc%Kd_extra_S(i,j,k) = (ks_extra(i,k) - kt_extra(i,k))
419 visc%Kd_extra_T(i,j,k) = 0.0
420 elseif (kt_extra(i,k) > 0.0)
then
421 kd_lay(i,j,k-1) = kd_lay(i,j,k-1) + 0.5 * ks_extra(i,k)
422 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * ks_extra(i,k)
423 visc%Kd_extra_T(i,j,k) = (kt_extra(i,k) - ks_extra(i,k))
424 visc%Kd_extra_S(i,j,k) = 0.0
426 visc%Kd_extra_T(i,j,k) = 0.0
427 visc%Kd_extra_S(i,j,k) = 0.0
430 if (
associated(dd%KT_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
431 dd%KT_extra(i,j,k) = kt_extra(i,k)
432 enddo ;
enddo ;
endif
434 if (
associated(dd%KS_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
435 dd%KS_extra(i,j,k) = ks_extra(i,k)
436 enddo ;
enddo ;
endif
441 if (cs%use_CVMix_ddiff)
then
442 call cpu_clock_begin(id_clock_cvmix_ddiff)
443 call compute_ddiff_coeffs(h, tv, g, gv, us, j, visc%Kd_extra_T, visc%Kd_extra_S, cs%CVMix_ddiff_csp)
444 call cpu_clock_end(id_clock_cvmix_ddiff)
448 if (cs%useKappaShear .or. cs%use_CVMix_shear)
then
449 if (
present(kd_int))
then
450 do k=2,nz ;
do i=is,ie
451 kd_int(i,j,k) = visc%Kd_shear(i,j,k) + 0.5 * (kd_lay(i,j,k-1) + kd_lay(i,j,k))
454 kd_int(i,j,1) = visc%Kd_shear(i,j,1)
455 kd_int(i,j,nz+1) = 0.0
458 do k=1,nz ;
do i=is,ie
459 kd_lay(i,j,k) = kd_lay(i,j,k) + 0.5 * (visc%Kd_shear(i,j,k) + visc%Kd_shear(i,j,k+1))
462 if (
present(kd_int))
then
464 kd_int(i,j,1) = kd_lay(i,j,1) ; kd_int(i,j,nz+1) = 0.0
466 do k=2,nz ;
do i=is,ie
467 kd_int(i,j,k) = 0.5 * (kd_lay(i,j,k-1) + kd_lay(i,j,k))
472 call find_tke_to_kd(h, tv, drho_int, n2_lay, j, dt_in_t, g, gv, us, cs, tke_to_kd, &
474 if (
associated(dd%maxTKE))
then ;
do k=1,nz ;
do i=is,ie
475 dd%maxTKE(i,j,k) = maxtke(i,k)
476 enddo ;
enddo ;
endif
477 if (
associated(dd%TKE_to_Kd))
then ;
do k=1,nz ;
do i=is,ie
478 dd%TKE_to_Kd(i,j,k) = tke_to_kd(i,k)
479 enddo ;
enddo ;
endif
482 if (cs%ML_radiation) &
483 call add_mlrad_diffusivity(h, fluxes, j, g, gv, us, cs, kd_lay, tke_to_kd, kd_int)
486 call calculate_tidal_mixing(h, n2_bot, j, tke_to_kd, maxtke, g, gv, us, cs%tm_csp, &
487 n2_lay, n2_int, kd_lay, kd_int, cs%Kd_max, visc%Kv_slow)
491 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then
492 if (cs%use_LOTW_BBL_diffusivity)
then
493 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, us, cs, &
494 kd_lay, kd_int, dd%Kd_BBL)
496 call add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, tke_to_kd, &
497 maxtke, kb, g, gv, us, cs, kd_lay, kd_int, dd%Kd_BBL)
501 if (cs%limit_dissipation)
then
507 do k=2,nz-1 ;
do i=is,ie
508 dissip = max( cs%dissip_min, &
509 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_lay(i,k)), &
510 cs%dissip_N2 * n2_lay(i,k))
511 kd_lay(i,j,k) = max(kd_lay(i,j,k) , &
512 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_lay(i,k) + omega2))))
515 if (
present(kd_int))
then ;
do k=2,nz ;
do i=is,ie
516 dissip = max( cs%dissip_min, &
517 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_int(i,k)), &
518 cs%dissip_N2 * n2_int(i,k))
519 kd_int(i,j,k) = max(kd_int(i,j,k) , &
520 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_int(i,k) + omega2))))
521 enddo ;
enddo ;
endif
524 if (
associated(dd%Kd_work))
then
525 do k=1,nz ;
do i=is,ie
526 dd%Kd_Work(i,j,k) = gv%Rho0 * kd_lay(i,j,k) * n2_lay(i,k) * &
533 call hchksum(kd_lay ,
"Kd_lay", g%HI, haloshift=0, &
534 scale=us%Z2_T_to_m2_s)
536 if (cs%useKappaShear)
call hchksum(visc%Kd_shear,
"Turbulent Kd", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
538 if (cs%use_CVMix_ddiff)
then
539 call hchksum(visc%Kd_extra_T,
"MOM_set_diffusivity: Kd_extra_T", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
540 call hchksum(visc%Kd_extra_S,
"MOM_set_diffusivity: Kd_extra_S", g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
543 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v))
then
544 call uvchksum(
"BBL Kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, &
545 g%HI, 0, symmetric=.true., scale=us%Z2_T_to_m2_s)
548 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v))
then
549 call uvchksum(
"BBL bbl_thick_[uv]", visc%bbl_thick_u, &
550 visc%bbl_thick_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m)
553 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v))
then
554 call uvchksum(
"Ray_[uv]", visc%Ray_u, visc%Ray_v, g%HI, 0, symmetric=.true., scale=us%Z_to_m*us%s_to_T)
559 if (cs%Kd_add > 0.0)
then
560 if (
present(kd_int))
then
562 do k=1,nz ;
do j=js,je ;
do i=is,ie
563 kd_int(i,j,k) = kd_int(i,j,k) + cs%Kd_add
564 kd_lay(i,j,k) = kd_lay(i,j,k) + cs%Kd_add
565 enddo ;
enddo ;
enddo
568 do k=1,nz ;
do j=js,je ;
do i=is,ie
569 kd_lay(i,j,k) = kd_lay(i,j,k) + cs%Kd_add
570 enddo ;
enddo ;
enddo
574 if (cs%user_change_diff)
then
575 call user_change_diff(h, tv, g, gv, cs%user_change_diff_CSp, kd_lay, kd_int, &
576 t_f, s_f, dd%Kd_user)
582 if (cs%bkgnd_mixing_csp%id_kd_bkgnd > 0) &
583 call post_data(cs%bkgnd_mixing_csp%id_kd_bkgnd, cs%bkgnd_mixing_csp%kd_bkgnd, cs%bkgnd_mixing_csp%diag)
584 if (cs%bkgnd_mixing_csp%id_kv_bkgnd > 0) &
585 call post_data(cs%bkgnd_mixing_csp%id_kv_bkgnd, cs%bkgnd_mixing_csp%kv_bkgnd, cs%bkgnd_mixing_csp%diag)
588 if (cs%CVMix_ddiff_csp%id_KT_extra > 0) &
589 call post_data(cs%CVMix_ddiff_csp%id_KT_extra, visc%Kd_extra_T, cs%CVMix_ddiff_csp%diag)
590 if (cs%CVMix_ddiff_csp%id_KS_extra > 0) &
591 call post_data(cs%CVMix_ddiff_csp%id_KS_extra, visc%Kd_extra_S, cs%CVMix_ddiff_csp%diag)
592 if (cs%CVMix_ddiff_csp%id_R_rho > 0) &
593 call post_data(cs%CVMix_ddiff_csp%id_R_rho, cs%CVMix_ddiff_csp%R_rho, cs%CVMix_ddiff_csp%diag)
595 if (cs%id_Kd_layer > 0)
call post_data(cs%id_Kd_layer, kd_lay, cs%diag)
598 call post_tidal_diagnostics(g,gv,h,cs%tm_csp)
600 if (cs%tm_csp%Int_tide_dissipation .or. cs%tm_csp%Lee_wave_dissipation .or. &
601 cs%tm_csp%Lowmode_itidal_dissipation)
then
603 if (cs%id_N2 > 0)
call post_data(cs%id_N2, dd%N2_3d, cs%diag)
604 if (cs%id_Kd_user > 0)
call post_data(cs%id_Kd_user, dd%Kd_user, cs%diag)
605 if (cs%id_Kd_Work > 0)
call post_data(cs%id_Kd_Work, dd%Kd_Work, cs%diag)
606 if (cs%id_maxTKE > 0)
call post_data(cs%id_maxTKE, dd%maxTKE, cs%diag)
607 if (cs%id_TKE_to_Kd > 0)
call post_data(cs%id_TKE_to_Kd, dd%TKE_to_Kd, cs%diag)
610 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, dd%KT_extra, cs%diag)
611 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, dd%KS_extra, cs%diag)
612 if (cs%id_Kd_BBL > 0)
call post_data(cs%id_Kd_BBL, dd%Kd_BBL, cs%diag)
614 if (
associated(dd%N2_3d))
deallocate(dd%N2_3d)
615 if (
associated(dd%Kd_work))
deallocate(dd%Kd_work)
616 if (
associated(dd%Kd_user))
deallocate(dd%Kd_user)
617 if (
associated(dd%maxTKE))
deallocate(dd%maxTKE)
618 if (
associated(dd%TKE_to_Kd))
deallocate(dd%TKE_to_Kd)
619 if (
associated(dd%KT_extra))
deallocate(dd%KT_extra)
620 if (
associated(dd%KS_extra))
deallocate(dd%KS_extra)
621 if (
associated(dd%Kd_BBL))
deallocate(dd%Kd_BBL)
623 if (showcalltree)
call calltree_leave(
"set_diffusivity()")