44 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
45 use mom_cpu_clock, only : clock_module_driver, clock_module, clock_routine
70 use fms_mod
, only : read_data
72 implicit none ;
private 74 #include <MOM_memory.h> 84 logical :: bulkmixedlayer
91 logical :: henyey_igw_background
98 logical :: henyey_igw_background_new
121 logical :: kd_tanh_lat_fn
125 real :: kd_tanh_lat_scale
129 logical :: bottomdraglaw
131 logical :: bbl_mixing_as_max
135 logical :: use_lotw_bbl_diffusivity
136 logical :: lotw_bbl_use_omega
155 logical :: bryan_lewis_diffusivity
157 real :: kd_bryan_lewis_deep
158 real :: kd_bryan_lewis_surface
159 real :: bryan_lewis_depth_cent
160 real :: bryan_lewis_width_trans
165 real :: n2_floor_iomega2
171 real :: int_tide_decay_scale
177 real :: decay_scale_factor_lee
179 real :: min_zbot_itides
180 logical :: int_tide_dissipation
183 logical :: lowmode_itidal_dissipation
186 integer :: int_tide_profile
192 real :: nbotref_polzin
195 real :: polzin_decay_scale_factor
198 real :: polzin_decay_scale_max_factor
202 real :: polzin_min_decay_scale
204 logical :: lee_wave_dissipation
209 integer :: lee_wave_profile
213 logical :: limit_dissipation
219 real :: dissip_kd_min
221 real :: tke_itide_max
227 real :: kappa_h2_factor
228 logical :: ml_radiation
241 real :: ml_rad_kd_max
243 real :: ml_rad_efold_coeff
247 logical :: ml_rad_tke_decay
256 logical :: ml_use_omega
259 real :: ml_omega_frac
262 logical :: user_change_diff
263 logical :: usekappashear
270 logical :: simple_tke_to_kd
272 real :: max_rrho_salt_fingers
273 real :: max_salt_diff_salt_fingers
276 real,
pointer,
dimension(:,:) :: tke_niku => null()
277 real,
pointer,
dimension(:,:) :: tke_itidal => null()
278 real,
pointer,
dimension(:,:) :: nb => null()
279 real,
pointer,
dimension(:,:) :: mask_itidal => null()
280 real,
pointer,
dimension(:,:) :: h2 => null()
281 real,
pointer,
dimension(:,:) :: tideamp => null()
283 character(len=200) :: inputdir
290 integer :: id_tke_itidal = -1
291 integer :: id_tke_leewave = -1
292 integer :: id_maxtke = -1
293 integer :: id_tke_to_kd = -1
295 integer :: id_kd_itidal = -1
296 integer :: id_kd_niku = -1
297 integer :: id_kd_lowmode = -1
298 integer :: id_kd_user = -1
299 integer :: id_kd_layer = -1
300 integer :: id_kd_bbl = -1
301 integer :: id_kd_bbl_z = -1
302 integer :: id_kd_itidal_z = -1
303 integer :: id_kd_niku_z = -1
304 integer :: id_kd_lowmode_z = -1
305 integer :: id_kd_user_z = -1
306 integer :: id_kd_work = -1
307 integer :: id_kd_itidal_work = -1
308 integer :: id_kd_niku_work = -1
309 integer :: id_kd_lowmode_work= -1
311 integer :: id_fl_itidal = -1
312 integer :: id_fl_lowmode = -1
313 integer :: id_polzin_decay_scale = -1
314 integer :: id_polzin_decay_scale_scaled = -1
316 integer :: id_nb = -1
317 integer :: id_n2 = -1
318 integer :: id_n2_z = -1
319 integer :: id_n2_bot = -1
320 integer :: id_n2_meanz = -1
322 integer :: id_kt_extra = -1
323 integer :: id_ks_extra = -1
324 integer :: id_kt_extra_z = -1
325 integer :: id_ks_extra_z = -1
330 real,
pointer,
dimension(:,:,:) :: &
332 kd_itidal => null(),&
333 fl_itidal => null(),&
334 kd_lowmode => null(),&
336 fl_lowmode => null(),&
342 kd_niku_work => null(),&
343 kd_itidal_work => null(),&
344 kd_lowmode_work=> null(),&
346 tke_to_kd => null(),&
352 real,
pointer,
dimension(:,:) :: &
353 tke_itidal_used => null(),&
356 polzin_decay_scale_scaled => null(),&
357 polzin_decay_scale => null()
371 subroutine set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt, &
372 G, GV, CS, Kd, Kd_int)
375 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
377 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
379 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
381 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
383 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
387 type(
forcing),
intent(in) :: fluxes
389 type(optics_type),
pointer :: optics
393 real,
intent(in) :: dt
395 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
397 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
398 optional,
intent(out) :: Kd_int
417 real,
dimension(SZI_(G)) :: &
420 real,
dimension(SZI_(G), SZJ_(G)) :: &
425 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
429 real,
dimension(SZI_(G),SZK_(G)) :: &
436 real,
dimension(SZI_(G),SZK_(G)+1) :: &
460 type(
p3d) :: z_ptrs(6)
461 integer :: kb(szi_(g))
463 integer :: num_z_diags
465 logical :: showCallTree
467 integer :: i, j, k, is, ie, js, je, nz
468 integer :: isd, ied, jsd, jed
473 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
474 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
475 showcalltree = calltree_showquery()
476 if (showcalltree)
call calltree_enter(
"set_diffusivity(), MOM_set_diffusivity.F90")
478 if (.not.
associated(cs))
call mom_error(fatal,
"set_diffusivity: "//&
479 "Module must be initialized before it is used.")
484 deg_to_rad = atan(1.0)/45.0
485 omega2 = cs%Omega*cs%Omega
486 i_2omega = 0.5/cs%Omega
489 use_eos =
associated(tv%eqn_of_state)
491 if ((cs%double_diffusion) .and. &
492 .not.(
associated(visc%Kd_extra_T) .and.
associated(visc%Kd_extra_S)) ) &
493 call mom_error(fatal,
"set_diffusivity: visc%Kd_extra_T and "//&
494 "visc%Kd_extra_S must be associated when DOUBLE_DIFFUSION is true.")
498 if ((cs%id_N2 > 0) .or. (cs%id_N2_z > 0))
then 499 allocate(dd%N2_3d(isd:ied,jsd:jed,nz+1)) ; dd%N2_3d(:,:,:) = 0.0
501 if ((cs%id_Kd_itidal > 0) .or. (cs%id_Kd_itidal_z > 0) .or. &
502 (cs%id_Kd_Itidal_work > 0))
then 503 allocate(dd%Kd_itidal(isd:ied,jsd:jed,nz+1)) ; dd%Kd_itidal(:,:,:) = 0.0
505 if ((cs%id_Kd_lowmode > 0) .or. (cs%id_Kd_lowmode_z > 0) .or. &
506 (cs%id_Kd_lowmode_work > 0))
then 507 allocate(dd%Kd_lowmode(isd:ied,jsd:jed,nz+1)) ; dd%Kd_lowmode(:,:,:) = 0.0
509 if ( (cs%id_Fl_itidal > 0) )
then 510 allocate(dd%Fl_itidal(isd:ied,jsd:jed,nz+1)) ; dd%Fl_itidal(:,:,:) = 0.0
512 if ( (cs%id_Fl_lowmode > 0) )
then 513 allocate(dd%Fl_lowmode(isd:ied,jsd:jed,nz+1)) ; dd%Fl_lowmode(:,:,:) = 0.0
515 if ( (cs%id_Polzin_decay_scale > 0) )
then 516 allocate(dd%Polzin_decay_scale(isd:ied,jsd:jed))
517 dd%Polzin_decay_scale(:,:) = 0.0
519 if ( (cs%id_Polzin_decay_scale_scaled > 0) )
then 520 allocate(dd%Polzin_decay_scale_scaled(isd:ied,jsd:jed))
521 dd%Polzin_decay_scale_scaled(:,:) = 0.0
523 if ( (cs%id_N2_bot > 0) )
then 524 allocate(dd%N2_bot(isd:ied,jsd:jed)) ; dd%N2_bot(:,:) = 0.0
526 if ( (cs%id_N2_meanz > 0) )
then 527 allocate(dd%N2_meanz(isd:ied,jsd:jed)) ; dd%N2_meanz(:,:) = 0.0
529 if ((cs%id_Kd_Niku > 0) .or. (cs%id_Kd_Niku_z > 0) .or. &
530 (cs%id_Kd_Niku_work > 0))
then 531 allocate(dd%Kd_Niku(isd:ied,jsd:jed,nz+1)) ; dd%Kd_Niku(:,:,:) = 0.0
533 if ((cs%id_Kd_user > 0) .or. (cs%id_Kd_user_z > 0))
then 534 allocate(dd%Kd_user(isd:ied,jsd:jed,nz+1)) ; dd%Kd_user(:,:,:) = 0.0
536 if (cs%id_Kd_work > 0)
then 537 allocate(dd%Kd_work(isd:ied,jsd:jed,nz)) ; dd%Kd_work(:,:,:) = 0.0
539 if (cs%id_Kd_Niku_work > 0)
then 540 allocate(dd%Kd_Niku_work(isd:ied,jsd:jed,nz)) ; dd%Kd_Niku_work(:,:,:) = 0.0
542 if (cs%id_Kd_Itidal_work > 0)
then 543 allocate(dd%Kd_Itidal_work(isd:ied,jsd:jed,nz))
544 dd%Kd_Itidal_work(:,:,:) = 0.0
546 if (cs%id_Kd_Lowmode_Work > 0)
then 547 allocate(dd%Kd_Lowmode_Work(isd:ied,jsd:jed,nz))
548 dd%Kd_Lowmode_Work(:,:,:) = 0.0
550 if (cs%id_TKE_itidal > 0)
then 551 allocate(dd%TKE_Itidal_used(isd:ied,jsd:jed)) ; dd%TKE_Itidal_used(:,:) = 0.
553 if (cs%id_maxTKE > 0)
then 554 allocate(dd%maxTKE(isd:ied,jsd:jed,nz)) ; dd%maxTKE(:,:,:) = 0.0
556 if (cs%id_TKE_to_Kd > 0)
then 557 allocate(dd%TKE_to_Kd(isd:ied,jsd:jed,nz)) ; dd%TKE_to_Kd(:,:,:) = 0.0
559 if ((cs%id_KT_extra > 0) .or. (cs%id_KT_extra_z > 0))
then 560 allocate(dd%KT_extra(isd:ied,jsd:jed,nz+1)) ; dd%KT_extra(:,:,:) = 0.0
562 if ((cs%id_KS_extra > 0) .or. (cs%id_KS_extra_z > 0))
then 563 allocate(dd%KS_extra(isd:ied,jsd:jed,nz+1)) ; dd%KS_extra(:,:,:) = 0.0
565 if ((cs%id_Kd_BBL > 0) .or. (cs%id_Kd_BBL_z > 0))
then 566 allocate(dd%Kd_BBL(isd:ied,jsd:jed,nz+1)) ; dd%Kd_BBL(:,:,:) = 0.0
572 call hchksum(tv%T,
"before vert_fill_TS tv%T",g%HI)
573 call hchksum(tv%S,
"before vert_fill_TS tv%S",g%HI)
574 call hchksum(h,
"before vert_fill_TS h",g%HI, scale=gv%H_to_m)
576 call vert_fill_ts(h, tv%T, tv%S, kappa_fill, dt_fill, t_f, s_f, g, gv)
578 call hchksum(tv%T,
"after vert_fill_TS tv%T",g%HI)
579 call hchksum(tv%S,
"after vert_fill_TS tv%S",g%HI)
580 call hchksum(h,
"after vert_fill_TS h",g%HI, scale=gv%H_to_m)
584 if (cs%useKappaShear)
then 586 call hchksum(u_h,
"before calc_KS u_h",g%HI)
587 call hchksum(v_h,
"before calc_KS v_h",g%HI)
593 visc%Kv_turb, dt, g, gv, cs%kappaShear_CSp)
596 call hchksum(visc%Kd_turb,
"after calc_KS visc%Kd_turb",g%HI)
597 call hchksum(visc%Kv_turb,
"after calc_KS visc%Kv_turb",g%HI)
598 call hchksum(visc%TKE_turb,
"after calc_KS visc%TKE_turb",g%HI)
600 if (showcalltree)
call calltree_waypoint(
"done with calculate_kappa_shear (set_diffusivity)")
601 elseif (cs%useCVMix)
then 604 elseif (
associated(visc%Kv_turb))
then 605 visc%Kv_turb(:,:,:) = 0.
612 if (cs%Bryan_Lewis_diffusivity)
then 614 do j=js,je ;
do i=is,ie
615 kd_sfc(i,j) = cs%Kd_Bryan_Lewis_surface
619 do j=js,je ;
do i=is,ie
623 if (cs%Henyey_IGW_background)
then 624 i_x30 = 2.0 /
invcosh(cs%N0_2Omega*2.0)
627 do j=js,je ;
do i=is,ie
628 abs_sin = abs(sin(g%geoLatT(i,j)*deg_to_rad))
629 kd_sfc(i,j) = max(cs%Kd_min, kd_sfc(i,j) * &
630 ((abs_sin *
invcosh(cs%N0_2Omega/max(epsilon,abs_sin))) * i_x30) )
632 elseif (cs%Kd_tanh_lat_fn)
then 634 do j=js,je ;
do i=is,ie
638 kd_sfc(i,j) = max(cs%Kd_min, kd_sfc(i,j) * (1.0 + &
639 cs%Kd_tanh_lat_scale * 0.5*tanh((abs(g%geoLatT(i,j)) - 35.0)/5.0) ))
643 if (cs%debug)
call hchksum(kd_sfc,
"Kd_sfc",g%HI,haloshift=0)
653 call find_n2(h, tv, t_f, s_f, fluxes, j, g, gv, cs, drho_int, n2_lay, n2_int, n2_bot)
654 if (
associated(dd%N2_3d))
then 655 do k=1,nz+1 ;
do i=is,ie ; dd%N2_3d(i,j,k) = n2_int(i,k) ;
enddo ;
enddo 659 if (cs%Bryan_Lewis_diffusivity)
then 660 i_trans = 1.0 / cs%Bryan_Lewis_width_trans
661 atan_fn_sfc = atan(cs%Bryan_Lewis_depth_cent*i_trans)
662 i_atan_fn = 1.0 / (2.0*atan(1.0) + atan_fn_sfc)
663 do i=is,ie ; depth(i) = 0.0 ;
enddo 664 do k=1,nz ;
do i=is,ie
665 atan_fn_lay = atan((cs%Bryan_Lewis_depth_cent - &
666 (depth(i)+0.5*gv%H_to_m*h(i,j,k)))*i_trans)
667 kd(i,j,k) = kd_sfc(i,j) + (cs%Kd_Bryan_Lewis_deep - kd_sfc(i,j)) * &
668 (atan_fn_sfc - atan_fn_lay) * i_atan_fn
669 depth(i) = depth(i) + gv%H_to_m*h(i,j,k)
671 elseif ((.not.cs%bulkmixedlayer) .and. (cs%Kd /= cs%Kdml))
then 672 i_hmix = 1.0 / cs%Hmix
673 do i=is,ie ; depth(i) = 0.0 ;
enddo 674 do k=1,nz ;
do i=is,ie
675 depth_c = depth(i) + 0.5*gv%H_to_m*h(i,j,k)
677 if (depth_c <= cs%Hmix)
then ; kd(i,j,k) = cs%Kdml
678 elseif (depth_c >= 2.0*cs%Hmix)
then ; kd(i,j,k) = kd_sfc(i,j)
680 kd(i,j,k) = ((kd_sfc(i,j) - cs%Kdml) * i_hmix) * depth_c + &
681 (2.0*cs%Kdml - kd_sfc(i,j))
684 depth(i) = depth(i) + gv%H_to_m*h(i,j,k)
686 elseif (cs%Henyey_IGW_background_new)
then 687 i_x30 = 2.0 /
invcosh(cs%N0_2Omega*2.0)
688 do k=1,nz ;
do i=is,ie
689 abs_sin = max(epsilon,abs(sin(g%geoLatT(i,j)*deg_to_rad)))
690 n_2omega = max(abs_sin,sqrt(n2_lay(i,k))*i_2omega)
691 n02_n2 = (cs%N0_2Omega/n_2omega)**2
692 kd(i,j,k) = max(cs%Kd_min, kd_sfc(i,j) * &
693 ((abs_sin *
invcosh(n_2omega/abs_sin)) * i_x30)*n02_n2)
696 do k=1,nz ;
do i=is,ie
697 kd(i,j,k) = kd_sfc(i,j)
701 if (cs%double_diffusion)
then 703 do k=2,nz ;
do i=is,ie
704 if (ks_extra(i,k) > kt_extra(i,k))
then 705 kd(i,j,k-1) = kd(i,j,k-1) + 0.5*kt_extra(i,k)
706 kd(i,j,k) = kd(i,j,k) + 0.5*kt_extra(i,k)
707 visc%Kd_extra_S(i,j,k) = ks_extra(i,k)-kt_extra(i,k)
708 visc%Kd_extra_T(i,j,k) = 0.0
709 elseif (kt_extra(i,k) > 0.0)
then 710 kd(i,j,k-1) = kd(i,j,k-1) + 0.5*ks_extra(i,k)
711 kd(i,j,k) = kd(i,j,k) + 0.5*ks_extra(i,k)
712 visc%Kd_extra_T(i,j,k) = kt_extra(i,k)-ks_extra(i,k)
713 visc%Kd_extra_S(i,j,k) = 0.0
715 visc%Kd_extra_T(i,j,k) = 0.0
716 visc%Kd_extra_S(i,j,k) = 0.0
719 if (
associated(dd%KT_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
720 dd%KT_extra(i,j,k) = kt_extra(i,k)
721 enddo ;
enddo ;
endif 723 if (
associated(dd%KS_extra))
then ;
do k=1,nz+1 ;
do i=is,ie
724 dd%KS_extra(i,j,k) = ks_extra(i,k)
725 enddo ;
enddo ;
endif 729 if (cs%useKappaShear .or. cs%useCVMix)
then 730 if (
present(kd_int))
then 731 do k=2,nz ;
do i=is,ie
732 kd_int(i,j,k) = visc%Kd_turb(i,j,k) + 0.5*(kd(i,j,k-1) + kd(i,j,k))
735 kd_int(i,j,1) = visc%Kd_turb(i,j,1)
736 kd_int(i,j,nz+1) = 0.0
739 do k=1,nz ;
do i=is,ie
740 kd(i,j,k) = kd(i,j,k) + 0.5*(visc%Kd_turb(i,j,k) + visc%Kd_turb(i,j,k+1))
743 if (
present(kd_int))
then 745 kd_int(i,j,1) = kd(i,j,1) ; kd_int(i,j,nz+1) = 0.0
747 do k=2,nz ;
do i=is,ie
748 kd_int(i,j,k) = 0.5*(kd(i,j,k-1) + kd(i,j,k))
753 call find_tke_to_kd(h, tv, drho_int, n2_lay, j, dt, g, gv, cs, tke_to_kd, &
755 if (
associated(dd%maxTKE))
then ;
do k=1,nz ;
do i=is,ie
756 dd%maxTKE(i,j,k) = maxtke(i,k)
757 enddo ;
enddo ;
endif 758 if (
associated(dd%TKE_to_Kd))
then ;
do k=1,nz ;
do i=is,ie
759 dd%TKE_to_Kd(i,j,k) = tke_to_kd(i,k)
760 enddo ;
enddo ;
endif 763 if (cs%ML_radiation) &
767 if (cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation .or. cs%Lowmode_itidal_dissipation) &
769 dd, n2_lay, kd, kd_int)
773 if (cs%bottomdraglaw .and. (cs%BBL_effic>0.0))
then 774 if (cs%use_LOTW_BBL_diffusivity)
then 775 call add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, n2_int, g, gv, cs, &
776 kd, kd_int, dd%Kd_BBL)
779 maxtke, kb, g, gv, cs, kd, kd_int, dd%Kd_BBL)
783 if (cs%limit_dissipation)
then 784 do k=2,nz-1 ;
do i=is,ie
790 dissip = max( cs%dissip_min, &
791 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_lay(i,k)), &
792 cs%dissip_N2 * n2_lay(i,k) )
793 kd(i,j,k) = max( kd(i,j,k) , &
794 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_lay(i,k) + omega2))) )
797 if (
present(kd_int))
then ;
do k=2,nz ;
do i=is,ie
803 dissip = max( cs%dissip_min, &
804 cs%dissip_N0 + cs%dissip_N1 * sqrt(n2_int(i,k)), &
805 cs%dissip_N2 * n2_int(i,k) )
806 kd_int(i,j,k) = max( kd_int(i,j,k) , &
807 dissip * (cs%FluxRi_max / (gv%Rho0 * (n2_int(i,k) + omega2))) )
808 enddo ;
enddo ;
endif 811 if (
associated(dd%Kd_work))
then 812 do k=1,nz ;
do i=is,ie
813 dd%Kd_Work(i,j,k) = gv%Rho0 * kd(i,j,k) * n2_lay(i,k) * &
820 call hchksum(kd,
"BBL Kd",g%HI,haloshift=0)
821 if (cs%useKappaShear)
call hchksum(visc%Kd_turb,
"Turbulent Kd",g%HI,haloshift=0)
822 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v))
then 823 call uvchksum(
"BBL Kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, &
824 g%HI, 0, symmetric=.true.)
826 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v))
then 827 call uvchksum(
"BBL bbl_thick_[uv]", visc%bbl_thick_u, &
828 visc%bbl_thick_v, g%HI, 0, symmetric=.true.)
830 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v))
then 831 call uvchksum(
"Ray_[uv]", visc%Ray_u, visc%Ray_v, g%HI, 0, symmetric=.true.)
835 if (cs%Kd_add > 0.0)
then 836 if (
present(kd_int))
then 838 do k=1,nz ;
do j=js,je ;
do i=is,ie
839 kd_int(i,j,k) = kd_int(i,j,k) + cs%Kd_add
840 kd(i,j,k) = kd(i,j,k) + cs%Kd_add
841 enddo ;
enddo ;
enddo 844 do k=1,nz ;
do j=js,je ;
do i=is,ie
845 kd(i,j,k) = kd(i,j,k) + cs%Kd_add
846 enddo ;
enddo ;
enddo 850 if (cs%user_change_diff)
then 851 call user_change_diff(h, tv, g, cs%user_change_diff_CSp, kd, kd_int, &
852 t_f, s_f, dd%Kd_user)
855 if (cs%id_Kd_layer > 0)
call post_data(cs%id_Kd_layer, kd, cs%diag)
858 if (cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation .or. cs%Lowmode_itidal_dissipation)
then 859 if (cs%id_TKE_itidal > 0)
call post_data(cs%id_TKE_itidal, dd%TKE_itidal_used, cs%diag)
860 if (cs%id_TKE_leewave > 0)
call post_data(cs%id_TKE_leewave, cs%TKE_Niku, cs%diag)
861 if (cs%id_Nb > 0)
call post_data(cs%id_Nb, cs%Nb, cs%diag)
862 if (cs%id_N2 > 0)
call post_data(cs%id_N2, dd%N2_3d, cs%diag)
863 if (cs%id_N2_bot > 0)
call post_data(cs%id_N2_bot, dd%N2_bot, cs%diag)
864 if (cs%id_N2_meanz > 0)
call post_data(cs%id_N2_meanz,dd%N2_meanz,cs%diag)
866 if (cs%id_Fl_itidal > 0)
call post_data(cs%id_Fl_itidal, dd%Fl_itidal, cs%diag)
867 if (cs%id_Kd_itidal > 0)
call post_data(cs%id_Kd_itidal, dd%Kd_itidal, cs%diag)
868 if (cs%id_Kd_Niku > 0)
call post_data(cs%id_Kd_Niku, dd%Kd_Niku, cs%diag)
869 if (cs%id_Kd_lowmode> 0)
call post_data(cs%id_Kd_lowmode, dd%Kd_lowmode, cs%diag)
870 if (cs%id_Fl_lowmode> 0)
call post_data(cs%id_Fl_lowmode, dd%Fl_lowmode, cs%diag)
871 if (cs%id_Kd_user > 0)
call post_data(cs%id_Kd_user, dd%Kd_user, cs%diag)
872 if (cs%id_Kd_Work > 0)
call post_data(cs%id_Kd_Work, dd%Kd_Work, cs%diag)
873 if (cs%id_Kd_Itidal_Work > 0) &
874 call post_data(cs%id_Kd_Itidal_Work, dd%Kd_Itidal_Work, cs%diag)
875 if (cs%id_Kd_Niku_Work > 0)
call post_data(cs%id_Kd_Niku_Work, dd%Kd_Niku_Work, cs%diag)
876 if (cs%id_Kd_Lowmode_Work > 0) &
877 call post_data(cs%id_Kd_Lowmode_Work, dd%Kd_Lowmode_Work, cs%diag)
878 if (cs%id_maxTKE > 0)
call post_data(cs%id_maxTKE, dd%maxTKE, cs%diag)
879 if (cs%id_TKE_to_Kd > 0)
call post_data(cs%id_TKE_to_Kd, dd%TKE_to_Kd, cs%diag)
881 if (cs%id_Polzin_decay_scale > 0 ) &
882 call post_data(cs%id_Polzin_decay_scale, dd%Polzin_decay_scale, cs%diag)
883 if (cs%id_Polzin_decay_scale_scaled > 0 ) &
884 call post_data(cs%id_Polzin_decay_scale_scaled, dd%Polzin_decay_scale_scaled, cs%diag)
886 if (cs%id_Kd_itidal_z > 0)
then 887 num_z_diags = num_z_diags + 1
888 z_ids(num_z_diags) = cs%id_Kd_itidal_z
889 z_ptrs(num_z_diags)%p => dd%Kd_itidal
892 if (cs%id_Kd_Niku_z > 0)
then 893 num_z_diags = num_z_diags + 1
894 z_ids(num_z_diags) = cs%id_Kd_Niku_z
895 z_ptrs(num_z_diags)%p => dd%Kd_Niku
898 if (cs%id_Kd_lowmode_z > 0)
then 899 num_z_diags = num_z_diags + 1
900 z_ids(num_z_diags) = cs%id_Kd_lowmode_z
901 z_ptrs(num_z_diags)%p => dd%Kd_lowmode
904 if (cs%id_N2_z > 0)
then 905 num_z_diags = num_z_diags + 1
906 z_ids(num_z_diags) = cs%id_N2_z
907 z_ptrs(num_z_diags)%p => dd%N2_3d
910 if (cs%id_Kd_user_z > 0)
then 911 num_z_diags = num_z_diags + 1
912 z_ids(num_z_diags) = cs%id_Kd_user_z
913 z_ptrs(num_z_diags)%p => dd%Kd_user
918 if (cs%id_KT_extra > 0)
call post_data(cs%id_KT_extra, dd%KT_extra, cs%diag)
919 if (cs%id_KS_extra > 0)
call post_data(cs%id_KS_extra, dd%KS_extra, cs%diag)
920 if (cs%id_Kd_BBL > 0)
call post_data(cs%id_Kd_BBL, dd%Kd_BBL, cs%diag)
922 if (cs%id_KT_extra_z > 0)
then 923 num_z_diags = num_z_diags + 1
924 z_ids(num_z_diags) = cs%id_KT_extra_z
925 z_ptrs(num_z_diags)%p => dd%KT_extra
928 if (cs%id_KS_extra_z > 0)
then 929 num_z_diags = num_z_diags + 1
930 z_ids(num_z_diags) = cs%id_KS_extra_z
931 z_ptrs(num_z_diags)%p => dd%KS_extra
934 if (cs%id_Kd_BBL_z > 0)
then 935 num_z_diags = num_z_diags + 1
936 z_ids(num_z_diags) = cs%id_Kd_BBL_z
937 z_ptrs(num_z_diags)%p => dd%KS_extra
940 if (num_z_diags > 0) &
941 call calc_zint_diags(h, z_ptrs, z_ids, num_z_diags, g, gv, cs%diag_to_Z_CSp)
943 if (
associated(dd%N2_3d))
deallocate(dd%N2_3d)
944 if (
associated(dd%Kd_itidal))
deallocate(dd%Kd_itidal)
945 if (
associated(dd%Kd_lowmode))
deallocate(dd%Kd_lowmode)
946 if (
associated(dd%Fl_itidal))
deallocate(dd%Fl_itidal)
947 if (
associated(dd%Fl_lowmode))
deallocate(dd%Fl_lowmode)
948 if (
associated(dd%Polzin_decay_scale))
deallocate(dd%Polzin_decay_scale)
949 if (
associated(dd%Polzin_decay_scale_scaled))
deallocate(dd%Polzin_decay_scale_scaled)
950 if (
associated(dd%N2_bot))
deallocate(dd%N2_bot)
951 if (
associated(dd%N2_meanz))
deallocate(dd%N2_meanz)
952 if (
associated(dd%Kd_work))
deallocate(dd%Kd_work)
953 if (
associated(dd%Kd_user))
deallocate(dd%Kd_user)
954 if (
associated(dd%Kd_Niku))
deallocate(dd%Kd_Niku)
955 if (
associated(dd%Kd_Niku_work))
deallocate(dd%Kd_Niku_work)
956 if (
associated(dd%Kd_Itidal_Work))
deallocate(dd%Kd_Itidal_Work)
957 if (
associated(dd%Kd_Lowmode_Work))
deallocate(dd%Kd_Lowmode_Work)
958 if (
associated(dd%TKE_itidal_used))
deallocate(dd%TKE_itidal_used)
959 if (
associated(dd%maxTKE))
deallocate(dd%maxTKE)
960 if (
associated(dd%TKE_to_Kd))
deallocate(dd%TKE_to_Kd)
961 if (
associated(dd%KT_extra))
deallocate(dd%KT_extra)
962 if (
associated(dd%KS_extra))
deallocate(dd%KS_extra)
963 if (
associated(dd%Kd_BBL))
deallocate(dd%Kd_BBL)
969 subroutine find_tke_to_kd(h, tv, dRho_int, N2_lay, j, dt, G, GV, CS, &
970 TKE_to_Kd, maxTKE, kb)
971 type(ocean_grid_type),
intent(in) :: G
972 type(verticalgrid_type),
intent(in) :: GV
973 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
974 type(thermo_var_ptrs),
intent(in) :: tv
975 real,
dimension(SZI_(G),SZK_(G)+1),
intent(in) :: dRho_int
976 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: N2_lay
977 integer,
intent(in) :: j
978 real,
intent(in) :: dt
980 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: TKE_to_Kd, maxTKE
981 integer,
dimension(SZI_(G)),
intent(out) :: kb
983 real,
dimension(SZI_(G),SZK_(G)) :: &
995 real,
dimension(SZI_(G)) :: &
1014 logical :: do_i(szi_(g))
1016 integer :: i, k, is, ie, nz, i_rem, kmb, kb_min
1017 is = g%isc ; ie = g%iec ; nz = g%ke
1020 omega2 = cs%Omega**2
1021 g_rho0 = gv%g_Earth / gv%Rho0
1022 h_neglect = gv%H_subroundoff
1023 i_rho0 = 1.0/gv%Rho0
1026 if (cs%simple_TKE_to_Kd)
then 1027 do k=1,nz ;
do i=is,ie
1028 hn2po2 = ( gv%H_to_m * h(i,j,k) ) * ( n2_lay(i,k) + omega2 )
1030 tke_to_kd(i,k) = 1./ hn2po2
1031 else; tke_to_kd(i,k) = 0.;
endif 1034 maxtke(i,k) = hn2po2 * cs%Kd_max
1041 if (cs%bulkmixedlayer)
then 1042 kmb = gv%nk_rho_varies
1043 do i=is,ie ; p_0(i) = 0.0 ; p_ref(i) = tv%P_Ref ;
enddo 1045 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p_0,rho_0(:,k),&
1046 is,ie-is+1,tv%eqn_of_state)
1048 call calculate_density(tv%T(:,j,kmb),tv%S(:,j,kmb),p_ref,rcv_kmb,&
1049 is,ie-is+1,tv%eqn_of_state)
1055 do k=kmb+1,nz-1 ;
if (rcv_kmb(i) <= gv%Rlay(k))
exit ;
enddo 1060 do k=kb(i)-1,kmb+1,-1
1061 if (rho_0(i,kmb) > rho_0(i,k))
exit 1062 if (h(i,j,k)>2.0*gv%Angstrom) kb(i) = k
1068 kb_min = 2 ; kmb = 0
1069 do i=is,ie ; kb(i) = 1 ;
enddo 1075 do k=2,nz-1 ;
do i=is,ie
1076 dsp1_ds(i,k) = 1.0 / ds_dsp1(i,k)
1078 do i=is,ie ; dsp1_ds(i,nz) = 0.0 ;
enddo 1080 if (cs%bulkmixedlayer)
then 1081 kmb = gv%nk_rho_varies
1083 htot(i) = gv%H_to_m*h(i,j,kmb)
1086 mfkb(i) = ds_dsp1(i,kb(i)) * (gv%H_to_m*(h(i,j,kmb) - gv%Angstrom))
1088 do k=1,kmb-1 ;
do i=is,ie
1089 htot(i) = htot(i) + gv%H_to_m*h(i,j,k)
1090 mfkb(i) = mfkb(i) + ds_dsp1(i,k+1)*(gv%H_to_m*(h(i,j,k) - gv%Angstrom))
1094 maxent(i,1) = 0.0 ; htot(i) = gv%H_to_m*(h(i,j,1) - gv%Angstrom)
1097 do k=kb_min,nz-1 ;
do i=is,ie
1098 if (k == kb(i))
then 1099 maxent(i,kb(i))= mfkb(i)
1100 elseif (k > kb(i))
then 1101 maxent(i,k) = (1.0/dsp1_ds(i,k))*(maxent(i,k-1) + htot(i))
1103 htot(i) = htot(i) + gv%H_to_m*(h(i,j,k) - gv%Angstrom)
1108 htot(i) = gv%H_to_m*(h(i,j,nz) - gv%Angstrom) ; maxent(i,nz) = 0.0
1109 do_i(i) = (g%mask2dT(i,j) > 0.5)
1113 do i=is,ie ;
if (do_i(i))
then 1114 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif 1116 maxent(i,k) = min(maxent(i,k),dsp1_ds(i,k+1)*maxent(i,k+1) + htot(i))
1117 htot(i) = htot(i) + gv%H_to_m*(h(i,j,k) - gv%Angstrom)
1119 if (i_rem == 0)
exit 1124 maxtke(i,1) = 0.0 ; tke_to_kd(i,1) = 0.0
1125 maxtke(i,nz) = 0.0 ; tke_to_kd(i,nz) = 0.0
1127 do k=2,kmb ;
do i=is,ie
1129 tke_to_kd(i,k) = 1.0 / ((n2_lay(i,k) + omega2) * &
1130 (gv%H_to_m*(h(i,j,k) + h_neglect)))
1132 do k=kmb+1,kb_min-1 ;
do i=is,ie
1135 maxtke(i,k) = 0.0 ; tke_to_kd(i,k) = 0.0
1137 do k=kb_min,nz-1 ;
do i=is,ie
1140 tke_to_kd(i,k) = 0.0
1148 dh_max = maxent(i,k) * (1.0 + dsp1_ds(i,k))
1149 drho_lay = 0.5 * max(drho_int(i,k) + drho_int(i,k+1), 0.0)
1150 maxtke(i,k) = i_dt * ((gv%g_Earth * i_rho0) * &
1151 (0.5*max(drho_int(i,k+1) + dsp1_ds(i,k)*drho_int(i,k),0.0))) * &
1152 ((gv%H_to_m*h(i,j,k) + dh_max) * maxent(i,k))
1153 tke_to_kd(i,k) = 1.0 / (g_rho0 * drho_lay + &
1154 cs%Omega**2 * gv%H_to_m*(h(i,j,k) + h_neglect))
1160 subroutine find_n2(h, tv, T_f, S_f, fluxes, j, G, GV, CS, dRho_int, &
1161 N2_lay, N2_int, N2_bot)
1162 type(ocean_grid_type),
intent(in) :: G
1163 type(verticalgrid_type),
intent(in) :: GV
1164 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1165 type(thermo_var_ptrs),
intent(in) :: tv
1166 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: T_f, S_f
1167 type(forcing),
intent(in) :: fluxes
1168 integer,
intent(in) :: j
1170 real,
dimension(SZI_(G),SZK_(G)+1),
intent(out) :: dRho_int, N2_int
1171 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: N2_lay
1172 real,
dimension(SZI_(G)),
intent(out) :: N2_bot
1174 real,
dimension(SZI_(G),SZK_(G)+1) :: &
1179 real,
dimension(SZI_(G)) :: &
1193 logical :: do_i(szi_(g)), do_any
1194 integer :: i, k, is, ie, nz
1196 is = g%isc ; ie = g%iec ; nz = g%ke
1197 g_rho0 = gv%g_Earth / gv%Rho0
1198 h_neglect = gv%H_subroundoff
1202 drho_int(i,1) = 0.0 ; drho_int(i,nz+1) = 0.0
1203 drho_int_unfilt(i,1) = 0.0 ; drho_int_unfilt(i,nz+1) = 0.0
1205 if (
associated(tv%eqn_of_state))
then 1206 if (
associated(fluxes%p_surf))
then 1207 do i=is,ie ; pres(i) = fluxes%p_surf(i,j) ;
enddo 1209 do i=is,ie ; pres(i) = 0.0 ;
enddo 1213 pres(i) = pres(i) + gv%H_to_Pa*h(i,j,k-1)
1214 temp_int(i) = 0.5 * (t_f(i,j,k) + t_f(i,j,k-1))
1215 salin_int(i) = 0.5 * (s_f(i,j,k) + s_f(i,j,k-1))
1217 call calculate_density_derivs(temp_int, salin_int, pres, &
1218 drho_dt(:,k), drho_ds(:,k), is, ie-is+1, tv%eqn_of_state)
1220 drho_int(i,k) = max(drho_dt(i,k)*(t_f(i,j,k) - t_f(i,j,k-1)) + &
1221 drho_ds(i,k)*(s_f(i,j,k) - s_f(i,j,k-1)), 0.0)
1222 drho_int_unfilt(i,k) = max(drho_dt(i,k)*(tv%T(i,j,k) - tv%T(i,j,k-1)) + &
1223 drho_ds(i,k)*(tv%S(i,j,k) - tv%S(i,j,k-1)), 0.0)
1227 do k=2,nz ;
do i=is,ie
1228 drho_int(i,k) = gv%Rlay(k) - gv%Rlay(k-1)
1233 do k=1,nz ;
do i=is,ie
1234 n2_lay(i,k) = g_rho0 * 0.5*(drho_int(i,k) + drho_int(i,k+1)) / &
1235 (gv%H_to_m*(h(i,j,k) + h_neglect))
1237 do i=is,ie ; n2_int(i,1) = 0.0 ; n2_int(i,nz+1) = 0.0 ;
enddo 1238 do k=2,nz ;
do i=is,ie
1239 n2_int(i,k) = g_rho0 * drho_int(i,k) / &
1240 (0.5*gv%H_to_m*(h(i,j,k-1) + h(i,j,k) + h_neglect))
1245 hb(i) = 0.0 ; drho_bot(i) = 0.0
1246 z_from_bot(i) = 0.5*gv%H_to_m*h(i,j,nz)
1247 do_i(i) = (g%mask2dT(i,j) > 0.5)
1249 if (cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation)
then 1250 h_amp(i) = sqrt(cs%h2(i,j))
1258 do i=is,ie ;
if (do_i(i))
then 1259 dz_int = 0.5*gv%H_to_m*(h(i,j,k) + h(i,j,k-1))
1260 z_from_bot(i) = z_from_bot(i) + dz_int
1262 hb(i) = hb(i) + dz_int
1263 drho_bot(i) = drho_bot(i) + drho_int(i,k)
1265 if (z_from_bot(i) > h_amp(i))
then 1268 hb(i) = hb(i) + 0.5*gv%H_to_m*(h(i,j,k-1) + h(i,j,k-2))
1269 drho_bot(i) = drho_bot(i) + drho_int(i,k-1)
1276 if (.not.do_any)
exit 1280 if (hb(i) > 0.0)
then 1281 n2_bot(i) = (g_rho0 * drho_bot(i)) / hb(i)
1282 else ; n2_bot(i) = 0.0 ;
endif 1283 z_from_bot(i) = 0.5*gv%H_to_m*h(i,j,nz)
1284 do_i(i) = (g%mask2dT(i,j) > 0.5)
1289 do i=is,ie ;
if (do_i(i))
then 1290 dz_int = 0.5*gv%H_to_m*(h(i,j,k) + h(i,j,k-1))
1291 z_from_bot(i) = z_from_bot(i) + dz_int
1293 n2_int(i,k) = n2_bot(i)
1294 if (k>2) n2_lay(i,k-1) = n2_bot(i)
1296 if (z_from_bot(i) > h_amp(i))
then 1297 if (k>2) n2_int(i,k-1) = n2_bot(i)
1303 if (.not.do_any)
exit 1306 if (
associated(tv%eqn_of_state))
then 1307 do k=1,nz+1 ;
do i=is,ie
1308 drho_int(i,k) = drho_int_unfilt(i,k)
1321 subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, CS, Kd_T_dd, Kd_S_dd)
1322 type(ocean_grid_type),
intent(in) :: G
1323 type(verticalgrid_type),
intent(in) :: GV
1324 type(thermo_var_ptrs),
intent(in) :: tv
1327 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1329 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1332 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1335 integer,
intent(in) :: j
1337 real,
dimension(SZI_(G),SZK_(G)+1), &
1338 intent(out) :: Kd_T_dd
1340 real,
dimension(SZI_(G),SZK_(G)+1), &
1341 intent(out) :: Kd_S_dd
1365 real,
dimension(SZI_(G)) :: &
1379 real,
parameter :: Rrho0 = 1.9
1380 real,
parameter :: dsfmax = 1.e-4
1381 real,
parameter :: Kv_molecular = 1.5e-6
1383 integer :: i, k, is, ie, nz
1384 is = g%isc ; ie = g%iec ; nz = g%ke
1386 if (
associated(tv%eqn_of_state))
then 1388 pres(i) = 0.0 ; kd_t_dd(i,1) = 0.0 ; kd_s_dd(i,1) = 0.0
1389 kd_t_dd(i,nz+1) = 0.0 ; kd_s_dd(i,nz+1) = 0.0
1393 pres(i) = pres(i) + gv%H_to_Pa*h(i,j,k-1)
1394 temp_int(i) = 0.5 * (t_f(i,j,k-1) + t_f(i,j,k))
1395 salin_int(i) = 0.5 * (s_f(i,j,k-1) + s_f(i,j,k))
1397 call calculate_density_derivs(temp_int, salin_int, pres, &
1398 drho_dt(:), drho_ds(:), is, ie-is+1, tv%eqn_of_state)
1401 alpha_dt = -1.0*drho_dt(i) * (t_f(i,j,k-1) - t_f(i,j,k))
1402 beta_ds = drho_ds(i) * (s_f(i,j,k-1) - s_f(i,j,k))
1404 if ((alpha_dt > beta_ds) .and. (beta_ds > 0.0))
then 1405 rrho = min(alpha_dt/beta_ds,rrho0)
1406 diff_dd = 1.0 - ((rrho-1.0)/(rrho0-1.0))
1407 diff_dd = dsfmax*diff_dd*diff_dd*diff_dd
1408 kd_t_dd(i,k) = 0.7*diff_dd
1409 kd_s_dd(i,k) = diff_dd
1410 elseif ((alpha_dt < 0.) .and. (beta_ds < 0.) .and. (alpha_dt > beta_ds))
then 1411 rrho = alpha_dt/beta_ds
1412 diff_dd = kv_molecular*0.909*exp(4.6*exp(-0.54*(1/rrho-1)))
1414 if (rrho > 0.5) prandtl = (1.85-0.85/rrho)*rrho
1415 kd_t_dd(i,k) = diff_dd
1416 kd_s_dd(i,k) = prandtl*diff_dd
1418 kd_t_dd(i,k) = 0.0 ; kd_s_dd(i,k) = 0.0
1427 maxTKE, kb, G, GV, CS, Kd, Kd_int, Kd_BBL)
1428 type(ocean_grid_type),
intent(in) :: G
1429 type(verticalgrid_type),
intent(in) :: GV
1430 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
1431 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1432 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1433 type(thermo_var_ptrs),
intent(in) :: tv
1434 type(forcing),
intent(in) :: fluxes
1435 type(vertvisc_type),
intent(in) :: visc
1436 integer,
intent(in) :: j
1437 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd, maxTKE
1438 integer,
dimension(SZI_(G)),
intent(in) :: kb
1440 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: Kd
1441 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
intent(inout) :: Kd_int
1442 real,
dimension(:,:,:),
pointer :: Kd_BBL
1446 real,
dimension(SZK_(G)+1) :: &
1448 real,
dimension(SZI_(G)) :: &
1459 real :: TKE_to_layer
1469 logical :: Rayleigh_drag
1473 logical :: domore, do_i(szi_(g))
1474 logical :: do_diag_Kd_BBL
1476 integer :: i, k, is, ie, nz, i_rem, kb_min
1477 is = g%isc ; ie = g%iec ; nz = g%ke
1479 do_diag_kd_bbl =
associated(kd_bbl)
1481 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return 1483 cdrag_sqrt = sqrt(cs%cdrag)
1484 tke_ray = 0.0 ; rayleigh_drag = .false.
1485 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1487 i_rho0 = 1.0/gv%Rho0
1488 r0_g = gv%Rho0/gv%g_Earth
1490 do k=2,nz ; rint(k) = 0.5*(gv%Rlay(k-1)+gv%Rlay(k)) ;
enddo 1492 kb_min = max(gv%nk_rho_varies+1,2)
1498 ustar_h = visc%ustar_BBL(i,j)
1499 if (
ASSOCIATED(fluxes%ustar_tidal)) &
1500 ustar_h = ustar_h + fluxes%ustar_tidal(i,j)
1501 absf = 0.25*((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1502 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1503 if ((ustar_h > 0.0) .and. (absf > 0.5*cs%IMax_decay*ustar_h))
then 1504 i2decay(i) = absf / ustar_h
1508 i2decay(i) = 0.5*cs%IMax_decay
1510 tke(i) = ((cs%BBL_effic * cdrag_sqrt) * &
1511 exp(-i2decay(i)*(gv%H_to_m*h(i,j,nz))) ) * &
1514 if (
ASSOCIATED(fluxes%TKE_tidal)) &
1515 tke(i) = tke(i) + fluxes%TKE_tidal(i,j) * i_rho0 * &
1516 (cs%BBL_effic * exp(-i2decay(i)*(gv%H_to_m*h(i,j,nz))))
1523 gh_sum_top(i) = r0_g * 400.0 * ustar_h**2
1525 do_i(i) = (g%mask2dT(i,j) > 0.5)
1526 htot(i) = gv%H_to_m*h(i,j,nz)
1527 rho_htot(i) = gv%Rlay(nz)*(gv%H_to_m*h(i,j,nz))
1528 rho_top(i) = gv%Rlay(1)
1529 if (cs%bulkmixedlayer .and. do_i(i)) rho_top(i) = gv%Rlay(kb(i)-1)
1532 do k=nz-1,2,-1 ; domore = .false.
1533 do i=is,ie ;
if (do_i(i))
then 1534 htot(i) = htot(i) + gv%H_to_m*h(i,j,k)
1535 rho_htot(i) = rho_htot(i) + gv%Rlay(k)*(gv%H_to_m*h(i,j,k))
1536 if (htot(i)*gv%Rlay(k-1) <= (rho_htot(i) - gh_sum_top(i)))
then 1538 rho_top(i) = (rho_htot(i) - gh_sum_top(i)) / htot(i)
1540 elseif (k <= kb(i))
then ; do_i(i) = .false.
1541 else ; domore = .true. ;
endif 1543 if (.not.domore)
exit 1546 do i=is,ie ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo 1549 do i=is,ie ;
if (do_i(i))
then 1550 if (k<kb(i))
then ; do_i(i) = .false. ; cycle ;
endif 1554 tke(i) = tke(i) * exp(-i2decay(i) * (gv%H_to_m*(h(i,j,k) + h(i,j,k+1))))
1557 if (maxtke(i,k) <= 0.0) cycle
1561 if (tke(i) > 0.0)
then 1562 if (rint(k) <= rho_top(i))
then 1563 tke_to_layer = tke(i)
1565 drl = rint(k+1) - rint(k) ; drbot = rint(k+1) - rho_top(i)
1566 tke_to_layer = tke(i) * drl * (3.0*drbot*(rint(k) - rho_top(i)) +&
1569 else ; tke_to_layer = 0.0 ;
endif 1572 if (rayleigh_drag) tke_ray = 0.5*cs%BBL_effic * g%IareaT(i,j) * &
1573 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1574 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1575 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1576 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1578 if (tke_to_layer + tke_ray > 0.0)
then 1579 if (cs%BBL_mixing_as_max)
then 1580 if (tke_to_layer + tke_ray > maxtke(i,k)) &
1581 tke_to_layer = maxtke(i,k) - tke_ray
1583 tke(i) = tke(i) - tke_to_layer
1585 if (kd(i,j,k) < (tke_to_layer+tke_ray)*tke_to_kd(i,k))
then 1586 delta_kd = (tke_to_layer+tke_ray)*tke_to_kd(i,k) - kd(i,j,k)
1587 if ((cs%Kd_max >= 0.0) .and. (delta_kd > cs%Kd_max))
then 1588 delta_kd = cs%Kd_Max
1589 kd(i,j,k) = kd(i,j,k) + delta_kd
1591 kd(i,j,k) = (tke_to_layer+tke_ray)*tke_to_kd(i,k)
1593 kd_int(i,j,k) = kd_int(i,j,k) + 0.5*delta_kd
1594 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5*delta_kd
1595 if (do_diag_kd_bbl)
then 1596 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5*delta_kd
1597 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5*delta_kd
1601 if (kd(i,j,k) >= maxtke(i,k)*tke_to_kd(i,k))
then 1603 tke(i) = tke(i) + tke_ray
1604 elseif (kd(i,j,k) + (tke_to_layer+tke_ray)*tke_to_kd(i,k) > &
1605 maxtke(i,k)*tke_to_kd(i,k))
then 1606 tke_here = ((tke_to_layer+tke_ray) + kd(i,j,k)/tke_to_kd(i,k)) - &
1608 tke(i) = tke(i) - tke_here + tke_ray
1610 tke_here = tke_to_layer + tke_ray
1611 tke(i) = tke(i) - tke_to_layer
1613 if (tke(i) < 0.0) tke(i) = 0.0
1615 if (tke_here > 0.0)
then 1616 delta_kd = tke_here*tke_to_kd(i,k)
1617 if (cs%Kd_max >= 0.0) delta_kd = min(delta_kd, cs%Kd_max)
1618 kd(i,j,k) = kd(i,j,k) + delta_kd
1619 kd_int(i,j,k) = kd_int(i,j,k) + 0.5*delta_kd
1620 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5*delta_kd
1621 if (do_diag_kd_bbl)
then 1622 kd_bbl(i,j,k) = kd_bbl(i,j,k) + 0.5*delta_kd
1623 kd_bbl(i,j,k+1) = kd_bbl(i,j,k+1) + 0.5*delta_kd
1633 if ((tke(i)<= 0.0) .and. (tke_ray == 0.0))
then 1634 do_i(i) = .false. ; i_rem = i_rem - 1
1638 if (i_rem == 0)
exit 1647 G, GV, CS, Kd, Kd_int, Kd_BBL)
1648 type(ocean_grid_type),
intent(in) :: G
1649 type(verticalgrid_type),
intent(in) :: GV
1650 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
1651 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1652 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1653 type(thermo_var_ptrs),
intent(in) :: tv
1654 type(forcing),
intent(in) :: fluxes
1655 type(vertvisc_type),
intent(in) :: visc
1656 integer,
intent(in) :: j
1657 real,
dimension(SZI_(G),SZK_(G)+1),
intent(in) :: N2_int
1659 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: Kd
1660 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
intent(inout) :: Kd_int
1661 real,
dimension(:,:,:),
pointer :: Kd_BBL
1665 real :: TKE_to_layer
1667 real :: TKE_remaining
1668 real :: TKE_consumed
1677 real :: total_thickness
1684 logical :: Rayleigh_drag
1686 integer :: i, k, km1
1687 real,
parameter :: von_karm = 0.41
1688 logical :: do_diag_Kd_BBL
1690 if (.not.(cs%bottomdraglaw .and. (cs%BBL_effic>0.0)))
return 1691 do_diag_kd_bbl =
associated(kd_bbl)
1694 if (cs%LOTW_BBL_use_omega) n2_min = (cs%omega**2)
1697 rayleigh_drag = .false.
1698 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) rayleigh_drag = .true.
1699 i_rho0 = 1.0/gv%Rho0
1700 cdrag_sqrt = sqrt(cs%cdrag)
1706 absf = 0.25*((abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) + &
1707 (abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))))
1710 ustar = visc%ustar_BBL(i,j)
1714 if (
ASSOCIATED(fluxes%ustar_tidal)) ustar = ustar + fluxes%ustar_tidal(i,j)
1718 idecay = cs%IMax_decay
1719 if ((ustar > 0.0) .and. (absf > cs%IMax_decay*ustar)) idecay = absf / ustar
1724 tke_column = cdrag_sqrt * visc%TKE_BBL(i,j)
1727 if (
ASSOCIATED(fluxes%TKE_tidal)) tke_column = tke_column + fluxes%TKE_tidal(i,j) * i_rho0
1728 tke_column = cs%BBL_effic * tke_column
1730 tke_remaining = tke_column
1731 total_thickness = ( sum(h(i,j,:)) + gv%H_subroundoff )* gv%H_to_m
1732 ustar_d = ustar * total_thickness
1739 dh = gv%H_to_m * h(i,j,k)
1741 dhm1 = gv%H_to_m * h(i,j,km1)
1744 if (rayleigh_drag) tke_remaining = tke_remaining + 0.5*cs%BBL_effic * g%IareaT(i,j) * &
1745 ((g%areaCu(i-1,j) * visc%Ray_u(i-1,j,k) * u(i-1,j,k)**2 + &
1746 g%areaCu(i,j) * visc%Ray_u(i,j,k) * u(i,j,k)**2) + &
1747 (g%areaCv(i,j-1) * visc%Ray_v(i,j-1,k) * v(i,j-1,k)**2 + &
1748 g%areaCv(i,j) * visc%Ray_v(i,j,k) * v(i,j,k)**2))
1752 tke_remaining = exp(-idecay*dh) * tke_remaining
1754 z = z + h(i,j,k)*gv%H_to_m
1755 d_minus_z = max(total_thickness - z, 0.)
1759 if ( ustar_d + absf * ( z * d_minus_z ) == 0.)
then 1762 kd_wall = ( ( von_karm * ustar2 ) * ( z * d_minus_z ) )/( ustar_d + absf * ( z * d_minus_z ) )
1767 tke_kd_wall = kd_wall * 0.5 * (dh + dhm1) * max(n2_int(i,k), n2_min)
1770 if (tke_kd_wall>0.)
then 1771 tke_consumed = min(tke_kd_wall, tke_remaining)
1772 kd_wall = (tke_consumed/tke_kd_wall) * kd_wall
1775 if (tke_remaining>0.)
then 1784 tke_remaining = tke_remaining - tke_consumed
1787 kd_int(i,j,k) = kd_int(i,j,k) + kd_wall
1788 kd(i,j,k) = kd(i,j,k) + 0.5*(kd_wall + kd_lower)
1790 if (do_diag_kd_bbl) kd_bbl(i,j,k) = kd_wall
1797 type(ocean_grid_type),
intent(in) :: G
1798 type(verticalgrid_type),
intent(in) :: GV
1799 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1800 type(forcing),
intent(in) :: fluxes
1801 integer,
intent(in) :: j
1803 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: Kd
1804 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd
1805 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
optional,
intent(inout) :: Kd_int
1809 real,
dimension(SZI_(G)) :: &
1815 real :: f_sq, h_ml_sq, ustar_sq, Kd_mlr, C1_6
1819 real :: I_decay_len2_TKE
1823 logical :: do_any, do_i(szi_(g))
1824 integer :: i, k, is, ie, nz, kml
1825 is = g%isc ; ie = g%iec ; nz = g%ke
1827 omega2 = cs%Omega**2
1830 h_neglect = gv%H_subroundoff*gv%H_to_m
1832 if (.not.cs%ML_radiation)
return 1834 do i=is,ie ; h_ml(i) = 0.0 ; do_i(i) = (g%mask2dT(i,j) > 0.5) ;
enddo 1835 do k=1,kml ;
do i=is,ie ; h_ml(i) = h_ml(i) + gv%H_to_m*h(i,j,k) ;
enddo ;
enddo 1837 do i=is,ie ;
if (do_i(i))
then 1838 if (cs%ML_omega_frac >= 1.0)
then 1841 f_sq = 0.25*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1842 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
1843 if (cs%ML_omega_frac > 0.0) &
1844 f_sq = cs%ML_omega_frac*4.0*omega2 + (1.0-cs%ML_omega_frac)*f_sq
1847 ustar_sq = max(fluxes%ustar(i,j), cs%ustar_min)**2
1849 tke_ml_flux(i) = (cs%mstar*cs%ML_rad_coeff)*(ustar_sq*fluxes%ustar(i,j))
1850 i_decay_len2_tke = cs%TKE_decay**2 * (f_sq / ustar_sq)
1852 if (cs%ML_rad_TKE_decay) &
1853 tke_ml_flux(i) = tke_ml_flux(i) * exp(-h_ml(i) * sqrt(i_decay_len2_tke))
1856 h_ml_sq = (cs%ML_rad_efold_coeff * (h_ml(i)+h_neglect))**2
1857 i_decay(i) = sqrt((i_decay_len2_tke * h_ml_sq + 1.0) / h_ml_sq)
1861 z1 = (gv%H_to_m*h(i,j,kml+1)) * i_decay(i)
1863 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,kml+1)) * &
1866 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,kml+1)) * &
1867 (z1 * (1.0 - z1 * (0.5 - c1_6*z1)))
1869 kd_mlr_ml(i) = min(kd_mlr,cs%ML_rad_kd_max)
1870 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1873 do k=1,kml+1 ;
do i=is,ie ;
if (do_i(i))
then 1874 kd(i,j,k) = kd(i,j,k) + kd_mlr_ml(i)
1875 endif ;
enddo ;
enddo 1876 if (
present(kd_int))
then 1877 do k=2,kml+1 ;
do i=is,ie ;
if (do_i(i))
then 1878 kd_int(i,j,k) = kd_int(i,j,k) + kd_mlr_ml(i)
1879 endif ;
enddo ;
enddo 1880 if (kml<=nz-1)
then ;
do i=is,ie ;
if (do_i(i))
then 1881 kd_int(i,j,kml+2) = kd_int(i,j,kml+2) + 0.5*kd_mlr_ml(i)
1882 endif ;
enddo ;
endif 1887 do i=is,ie ;
if (do_i(i))
then 1888 dzl = gv%H_to_m*h(i,j,k) ; z1 = dzl*i_decay(i)
1890 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1891 ((1.0 - exp(-z1)) / dzl)
1893 kd_mlr = (tke_ml_flux(i) * tke_to_kd(i,k)) * &
1894 (i_decay(i) * (1.0 - z1 * (0.5 - c1_6*z1)))
1896 kd_mlr = min(kd_mlr,cs%ML_rad_kd_max)
1897 kd(i,j,k) = kd(i,j,k) + kd_mlr
1898 if (
present(kd_int))
then 1899 kd_int(i,j,k) = kd_int(i,j,k) + 0.5*kd_mlr
1900 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5*kd_mlr
1903 tke_ml_flux(i) = tke_ml_flux(i) * exp(-z1)
1904 if (tke_ml_flux(i) * i_decay(i) < 0.1*cs%Kd_min*omega2)
then 1906 else ; do_any = .true. ;
endif 1908 if (.not.do_any)
exit 1920 dd, N2_lay, Kd, Kd_int )
1921 type(ocean_grid_type),
intent(in) :: G
1922 type(verticalgrid_type),
intent(in) :: GV
1923 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1924 real,
dimension(SZI_(G)),
intent(in) :: N2_bot
1925 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: N2_lay
1926 integer,
intent(in) :: j
1927 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: TKE_to_Kd, max_TKE
1930 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: Kd
1931 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
optional,
intent(inout) :: Kd_int
1940 real,
dimension(SZI_(G)) :: &
1961 tke_frac_top_lowmode, &
1968 real :: TKE_itide_lay
1969 real :: TKE_Niku_lay
1970 real :: TKE_lowmode_lay
1975 real :: TKE_lowmode_tot
1978 logical :: use_Polzin, use_Simmons
1979 integer :: i, k, is, ie, nz
1981 is = g%isc ; ie = g%iec ; nz = g%ke
1983 if (.not.(cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation))
return 1985 do i=is,ie ; htot(i) = 0.0 ; inv_int(i) = 0.0 ; inv_int_lee(i) = 0.0 ; inv_int_low(i) = 0.0 ;
enddo 1986 do k=1,nz ;
do i=is,ie
1987 htot(i) = htot(i) + gv%H_to_m*h(i,j,k)
1990 i_rho0 = 1.0/gv%Rho0
1992 use_polzin = ((cs%Int_tide_dissipation .and. (cs%int_tide_profile ==
polzin_09)) .or. &
1993 (cs%lee_wave_dissipation .and. (cs%lee_wave_profile ==
polzin_09)) .or. &
1994 (cs%Lowmode_itidal_dissipation .and. (cs%int_tide_profile ==
polzin_09)))
1995 use_simmons = ((cs%Int_tide_dissipation .and. (cs%int_tide_profile ==
stlaurent_02)) .or. &
1996 (cs%lee_wave_dissipation .and. (cs%lee_wave_profile ==
stlaurent_02)) .or. &
1997 (cs%Lowmode_itidal_dissipation .and. (cs%int_tide_profile ==
stlaurent_02)))
2001 if ( use_simmons )
then 2002 izeta = 1.0 / max(cs%Int_tide_decay_scale, gv%H_subroundoff*gv%H_to_m)
2003 izeta_lee = 1.0 / max(cs%Int_tide_decay_scale*cs%Decay_scale_factor_lee, &
2004 gv%H_subroundoff*gv%H_to_m)
2006 cs%Nb(i,j) = sqrt(n2_bot(i))
2007 if (
associated(dd%N2_bot)) dd%N2_bot(i,j) = n2_bot(i)
2008 if ( cs%Int_tide_dissipation )
then 2009 if (izeta*htot(i) > 1.0e-14)
then 2010 inv_int(i) = 1.0 / (1.0 - exp(-izeta*htot(i)))
2013 if ( cs%Lee_wave_dissipation )
then 2014 if (izeta_lee*htot(i) > 1.0e-14)
then 2015 inv_int_lee(i) = 1.0 / (1.0 - exp(-izeta_lee*htot(i)))
2018 if ( cs%Lowmode_itidal_dissipation)
then 2019 if (izeta*htot(i) > 1.0e-14)
then 2020 inv_int_low(i) = 1.0 / (1.0 - exp(-izeta*htot(i)))
2023 z_from_bot(i) = gv%H_to_m*h(i,j,nz)
2028 if ( use_polzin )
then 2030 do i=is,ie ; n2_meanz(i)=0.0 ;
enddo 2031 do k=1,nz ;
do i=is,ie
2032 n2_meanz(i) = n2_meanz(i) + n2_lay(i,k)*gv%H_to_m*h(i,j,k)
2035 n2_meanz(i) = n2_meanz(i) / (htot(i) + gv%H_subroundoff*gv%H_to_m)
2036 if (
associated(dd%N2_meanz)) dd%N2_meanz(i,j) = n2_meanz(i)
2040 do i=is,ie ; htot_wkb(i) = htot(i) ;
enddo 2048 cs%Nb(i,j) = sqrt(n2_bot(i))
2049 if ((cs%tideamp(i,j) > 0.0) .and. &
2050 (cs%kappa_itides**2 * cs%h2(i,j) * cs%Nb(i,j)**3 > 1.0e-14) )
then 2051 z0_polzin(i) = cs%Polzin_decay_scale_factor * cs%Nu_Polzin * &
2052 cs%Nbotref_Polzin**2 * cs%tideamp(i,j) / &
2053 ( cs%kappa_itides**2 * cs%h2(i,j) * cs%Nb(i,j)**3 )
2054 if (z0_polzin(i) < cs%Polzin_min_decay_scale) &
2055 z0_polzin(i) = cs%Polzin_min_decay_scale
2056 if (n2_meanz(i) > 1.0e-14 )
then 2057 z0_polzin_scaled(i) = z0_polzin(i)*cs%Nb(i,j)**2 / n2_meanz(i)
2059 z0_polzin_scaled(i) = cs%Polzin_decay_scale_max_factor * htot(i)
2061 if (z0_polzin_scaled(i) > (cs%Polzin_decay_scale_max_factor * htot(i)) ) &
2062 z0_polzin_scaled(i) = cs%Polzin_decay_scale_max_factor * htot(i)
2064 z0_polzin(i) = cs%Polzin_decay_scale_max_factor * htot(i)
2065 z0_polzin_scaled(i) = cs%Polzin_decay_scale_max_factor * htot(i)
2068 if (
associated(dd%Polzin_decay_scale)) &
2069 dd%Polzin_decay_scale(i,j) = z0_polzin(i)
2070 if (
associated(dd%Polzin_decay_scale_scaled)) &
2071 dd%Polzin_decay_scale_scaled(i,j) = z0_polzin_scaled(i)
2072 if (
associated(dd%N2_bot)) dd%N2_bot(i,j) = cs%Nb(i,j)*cs%Nb(i,j)
2074 if ( cs%Int_tide_dissipation .and. (cs%int_tide_profile ==
polzin_09) )
then 2077 if (htot_wkb(i) > 1.0e-14)
then 2078 inv_int(i) = ( z0_polzin_scaled(i) / htot_wkb(i) ) + 1
2081 if ( cs%lee_wave_dissipation .and. (cs%lee_wave_profile ==
polzin_09) )
then 2084 if (htot_wkb(i) > 1.0e-14)
then 2085 inv_int_lee(i) = ( z0_polzin_scaled(i)*cs%Decay_scale_factor_lee / htot_wkb(i) ) + 1
2088 if ( cs%Lowmode_itidal_dissipation .and. (cs%int_tide_profile ==
polzin_09) )
then 2091 if (htot_wkb(i) > 1.0e-14)
then 2092 inv_int_low(i) = ( z0_polzin_scaled(i) / htot_wkb(i) ) + 1
2096 z_from_bot(i) = gv%H_to_m*h(i,j,nz)
2099 if (n2_meanz(i) > 1.0e-14 )
then 2100 z_from_bot_wkb(i) = gv%H_to_m*h(i,j,nz)*n2_lay(i,nz) / n2_meanz(i)
2101 else ; z_from_bot_wkb(i) = 0 ;
endif 2109 tke_itidal_bot(i) = min(cs%TKE_itidal(i,j)*cs%Nb(i,j),cs%TKE_itide_max)
2110 if (
associated(dd%TKE_itidal_used)) &
2111 dd%TKE_itidal_used(i,j) = tke_itidal_bot(i)
2112 tke_itidal_bot(i) = (i_rho0 * cs%Mu_itides * cs%Gamma_itides) * tke_itidal_bot(i)
2114 tke_niku_bot(i) = 0.0
2115 if (cs%Lee_wave_dissipation)
then 2116 tke_niku_bot(i) = (i_rho0 * cs%Mu_itides * cs%Gamma_lee) * cs%TKE_Niku(i,j)
2119 tke_lowmode_tot = 0.0
2120 tke_lowmode_bot(i) = 0.0
2121 if (cs%Lowmode_itidal_dissipation)
then 2123 call get_lowmode_loss(i,j,g,cs%int_tide_CSp,
"WaveDrag",tke_lowmode_tot)
2124 tke_lowmode_bot(i) = cs%Mu_itides * i_rho0 * tke_lowmode_tot
2127 tke_itidal_rem(i) = inv_int(i) * tke_itidal_bot(i)
2128 tke_niku_rem(i) = inv_int_lee(i) * tke_niku_bot(i)
2129 tke_lowmode_rem(i) = inv_int_low(i) * tke_lowmode_bot(i)
2131 if (
associated(dd%Fl_itidal)) dd%Fl_itidal(i,j,nz) = tke_itidal_rem(i)
2136 if ( use_simmons )
then 2137 do k=nz-1,2,-1 ;
do i=is,ie
2138 if (max_tke(i,k) <= 0.0) cycle
2139 z_from_bot(i) = z_from_bot(i) + gv%H_to_m*h(i,j,k)
2142 tke_frac_top(i) = inv_int(i) * exp(-izeta * z_from_bot(i))
2143 tke_frac_top_lee(i) = inv_int_lee(i) * exp(-izeta_lee * z_from_bot(i))
2144 tke_frac_top_lowmode(i) = inv_int_low(i) * exp(-izeta * z_from_bot(i))
2148 tke_itide_lay = tke_itidal_rem(i) - tke_itidal_bot(i) * tke_frac_top(i)
2149 tke_niku_lay = tke_niku_rem(i) - tke_niku_bot(i) * tke_frac_top_lee(i)
2150 tke_lowmode_lay = tke_lowmode_rem(i) - tke_lowmode_bot(i)* tke_frac_top_lowmode(i)
2153 if (tke_itide_lay + tke_niku_lay + tke_lowmode_lay > max_tke(i,k))
then 2154 frac_used = max_tke(i,k) / (tke_itide_lay + tke_niku_lay + tke_lowmode_lay)
2155 tke_itide_lay = frac_used * tke_itide_lay
2156 tke_niku_lay = frac_used * tke_niku_lay
2157 tke_lowmode_lay = frac_used * tke_lowmode_lay
2161 tke_itidal_rem(i) = tke_itidal_rem(i) - tke_itide_lay
2162 tke_niku_rem(i) = tke_niku_rem(i) - tke_niku_lay
2163 tke_lowmode_rem(i) = tke_lowmode_rem(i) - tke_lowmode_lay
2166 kd_add = tke_to_kd(i,k) * (tke_itide_lay + tke_niku_lay + tke_lowmode_lay)
2168 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2169 kd(i,j,k) = kd(i,j,k) + kd_add
2171 if (
present(kd_int))
then 2172 kd_int(i,j,k) = kd_int(i,j,k) + 0.5*kd_add
2173 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5*kd_add
2177 if (
associated(dd%Kd_itidal))
then 2180 kd_add = tke_to_kd(i,k) * tke_itide_lay
2181 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2182 if (k>1) dd%Kd_itidal(i,j,k) = dd%Kd_itidal(i,j,k) + 0.5*kd_add
2183 if (k<nz) dd%Kd_itidal(i,j,k+1) = dd%Kd_itidal(i,j,k+1) + 0.5*kd_add
2185 if (
associated(dd%Kd_Itidal_work)) &
2186 dd%Kd_itidal_work(i,j,k) = gv%Rho0 * tke_itide_lay
2187 if (
associated(dd%Fl_itidal)) dd%Fl_itidal(i,j,k) = tke_itidal_rem(i)
2189 if (
associated(dd%Kd_Niku))
then 2192 kd_add = tke_to_kd(i,k) * tke_niku_lay
2193 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2194 if (k>1) dd%Kd_Niku(i,j,k) = dd%Kd_Niku(i,j,k) + 0.5*kd_add
2195 if (k<nz) dd%Kd_Niku(i,j,k+1) = dd%Kd_Niku(i,j,k+1) + 0.5*kd_add
2198 if (
associated(dd%Kd_Niku_work)) &
2199 dd%Kd_Niku_work(i,j,k) = gv%Rho0 * tke_niku_lay
2201 if (
associated(dd%Kd_lowmode))
then 2204 kd_add = tke_to_kd(i,k) * tke_lowmode_lay
2205 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2206 if (k>1) dd%Kd_lowmode(i,j,k) = dd%Kd_lowmode(i,j,k) + 0.5*kd_add
2207 if (k<nz) dd%Kd_lowmode(i,j,k+1) = dd%Kd_lowmode(i,j,k+1) + 0.5*kd_add
2209 if (
associated(dd%Kd_lowmode_work)) &
2210 dd%Kd_lowmode_work(i,j,k) = gv%Rho0 * tke_lowmode_lay
2211 if (
associated(dd%Fl_lowmode)) dd%Fl_lowmode(i,j,k) = tke_lowmode_rem(i)
2217 if ( use_polzin )
then 2218 do k=nz-1,2,-1 ;
do i=is,ie
2219 if (max_tke(i,k) <= 0.0) cycle
2220 z_from_bot(i) = z_from_bot(i) + gv%H_to_m*h(i,j,k)
2221 if (n2_meanz(i) > 1.0e-14 )
then 2222 z_from_bot_wkb(i) = z_from_bot_wkb(i) + gv%H_to_m*h(i,j,k)*n2_lay(i,k)/n2_meanz(i)
2223 else ; z_from_bot_wkb(i) = 0 ;
endif 2226 tke_frac_top(i) = ( inv_int(i) * z0_polzin_scaled(i) ) / &
2227 ( z0_polzin_scaled(i) + z_from_bot_wkb(i) )
2228 z0_psl = z0_polzin_scaled(i)*cs%Decay_scale_factor_lee
2229 tke_frac_top_lee(i) = (inv_int_lee(i) * z0_psl) / (z0_psl + z_from_bot_wkb(i))
2230 tke_frac_top_lowmode(i) = ( inv_int_low(i) * z0_polzin_scaled(i) ) / &
2231 ( z0_polzin_scaled(i) + z_from_bot_wkb(i) )
2235 tke_itide_lay = tke_itidal_rem(i) - tke_itidal_bot(i) *tke_frac_top(i)
2236 tke_niku_lay = tke_niku_rem(i) - tke_niku_bot(i) * tke_frac_top_lee(i)
2237 tke_lowmode_lay = tke_lowmode_rem(i) - tke_lowmode_bot(i)*tke_frac_top_lowmode(i)
2240 if (tke_itide_lay + tke_niku_lay + tke_lowmode_lay > max_tke(i,k))
then 2241 frac_used = max_tke(i,k) / (tke_itide_lay + tke_niku_lay + tke_lowmode_lay)
2242 tke_itide_lay = frac_used * tke_itide_lay
2243 tke_niku_lay = frac_used * tke_niku_lay
2244 tke_lowmode_lay = frac_used * tke_lowmode_lay
2248 tke_itidal_rem(i) = tke_itidal_rem(i) - tke_itide_lay
2249 tke_niku_rem(i) = tke_niku_rem(i) - tke_niku_lay
2250 tke_lowmode_rem(i) = tke_lowmode_rem(i) - tke_lowmode_lay
2253 kd_add = tke_to_kd(i,k) * (tke_itide_lay + tke_niku_lay + tke_lowmode_lay)
2255 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2256 kd(i,j,k) = kd(i,j,k) + kd_add
2258 if (
present(kd_int))
then 2259 kd_int(i,j,k) = kd_int(i,j,k) + 0.5*kd_add
2260 kd_int(i,j,k+1) = kd_int(i,j,k+1) + 0.5*kd_add
2264 if (
associated(dd%Kd_itidal))
then 2267 kd_add = tke_to_kd(i,k) * tke_itide_lay
2268 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2269 if (k>1) dd%Kd_itidal(i,j,k) = dd%Kd_itidal(i,j,k) + 0.5*kd_add
2270 if (k<nz) dd%Kd_itidal(i,j,k+1) = dd%Kd_itidal(i,j,k+1) + 0.5*kd_add
2272 if (
associated(dd%Kd_Itidal_work)) &
2273 dd%Kd_itidal_work(i,j,k) = gv%Rho0 * tke_itide_lay
2274 if (
associated(dd%Fl_itidal)) dd%Fl_itidal(i,j,k) = tke_itidal_rem(i)
2276 if (
associated(dd%Kd_Niku))
then 2279 kd_add = tke_to_kd(i,k) * tke_niku_lay
2280 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2281 if (k>1) dd%Kd_Niku(i,j,k) = dd%Kd_Niku(i,j,k) + 0.5*kd_add
2282 if (k<nz) dd%Kd_Niku(i,j,k+1) = dd%Kd_Niku(i,j,k+1) + 0.5*kd_add
2285 if (
associated(dd%Kd_Niku_work)) dd%Kd_Niku_work(i,j,k) = gv%Rho0 * tke_niku_lay
2287 if (
associated(dd%Kd_lowmode))
then 2290 kd_add = tke_to_kd(i,k) * tke_lowmode_lay
2291 if (cs%Kd_max >= 0.0) kd_add = min(kd_add, cs%Kd_max)
2292 if (k>1) dd%Kd_lowmode(i,j,k) = dd%Kd_lowmode(i,j,k) + 0.5*kd_add
2293 if (k<nz) dd%Kd_lowmode(i,j,k+1) = dd%Kd_lowmode(i,j,k+1) + 0.5*kd_add
2295 if (
associated(dd%Kd_lowmode_work)) &
2296 dd%Kd_lowmode_work(i,j,k) = gv%Rho0 * tke_lowmode_lay
2297 if (
associated(dd%Fl_lowmode)) dd%Fl_lowmode(i,j,k) = tke_lowmode_rem(i)
2305 subroutine set_bbl_tke(u, v, h, fluxes, visc, G, GV, CS)
2306 type(ocean_grid_type),
intent(in) :: G
2307 type(verticalgrid_type),
intent(in) :: GV
2308 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
2309 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
2310 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
2311 type(forcing),
intent(in) :: fluxes
2312 type(vertvisc_type),
intent(inout) :: visc
2318 real,
dimension(SZI_(G)) :: &
2322 real,
dimension(SZIB_(G)) :: &
2327 real :: vhtot(szi_(g))
2329 real,
dimension(SZI_(G),SZJB_(G)) :: &
2336 logical :: domore, do_i(szi_(g))
2337 integer :: i, j, k, is, ie, js, je, nz
2338 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
2340 if (.not.
associated(cs))
call mom_error(fatal,
"set_BBL_TKE: "//&
2341 "Module must be initialized before it is used.")
2343 if (.not.cs%bottomdraglaw .or. (cs%BBL_effic<=0.0))
then 2344 if (
associated(visc%ustar_BBL))
then 2345 do j=js,je ;
do i=is,ie ; visc%ustar_BBL(i,j) = 0.0 ;
enddo ;
enddo 2347 if (
associated(visc%TKE_BBL))
then 2348 do j=js,je ;
do i=is,ie ; visc%TKE_BBL(i,j) = 0.0 ;
enddo ;
enddo 2353 cdrag_sqrt = sqrt(cs%cdrag)
2363 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_v(i,j) > 0.0))
then 2364 do_i(i) = .true. ; vhtot(i) = 0.0 ; htot(i) = 0.0
2365 vstar(i,j) = visc%kv_bbl_v(i,j)/(cdrag_sqrt*visc%bbl_thick_v(i,j))
2367 do_i(i) = .false. ; vstar(i,j) = 0.0 ; htot(i) = 0.0
2371 do i=is,ie ;
if (do_i(i))
then 2372 hvel = 0.5*gv%H_to_m*(h(i,j,k) + h(i,j+1,k))
2373 if ((htot(i) + hvel) >= visc%bbl_thick_v(i,j))
then 2374 vhtot(i) = vhtot(i) + (visc%bbl_thick_v(i,j) - htot(i))*v(i,j,k)
2375 htot(i) = visc%bbl_thick_v(i,j)
2378 vhtot(i) = vhtot(i) + hvel*v(i,j,k)
2379 htot(i) = htot(i) + hvel
2383 if (.not.domore)
exit 2385 do i=is,ie ;
if ((g%mask2dCv(i,j) > 0.5) .and. (htot(i) > 0.0))
then 2386 v2_bbl(i,j) = (vhtot(i)*vhtot(i))/(htot(i)*htot(i))
2393 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (cdrag_sqrt*visc%bbl_thick_u(i,j) > 0.0))
then 2394 do_i(i) = .true. ; uhtot(i) = 0.0 ; htot(i) = 0.0
2395 ustar(i) = visc%kv_bbl_u(i,j)/(cdrag_sqrt*visc%bbl_thick_u(i,j))
2397 do_i(i) = .false. ; ustar(i) = 0.0 ; htot(i) = 0.0
2399 do k=nz,1,-1 ; domore = .false.
2400 do i=is-1,ie ;
if (do_i(i))
then 2401 hvel = 0.5*gv%H_to_m*(h(i,j,k) + h(i+1,j,k))
2402 if ((htot(i) + hvel) >= visc%bbl_thick_u(i,j))
then 2403 uhtot(i) = uhtot(i) + (visc%bbl_thick_u(i,j) - htot(i))*u(i,j,k)
2404 htot(i) = visc%bbl_thick_u(i,j)
2407 uhtot(i) = uhtot(i) + hvel*u(i,j,k)
2408 htot(i) = htot(i) + hvel
2412 if (.not.domore)
exit 2414 do i=is-1,ie ;
if ((g%mask2dCu(i,j) > 0.5) .and. (htot(i) > 0.0))
then 2415 u2_bbl(i) = (uhtot(i)*uhtot(i))/(htot(i)*htot(i))
2421 visc%ustar_BBL(i,j) = sqrt(0.5*g%IareaT(i,j) * &
2422 ((g%areaCu(i-1,j)*(ustar(i-1)*ustar(i-1)) + &
2423 g%areaCu(i,j)*(ustar(i)*ustar(i))) + &
2424 (g%areaCv(i,j-1)*(vstar(i,j-1)*vstar(i,j-1)) + &
2425 g%areaCv(i,j)*(vstar(i,j)*vstar(i,j))) ) )
2426 visc%TKE_BBL(i,j) = (((g%areaCu(i-1,j)*(ustar(i-1)*u2_bbl(i-1)) + &
2427 g%areaCu(i,j) * (ustar(i)*u2_bbl(i))) + &
2428 (g%areaCv(i,j-1)*(vstar(i,j-1)*v2_bbl(i,j-1)) + &
2429 g%areaCv(i,j) * (vstar(i,j)*v2_bbl(i,j))))*g%IareaT(i,j))
2437 type(ocean_grid_type),
intent(in) :: G
2438 type(verticalgrid_type),
intent(in) :: GV
2439 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
2442 type(thermo_var_ptrs),
intent(in) :: tv
2445 integer,
dimension(SZI_(G)),
intent(in) :: kb
2449 integer,
intent(in) :: j
2450 real,
dimension(SZI_(G),SZK_(G)),
intent(out) :: ds_dsp1
2454 real,
dimension(SZI_(G),SZK_(G)), &
2455 optional,
intent(in) :: rho_0
2474 real :: a(szk_(g)), a_0(szk_(g))
2475 real :: p_ref(szi_(g))
2476 real :: Rcv(szi_(g),szk_(g))
2479 integer :: i, k, k3, is, ie, nz, kmb
2480 is = g%isc ; ie = g%iec ; nz = g%ke
2483 if (gv%g_prime(k+1)/=0.)
then 2485 ds_dsp1(i,k) = gv%g_prime(k) / gv%g_prime(k+1)
2494 if (cs%bulkmixedlayer)
then 2495 g_r0 = gv%g_Earth/gv%Rho0
2496 kmb = gv%nk_rho_varies
2498 do i=is,ie ; p_ref(i) = tv%P_Ref ;
enddo 2500 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p_ref,rcv(:,k),&
2501 is,ie-is+1,tv%eqn_of_state)
2504 if (kb(i) <= nz-1)
then 2509 i_drho = g_r0 / gv%g_prime(k+1)
2512 a(k3+1) = (gv%Rlay(k) - rcv(i,k3)) * i_drho
2514 if ((
present(rho_0)) .and. (a(kmb+1) < 2.0*eps*ds_dsp1(i,k)))
then 2518 if ((rho_0(i,k) > rho_0(i,kmb)) .and. &
2519 (rho_0(i,k+1) > rho_0(i,k)))
then 2520 i_drho = 1.0 / (rho_0(i,k+1)-rho_0(i,k))
2521 a_0(kmb+1) = min((rho_0(i,k)-rho_0(i,kmb)) * i_drho, ds_dsp1(i,k))
2522 if (a_0(kmb+1) > a(kmb+1))
then 2524 a_0(k3) = a_0(kmb+1) + (rho_0(i,kmb)-rho_0(i,k3-1)) * i_drho
2526 if (a(kmb+1) <= eps*ds_dsp1(i,k))
then 2527 do k3=2,kmb+1 ; a(k3) = a_0(k3) ;
enddo 2530 tmp = a(kmb+1)/(eps*ds_dsp1(i,k)) - 1.0
2531 do k3=2,kmb+1 ; a(k3) = tmp*a(k3) + (1.0-tmp)*a_0(k3) ;
enddo 2537 ds_dsp1(i,k) = max(a(kmb+1),1e-5)
2546 ds_dsp1(i,k3) = max(a(k3),ds_dsp1(i,k))
2554 subroutine set_diffusivity_init(Time, G, GV, param_file, diag, CS, diag_to_Z_CSp, int_tide_CSp)
2555 type(time_type),
intent(in) :: Time
2556 type(ocean_grid_type),
intent(inout) :: G
2557 type(verticalgrid_type),
intent(in) :: GV
2558 type(param_file_type),
intent(in) :: param_file
2560 type(diag_ctrl),
target,
intent(inout) :: diag
2563 type(diag_to_z_cs),
pointer :: diag_to_Z_CSp
2565 type(int_tide_cs),
pointer :: int_tide_CSp
2578 real :: decay_length, utide, zbot, hamp
2580 logical :: read_tideamp, ML_use_omega
2582 #include "version_variable.h" 2583 character(len=40) :: mdl =
"MOM_set_diffusivity" 2584 character(len=20) :: tmpstr
2585 character(len=200) :: filename, tideamp_file, h2_file, Niku_TKE_input_file
2587 real :: omega_frac_dflt
2588 integer :: i, j, is, ie, js, je
2589 integer :: isd, ied, jsd, jed
2591 if (
associated(cs))
then 2592 call mom_error(warning,
"diabatic_entrain_init called with an associated "// &
2593 "control structure.")
2598 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2599 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2602 if (
associated(int_tide_csp)) cs%int_tide_CSp => int_tide_csp
2603 if (
associated(diag_to_z_csp)) cs%diag_to_Z_CSp => diag_to_z_csp
2606 cs%BBL_mixing_as_max = .true.
2607 cs%Kdml = 0.0 ; cs%cdrag = 0.003 ; cs%BBL_effic = 0.0 ;
2608 cs%bulkmixedlayer = (gv%nkml > 0)
2612 call log_version(param_file, mdl, version,
"")
2614 call get_param(param_file, mdl,
"INPUTDIR", cs%inputdir, default=
".")
2615 cs%inputdir = slasher(cs%inputdir)
2616 call get_param(param_file, mdl,
"FLUX_RI_MAX", cs%FluxRi_max, &
2617 "The flux Richardson number where the stratification is \n"//&
2618 "large enough that N2 > omega2. The full expression for \n"//&
2619 "the Flux Richardson number is usually \n"//&
2620 "FLUX_RI_MAX*N2/(N2+OMEGA2).", default=0.2)
2621 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
2622 "The rotation rate of the earth.", units=
"s-1", &
2625 call get_param(param_file, mdl,
"ML_RADIATION", cs%ML_radiation, &
2626 "If true, allow a fraction of TKE available from wind \n"//&
2627 "work to penetrate below the base of the mixed layer \n"//&
2628 "with a vertical decay scale determined by the minimum \n"//&
2629 "of: (1) The depth of the mixed layer, (2) an Ekman \n"//&
2630 "length scale.", default=.false.)
2631 if (cs%ML_radiation)
then 2633 cs%ustar_min = 2e-4*cs%omega*(gv%Angstrom + gv%H_subroundoff)
2635 call get_param(param_file, mdl,
"ML_RAD_EFOLD_COEFF", cs%ML_rad_efold_coeff, &
2636 "A coefficient that is used to scale the penetration \n"//&
2637 "depth for turbulence below the base of the mixed layer. \n"//&
2638 "This is only used if ML_RADIATION is true.", units=
"nondim", &
2640 call get_param(param_file, mdl,
"ML_RAD_KD_MAX", cs%ML_rad_kd_max, &
2641 "The maximum diapycnal diffusivity due to turbulence \n"//&
2642 "radiated from the base of the mixed layer. \n"//&
2643 "This is only used if ML_RADIATION is true.", units=
"m2 s-1", &
2645 call get_param(param_file, mdl,
"ML_RAD_COEFF", cs%ML_rad_coeff, &
2646 "The coefficient which scales MSTAR*USTAR^3 to obtain \n"//&
2647 "the energy available for mixing below the base of the \n"//&
2648 "mixed layer. This is only used if ML_RADIATION is true.", &
2649 units=
"nondim", default=0.2)
2650 call get_param(param_file, mdl,
"ML_RAD_APPLY_TKE_DECAY", cs%ML_rad_TKE_decay, &
2651 "If true, apply the same exponential decay to ML_rad as \n"//&
2652 "is applied to the other surface sources of TKE in the \n"//&
2653 "mixed layer code. This is only used if ML_RADIATION is true.",&
2655 call get_param(param_file, mdl,
"MSTAR", cs%mstar, &
2656 "The ratio of the friction velocity cubed to the TKE \n"//&
2657 "input to the mixed layer.",
"units=nondim", default=1.2)
2658 call get_param(param_file, mdl,
"TKE_DECAY", cs%TKE_decay, &
2659 "The ratio of the natural Ekman depth to the TKE decay scale.", &
2660 units=
"nondim", default=2.5)
2661 call get_param(param_file, mdl,
"ML_USE_OMEGA", ml_use_omega, &
2662 "If true, use the absolute rotation rate instead of the \n"//&
2663 "vertical component of rotation when setting the decay \n"//&
2664 "scale for turbulence.", default=.false., do_not_log=.true.)
2665 omega_frac_dflt = 0.0
2666 if (ml_use_omega)
then 2667 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
2668 omega_frac_dflt = 1.0
2670 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%ML_omega_frac, &
2671 "When setting the decay scale for turbulence, use this \n"//&
2672 "fraction of the absolute rotation rate blended with the \n"//&
2673 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
2674 units=
"nondim", default=omega_frac_dflt)
2677 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
2678 "If true, the bottom stress is calculated with a drag \n"//&
2679 "law of the form c_drag*|u|*u. The velocity magnitude \n"//&
2680 "may be an assumed value or it may be based on the \n"//&
2681 "actual velocity in the bottommost HBBL, depending on \n"//&
2682 "LINEAR_DRAG.", default=.true.)
2683 if (cs%bottomdraglaw)
then 2684 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
2685 "The drag coefficient relating the magnitude of the \n"//&
2686 "velocity field to the bottom stress. CDRAG is only used \n"//&
2687 "if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.003)
2688 call get_param(param_file, mdl,
"BBL_EFFIC", cs%BBL_effic, &
2689 "The efficiency with which the energy extracted by \n"//&
2690 "bottom drag drives BBL diffusion. This is only \n"//&
2691 "used if BOTTOMDRAGLAW is true.", units=
"nondim", default=0.20)
2692 call get_param(param_file, mdl,
"BBL_MIXING_MAX_DECAY", decay_length, &
2693 "The maximum decay scale for the BBL diffusion, or 0 \n"//&
2694 "to allow the mixing to penetrate as far as \n"//&
2695 "stratification and rotation permit. The default is 0. \n"//&
2696 "This is only used if BOTTOMDRAGLAW is true.", units=
"m", &
2699 cs%IMax_decay = 1.0/200.0
2700 if (decay_length > 0.0) cs%IMax_decay = 1.0/decay_length
2701 call get_param(param_file, mdl,
"BBL_MIXING_AS_MAX", cs%BBL_mixing_as_max, &
2702 "If true, take the maximum of the diffusivity from the \n"//&
2703 "BBL mixing and the other diffusivities. Otherwise, \n"//&
2704 "diffusiviy from the BBL_mixing is simply added.", &
2706 call get_param(param_file, mdl,
"USE_LOTW_BBL_DIFFUSIVITY", cs%use_LOTW_BBL_diffusivity, &
2707 "If true, uses a simple, imprecise but non-coordinate dependent, model\n"//&
2708 "of BBL mixing diffusivity based on Law of the Wall. Otherwise, uses\n"//&
2709 "the original BBL scheme.", default=.false.)
2710 if (cs%use_LOTW_BBL_diffusivity)
then 2711 call get_param(param_file, mdl,
"LOTW_BBL_USE_OMEGA", cs%LOTW_BBL_use_omega, &
2712 "If true, use the maximum of Omega and N for the TKE to diffusion\n"//&
2713 "calculation. Otherwise, N is N.", default=.true.)
2716 cs%use_LOTW_BBL_diffusivity = .false.
2718 cs%id_Kd_BBL = register_diag_field(
'ocean_model',
'Kd_BBL',diag%axesTi,time, &
2719 'Bottom Boundary Layer Diffusivity',
'meter2 sec-1')
2720 call get_param(param_file, mdl,
"SIMPLE_TKE_TO_KD", cs%simple_TKE_to_Kd, &
2721 "If true, uses a simple estimate of Kd/TKE that will\n"//&
2722 "work for arbitrary vertical coordinates. If false,\n"//&
2723 "calculates Kd/TKE and bounds based on exact energetics/n"//&
2724 "for an isopycnal layer-formulation.", &
2727 call get_param(param_file, mdl,
"BRYAN_LEWIS_DIFFUSIVITY", &
2728 cs%Bryan_Lewis_diffusivity, &
2729 "If true, use a Bryan & Lewis (JGR 1979) like tanh \n"//&
2730 "profile of background diapycnal diffusivity with depth.", &
2732 if (cs%Bryan_Lewis_diffusivity)
then 2733 call get_param(param_file, mdl,
"KD_BRYAN_LEWIS_DEEP", &
2734 cs%Kd_Bryan_Lewis_deep, &
2735 "The abyssal value of a Bryan-Lewis diffusivity profile. \n"//&
2736 "KD_BRYAN_LEWIS_DEEP is only used if \n"//&
2737 "BRYAN_LEWIS_DIFFUSIVITY is true.", units=
"m2 s-1", &
2738 fail_if_missing=.true.)
2739 call get_param(param_file, mdl,
"KD_BRYAN_LEWIS_SURFACE", &
2740 cs%Kd_Bryan_Lewis_surface, &
2741 "The surface value of a Bryan-Lewis diffusivity profile. \n"//&
2742 "KD_BRYAN_LEWIS_SURFACE is only used if \n"//&
2743 "BRYAN_LEWIS_DIFFUSIVITY is true.", units=
"m2 s-1", &
2744 fail_if_missing=.true.)
2745 call get_param(param_file, mdl,
"BRYAN_LEWIS_DEPTH_CENT", &
2746 cs%Bryan_Lewis_depth_cent, &
2747 "The depth about which the transition in the Bryan-Lewis \n"//&
2748 "profile is centered. BRYAN_LEWIS_DEPTH_CENT is only \n"//&
2749 "used if BRYAN_LEWIS_DIFFUSIVITY is true.", units=
"m", &
2750 fail_if_missing=.true.)
2751 call get_param(param_file, mdl,
"BRYAN_LEWIS_WIDTH_TRANS", &
2752 cs%Bryan_Lewis_width_trans, &
2753 "The width of the transition in the Bryan-Lewis \n"//&
2754 "profile. BRYAN_LEWIS_WIDTH_TRANS is only \n"//&
2755 "used if BRYAN_LEWIS_DIFFUSIVITY is true.", units=
"m", &
2756 fail_if_missing=.true.)
2759 call get_param(param_file, mdl,
"HENYEY_IGW_BACKGROUND", &
2760 cs%Henyey_IGW_background, &
2761 "If true, use a latitude-dependent scaling for the near \n"//&
2762 "surface background diffusivity, as described in \n"//&
2763 "Harrison & Hallberg, JPO 2008.", default=.false.)
2764 call get_param(param_file, mdl,
"HENYEY_IGW_BACKGROUND_NEW", &
2765 cs%Henyey_IGW_background_new, &
2766 "If true, use a better latitude-dependent scaling for the\n"//&
2767 "background diffusivity, as described in \n"//&
2768 "Harrison & Hallberg, JPO 2008.", default=.false.)
2769 if (cs%Henyey_IGW_background .and. cs%Henyey_IGW_background_new)
call mom_error(fatal, &
2770 "set_diffusivity_init: HENYEY_IGW_BACKGROUND and HENYEY_IGW_BACKGROUND_NEW "// &
2771 "are mutually exclusive. Set only one or none.")
2772 if (cs%Henyey_IGW_background) &
2773 call get_param(param_file, mdl,
"HENYEY_N0_2OMEGA", cs%N0_2Omega, &
2774 "The ratio of the typical Buoyancy frequency to twice \n"//&
2775 "the Earth's rotation period, used with the Henyey \n"//&
2776 "scaling from the mixing.", units=
"nondim", default=20.0)
2777 call get_param(param_file, mdl,
"N2_FLOOR_IOMEGA2", cs%N2_FLOOR_IOMEGA2, &
2778 "The floor applied to N2(k) scaled by Omega^2:\n"//&
2779 "\tIf =0., N2(k) is simply positive definite.\n"//&
2780 "\tIf =1., N2(k) > Omega^2 everywhere.", units=
"nondim", &
2783 call get_param(param_file, mdl,
"KD_TANH_LAT_FN", &
2784 cs%Kd_tanh_lat_fn, &
2785 "If true, use a tanh dependence of Kd_sfc on latitude, \n"//&
2786 "like CM2.1/CM2M. There is no physical justification \n"//&
2787 "for this form, and it can not be used with \n"//&
2788 "HENYEY_IGW_BACKGROUND.", default=.false.)
2789 if (cs%Kd_tanh_lat_fn) &
2790 call get_param(param_file, mdl,
"KD_TANH_LAT_SCALE", &
2791 cs%Kd_tanh_lat_scale, &
2792 "A nondimensional scaling for the range ofdiffusivities \n"//&
2793 "with KD_TANH_LAT_FN. Valid values are in the range of \n"//&
2794 "-2 to 2; 0.4 reproduces CM2M.", units=
"nondim", default=0.0)
2796 call get_param(param_file, mdl,
"KV", cs%Kv, &
2797 "The background kinematic viscosity in the interior. \n"//&
2798 "The molecular value, ~1e-6 m2 s-1, may be used.", &
2799 units=
"m2 s-1", fail_if_missing=.true.)
2801 call get_param(param_file, mdl,
"KD", cs%Kd, &
2802 "The background diapycnal diffusivity of density in the \n"//&
2803 "interior. Zero or the molecular value, ~1e-7 m2 s-1, \n"//&
2804 "may be used.", units=
"m2 s-1", fail_if_missing=.true.)
2805 call get_param(param_file, mdl,
"KD_MIN", cs%Kd_min, &
2806 "The minimum diapycnal diffusivity.", &
2807 units=
"m2 s-1", default=0.01*cs%Kd)
2808 call get_param(param_file, mdl,
"KD_MAX", cs%Kd_max, &
2809 "The maximum permitted increment for the diapycnal \n"//&
2810 "diffusivity from TKE-based parameterizations, or a \n"//&
2811 "negative value for no limit.", units=
"m2 s-1", default=-1.0)
2812 if (cs%simple_TKE_to_Kd .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2813 "set_diffusivity_init: To use SIMPLE_TKE_TO_KD, KD_MAX must be set to >0.")
2814 call get_param(param_file, mdl,
"KD_ADD", cs%Kd_add, &
2815 "A uniform diapycnal diffusivity that is added \n"//&
2816 "everywhere without any filtering or scaling.", &
2817 units=
"m2 s-1", default=0.0)
2818 if (cs%use_LOTW_BBL_diffusivity .and. cs%Kd_max<=0.)
call mom_error(fatal, &
2819 "set_diffusivity_init: KD_MAX must be set (positive) when "// &
2820 "USE_LOTW_BBL_DIFFUSIVITY=True.")
2822 if (cs%bulkmixedlayer)
then 2824 call get_param(param_file, mdl,
"KDML", cs%Kdml, default=-1.)
2825 if (cs%Kdml>0.)
call mom_error(fatal, &
2826 "set_diffusivity_init: KDML cannot be set when using"// &
2827 "bulk mixed layer.")
2831 call get_param(param_file, mdl,
"KDML", cs%Kdml, &
2832 "If BULKMIXEDLAYER is false, KDML is the elevated \n"//&
2833 "diapycnal diffusivity in the topmost HMIX of fluid. \n"//&
2834 "KDML is only used if BULKMIXEDLAYER is false.", &
2835 units=
"m2 s-1", default=cs%Kd)
2836 call get_param(param_file, mdl,
"HMIX_FIXED", cs%Hmix, &
2837 "The prescribed depth over which the near-surface \n"//&
2838 "viscosity and diffusivity are elevated when the bulk \n"//&
2839 "mixed layer is not used.", units=
"m", fail_if_missing=.true.)
2841 call get_param(param_file, mdl,
"DEBUG", cs%debug, &
2842 "If true, write out verbose debugging data.", default=.false.)
2844 call get_param(param_file, mdl,
"INT_TIDE_DISSIPATION", cs%Int_tide_dissipation, &
2845 "If true, use an internal tidal dissipation scheme to \n"//&
2846 "drive diapycnal mixing, along the lines of St. Laurent \n"//&
2847 "et al. (2002) and Simmons et al. (2004).", default=.false.)
2848 if (cs%Int_tide_dissipation)
then 2849 call get_param(param_file, mdl,
"INT_TIDE_PROFILE", tmpstr, &
2850 "INT_TIDE_PROFILE selects the vertical profile of energy \n"//&
2851 "dissipation with INT_TIDE_DISSIPATION. Valid values are:\n"//&
2852 "\t STLAURENT_02 - Use the St. Laurent et al exponential \n"//&
2853 "\t decay profile.\n"//&
2854 "\t POLZIN_09 - Use the Polzin WKB-streched algebraic \n"//&
2855 "\t decay profile.", &
2857 tmpstr = uppercase(tmpstr)
2858 select case (tmpstr)
2862 call mom_error(fatal,
"set_diffusivity_init: Unrecognized setting "// &
2863 "#define INT_TIDE_PROFILE "//trim(tmpstr)//
" found in input file.")
2867 call get_param(param_file, mdl,
"LEE_WAVE_DISSIPATION", cs%Lee_wave_dissipation, &
2868 "If true, use an lee wave driven dissipation scheme to \n"//&
2869 "drive diapycnal mixing, along the lines of Nikurashin \n"//&
2870 "(2010) and using the St. Laurent et al. (2002) \n"//&
2871 "and Simmons et al. (2004) vertical profile", default=.false.)
2872 if (cs%lee_wave_dissipation)
then 2873 call get_param(param_file, mdl,
"LEE_WAVE_PROFILE", tmpstr, &
2874 "LEE_WAVE_PROFILE selects the vertical profile of energy \n"//&
2875 "dissipation with LEE_WAVE_DISSIPATION. Valid values are:\n"//&
2876 "\t STLAURENT_02 - Use the St. Laurent et al exponential \n"//&
2877 "\t decay profile.\n"//&
2878 "\t POLZIN_09 - Use the Polzin WKB-streched algebraic \n"//&
2879 "\t decay profile.", &
2881 tmpstr = uppercase(tmpstr)
2882 select case (tmpstr)
2886 call mom_error(fatal,
"set_diffusivity_init: Unrecognized setting "// &
2887 "#define LEE_WAVE_PROFILE "//trim(tmpstr)//
" found in input file.")
2891 call get_param(param_file, mdl,
"INT_TIDE_LOWMODE_DISSIPATION", cs%Lowmode_itidal_dissipation, &
2892 "If true, consider mixing due to breaking low modes that \n"//&
2893 "have been remotely generated; as with itidal drag on the \n"//&
2894 "barotropic tide, use an internal tidal dissipation scheme to \n"//&
2895 "drive diapycnal mixing, along the lines of St. Laurent \n"//&
2896 "et al. (2002) and Simmons et al. (2004).", default=.false.)
2898 if ((cs%Int_tide_dissipation .and. (cs%int_tide_profile ==
polzin_09)) .or. &
2899 (cs%lee_wave_dissipation .and. (cs%lee_wave_profile ==
polzin_09)))
then 2900 call get_param(param_file, mdl,
"NU_POLZIN", cs%Nu_Polzin, &
2901 "When the Polzin decay profile is used, this is a \n"//&
2902 "non-dimensional constant in the expression for the \n"//&
2903 "vertical scale of decay for the tidal energy dissipation.", &
2904 units=
"nondim", default=0.0697)
2905 call get_param(param_file, mdl,
"NBOTREF_POLZIN", cs%Nbotref_Polzin, &
2906 "When the Polzin decay profile is used, this is the \n"//&
2907 "Rreference value of the buoyancy frequency at the ocean \n"//&
2908 "bottom in the Polzin formulation for the vertical \n"//&
2909 "scale of decay for the tidal energy dissipation.", &
2910 units=
"s-1", default=9.61e-4)
2911 call get_param(param_file, mdl,
"POLZIN_DECAY_SCALE_FACTOR", &
2912 cs%Polzin_decay_scale_factor, &
2913 "When the Polzin decay profile is used, this is a \n"//&
2914 "scale factor for the vertical scale of decay of the tidal \n"//&
2915 "energy dissipation.", default=1.0, units=
"nondim")
2916 call get_param(param_file, mdl,
"POLZIN_SCALE_MAX_FACTOR", &
2917 cs%Polzin_decay_scale_max_factor, &
2918 "When the Polzin decay profile is used, this is a factor \n"//&
2919 "to limit the vertical scale of decay of the tidal \n"//&
2920 "energy dissipation to POLZIN_DECAY_SCALE_MAX_FACTOR \n"//&
2921 "times the depth of the ocean.", units=
"nondim", default=1.0)
2922 call get_param(param_file, mdl,
"POLZIN_MIN_DECAY_SCALE", cs%Polzin_min_decay_scale, &
2923 "When the Polzin decay profile is used, this is the \n"//&
2924 "minimum vertical decay scale for the vertical profile\n"//&
2925 "of internal tide dissipation with the Polzin (2009) formulation", &
2926 units=
"m", default=0.0)
2928 call get_param(param_file, mdl,
"USER_CHANGE_DIFFUSIVITY", cs%user_change_diff, &
2929 "If true, call user-defined code to change the diffusivity.", &
2932 call get_param(param_file, mdl,
"DISSIPATION_MIN", cs%dissip_min, &
2933 "The minimum dissipation by which to determine a lower \n"//&
2934 "bound of Kd (a floor).", units=
"W m-3", default=0.0)
2935 call get_param(param_file, mdl,
"DISSIPATION_N0", cs%dissip_N0, &
2936 "The intercept when N=0 of the N-dependent expression \n"//&
2937 "used to set a minimum dissipation by which to determine \n"//&
2938 "a lower bound of Kd (a floor): A in eps_min = A + B*N.", &
2939 units=
"W m-3", default=0.0)
2940 call get_param(param_file, mdl,
"DISSIPATION_N1", cs%dissip_N1, &
2941 "The coefficient multiplying N, following Gargett, used to \n"//&
2942 "set a minimum dissipation by which to determine a lower \n"//&
2943 "bound of Kd (a floor): B in eps_min = A + B*N", &
2944 units=
"J m-3", default=0.0)
2945 call get_param(param_file, mdl,
"DISSIPATION_KD_MIN", cs%dissip_Kd_min, &
2946 "The minimum vertical diffusivity applied as a floor.", &
2947 units=
"m2 s-1", default=0.0)
2949 cs%limit_dissipation = (cs%dissip_min>0.) .or. (cs%dissip_N1>0.) .or. &
2950 (cs%dissip_N0>0.) .or. (cs%dissip_Kd_min>0.)
2952 if (cs%FluxRi_max > 0.0) &
2953 cs%dissip_N2 = cs%dissip_Kd_min * gv%Rho0 / cs%FluxRi_max
2955 if (cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation)
then 2956 call get_param(param_file, mdl,
"INT_TIDE_DECAY_SCALE", cs%Int_tide_decay_scale, &
2957 "The decay scale away from the bottom for tidal TKE with \n"//&
2958 "the new coding when INT_TIDE_DISSIPATION is used.", &
2959 units=
"m", default=0.0)
2960 call get_param(param_file, mdl,
"MU_ITIDES", cs%Mu_itides, &
2961 "A dimensionless turbulent mixing efficiency used with \n"//&
2962 "INT_TIDE_DISSIPATION, often 0.2.", units=
"nondim", default=0.2)
2963 call get_param(param_file, mdl,
"GAMMA_ITIDES", cs%Gamma_itides, &
2964 "The fraction of the internal tidal energy that is \n"//&
2965 "dissipated locally with INT_TIDE_DISSIPATION. \n"//&
2966 "THIS NAME COULD BE BETTER.", &
2967 units=
"nondim", default=0.3333)
2968 call get_param(param_file, mdl,
"MIN_ZBOT_ITIDES", cs%min_zbot_itides, &
2969 "Turn off internal tidal dissipation when the total \n"//&
2970 "ocean depth is less than this value.", units=
"m", default=0.0)
2972 call safe_alloc_ptr(cs%Nb,isd,ied,jsd,jed)
2973 call safe_alloc_ptr(cs%h2,isd,ied,jsd,jed)
2974 call safe_alloc_ptr(cs%TKE_itidal,isd,ied,jsd,jed)
2975 call safe_alloc_ptr(cs%mask_itidal,isd,ied,jsd,jed) ; cs%mask_itidal(:,:) = 1.0
2977 call get_param(param_file, mdl,
"KAPPA_ITIDES", cs%kappa_itides, &
2978 "A topographic wavenumber used with INT_TIDE_DISSIPATION. \n"//&
2979 "The default is 2pi/10 km, as in St.Laurent et al. 2002.", &
2980 units=
"m-1", default=8.e-4*atan(1.0))
2982 call get_param(param_file, mdl,
"UTIDE", cs%utide, &
2983 "The constant tidal amplitude used with INT_TIDE_DISSIPATION.", &
2984 units=
"m s-1", default=0.0)
2985 call safe_alloc_ptr(cs%tideamp,is,ie,js,je) ; cs%tideamp(:,:) = cs%utide
2987 call get_param(param_file, mdl,
"KAPPA_H2_FACTOR", cs%kappa_h2_factor, &
2988 "A scaling factor for the roughness amplitude with n"//&
2989 "INT_TIDE_DISSIPATION.", units=
"nondim", default=1.0)
2990 call get_param(param_file, mdl,
"TKE_ITIDE_MAX", cs%TKE_itide_max, &
2991 "The maximum internal tide energy source availble to mix \n"//&
2992 "above the bottom boundary layer with INT_TIDE_DISSIPATION.", &
2993 units=
"W m-2", default=1.0e3)
2995 call get_param(param_file, mdl,
"READ_TIDEAMP", read_tideamp, &
2996 "If true, read a file (given by TIDEAMP_FILE) containing \n"//&
2997 "the tidal amplitude with INT_TIDE_DISSIPATION.", default=.false.)
2998 if (read_tideamp)
then 2999 call get_param(param_file, mdl,
"TIDEAMP_FILE", tideamp_file, &
3000 "The path to the file containing the spatially varying \n"//&
3001 "tidal amplitudes with INT_TIDE_DISSIPATION.", default=
"tideamp.nc")
3002 filename = trim(cs%inputdir) // trim(tideamp_file)
3003 call log_param(param_file, mdl,
"INPUTDIR/TIDEAMP_FILE", filename)
3004 call read_data(filename,
'tideamp', cs%tideamp, &
3005 domain=g%domain%mpp_domain, timelevel=1)
3008 call get_param(param_file, mdl,
"H2_FILE", h2_file, &
3009 "The path to the file containing the sub-grid-scale \n"//&
3010 "topographic roughness amplitude with INT_TIDE_DISSIPATION.", &
3011 fail_if_missing=.true.)
3012 filename = trim(cs%inputdir) // trim(h2_file)
3013 call log_param(param_file, mdl,
"INPUTDIR/H2_FILE", filename)
3014 call read_data(filename,
'h2', cs%h2, domain=g%domain%mpp_domain, &
3017 do j=js,je ;
do i=is,ie
3018 if (g%bathyT(i,j) < cs%min_zbot_itides) cs%mask_itidal(i,j) = 0.0
3019 cs%tideamp(i,j) = cs%tideamp(i,j) * cs%mask_itidal(i,j) * g%mask2dT(i,j)
3022 zbot = g%bathyT(i,j)
3023 hamp = sqrt(cs%h2(i,j))
3024 hamp = min(0.1*zbot,hamp)
3025 cs%h2(i,j) = hamp*hamp
3027 utide = cs%tideamp(i,j)
3029 cs%TKE_itidal(i,j) = 0.5*cs%kappa_h2_factor*gv%Rho0*&
3030 cs%kappa_itides*cs%h2(i,j)*utide*utide
3035 cs%id_Kd_layer = register_diag_field(
'ocean_model',
'Kd_layer', diag%axesTL, time, &
3036 'Diapycnal diffusivity of layers (as set)',
'meter2 second-1')
3038 if (cs%Lee_wave_dissipation)
then 3040 call get_param(param_file, mdl,
"NIKURASHIN_TKE_INPUT_FILE",niku_tke_input_file, &
3041 "The path to the file containing the TKE input from lee \n"//&
3042 "wave driven mixing. Used with LEE_WAVE_DISSIPATION.", &
3043 fail_if_missing=.true.)
3044 call get_param(param_file, mdl,
"NIKURASHIN_SCALE",niku_scale, &
3045 "A non-dimensional factor by which to scale the lee-wave \n"//&
3046 "driven TKE input. Used with LEE_WAVE_DISSIPATION.", &
3047 units=
"nondim", default=1.0)
3049 filename = trim(cs%inputdir) // trim(niku_tke_input_file)
3050 call log_param(param_file, mdl,
"INPUTDIR/NIKURASHIN_TKE_INPUT_FILE", &
3052 call safe_alloc_ptr(cs%TKE_Niku,is,ie,js,je); cs%TKE_Niku(:,:) = 0.0
3053 call read_data(filename,
'TKE_input', cs%TKE_Niku, &
3054 domain=g%domain%mpp_domain, timelevel=1 )
3055 cs%TKE_Niku(:,:) = niku_scale * cs%TKE_Niku(:,:)
3057 call get_param(param_file, mdl,
"GAMMA_NIKURASHIN",cs%Gamma_lee, &
3058 "The fraction of the lee wave energy that is dissipated \n"//&
3059 "locally with LEE_WAVE_DISSIPATION.", units=
"nondim", &
3061 call get_param(param_file, mdl,
"DECAY_SCALE_FACTOR_LEE",cs%Decay_scale_factor_lee, &
3062 "Scaling for the vertical decay scaleof the local \n"//&
3063 "dissipation of lee waves dissipation.", units=
"nondim", &
3066 cs%id_TKE_leewave = register_diag_field(
'ocean_model',
'TKE_leewave',diag%axesT1,time, &
3067 'Lee wave Driven Turbulent Kinetic Energy',
'Watt meter-2')
3068 cs%id_Kd_Niku = register_diag_field(
'ocean_model',
'Kd_Nikurashin',diag%axesTi,time, &
3069 'Lee Wave Driven Diffusivity',
'meter2 sec-1')
3071 cs%Decay_scale_factor_lee = -9.e99
3074 if (cs%Int_tide_dissipation .or. cs%Lee_wave_dissipation .or. &
3075 cs%Lowmode_itidal_dissipation)
then 3077 cs%id_TKE_itidal = register_diag_field(
'ocean_model',
'TKE_itidal',diag%axesT1,time, &
3078 'Internal Tide Driven Turbulent Kinetic Energy',
'Watt meter-2')
3079 cs%id_maxTKE = register_diag_field(
'ocean_model',
'maxTKE',diag%axesTL,time, &
3080 'Maximum layer TKE',
'meter3 second-3')
3081 cs%id_TKE_to_Kd = register_diag_field(
'ocean_model',
'TKE_to_Kd',diag%axesTL,time, &
3082 'Convert TKE to Kd',
'second2 meter')
3084 cs%id_Nb = register_diag_field(
'ocean_model',
'Nb',diag%axesT1,time, &
3085 'Bottom Buoyancy Frequency',
'sec-1')
3087 cs%id_Kd_itidal = register_diag_field(
'ocean_model',
'Kd_itides',diag%axesTi,time, &
3088 'Internal Tide Driven Diffusivity',
'meter2 sec-1')
3090 cs%id_Kd_lowmode = register_diag_field(
'ocean_model',
'Kd_lowmode',diag%axesTi,time, &
3091 'Internal Tide Driven Diffusivity (from propagating low modes)',
'meter2 sec-1')
3093 cs%id_Fl_itidal = register_diag_field(
'ocean_model',
'Fl_itides',diag%axesTi,time, &
3094 'Vertical flux of tidal turbulent dissipation',
'meter3 sec-3')
3096 cs%id_Fl_lowmode = register_diag_field(
'ocean_model',
'Fl_lowmode',diag%axesTi,time, &
3097 'Vertical flux of tidal turbulent dissipation (from propagating low modes)',
'meter3 sec-3')
3099 cs%id_Polzin_decay_scale = register_diag_field(
'ocean_model',
'Polzin_decay_scale',diag%axesT1,time, &
3100 'Vertical decay scale for the tidal turbulent dissipation with Polzin scheme',
'meter')
3102 cs%id_Polzin_decay_scale_scaled = register_diag_field(
'ocean_model',
'Polzin_decay_scale_scaled',diag%axesT1,time, &
3103 'Vertical decay scale for the tidal turbulent dissipation with Polzin scheme, scaled by N2_bot/N2_meanz',
'meter')
3105 cs%id_N2_bot = register_diag_field(
'ocean_model',
'N2_b',diag%axesT1,time, &
3106 'Bottom Buoyancy frequency squared',
's-2')
3108 cs%id_N2_meanz = register_diag_field(
'ocean_model',
'N2_meanz',diag%axesT1,time, &
3109 'Buoyancy frequency squared averaged over the water column',
's-2')
3111 cs%id_Kd_Work = register_diag_field(
'ocean_model',
'Kd_Work',diag%axesTL,time, &
3112 'Work done by Diapycnal Mixing',
'Watts m-2')
3114 cs%id_Kd_Itidal_Work = register_diag_field(
'ocean_model',
'Kd_Itidal_Work',diag%axesTL,time, &
3115 'Work done by Internal Tide Diapycnal Mixing',
'Watts m-2')
3117 cs%id_Kd_Niku_Work = register_diag_field(
'ocean_model',
'Kd_Nikurashin_Work',diag%axesTL,time, &
3118 'Work done by Nikurashin Lee Wave Drag Scheme',
'Watts m-2')
3120 cs%id_Kd_Lowmode_Work = register_diag_field(
'ocean_model',
'Kd_Lowmode_Work',diag%axesTL,time, &
3121 'Work done by Internal Tide Diapycnal Mixing (low modes)',
'Watts m-2')
3123 cs%id_N2 = register_diag_field(
'ocean_model',
'N2',diag%axesTi,time, &
3124 'Buoyancy frequency squared',
'sec-2', cmor_field_name=
'obvfsq', &
3125 cmor_units=
's-2', cmor_long_name=
'Square of seawater buoyancy frequency',&
3126 cmor_standard_name=
'square_of_brunt_vaisala_frequency_in_sea_water')
3128 if (cs%user_change_diff) &
3129 cs%id_Kd_user = register_diag_field(
'ocean_model',
'Kd_user',diag%axesTi,time, &
3130 'User-specified Extra Diffusivity',
'meter2 sec-1')
3132 if (
associated(diag_to_z_csp))
then 3133 vd = var_desc(
"N2",
"second-2",&
3134 "Buoyancy frequency, interpolated to z", z_grid=
'z')
3135 cs%id_N2_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3136 vd = var_desc(
"Kd_itides",
"meter2 second-1", &
3137 "Internal Tide Driven Diffusivity, interpolated to z", z_grid=
'z')
3138 cs%id_Kd_itidal_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3139 if (cs%Lee_wave_dissipation)
then 3140 vd = var_desc(
"Kd_Nikurashin",
"meter2 second-1", &
3141 "Lee Wave Driven Diffusivity, interpolated to z", z_grid=
'z')
3142 cs%id_Kd_Niku_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3144 if (cs%Lowmode_itidal_dissipation)
then 3145 vd = var_desc(
"Kd_lowmode",
"meter2 second-1", &
3146 "Internal Tide Driven Diffusivity (from low modes), interpolated to z",&
3148 cs%id_Kd_lowmode_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3150 if (cs%user_change_diff) &
3151 cs%id_Kd_user_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3155 call get_param(param_file, mdl,
"DOUBLE_DIFFUSION", cs%double_diffusion, &
3156 "If true, increase diffusivitives for temperature or salt \n"//&
3157 "based on double-diffusive paramaterization from MOM4/KPP.", &
3159 if (cs%double_diffusion)
then 3160 call get_param(param_file, mdl,
"MAX_RRHO_SALT_FINGERS", cs%Max_Rrho_salt_fingers, &
3161 "Maximum density ratio for salt fingering regime.", &
3162 default=2.55, units=
"nondim")
3163 call get_param(param_file, mdl,
"MAX_SALT_DIFF_SALT_FINGERS", cs%Max_salt_diff_salt_fingers, &
3164 "Maximum salt diffusivity for salt fingering regime.", &
3165 default=1.e-4, units=
"m2 s-1")
3166 call get_param(param_file, mdl,
"KV_MOLECULAR", cs%Kv_molecular, &
3167 "Molecular viscosity for calculation of fluxes under \n"//&
3168 "double-diffusive convection.", default=1.5e-6, units=
"m2 s-1")
3171 cs%id_KT_extra = register_diag_field(
'ocean_model',
'KT_extra',diag%axesTi,time, &
3172 'Double-diffusive diffusivity for temperature',
'meter2 sec-1')
3174 cs%id_KS_extra = register_diag_field(
'ocean_model',
'KS_extra',diag%axesTi,time, &
3175 'Double-diffusive diffusivity for salinity',
'meter2 sec-1')
3177 if (
associated(diag_to_z_csp))
then 3178 vd = var_desc(
"KT_extra",
"meter2 second-1", &
3179 "Double-Diffusive Temperature Diffusivity, interpolated to z", &
3181 cs%id_KT_extra_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3182 vd = var_desc(
"KS_extra",
"meter2 second-1", &
3183 "Double-Diffusive Salinity Diffusivity, interpolated to z",&
3185 cs%id_KS_extra_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3186 vd = var_desc(
"Kd_BBL",
"meter2 second-1", &
3187 "Bottom Boundary Layer Diffusivity", z_grid=
'z')
3188 cs%id_Kd_BBL_z = register_zint_diag(vd, cs%diag_to_Z_CSp, time)
3192 if (cs%Int_tide_dissipation .and. cs%Bryan_Lewis_diffusivity) &
3193 call mom_error(fatal,
"MOM_Set_Diffusivity: "// &
3194 "Bryan-Lewis and internal tidal dissipation are both enabled. Choose one.")
3195 if (cs%Henyey_IGW_background .and. cs%Kd_tanh_lat_fn)
call mom_error(fatal, &
3196 "Set_diffusivity: KD_TANH_LAT_FN can not be used with HENYEY_IGW_BACKGROUND.")
3198 if (cs%user_change_diff)
then 3199 call user_change_diff_init(time, g, param_file, diag, cs%user_change_diff_CSp)
3202 cs%useKappaShear = kappa_shear_init(time, g, gv, param_file, cs%diag, cs%kappaShear_CSp)
3203 if (cs%useKappaShear) &
3205 cs%useCVMix = cvmix_shear_init(time, g, gv, param_file, cs%diag, cs%CVMix_shear_CSp)
3214 if (cs%user_change_diff) &
3215 call user_change_diff_end(cs%user_change_diff_CSp)
3217 if (
associated(cs))
deallocate(cs)
subroutine add_int_tide_diffusivity(h, N2_bot, j, TKE_to_Kd, max_TKE, G, GV, CS, dd, N2_lay, Kd, Kd_int)
This subroutine adds the effect of internal-tide-driven mixing to the layer diffusivities. The mechanisms considered are (1) local dissipation of internal waves generated by the barotropic flow ("itidal"), (2) local dissipation of internal waves generated by the propagating low modes (rays) of the internal tide ("lowmode"), and (3) local dissipation of internal lee waves. Will eventually need to add diffusivity due to other wave-breaking processes (e.g. Bottom friction, Froude-number-depending breaking, PSI, etc.).
character *(20), parameter polzin_profile_string
subroutine, public set_diffusivity_end(CS)
subroutine add_drag_diffusivity(h, u, v, tv, fluxes, visc, j, TKE_to_Kd, maxTKE, kb, G, GV, CS, Kd, Kd_int, Kd_BBL)
This routine adds diffusion sustained by flow energy extracted by bottom drag.
subroutine, public user_change_diff_end(CS)
Clean up the module control structure.
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
subroutine set_density_ratios(h, tv, kb, G, GV, CS, j, ds_dsp1, rho_0)
This module implements boundary forcing for MOM6.
Control structure including parameters for CVMix interior shear schemes.
Interface to CVMix interior shear schemes.
subroutine, public vert_fill_ts(h, T_in, S_in, kappa, dt, T_f, S_f, G, GV, halo_here)
Fills tracer values in massless layers with sensible values by diffusing vertically with a (small) co...
integer, parameter stlaurent_02
subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, CS, Kd_T_dd, Kd_S_dd)
This subroutine sets the additional diffusivities of temperature and salinity due to double diffusion...
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
subroutine, public calculate_cvmix_shear(u_H, v_H, h, tv, KH, KM, G, GV, CS)
Subroutine for calculating (internal) diffusivity.
Provides the ocean grid type.
The vertvisc_type structure contains vertical viscosities, drag coefficients, and related fields...
subroutine, public get_lowmode_loss(i, j, G, CS, mechanism, TKE_loss_sum)
This subroutine extracts the energy lost from the propagating internal which has been summed across a...
logical function, public cvmix_shear_init(Time, G, GV, param_file, diag, CS)
Initialized the cvmix internal shear mixing routine.
subroutine, public user_change_diff_init(Time, G, param_file, diag, CS)
Set up the module control structure.
subroutine, public calltree_leave(mesg)
Writes a message about leaving a subroutine if call tree reporting is active.
This module contains I/O framework code.
subroutine, public set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt, G, GV, CS, Kd, Kd_int)
logical function, public kappa_shear_init(Time, G, GV, param_file, diag, CS)
character *(20), parameter stlaurent_profile_string
real function, public invcosh(x)
subroutine, public set_diffusivity_init(Time, G, GV, param_file, diag, CS, diag_to_Z_CSp, int_tide_CSp)
integer, parameter polzin_09
subroutine, public calltree_waypoint(mesg, n)
Writes a message about reaching a milestone if call tree reporting is active.
subroutine, public calculate_density_derivs(T, S, pressure, drho_dT, drho_dS, start, npts, EOS)
Calls the appropriate subroutine to calculate density derivatives for 1-D array inputs.
character(len=len(input_string)) function, public uppercase(input_string)
subroutine add_mlrad_diffusivity(h, fluxes, j, G, GV, CS, Kd, TKE_to_Kd, Kd_int)
This routine adds effects of mixed layer radiation to the layer diffusivities.
integer id_clock_kappashear
Thickness diffusion (or Gent McWilliams)
logical function, public is_root_pe()
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Provides subroutines for quantities specific to the equation of state.
logical function, public calltree_showquery()
Returns True, if the verbosity>=6 indicating to show the call tree.
Type for describing a variable, typically a tracer.
subroutine, public user_change_diff(h, tv, G, CS, Kd, Kd_int, T_f, S_f, Kd_int_add)
This subroutine provides an interface for a user to use to modify the main code to alter the diffusiv...
subroutine, public set_bbl_tke(u, v, h, fluxes, visc, G, GV, CS)
This subroutine calculates several properties related to bottom boundary layer turbulence.
subroutine find_tke_to_kd(h, tv, dRho_int, N2_lay, j, dt, G, GV, CS, TKE_to_Kd, maxTKE, kb)
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine add_lotw_bbl_diffusivity(h, u, v, tv, fluxes, visc, j, N2_int, G, GV, CS, Kd, Kd_int, Kd_BBL)
Calculates a BBL diffusivity use a Prandtl number 1 diffusivitiy with a law of the wall turbulent vis...
integer function, public register_zint_diag(var_desc, CS, day)
By Robert Hallberg, May 2012.
subroutine find_n2(h, tv, T_f, S_f, fluxes, j, G, GV, CS, dRho_int, N2_lay, N2_int, N2_bot)
subroutine, public mom_error(level, message, all_print)
subroutine, public calc_zint_diags(h, in_ptrs, ids, num_diags, G, GV, CS)
subroutine, public calculate_kappa_shear(u_in, v_in, h, tv, p_surf, kappa_io, tke_io, kv_io, dt, G, GV, CS, initialize_all)
Subroutine for calculating diffusivity and TKE.
subroutine, public calltree_enter(mesg, n)
Writes a message about entering a subroutine if call tree reporting is active.