6 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
21 implicit none ;
private 23 #include <MOM_memory.h> 25 public energetic_pbl, energetic_pbl_init, energetic_pbl_end
26 public energetic_pbl_get_mld
51 logical :: use_mld_iteration
53 logical :: mld_iteration_guess
55 logical :: mld_bisection
59 integer :: max_mld_its
61 real :: mixlenexponent
64 real :: mke_to_tke_effic
69 real :: ekman_scale_coef
72 real :: translay_scale
86 real :: wstar_ustar_coef
90 real :: vstar_surf_fac
92 real :: vstar_scale_fac
97 integer :: mstar_scheme
98 logical :: mstar_flatcap=.true.
116 real :: mstar_coef = 0.3
119 real :: rh18_mstar_cn1
123 real :: rh18_mstar_cn2
127 real :: rh18_mstar_cn3
130 real :: rh18_mstar_cs1
132 real :: rh18_mstar_cs2
136 real :: mstar_convect_coef
139 logical :: use_lt = .false.
140 integer :: lt_enhance_form
141 real :: lt_enhance_coef
142 real :: lt_enhance_exp
145 real :: lac_mldoob_stab
147 real :: lac_ekoob_stab
149 real :: lac_mldoob_un
153 real :: max_enhance_m = 5.
156 type(time_type),
pointer :: time=>null()
158 logical :: tke_diagnostics = .false.
159 logical :: answers_2018
162 logical :: orig_pe_calc
169 real,
allocatable,
dimension(:,:) :: &
173 real,
allocatable,
dimension(:,:) :: &
174 diag_tke_wind, & !< The wind source of TKE [R Z3 T-3 ~> W m-2].
175 diag_tke_mke, & !< The resolved KE source of TKE [R Z3 T-3 ~> W m-2].
176 diag_tke_conv, & !< The convective source of TKE [R Z3 T-3 ~> W m-2].
177 diag_tke_forcing, & !< The TKE sink required to mix surface penetrating shortwave heating
179 diag_tke_mech_decay, &
180 diag_tke_conv_decay, &
190 real,
allocatable,
dimension(:,:,:) :: &
191 velocity_scale, & !< The velocity scale used in getting Kd [Z T-1 ~> m s-1]
194 integer :: id_ml_depth = -1, id_hml_depth = -1, id_tke_wind = -1, id_tke_mixing = -1
195 integer :: id_tke_mke = -1, id_tke_conv = -1, id_tke_forcing = -1
196 integer :: id_tke_mech_decay = -1, id_tke_conv_decay = -1
197 integer :: id_mixing_length = -1, id_velocity_scale = -1
198 integer :: id_mstar_mix = -1, id_la_mod = -1, id_la = -1, id_mstar_lt = -1
203 integer,
parameter :: use_fixed_mstar = 0
204 integer,
parameter :: mstar_from_ekman = 2
206 integer,
parameter :: mstar_from_rh18 = 3
207 integer,
parameter :: no_langmuir = 0
208 integer,
parameter :: langmuir_rescale = 2
210 integer,
parameter :: langmuir_add = 3
212 integer,
parameter :: wt_from_croot_tke = 0
214 integer,
parameter :: wt_from_rh18 = 1
217 character*(20),
parameter :: constant_string =
"CONSTANT" 218 character*(20),
parameter :: om4_string =
"OM4" 219 character*(20),
parameter :: rh18_string =
"REICHL_H18" 220 character*(20),
parameter :: root_tke_string =
"CUBE_ROOT_TKE" 221 character*(20),
parameter :: none_string =
"NONE" 222 character*(20),
parameter :: rescaled_string =
"RESCALE" 223 character*(20),
parameter :: additive_string =
"ADDITIVE" 226 logical :: report_avg_its = .false.
231 real :: dtke_conv, dtke_forcing, dtke_wind, dtke_mixing
232 real :: dtke_mke, dtke_mech_decay, dtke_conv_decay
238 real,
allocatable,
dimension(:) :: dt_expect
239 real,
allocatable,
dimension(:) :: ds_expect
248 subroutine energetic_pbl(h_3d, u_3d, v_3d, tv, fluxes, dt, Kd_int, G, GV, US, CS, &
249 dSV_dT, dSV_dS, TKE_forced, buoy_flux, dt_diag, last_call, &
250 dT_expected, dS_expected, Waves )
254 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
255 intent(inout) :: h_3d
256 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
259 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
262 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
266 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
269 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
270 intent(in) :: tke_forced
276 type(
forcing),
intent(inout) :: fluxes
279 real,
intent(in) :: dt
280 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
281 intent(out) :: kd_int
285 real,
dimension(SZI_(G),SZJ_(G)), &
286 intent(in) :: buoy_flux
287 real,
optional,
intent(in) :: dt_diag
289 logical,
optional,
intent(in) :: last_call
293 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
294 optional,
intent(out) :: dt_expected
297 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
298 optional,
intent(out) :: ds_expected
302 optional,
pointer :: waves
327 real,
dimension(SZI_(G),SZK_(GV)) :: &
336 real,
dimension(SZI_(G),SZK_(GV)+1) :: &
338 real,
dimension(SZK_(GV)) :: &
347 real,
dimension(SZK_(GV)+1) :: &
362 logical :: write_diags
363 logical :: reset_diags
365 logical :: debug=.false.
368 integer :: i, j, k, is, ie, js, je, nz
370 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
372 if (.not.
associated(cs))
call mom_error(fatal,
"energetic_PBL: "//&
373 "Module must be initialized before it is used.")
375 if (.not.
associated(tv%eqn_of_state))
call mom_error(fatal, &
376 "energetic_PBL: Temperature, salinity and an equation of state "//&
378 if (.NOT.
associated(fluxes%ustar))
call mom_error(fatal, &
379 "energetic_PBL: No surface TKE fluxes (ustar) defined in mixedlayer!")
380 debug = .false. ;
if (
present(dt_expected) .or.
present(ds_expected)) debug = .true.
382 if (debug)
allocate(ecd%dT_expect(nz), ecd%dS_expect(nz))
384 h_neglect = gv%H_subroundoff
386 dt__diag = dt ;
if (
present(dt_diag)) dt__diag = dt_diag
387 write_diags = .true. ;
if (
present(last_call)) write_diags = last_call
392 if (
present(dt_diag) .and. write_diags .and. (dt__diag > dt)) &
393 reset_diags = .false.
395 if (reset_diags)
then 396 if (cs%TKE_diagnostics)
then 398 do j=js,je ;
do i=is,ie
399 cs%diag_TKE_wind(i,j) = 0.0 ; cs%diag_TKE_MKE(i,j) = 0.0
400 cs%diag_TKE_conv(i,j) = 0.0 ; cs%diag_TKE_forcing(i,j) = 0.0
401 cs%diag_TKE_mixing(i,j) = 0.0 ; cs%diag_TKE_mech_decay(i,j) = 0.0
402 cs%diag_TKE_conv_decay(i,j) = 0.0
414 do k=1,nz ;
do i=is,ie
415 h_2d(i,k) = h_3d(i,j,k) ; u_2d(i,k) = u_3d(i,j,k) ; v_2d(i,k) = v_3d(i,j,k)
416 t_2d(i,k) = tv%T(i,j,k) ; s_2d(i,k) = tv%S(i,j,k)
417 tke_forced_2d(i,k) = tke_forced(i,j,k)
418 dsv_dt_2d(i,k) = dsv_dt(i,j,k) ; dsv_ds_2d(i,k) = dsv_ds(i,j,k)
427 do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 431 h(k) = h_2d(i,k) + gv%H_subroundoff ; u(k) = u_2d(i,k) ; v(k) = v_2d(i,k)
432 t0(k) = t_2d(i,k) ; s0(k) = s_2d(i,k) ; tke_forcing(k) = tke_forced_2d(i,k)
433 dsv_dt_1d(k) = dsv_dt_2d(i,k) ; dsv_ds_1d(k) = dsv_ds_2d(i,k)
435 do k=1,nz+1 ; kd(k) = 0.0 ;
enddo 438 u_star = fluxes%ustar(i,j)
439 u_star_mean = fluxes%ustar_gustless(i,j)
440 b_flux = buoy_flux(i,j)
441 if (
associated(fluxes%ustar_shelf) .and.
associated(fluxes%frac_shelf_h))
then 442 if (fluxes%frac_shelf_h(i,j) > 0.0) &
443 u_star = (1.0 - fluxes%frac_shelf_h(i,j)) * u_star + &
444 fluxes%frac_shelf_h(i,j) * fluxes%ustar_shelf(i,j)
446 if (u_star < cs%ustar_min) u_star = cs%ustar_min
447 if (cs%omega_frac >= 1.0)
then 450 absf = 0.25*((abs(g%CoriolisBu(i,j)) + abs(g%CoriolisBu(i-1,j-1))) + &
451 (abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i-1,j))))
452 if (cs%omega_frac > 0.0) &
453 absf = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf**2)
458 if (cs%MLD_iteration_guess .and. (cs%ML_Depth(i,j) > 0.0)) mld_io = cs%ML_Depth(i,j)
460 call epbl_column(h, u, v, t0, s0, dsv_dt_1d, dsv_ds_1d, tke_forcing, b_flux, absf, &
461 u_star, u_star_mean, dt, mld_io, kd, mixvel, mixlen, gv, &
462 us, cs, ecd, dt_diag=dt_diag, waves=waves, g=g, i=i, j=j)
469 cs%ML_depth(i,j) = mld_io
471 if (
present(dt_expected))
then 472 do k=1,nz ; dt_expected(i,j,k) = ecd%dT_expect(k) ;
enddo 474 if (
present(ds_expected))
then 475 do k=1,nz ; ds_expected(i,j,k) = ecd%dS_expect(k) ;
enddo 478 if (cs%TKE_diagnostics)
then 479 cs%diag_TKE_MKE(i,j) = cs%diag_TKE_MKE(i,j) + ecd%dTKE_MKE
480 cs%diag_TKE_conv(i,j) = cs%diag_TKE_conv(i,j) + ecd%dTKE_conv
481 cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + ecd%dTKE_forcing
482 cs%diag_TKE_wind(i,j) = cs%diag_TKE_wind(i,j) + ecd%dTKE_wind
483 cs%diag_TKE_mixing(i,j) = cs%diag_TKE_mixing(i,j) + ecd%dTKE_mixing
484 cs%diag_TKE_mech_decay(i,j) = cs%diag_TKE_mech_decay(i,j) + ecd%dTKE_mech_decay
485 cs%diag_TKE_conv_decay(i,j) = cs%diag_TKE_conv_decay(i,j) + ecd%dTKE_conv_decay
489 if (cs%id_Mixing_Length>0)
then ;
do k=1,nz
490 cs%Mixing_Length(i,j,k) = mixlen(k)
492 if (cs%id_Velocity_Scale>0)
then ;
do k=1,nz
493 cs%Velocity_Scale(i,j,k) = mixvel(k)
495 if (
allocated(cs%mstar_mix)) cs%mstar_mix(i,j) = ecd%mstar
496 if (
allocated(cs%mstar_lt)) cs%mstar_lt(i,j) = ecd%mstar_LT
497 if (
allocated(cs%La)) cs%La(i,j) = ecd%LA
498 if (
allocated(cs%La_mod)) cs%La_mod(i,j) = ecd%LAmod
501 do k=1,nz+1 ; kd_2d(i,k) = 0. ;
enddo 502 cs%ML_depth(i,j) = 0.0
504 if (
present(dt_expected))
then 505 do k=1,nz ; dt_expected(i,j,k) = 0.0 ;
enddo 507 if (
present(ds_expected))
then 508 do k=1,nz ; ds_expected(i,j,k) = 0.0 ;
enddo 512 do k=1,nz+1 ;
do i=is,ie ; kd_int(i,j,k) = kd_2d(i,k) ;
enddo ;
enddo 516 if (write_diags)
then 517 if (cs%id_ML_depth > 0)
call post_data(cs%id_ML_depth, cs%ML_depth, cs%diag)
518 if (cs%id_hML_depth > 0)
call post_data(cs%id_hML_depth, cs%ML_depth, cs%diag)
519 if (cs%id_TKE_wind > 0)
call post_data(cs%id_TKE_wind, cs%diag_TKE_wind, cs%diag)
520 if (cs%id_TKE_MKE > 0)
call post_data(cs%id_TKE_MKE, cs%diag_TKE_MKE, cs%diag)
521 if (cs%id_TKE_conv > 0)
call post_data(cs%id_TKE_conv, cs%diag_TKE_conv, cs%diag)
522 if (cs%id_TKE_forcing > 0)
call post_data(cs%id_TKE_forcing, cs%diag_TKE_forcing, cs%diag)
523 if (cs%id_TKE_mixing > 0)
call post_data(cs%id_TKE_mixing, cs%diag_TKE_mixing, cs%diag)
524 if (cs%id_TKE_mech_decay > 0) &
525 call post_data(cs%id_TKE_mech_decay, cs%diag_TKE_mech_decay, cs%diag)
526 if (cs%id_TKE_conv_decay > 0) &
527 call post_data(cs%id_TKE_conv_decay, cs%diag_TKE_conv_decay, cs%diag)
528 if (cs%id_Mixing_Length > 0)
call post_data(cs%id_Mixing_Length, cs%Mixing_Length, cs%diag)
529 if (cs%id_Velocity_Scale >0)
call post_data(cs%id_Velocity_Scale, cs%Velocity_Scale, cs%diag)
530 if (cs%id_MSTAR_MIX > 0)
call post_data(cs%id_MSTAR_MIX, cs%MSTAR_MIX, cs%diag)
531 if (cs%id_LA > 0)
call post_data(cs%id_LA, cs%LA, cs%diag)
532 if (cs%id_LA_MOD > 0)
call post_data(cs%id_LA_MOD, cs%LA_MOD, cs%diag)
533 if (cs%id_MSTAR_LT > 0)
call post_data(cs%id_MSTAR_LT, cs%MSTAR_LT, cs%diag)
536 if (debug)
deallocate(ecd%dT_expect, ecd%dS_expect)
538 end subroutine energetic_pbl
544 subroutine epbl_column(h, u, v, T0, S0, dSV_dT, dSV_dS, TKE_forcing, B_flux, absf, &
545 u_star, u_star_mean, dt, MLD_io, Kd, mixvel, mixlen, GV, US, CS, eCD, &
546 dt_diag, Waves, G, i, j)
547 type(verticalGrid_type),
intent(in) :: GV
548 type(unit_scale_type),
intent(in) :: US
549 real,
dimension(SZK_(GV)),
intent(in) :: h
550 real,
dimension(SZK_(GV)),
intent(in) :: u
552 real,
dimension(SZK_(GV)),
intent(in) :: v
554 real,
dimension(SZK_(GV)),
intent(in) :: T0
555 real,
dimension(SZK_(GV)),
intent(in) :: S0
557 real,
dimension(SZK_(GV)),
intent(in) :: dSV_dT
560 real,
dimension(SZK_(GV)),
intent(in) :: dSV_dS
562 real,
dimension(SZK_(GV)),
intent(in) :: TKE_forcing
565 real,
intent(in) :: B_flux
566 real,
intent(in) :: absf
567 real,
intent(in) :: u_star
568 real,
intent(in) :: u_star_mean
570 real,
intent(inout) :: MLD_io
572 real,
intent(in) :: dt
573 real,
dimension(SZK_(GV)+1), &
576 real,
dimension(SZK_(GV)+1), &
577 intent(out) :: mixvel
579 real,
dimension(SZK_(GV)+1), &
580 intent(out) :: mixlen
581 type(energetic_PBL_CS),
pointer :: CS
583 type(ePBL_column_diags),
intent(inout) :: eCD
584 real,
optional,
intent(in) :: dt_diag
586 type(wave_parameters_CS), &
587 optional,
pointer :: Waves
588 type(ocean_grid_type), &
589 optional,
intent(inout) :: G
590 integer,
optional,
intent(in) :: i
591 integer,
optional,
intent(in) :: j
607 real,
dimension(SZK_(GV)+1) :: &
620 real :: Idecay_len_TKE
623 real,
dimension(SZK_(GV)) :: &
657 real,
dimension(SZK_(GV)+1) :: &
732 real :: TKE_left_min, TKE_left_max
733 real :: Kddt_h_max, Kddt_h_min
740 real :: vstar_unit_scale
742 logical :: convectively_stable
743 logical :: sfc_connected
745 logical :: sfc_disconnect
755 real :: MLD_guess, MLD_found
772 logical :: OBL_converged
775 real :: Surface_Scale
776 logical :: calc_dT_expect
778 logical :: debug=.false.
781 real :: dPE_debug, mixing_debug, taux2, tauy2
782 real,
dimension(20) :: TKE_left_itt, PE_chg_itt, Kddt_h_itt, dPEa_dKd_itt, MKE_src_itt
783 real,
dimension(SZK_(GV)) :: mech_TKE_k, conv_PErel_k, nstar_k
784 integer,
dimension(SZK_(GV)) :: num_itts
786 integer :: k, nz, itt, max_itt
790 if (.not.
associated(cs))
call mom_error(fatal,
"energetic_PBL: "//&
791 "Module must be initialized before it is used.")
793 calc_dt_expect = debug ;
if (
allocated(ecd%dT_expect) .or.
allocated(ecd%dS_expect)) calc_dt_expect = .true.
794 calc_te = (calc_dt_expect .or. (.not.cs%orig_PE_calc))
796 h_neglect = gv%H_subroundoff
799 dt__diag = dt ;
if (
present(dt_diag)) dt__diag = dt_diag
800 i_dtdiag = 1.0 / dt__diag
804 i_dtrho = 0.0 ;
if (dt*gv%Rho0 > 0.0) i_dtrho = (us%Z_to_m**3*us%s_to_T**3) / (dt*gv%Rho0)
805 vstar_unit_scale = us%m_to_Z * us%T_to_s
816 do k=1,nz+1 ; kd(k) = 0.0 ;
enddo 820 dmass = gv%H_to_RZ * h(k)
821 dpres = us%L_to_Z**2 * gv%g_Earth * dmass
822 dt_to_dpe(k) = (dmass * (pres_z(k) + 0.5*dpres)) * dsv_dt(k)
823 ds_to_dpe(k) = (dmass * (pres_z(k) + 0.5*dpres)) * dsv_ds(k)
824 dt_to_dcolht(k) = dmass * dsv_dt(k)
825 ds_to_dcolht(k) = dmass * dsv_ds(k)
827 pres_z(k+1) = pres_z(k) + dpres
831 h_sum = h_neglect ;
do k=1,nz ; h_sum = h_sum + h(k) ;
enddo 832 i_hs = 0.0 ;
if (h_sum > 0.0) i_hs = 1.0 / h_sum
837 hb_hs(k) = h_bot * i_hs
840 mld_output = h(1)*gv%H_to_Z
844 max_mld = 0.0 ;
do k=1,nz ; max_mld = max_mld + h(k)*gv%H_to_Z ;
enddo 848 dmld_min = -1.0*us%m_to_Z ; dmld_max = 1.0*us%m_to_Z
851 if (mld_guess <= min_mld) mld_guess = 0.5 * (min_mld + max_mld)
854 obl_converged = .false.
855 do obl_it=1,cs%Max_MLD_Its
857 if (.not. obl_converged)
then 859 if (.not.cs%Use_MLD_iteration) obl_converged = .true.
861 if (debug)
then ; mech_tke_k(:) = 0.0 ; conv_perel_k(:) = 0.0 ;
endif 864 mld_output = h(1)*gv%H_to_Z
865 sfc_connected = .true.
869 call get_langmuir_number(la, g, gv, us, abs(mld_guess), u_star_mean, i, j, &
870 h=h, u_h=u, v_h=v, waves=waves)
871 call find_mstar(cs, us, b_flux, u_star, u_star_mean, mld_guess, absf, &
872 mstar_total, langmuir_number=la, convect_langmuir_number=lamod,&
875 call find_mstar(cs, us, b_flux, u_star, u_star_mean, mld_guess, absf, mstar_total)
879 if ((cs%answers_2018) .and. (cs%mstar_scheme==use_fixed_mstar))
then 880 mech_tke = (dt*mstar_total*gv%Rho0) * u_star**3
882 mech_tke = mstar_total * (dt*gv%Rho0* u_star**3)
885 if (cs%TKE_diagnostics)
then 886 ecd%dTKE_conv = 0.0 ; ecd%dTKE_mixing = 0.0
887 ecd%dTKE_MKE = 0.0 ; ecd%dTKE_mech_decay = 0.0 ; ecd%dTKE_conv_decay = 0.0
889 ecd%dTKE_wind = mech_tke * i_dtdiag
890 if (tke_forcing(1) <= 0.0)
then 891 ecd%dTKE_forcing = max(-mech_tke, tke_forcing(1)) * i_dtdiag
894 ecd%dTKE_forcing = cs%nstar*tke_forcing(1) * i_dtdiag
899 if (tke_forcing(1) <= 0.0)
then 900 mech_tke = mech_tke + tke_forcing(1)
901 if (mech_tke < 0.0) mech_tke = 0.0
904 conv_perel = tke_forcing(1)
909 do k=1,nz+1 ; mixvel(k) = 0.0 ; mixlen(k) = 0.0 ;
enddo 912 if ((.not.cs%Use_MLD_iteration) .or. &
913 (cs%transLay_scale >= 1.0) .or. (cs%transLay_scale < 0.0) )
then 915 mixlen_shape(k) = 1.0
917 elseif (mld_guess <= 0.0)
then 918 if (cs%transLay_scale > 0.0)
then ;
do k=1,nz+1
919 mixlen_shape(k) = cs%transLay_scale
920 enddo ;
else ;
do k=1,nz+1
921 mixlen_shape(k) = 1.0
926 i_mld = 1.0 / mld_guess
928 mixlen_shape(1) = 1.0
930 h_rsum = h_rsum + h(k-1)*gv%H_to_Z
931 if (cs%MixLenExponent==2.0)
then 932 mixlen_shape(k) = cs%transLay_scale + (1.0 - cs%transLay_scale) * &
933 (max(0.0, (mld_guess - h_rsum)*i_mld) )**2
935 mixlen_shape(k) = cs%transLay_scale + (1.0 - cs%transLay_scale) * &
936 (max(0.0, (mld_guess - h_rsum)*i_mld) )**cs%MixLenExponent
941 kd(1) = 0.0 ; kddt_h(1) = 0.0
943 dt_to_dpe_a(1) = dt_to_dpe(1) ; dt_to_dcolht_a(1) = dt_to_dcolht(1)
944 ds_to_dpe_a(1) = ds_to_dpe(1) ; ds_to_dcolht_a(1) = ds_to_dcolht(1)
946 htot = h(1) ; uhtot = u(1)*h(1) ; vhtot = v(1)*h(1)
949 mech_tke_k(1) = mech_tke ; conv_perel_k(1) = conv_perel
950 nstar_k(:) = 0.0 ; nstar_k(1) = cs%nstar ; num_itts(:) = -1
961 idecay_len_tke = (cs%TKE_decay * absf / u_star) * gv%H_to_Z
963 if (idecay_len_tke > 0.0) exp_kh = exp(-h(k-1)*idecay_len_tke)
964 if (cs%TKE_diagnostics) &
965 ecd%dTKE_mech_decay = ecd%dTKE_mech_decay + (exp_kh-1.0) * mech_tke * i_dtdiag
966 mech_tke = mech_tke * exp_kh
970 if (tke_forcing(k) > 0.0)
then 971 conv_perel = conv_perel + tke_forcing(k)
972 if (cs%TKE_diagnostics) &
973 ecd%dTKE_forcing = ecd%dTKE_forcing + cs%nstar*tke_forcing(k) * i_dtdiag
977 mech_tke_k(k) = mech_tke ; conv_perel_k(k) = conv_perel
982 if (cs%nstar * conv_perel > 0.0)
then 986 nstar_fc = cs%nstar * conv_perel / (conv_perel + 0.2 * &
987 sqrt(0.5 * dt * gv%Rho0 * (absf*(htot*gv%H_to_Z))**3 * conv_perel))
990 if (debug) nstar_k(k) = nstar_fc
992 tot_tke = mech_tke + nstar_fc * conv_perel
996 if (tke_forcing(k) < 0.0)
then 997 if (tke_forcing(k) + tot_tke < 0.0)
then 999 if (cs%TKE_diagnostics)
then 1000 ecd%dTKE_mixing = ecd%dTKE_mixing + tot_tke * i_dtdiag
1001 ecd%dTKE_forcing = ecd%dTKE_forcing - tot_tke * i_dtdiag
1003 ecd%dTKE_conv_decay = ecd%dTKE_conv_decay + (cs%nstar-nstar_fc) * conv_perel * i_dtdiag
1005 tot_tke = 0.0 ; mech_tke = 0.0 ; conv_perel = 0.0
1008 tke_reduc = (tot_tke + tke_forcing(k)) / tot_tke
1009 if (cs%TKE_diagnostics)
then 1010 ecd%dTKE_mixing = ecd%dTKE_mixing - tke_forcing(k) * i_dtdiag
1011 ecd%dTKE_forcing = ecd%dTKE_forcing + tke_forcing(k) * i_dtdiag
1012 ecd%dTKE_conv_decay = ecd%dTKE_conv_decay + &
1013 (1.0-tke_reduc)*(cs%nstar-nstar_fc) * conv_perel * i_dtdiag
1015 tot_tke = tke_reduc*tot_tke
1016 mech_tke = tke_reduc*mech_tke
1017 conv_perel = tke_reduc*conv_perel
1022 if (cs%orig_PE_calc)
then 1024 dte_t2 = 0.0 ; dse_t2 = 0.0
1026 dte_t2 = kddt_h(k-1) * ((t0(k-2) - t0(k-1)) + dte(k-2))
1027 dse_t2 = kddt_h(k-1) * ((s0(k-2) - s0(k-1)) + dse(k-2))
1030 dt_h = (gv%Z_to_H**2*dt) / max(0.5*(h(k-1)+h(k)), 1e-15*h_sum)
1038 convectively_stable = ( 0.0 <= &
1039 ( (dt_to_dcolht(k) + dt_to_dcolht(k-1) ) * (t0(k-1)-t0(k)) + &
1040 (ds_to_dcolht(k) + ds_to_dcolht(k-1) ) * (s0(k-1)-s0(k)) ) )
1042 if ((mech_tke + conv_perel) <= 0.0 .and. convectively_stable)
then 1044 tot_tke = 0.0 ; mech_tke = 0.0 ; conv_perel = 0.0
1045 kd(k) = 0.0 ; kddt_h(k) = 0.0
1046 sfc_disconnect = .true.
1056 if (cs%orig_PE_calc)
then 1057 dte(k-1) = b1 * ( dte_t2 )
1058 dse(k-1) = b1 * ( dse_t2 )
1062 dt_to_dpe_a(k) = dt_to_dpe(k)
1063 ds_to_dpe_a(k) = ds_to_dpe(k)
1064 dt_to_dcolht_a(k) = dt_to_dcolht(k)
1065 ds_to_dcolht_a(k) = ds_to_dcolht(k)
1068 sfc_disconnect = .false.
1072 if (cs%orig_PE_calc)
then 1074 dt_km1_t2 = (t0(k)-t0(k-1))
1075 ds_km1_t2 = (s0(k)-s0(k-1))
1077 dt_km1_t2 = (t0(k)-t0(k-1)) - &
1078 (kddt_h(k-1) / hp_a) * ((t0(k-2) - t0(k-1)) + dte(k-2))
1079 ds_km1_t2 = (s0(k)-s0(k-1)) - &
1080 (kddt_h(k-1) / hp_a) * ((s0(k-2) - s0(k-1)) + dse(k-2))
1082 dte_term = dte_t2 + hp_a * (t0(k-1)-t0(k))
1083 dse_term = dse_t2 + hp_a * (s0(k-1)-s0(k))
1086 th_a(k-1) = h(k-1) * t0(k-1) ; sh_a(k-1) = h(k-1) * s0(k-1)
1088 th_a(k-1) = h(k-1) * t0(k-1) + kddt_h(k-1) * te(k-2)
1089 sh_a(k-1) = h(k-1) * s0(k-1) + kddt_h(k-1) * se(k-2)
1091 th_b(k) = h(k) * t0(k) ; sh_b(k) = h(k) * s0(k)
1099 if ((cs%MKE_to_TKE_effic > 0.0) .and. (htot*h(k) > 0.0))
then 1102 dmke_max = (us%L_to_Z**2*gv%H_to_RZ * cs%MKE_to_TKE_effic) * 0.5 * &
1103 (h(k) / ((htot + h(k))*htot)) * &
1104 ((uhtot-u(k)*htot)**2 + (vhtot-v(k)*htot)**2)
1107 mke2_hharm = (htot + h(k) + 2.0*h_neglect) / &
1108 ((htot+h_neglect) * (h(k)+h_neglect))
1117 h_tt = htot + h_tt_min
1118 tke_here = mech_tke + cs%wstar_ustar_coef*conv_perel
1119 if (tke_here > 0.0)
then 1120 if (cs%wT_scheme==wt_from_croot_tke)
then 1121 vstar = cs%vstar_scale_fac * vstar_unit_scale * (i_dtrho*tke_here)**c1_3
1122 elseif (cs%wT_scheme==wt_from_rh18)
then 1123 surface_scale = max(0.05, 1.0 - htot/mld_guess)
1124 vstar = cs%vstar_scale_fac * surface_scale * (cs%vstar_surf_fac*u_star + &
1125 vstar_unit_scale * (cs%wstar_ustar_coef*conv_perel*i_dtrho)**c1_3)
1127 hbs_here = gv%H_to_Z * min(hb_hs(k), mixlen_shape(k))
1128 mixlen(k) = max(cs%min_mix_len, ((h_tt*hbs_here)*vstar) / &
1129 ((cs%Ekman_scale_coef * absf) * (h_tt*hbs_here) + vstar))
1132 if (.not.cs%Use_MLD_iteration)
then 1133 kd_guess0 = vstar * cs%vonKar * ((h_tt*hbs_here)*vstar) / &
1134 ((cs%Ekman_scale_coef * absf) * (h_tt*hbs_here) + vstar)
1136 kd_guess0 = vstar * cs%vonKar * mixlen(k)
1139 vstar = 0.0 ; kd_guess0 = 0.0
1142 kddt_h_g0 = kd_guess0 * dt_h
1144 if (cs%orig_PE_calc)
then 1145 call find_pe_chg_orig(kddt_h_g0, h(k), hp_a, dte_term, dse_term, &
1146 dt_km1_t2, ds_km1_t2, dt_to_dpe(k), ds_to_dpe(k), &
1147 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), &
1148 pres_z(k), dt_to_dcolht(k), ds_to_dcolht(k), &
1149 dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1150 pe_chg=pe_chg_g0, dpe_max=pe_chg_max, dpec_dkd_0=dpec_dkd_kd0 )
1152 call find_pe_chg(0.0, kddt_h_g0, hp_a, h(k), &
1153 th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1154 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), dt_to_dpe(k), ds_to_dpe(k), &
1155 pres_z(k), dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1156 dt_to_dcolht(k), ds_to_dcolht(k), &
1157 pe_chg=pe_chg_g0, dpe_max=pe_chg_max, dpec_dkd_0=dpec_dkd_kd0 )
1160 mke_src = dmke_max*(1.0 - exp(-kddt_h_g0 * mke2_hharm))
1163 if ((pe_chg_g0 < 0.0) .or. ((vstar == 0.0) .and. (dpec_dkd_kd0 < 0.0)))
then 1165 if (pe_chg_max <= 0.0)
then 1167 tke_here = mech_tke + cs%wstar_ustar_coef*(conv_perel-pe_chg_max)
1168 if (tke_here > 0.0)
then 1169 if (cs%wT_scheme==wt_from_croot_tke)
then 1170 vstar = cs%vstar_scale_fac * vstar_unit_scale * (i_dtrho*tke_here)**c1_3
1171 elseif (cs%wT_scheme==wt_from_rh18)
then 1172 surface_scale = max(0.05, 1. - htot/mld_guess)
1173 vstar = cs%vstar_scale_fac * surface_scale * (cs%vstar_surf_fac*u_star + &
1174 vstar_unit_scale * (cs%wstar_ustar_coef*conv_perel*i_dtrho)**c1_3)
1176 hbs_here = gv%H_to_Z * min(hb_hs(k), mixlen_shape(k))
1177 mixlen(k) = max(cs%min_mix_len, ((h_tt*hbs_here)*vstar) / &
1178 ((cs%Ekman_scale_coef * absf) * (h_tt*hbs_here) + vstar))
1179 if (.not.cs%Use_MLD_iteration)
then 1182 kd(k) = vstar * cs%vonKar * ((h_tt*hbs_here)*vstar) / &
1183 ((cs%Ekman_scale_coef * absf) * (h_tt*hbs_here) + vstar)
1185 kd(k) = vstar * cs%vonKar * mixlen(k)
1188 vstar = 0.0 ; kd(k) = 0.0
1192 if (cs%orig_PE_calc)
then 1193 call find_pe_chg_orig(kd(k)*dt_h, h(k), hp_a, dte_term, dse_term, &
1194 dt_km1_t2, ds_km1_t2, dt_to_dpe(k), ds_to_dpe(k), &
1195 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), &
1196 pres_z(k), dt_to_dcolht(k), ds_to_dcolht(k), &
1197 dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1200 call find_pe_chg(0.0, kd(k)*dt_h, hp_a, h(k), &
1201 th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1202 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), dt_to_dpe(k), ds_to_dpe(k), &
1203 pres_z(k), dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1204 dt_to_dcolht(k), ds_to_dcolht(k), &
1208 if (dpe_conv > 0.0)
then 1209 kd(k) = kd_guess0 ; dpe_conv = pe_chg_g0
1211 mke_src = dmke_max*(1.0 - exp(-(kd(k)*dt_h) * mke2_hharm))
1215 kd(k) = kd_guess0 ; dpe_conv = pe_chg_g0
1218 conv_perel = conv_perel - dpe_conv
1219 mech_tke = mech_tke + mke_src
1220 if (cs%TKE_diagnostics)
then 1221 ecd%dTKE_conv = ecd%dTKE_conv - cs%nstar*dpe_conv * i_dtdiag
1222 ecd%dTKE_MKE = ecd%dTKE_MKE + mke_src * i_dtdiag
1224 if (sfc_connected)
then 1225 mld_output = mld_output + gv%H_to_Z * h(k)
1228 kddt_h(k) = kd(k) * dt_h
1229 elseif (tot_tke + (mke_src - pe_chg_g0) >= 0.0)
then 1233 kddt_h(k) = kddt_h_g0
1236 tot_tke = tot_tke + mke_src
1238 if (tot_tke > 0.0) tke_reduc = (tot_tke - pe_chg_g0) / tot_tke
1239 if (cs%TKE_diagnostics)
then 1240 ecd%dTKE_mixing = ecd%dTKE_mixing - pe_chg_g0 * i_dtdiag
1241 ecd%dTKE_MKE = ecd%dTKE_MKE + mke_src * i_dtdiag
1242 ecd%dTKE_conv_decay = ecd%dTKE_conv_decay + &
1243 (1.0-tke_reduc)*(cs%nstar-nstar_fc) * conv_perel * i_dtdiag
1245 tot_tke = tke_reduc*tot_tke
1246 mech_tke = tke_reduc*(mech_tke + mke_src)
1247 conv_perel = tke_reduc*conv_perel
1248 if (sfc_connected)
then 1249 mld_output = mld_output + gv%H_to_Z * h(k)
1252 elseif (tot_tke == 0.0)
then 1254 kd(k) = 0.0 ; kddt_h(k) = 0.0
1255 tot_tke = 0.0 ; conv_perel = 0.0 ; mech_tke = 0.0
1256 sfc_disconnect = .true.
1260 kddt_h_max = kddt_h_g0 ; kddt_h_min = 0.0
1261 tke_left_max = tot_tke + (mke_src - pe_chg_g0)
1262 tke_left_min = tot_tke
1266 kddt_h_guess = tot_tke * kddt_h_max / max( pe_chg_g0 - mke_src, &
1267 kddt_h_max * (dpec_dkd_kd0 - dmke_max * mke2_hharm) )
1274 tke_left_itt(:) = 0.0 ; dpea_dkd_itt(:) = 0.0 ; pe_chg_itt(:) = 0.0
1275 mke_src_itt(:) = 0.0 ; kddt_h_itt(:) = 0.0
1278 if (cs%orig_PE_calc)
then 1279 call find_pe_chg_orig(kddt_h_guess, h(k), hp_a, dte_term, dse_term, &
1280 dt_km1_t2, ds_km1_t2, dt_to_dpe(k), ds_to_dpe(k), &
1281 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), &
1282 pres_z(k), dt_to_dcolht(k), ds_to_dcolht(k), &
1283 dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1284 pe_chg=pe_chg, dpec_dkd=dpec_dkd )
1286 call find_pe_chg(0.0, kddt_h_guess, hp_a, h(k), &
1287 th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1288 dt_to_dpe_a(k-1), ds_to_dpe_a(k-1), dt_to_dpe(k), ds_to_dpe(k), &
1289 pres_z(k), dt_to_dcolht_a(k-1), ds_to_dcolht_a(k-1), &
1290 dt_to_dcolht(k), ds_to_dcolht(k), &
1291 pe_chg=dpe_conv, dpec_dkd=dpec_dkd)
1293 mke_src = dmke_max * (1.0 - exp(-mke2_hharm * kddt_h_guess))
1294 dmke_src_dk = dmke_max * mke2_hharm * exp(-mke2_hharm * kddt_h_guess)
1296 tke_left = tot_tke + (mke_src - pe_chg)
1297 if (debug .and. itt<=20)
then 1298 kddt_h_itt(itt) = kddt_h_guess ; mke_src_itt(itt) = mke_src
1299 pe_chg_itt(itt) = pe_chg ; dpea_dkd_itt(itt) = dpec_dkd
1300 tke_left_itt(itt) = tke_left
1304 if (tke_left >= 0.0)
then 1305 kddt_h_min = kddt_h_guess ; tke_left_min = tke_left
1307 kddt_h_max = kddt_h_guess ; tke_left_max = tke_left
1313 if (dpec_dkd - dmke_src_dk <= 0.0)
then 1316 dkddt_h_newt = tke_left / (dpec_dkd - dmke_src_dk)
1317 kddt_h_newt = kddt_h_guess + dkddt_h_newt
1318 if ((kddt_h_newt > kddt_h_max) .or. (kddt_h_newt < kddt_h_min)) &
1323 kddt_h_next = kddt_h_guess + dkddt_h_newt
1324 dkddt_h = dkddt_h_newt
1326 kddt_h_next = (tke_left_max * kddt_h_min - kddt_h_max * tke_left_min) / &
1327 (tke_left_max - tke_left_min)
1328 dkddt_h = kddt_h_next - kddt_h_guess
1331 if ((abs(dkddt_h) < 1e-9*kddt_h_guess) .or. (itt==max_itt))
then 1333 if (debug) num_itts(k) = itt
1336 kddt_h_guess = kddt_h_next
1339 kd(k) = kddt_h_guess / dt_h ; kddt_h(k) = kd(k) * dt_h
1342 if (cs%TKE_diagnostics)
then 1343 ecd%dTKE_mixing = ecd%dTKE_mixing - (tot_tke + mke_src) * i_dtdiag
1344 ecd%dTKE_MKE = ecd%dTKE_MKE + mke_src * i_dtdiag
1345 ecd%dTKE_conv_decay = ecd%dTKE_conv_decay + &
1346 (cs%nstar-nstar_fc) * conv_perel * i_dtdiag
1349 if (sfc_connected) mld_output = mld_output + &
1350 (pe_chg / (pe_chg_g0)) * gv%H_to_Z * h(k)
1352 tot_tke = 0.0 ; mech_tke = 0.0 ; conv_perel = 0.0
1353 sfc_disconnect = .true.
1356 kddt_h(k) = kd(k) * dt_h
1359 b1 = 1.0 / (hp_a + kddt_h(k))
1360 c1(k) = kddt_h(k) * b1
1361 if (cs%orig_PE_calc)
then 1362 dte(k-1) = b1 * ( kddt_h(k)*(t0(k)-t0(k-1)) + dte_t2 )
1363 dse(k-1) = b1 * ( kddt_h(k)*(s0(k)-s0(k-1)) + dse_t2 )
1366 hp_a = h(k) + (hp_a * b1) * kddt_h(k)
1367 dt_to_dpe_a(k) = dt_to_dpe(k) + c1(k)*dt_to_dpe_a(k-1)
1368 ds_to_dpe_a(k) = ds_to_dpe(k) + c1(k)*ds_to_dpe_a(k-1)
1369 dt_to_dcolht_a(k) = dt_to_dcolht(k) + c1(k)*dt_to_dcolht_a(k-1)
1370 ds_to_dcolht_a(k) = ds_to_dcolht(k) + c1(k)*ds_to_dcolht_a(k-1)
1375 if (sfc_disconnect)
then 1380 sfc_connected = .false.
1382 uhtot = uhtot + u(k)*h(k)
1383 vhtot = vhtot + v(k)*h(k)
1389 te(1) = b1*(h(1)*t0(1))
1390 se(1) = b1*(h(1)*s0(1))
1392 te(k-1) = b1 * (h(k-1) * t0(k-1) + kddt_h(k-1) * te(k-2))
1393 se(k-1) = b1 * (h(k-1) * s0(k-1) + kddt_h(k-1) * se(k-2))
1399 if (calc_dt_expect)
then 1402 te(nz) = b1 * (h(nz) * t0(nz) + kddt_h(nz) * te(nz-1))
1403 se(nz) = b1 * (h(nz) * s0(nz) + kddt_h(nz) * se(nz-1))
1404 ecd%dT_expect(nz) = te(nz) - t0(nz) ; ecd%dS_expect(nz) = se(nz) - s0(nz)
1406 te(k) = te(k) + c1(k+1)*te(k+1)
1407 se(k) = se(k) + c1(k+1)*se(k+1)
1408 ecd%dT_expect(k) = te(k) - t0(k) ; ecd%dS_expect(k) = se(k) - s0(k)
1415 dpe_debug = dpe_debug + (dt_to_dpe(k) * (te(k) - t0(k)) + &
1416 ds_to_dpe(k) * (se(k) - s0(k)))
1418 mixing_debug = dpe_debug * i_dtdiag
1429 mld_found = mld_output
1430 if (mld_found - mld_guess > cs%MLD_tol)
then 1431 min_mld = mld_guess ; dmld_min = mld_found - mld_guess
1432 elseif (abs(mld_found - mld_guess) < cs%MLD_tol)
then 1433 obl_converged = .true.
1435 max_mld = mld_guess ; dmld_max = mld_found - mld_guess
1438 if (.not.obl_converged)
then ;
if (cs%MLD_bisection)
then 1440 mld_guess = 0.5*(min_mld + max_mld)
1443 if ((dmld_min > 0.0) .and. (dmld_max < 0.0) .and. (obl_it > 2) .and. (mod(obl_it-1,4)>0))
then 1445 mld_guess = (dmld_min*max_mld - dmld_max*min_mld) / (dmld_min - dmld_max)
1446 elseif ((mld_found > min_mld) .and. (mld_found < max_mld))
then 1449 mld_guess = mld_found
1451 mld_guess = 0.5*(min_mld + max_mld)
1455 if ((obl_converged) .or. (obl_it==cs%Max_MLD_Its))
then 1456 if (report_avg_its)
then 1457 cs%sum_its(1) = cs%sum_its(1) + real_to_efp(
real(OBL_it))
1458 cs%sum_its(2) = cs%sum_its(2) + real_to_efp(1.0)
1464 ecd%LA = la ; ecd%LAmod = lamod ; ecd%mstar = mstar_total ; ecd%mstar_LT = mstar_lt
1466 ecd%LA = 0.0 ; ecd%LAmod = 0.0 ; ecd%mstar = mstar_total ; ecd%mstar_LT = 0.0
1471 end subroutine epbl_column
1475 subroutine find_pe_chg(Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, &
1476 dT_to_dPE_a, dS_to_dPE_a, dT_to_dPE_b, dS_to_dPE_b, &
1477 pres_Z, dT_to_dColHt_a, dS_to_dColHt_a, dT_to_dColHt_b, dS_to_dColHt_b, &
1478 PE_chg, dPEc_dKd, dPE_max, dPEc_dKd_0, PE_ColHt_cor)
1479 real,
intent(in) :: Kddt_h0
1482 real,
intent(in) :: dKddt_h
1485 real,
intent(in) :: hp_a
1489 real,
intent(in) :: hp_b
1493 real,
intent(in) :: Th_a
1496 real,
intent(in) :: Sh_a
1499 real,
intent(in) :: Th_b
1502 real,
intent(in) :: Sh_b
1505 real,
intent(in) :: dT_to_dPE_a
1509 real,
intent(in) :: dS_to_dPE_a
1513 real,
intent(in) :: dT_to_dPE_b
1517 real,
intent(in) :: dS_to_dPE_b
1521 real,
intent(in) :: pres_Z
1524 real,
intent(in) :: dT_to_dColHt_a
1528 real,
intent(in) :: dS_to_dColHt_a
1532 real,
intent(in) :: dT_to_dColHt_b
1536 real,
intent(in) :: dS_to_dColHt_b
1541 real,
optional,
intent(out) :: PE_chg
1543 real,
optional,
intent(out) :: dPEc_dKd
1545 real,
optional,
intent(out) :: dPE_max
1548 real,
optional,
intent(out) :: dPEc_dKd_0
1550 real,
optional,
intent(out) :: PE_ColHt_cor
1574 bdt1 = hp_a * hp_b + kddt_h0 * hps
1575 dt_c = hp_a * th_b - hp_b * th_a
1576 ds_c = hp_a * sh_b - hp_b * sh_a
1577 pec_core = hp_b * (dt_to_dpe_a * dt_c + ds_to_dpe_a * ds_c) - &
1578 hp_a * (dt_to_dpe_b * dt_c + ds_to_dpe_b * ds_c)
1579 colht_core = hp_b * (dt_to_dcolht_a * dt_c + ds_to_dcolht_a * ds_c) - &
1580 hp_a * (dt_to_dcolht_b * dt_c + ds_to_dcolht_b * ds_c)
1582 if (
present(pe_chg))
then 1585 y1_3 = dkddt_h / (bdt1 * (bdt1 + dkddt_h * hps))
1586 pe_chg = pec_core * y1_3
1587 colht_chg = colht_core * y1_3
1588 if (colht_chg < 0.0) pe_chg = pe_chg - pres_z * colht_chg
1589 if (
present(pe_colht_cor)) pe_colht_cor = -pres_z * min(colht_chg, 0.0)
1590 elseif (
present(pe_colht_cor))
then 1591 y1_3 = dkddt_h / (bdt1 * (bdt1 + dkddt_h * hps))
1592 pe_colht_cor = -pres_z * min(colht_core * y1_3, 0.0)
1595 if (
present(dpec_dkd))
then 1597 y1_4 = 1.0 / (bdt1 + dkddt_h * hps)**2
1598 dpec_dkd = pec_core * y1_4
1599 colht_chg = colht_core * y1_4
1600 if (colht_chg < 0.0) dpec_dkd = dpec_dkd - pres_z * colht_chg
1603 if (
present(dpe_max))
then 1605 y1_3 = 1.0 / (bdt1 * hps)
1606 dpe_max = pec_core * y1_3
1607 colht_chg = colht_core * y1_3
1608 if (colht_chg < 0.0) dpe_max = dpe_max - pres_z * colht_chg
1611 if (
present(dpec_dkd_0))
then 1613 y1_4 = 1.0 / bdt1**2
1614 dpec_dkd_0 = pec_core * y1_4
1615 colht_chg = colht_core * y1_4
1616 if (colht_chg < 0.0) dpec_dkd_0 = dpec_dkd_0 - pres_z * colht_chg
1619 end subroutine find_pe_chg
1624 subroutine find_pe_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, &
1625 dT_km1_t2, dS_km1_t2, dT_to_dPE_k, dS_to_dPE_k, &
1626 dT_to_dPEa, dS_to_dPEa, pres_Z, dT_to_dColHt_k, &
1627 dS_to_dColHt_k, dT_to_dColHta, dS_to_dColHta, &
1628 PE_chg, dPEc_dKd, dPE_max, dPEc_dKd_0)
1629 real,
intent(in) :: Kddt_h
1632 real,
intent(in) :: h_k
1633 real,
intent(in) :: b_den_1
1637 real,
intent(in) :: dTe_term
1639 real,
intent(in) :: dSe_term
1641 real,
intent(in) :: dT_km1_t2
1643 real,
intent(in) :: dS_km1_t2
1645 real,
intent(in) :: pres_Z
1648 real,
intent(in) :: dT_to_dPE_k
1652 real,
intent(in) :: dS_to_dPE_k
1656 real,
intent(in) :: dT_to_dPEa
1660 real,
intent(in) :: dS_to_dPEa
1664 real,
intent(in) :: dT_to_dColHt_k
1668 real,
intent(in) :: dS_to_dColHt_k
1672 real,
intent(in) :: dT_to_dColHta
1676 real,
intent(in) :: dS_to_dColHta
1681 real,
optional,
intent(out) :: PE_chg
1683 real,
optional,
intent(out) :: dPEc_dKd
1685 real,
optional,
intent(out) :: dPE_max
1688 real,
optional,
intent(out) :: dPEc_dKd_0
1705 real :: dT_k, dT_km1
1706 real :: dS_k, dS_km1
1709 real :: ddT_k_dKd, ddT_km1_dKd
1710 real :: ddS_k_dKd, ddS_km1_dKd
1712 b1 = 1.0 / (b_den_1 + kddt_h)
1720 i_kr_denom = 1.0 / (h_k*b_den_1 + (b_den_1 + h_k)*kddt_h)
1722 dt_k = (kddt_h*i_kr_denom) * dte_term
1723 ds_k = (kddt_h*i_kr_denom) * dse_term
1725 if (
present(pe_chg))
then 1728 dt_km1 = b1kd * ( dt_k + dt_km1_t2 )
1729 ds_km1 = b1kd * ( ds_k + ds_km1_t2 )
1730 pe_chg = (dt_to_dpe_k * dt_k + dt_to_dpea * dt_km1) + &
1731 (ds_to_dpe_k * ds_k + ds_to_dpea * ds_km1)
1732 colht_chg = (dt_to_dcolht_k * dt_k + dt_to_dcolhta * dt_km1) + &
1733 (ds_to_dcolht_k * ds_k + ds_to_dcolhta * ds_km1)
1734 if (colht_chg < 0.0) pe_chg = pe_chg - pres_z * colht_chg
1737 if (
present(dpec_dkd))
then 1739 dkr_dkd = (h_k*b_den_1) * i_kr_denom**2
1741 ddt_k_dkd = dkr_dkd * dte_term
1742 dds_k_dkd = dkr_dkd * dse_term
1743 ddt_km1_dkd = (b1**2 * b_den_1) * ( dt_k + dt_km1_t2 ) + b1kd * ddt_k_dkd
1744 dds_km1_dkd = (b1**2 * b_den_1) * ( ds_k + ds_km1_t2 ) + b1kd * dds_k_dkd
1747 dpec_dkd = (dt_to_dpe_k * ddt_k_dkd + dt_to_dpea * ddt_km1_dkd) + &
1748 (ds_to_dpe_k * dds_k_dkd + ds_to_dpea * dds_km1_dkd)
1749 dcolht_dkd = (dt_to_dcolht_k * ddt_k_dkd + dt_to_dcolhta * ddt_km1_dkd) + &
1750 (ds_to_dcolht_k * dds_k_dkd + ds_to_dcolhta * dds_km1_dkd)
1751 if (dcolht_dkd < 0.0) dpec_dkd = dpec_dkd - pres_z * dcolht_dkd
1754 if (
present(dpe_max))
then 1756 dpe_max = (dt_to_dpea * dt_km1_t2 + ds_to_dpea * ds_km1_t2) + &
1757 ((dt_to_dpe_k + dt_to_dpea) * dte_term + &
1758 (ds_to_dpe_k + ds_to_dpea) * dse_term) / (b_den_1 + h_k)
1759 dcolht_max = (dt_to_dcolhta * dt_km1_t2 + ds_to_dcolhta * ds_km1_t2) + &
1760 ((dt_to_dcolht_k + dt_to_dcolhta) * dte_term + &
1761 (ds_to_dcolht_k + ds_to_dcolhta) * dse_term) / (b_den_1 + h_k)
1762 if (dcolht_max < 0.0) dpe_max = dpe_max - pres_z*dcolht_max
1765 if (
present(dpec_dkd_0))
then 1767 dpec_dkd_0 = (dt_to_dpea * dt_km1_t2 + ds_to_dpea * ds_km1_t2) / (b_den_1) + &
1768 (dt_to_dpe_k * dte_term + ds_to_dpe_k * dse_term) / (h_k*b_den_1)
1769 dcolht_dkd = (dt_to_dcolhta * dt_km1_t2 + ds_to_dcolhta * ds_km1_t2) / (b_den_1) + &
1770 (dt_to_dcolht_k * dte_term + ds_to_dcolht_k * dse_term) / (h_k*b_den_1)
1771 if (dcolht_dkd < 0.0) dpec_dkd_0 = dpec_dkd_0 - pres_z*dcolht_dkd
1774 end subroutine find_pe_chg_orig
1777 subroutine find_mstar(CS, US, Buoyancy_Flux, UStar, UStar_Mean,&
1778 BLD, Abs_Coriolis, MStar, Langmuir_Number,&
1779 MStar_LT, Convect_Langmuir_Number)
1780 type(energetic_PBL_CS),
pointer :: CS
1781 type(unit_scale_type),
intent(in) :: US
1782 real,
intent(in) :: UStar
1783 real,
intent(in) :: UStar_Mean
1784 real,
intent(in) :: Abs_Coriolis
1785 real,
intent(in) :: Buoyancy_Flux
1786 real,
intent(in) :: BLD
1787 real,
intent(out) :: Mstar
1788 real,
optional,
intent(in) :: Langmuir_Number
1789 real,
optional,
intent(out) :: MStar_LT
1790 real,
optional,
intent(out) :: Convect_Langmuir_number
1794 real :: MSCR_term1, MSCR_term2
1795 real :: MStar_Conv_Red
1796 real :: MStar_S, MStar_N
1802 if (cs%mstar_scheme == use_fixed_mstar)
then 1803 mstar = cs%Fixed_MStar
1805 elseif (cs%mstar_scheme == mstar_from_ekman)
then 1807 if (cs%answers_2018)
then 1809 mstar_s = cs%MStar_coef*sqrt(max(0.0,buoyancy_flux) / ustar**2 / &
1810 (abs_coriolis + 1.e-10*us%T_to_s) )
1812 mstar_n = cs%C_Ek * log( max( 1., ustar / (abs_coriolis + 1.e-10*us%T_to_s) / bld ) )
1815 mstar_s = cs%MSTAR_COEF*sqrt(max(0.0, buoyancy_flux) / (ustar**2 * max(abs_coriolis, 1.e-20*us%T_to_s)))
1818 if (ustar > abs_coriolis * bld) mstar_n = cs%C_EK * log(ustar / (abs_coriolis * bld))
1822 mstar = max(mstar_s, min(1.25, mstar_n))
1823 if (cs%MStar_Cap > 0.0) mstar = min( cs%MStar_Cap,mstar )
1824 elseif ( cs%mstar_scheme == mstar_from_rh18 )
then 1825 if (cs%answers_2018)
then 1826 mstar_n = cs%RH18_MStar_cn1 * ( 1.0 - 1.0 / ( 1. + cs%RH18_MStar_cn2 * &
1827 exp( cs%RH18_mstar_CN3 * bld * abs_coriolis / ustar) ) )
1829 msn_term = cs%RH18_MStar_cn2 * exp( cs%RH18_mstar_CN3 * bld * abs_coriolis / ustar)
1830 mstar_n = (cs%RH18_MStar_cn1 * msn_term) / ( 1. + msn_term)
1832 mstar_s = cs%RH18_MStar_CS1 * ( max(0.0, buoyancy_flux)**2 * bld / &
1833 ( ustar**5 * max(abs_coriolis,1.e-20*us%T_to_s) ) )**cs%RH18_mstar_cs2
1834 mstar = mstar_n + mstar_s
1838 if (cs%answers_2018)
then 1839 mstar_conv_red = 1. - cs%MStar_Convect_coef * (-min(0.0,buoyancy_flux) + 1.e-10*us%T_to_s**3*us%m_to_Z**2) / &
1840 ( (-min(0.0,buoyancy_flux) + 1.e-10*us%T_to_s**3*us%m_to_Z**2) + &
1841 2.0 *mstar * ustar**3 / bld )
1843 mscr_term1 = -bld * min(0.0, buoyancy_flux)
1844 mscr_term2 = 2.0*mstar * ustar**3
1845 if ( abs(mscr_term2) > 0.0)
then 1846 mstar_conv_red = ((1.-cs%mstar_convect_coef) * mscr_term1 + mscr_term2) / (mscr_term1 + mscr_term2)
1848 mstar_conv_red = 1.-cs%mstar_convect_coef
1853 mstar = mstar * mstar_conv_red
1855 if (
present(langmuir_number))
then 1857 call mstar_langmuir(cs, us, abs_coriolis, buoyancy_flux, ustar, bld, langmuir_number, mstar, &
1858 mstar_lt, convect_langmuir_number)
1861 end subroutine find_mstar
1864 subroutine mstar_langmuir(CS, US, Abs_Coriolis, Buoyancy_Flux, UStar, BLD, Langmuir_Number, &
1865 Mstar, MStar_LT, Convect_Langmuir_Number)
1866 type(energetic_PBL_CS),
pointer :: CS
1867 type(unit_scale_type),
intent(in) :: US
1868 real,
intent(in) :: Abs_Coriolis
1869 real,
intent(in) :: Buoyancy_Flux
1870 real,
intent(in) :: UStar
1871 real,
intent(in) :: BLD
1872 real,
intent(inout) :: Mstar
1873 real,
intent(in) :: Langmuir_Number
1874 real,
intent(out) :: MStar_LT
1875 real,
intent(out) :: Convect_Langmuir_number
1878 real,
parameter :: Max_ratio = 1.0e16
1879 real :: enhance_mstar
1880 real :: mstar_LT_add
1886 real :: Ekman_Obukhov
1888 real :: MLD_Obukhov_stab
1889 real :: Ekman_Obukhov_stab
1890 real :: MLD_Obukhov_un
1891 real :: Ekman_Obukhov_un
1894 enhance_mstar = 1.0 ; mstar_lt_add = 0.0
1896 if (cs%LT_Enhance_Form /= no_langmuir)
then 1898 if (cs%answers_2018)
then 1899 il_ekman = abs_coriolis / ustar
1900 il_obukhov = buoyancy_flux*cs%vonkar / ustar**3
1901 ekman_obukhov_stab = abs(max(0., il_obukhov / (il_ekman + 1.e-10*us%Z_to_m)))
1902 ekman_obukhov_un = abs(min(0., il_obukhov / (il_ekman + 1.e-10*us%Z_to_m)))
1903 mld_obukhov_stab = abs(max(0., bld*il_obukhov))
1904 mld_obukhov_un = abs(min(0., bld*il_obukhov))
1905 mld_ekman = abs( bld*il_ekman )
1907 ekman_obukhov = max_ratio ; mld_obukhov = max_ratio ; mld_ekman = max_ratio
1908 i_f = 0.0 ;
if (abs(abs_coriolis) > 0.0) i_f = 1.0 / abs_coriolis
1909 i_ustar = 0.0 ;
if (abs(ustar) > 0.0) i_ustar = 1.0 / ustar
1910 if (abs(buoyancy_flux*cs%vonkar) < max_ratio*(abs_coriolis * ustar**2)) &
1911 ekman_obukhov = abs(buoyancy_flux*cs%vonkar) * (i_f * i_ustar**2)
1912 if (abs(bld*buoyancy_flux*cs%vonkar) < max_ratio*ustar**3) &
1913 mld_obukhov = abs(bld*buoyancy_flux*cs%vonkar) * i_ustar**3
1914 if (bld*abs_coriolis < max_ratio*ustar) &
1915 mld_ekman = bld*abs_coriolis * i_ustar
1917 if (buoyancy_flux > 0.0)
then 1918 ekman_obukhov_stab = ekman_obukhov ; ekman_obukhov_un = 0.0
1919 mld_obukhov_stab = mld_obukhov ; mld_obukhov_un = 0.0
1921 ekman_obukhov_un = ekman_obukhov ; ekman_obukhov_stab = 0.0
1922 mld_obukhov_un = mld_obukhov ; mld_obukhov_stab = 0.0
1929 convect_langmuir_number = langmuir_number * &
1930 ( (1.0 + max(-0.5, cs%LaC_MLDoEK * mld_ekman)) + &
1931 ((cs%LaC_EKoOB_stab * ekman_obukhov_stab + cs%LaC_EKoOB_un * ekman_obukhov_un) + &
1932 (cs%LaC_MLDoOB_stab * mld_obukhov_stab + cs%LaC_MLDoOB_un * mld_obukhov_un)) )
1934 if (cs%LT_Enhance_Form == langmuir_rescale)
then 1936 enhance_mstar = min(cs%Max_Enhance_M, &
1937 (1. + cs%LT_ENHANCE_COEF * convect_langmuir_number**cs%LT_ENHANCE_EXP) )
1938 elseif (cs%LT_ENHANCE_Form == langmuir_add)
then 1940 mstar_lt_add = cs%LT_ENHANCE_COEF * convect_langmuir_number**cs%LT_ENHANCE_EXP
1944 mstar_lt = (enhance_mstar - 1.0)*mstar + mstar_lt_add
1945 mstar = mstar*enhance_mstar + mstar_lt_add
1947 end subroutine mstar_langmuir
1951 subroutine energetic_pbl_get_mld(CS, MLD, G, US, m_to_MLD_units)
1955 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: mld
1956 real,
optional,
intent(in) :: m_to_mld_units
1962 scale = 1.0 ;
if (
present(m_to_mld_units)) scale = us%Z_to_m * m_to_mld_units
1964 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
1965 mld(i,j) = scale*cs%ML_Depth(i,j)
1968 end subroutine energetic_pbl_get_mld
1972 subroutine energetic_pbl_init(Time, G, GV, US, param_file, diag, CS)
1973 type(time_type),
target,
intent(in) :: time
1978 type(
diag_ctrl),
target,
intent(inout) :: diag
1983 # include "version_variable.h" 1984 character(len=40) :: mdl =
"MOM_energetic_PBL" 1985 character(len=20) :: tmpstr
1986 real :: omega_frac_dflt
1987 integer :: isd, ied, jsd, jed
1988 integer :: mstar_mode, lt_enhance, wt_mode
1989 logical :: default_2018_answers
1990 logical :: use_temperature, use_omega
1991 logical :: use_la_windsea
1992 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1994 if (
associated(cs))
then 1995 call mom_error(warning,
"mixedlayer_init called with an associated"//&
1996 "associated control structure.")
1998 else ;
allocate(cs) ;
endif 2008 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
2009 "The rotation rate of the earth.", units=
"s-1", &
2010 default=7.2921e-5, scale=us%T_to_S)
2011 call get_param(param_file, mdl,
"ML_USE_OMEGA", use_omega, &
2012 "If true, use the absolute rotation rate instead of the "//&
2013 "vertical component of rotation when setting the decay "//&
2014 "scale for turbulence.", default=.false., do_not_log=.true.)
2015 omega_frac_dflt = 0.0
2017 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
2018 omega_frac_dflt = 1.0
2020 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%omega_frac, &
2021 "When setting the decay scale for turbulence, use this "//&
2022 "fraction of the absolute rotation rate blended with the "//&
2023 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
2024 units=
"nondim", default=omega_frac_dflt)
2025 call get_param(param_file, mdl,
"EKMAN_SCALE_COEF", cs%Ekman_scale_coef, &
2026 "A nondimensional scaling factor controlling the inhibition "//&
2027 "of the diffusive length scale by rotation. Making this larger "//&
2028 "decreases the PBL diffusivity.", units=
"nondim", default=1.0)
2029 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
2030 "This sets the default value for the various _2018_ANSWERS parameters.", &
2032 call get_param(param_file, mdl,
"EPBL_2018_ANSWERS", cs%answers_2018, &
2033 "If true, use the order of arithmetic and expressions that recover the "//&
2034 "answers from the end of 2018. Otherwise, use updated and more robust "//&
2035 "forms of the same expressions.", default=default_2018_answers)
2038 call get_param(param_file, mdl,
"EPBL_ORIGINAL_PE_CALC", cs%orig_PE_calc, &
2039 "If true, the ePBL code uses the original form of the "//&
2040 "potential energy change code. Otherwise, the newer "//&
2041 "version that can work with successive increments to the "//&
2042 "diffusivity in upward or downward passes is used.", default=.true.)
2044 call get_param(param_file, mdl,
"MKE_TO_TKE_EFFIC", cs%MKE_to_TKE_effic, &
2045 "The efficiency with which mean kinetic energy released "//&
2046 "by mechanically forced entrainment of the mixed layer "//&
2047 "is converted to turbulent kinetic energy.", units=
"nondim", &
2049 call get_param(param_file, mdl,
"TKE_DECAY", cs%TKE_decay, &
2050 "TKE_DECAY relates the vertical rate of decay of the "//&
2051 "TKE available for mechanical entrainment to the natural "//&
2052 "Ekman depth.", units=
"nondim", default=2.5)
2056 call get_param(param_file, mdl,
"EPBL_MSTAR_SCHEME", tmpstr, &
2057 "EPBL_MSTAR_SCHEME selects the method for setting mstar. Valid values are: \n"//&
2058 "\t CONSTANT - Use a fixed mstar given by MSTAR \n"//&
2059 "\t OM4 - Use L_Ekman/L_Obukhov in the sabilizing limit, as in OM4 \n"//&
2060 "\t REICHL_H18 - Use the scheme documented in Reichl & Hallberg, 2018.", &
2061 default=constant_string, do_not_log=.true.)
2062 call get_param(param_file, mdl,
"MSTAR_MODE", mstar_mode, default=-1)
2063 if (mstar_mode == 0)
then 2064 tmpstr = constant_string
2065 call mom_error(warning,
"Use EPBL_MSTAR_SCHEME = CONSTANT instead of the archaic MSTAR_MODE = 0.")
2066 elseif (mstar_mode == 1)
then 2067 call mom_error(fatal,
"You are using a legacy mstar mode in ePBL that has been phased out. "//&
2068 "If you need to use this setting please report this error. Also use "//&
2069 "EPBL_MSTAR_SCHEME to specify the scheme for mstar.")
2070 elseif (mstar_mode == 2)
then 2072 call mom_error(warning,
"Use EPBL_MSTAR_SCHEME = OM4 instead of the archaic MSTAR_MODE = 2.")
2073 elseif (mstar_mode == 3)
then 2074 tmpstr = rh18_string
2075 call mom_error(warning,
"Use EPBL_MSTAR_SCHEME = REICHL_H18 instead of the archaic MSTAR_MODE = 3.")
2076 elseif (mstar_mode > 3)
then 2077 call mom_error(fatal,
"An unrecognized value of the obsolete parameter MSTAR_MODE was specified.")
2079 call log_param(param_file, mdl,
"EPBL_MSTAR_SCHEME", tmpstr, &
2080 "EPBL_MSTAR_SCHEME selects the method for setting mstar. Valid values are: \n"//&
2081 "\t CONSTANT - Use a fixed mstar given by MSTAR \n"//&
2082 "\t OM4 - Use L_Ekman/L_Obukhov in the sabilizing limit, as in OM4 \n"//&
2083 "\t REICHL_H18 - Use the scheme documented in Reichl & Hallberg, 2018.", &
2084 default=constant_string)
2085 tmpstr = uppercase(tmpstr)
2086 select case (tmpstr)
2087 case (constant_string)
2088 cs%mstar_Scheme = use_fixed_mstar
2090 cs%mstar_Scheme = mstar_from_ekman
2092 cs%mstar_Scheme = mstar_from_rh18
2094 call mom_mesg(
'energetic_PBL_init: EPBL_MSTAR_SCHEME ="'//trim(tmpstr)//
'"', 0)
2095 call mom_error(fatal,
"energetic_PBL_init: Unrecognized setting "// &
2096 "EPBL_MSTAR_SCHEME = "//trim(tmpstr)//
" found in input file.")
2099 call get_param(param_file, mdl,
"MSTAR", cs%fixed_mstar, &
2100 "The ratio of the friction velocity cubed to the TKE input to the "//&
2101 "mixed layer. This option is used if EPBL_MSTAR_SCHEME = CONSTANT.", &
2102 units=
"nondim", default=1.2, do_not_log=(cs%mstar_scheme/=use_fixed_mstar))
2103 call get_param(param_file, mdl,
"MSTAR_CAP", cs%mstar_cap, &
2104 "If this value is positive, it sets the maximum value of mstar "//&
2105 "allowed in ePBL. (This is not used if EPBL_MSTAR_SCHEME = CONSTANT).", &
2106 units=
"nondim", default=-1.0, do_not_log=(cs%mstar_scheme==use_fixed_mstar))
2108 call get_param(param_file, mdl,
"MSTAR2_COEF1", cs%MSTAR_COEF, &
2109 "Coefficient in computing mstar when rotation and stabilizing "//&
2110 "effects are both important (used if EPBL_MSTAR_SCHEME = OM4).", &
2111 units=
"nondim", default=0.3, do_not_log=(cs%mstar_scheme/=mstar_from_ekman))
2112 call get_param(param_file, mdl,
"MSTAR2_COEF2", cs%C_EK, &
2113 "Coefficient in computing mstar when only rotation limits "// &
2114 "the total mixing (used if EPBL_MSTAR_SCHEME = OM4)", &
2115 units=
"nondim", default=0.085, do_not_log=(cs%mstar_scheme/=mstar_from_ekman))
2117 call get_param(param_file, mdl,
"RH18_MSTAR_CN1", cs%RH18_mstar_cn1,&
2118 "MSTAR_N coefficient 1 (outter-most coefficient for fit). "//&
2119 "The value of 0.275 is given in RH18. Increasing this "//&
2120 "coefficient increases MSTAR for all values of Hf/ust, but more "//&
2121 "effectively at low values (weakly developed OSBLs).", &
2122 units=
"nondim", default=0.275, do_not_log=(cs%mstar_scheme/=mstar_from_rh18))
2123 call get_param(param_file, mdl,
"RH18_MSTAR_CN2", cs%RH18_mstar_cn2,&
2124 "MSTAR_N coefficient 2 (coefficient outside of exponential decay). "//&
2125 "The value of 8.0 is given in RH18. Increasing this coefficient "//&
2126 "increases MSTAR for all values of HF/ust, with a much more even "//&
2127 "effect across a wide range of Hf/ust than CN1.", &
2128 units=
"nondim", default=8.0, do_not_log=(cs%mstar_scheme/=mstar_from_rh18))
2129 call get_param(param_file, mdl,
"RH18_MSTAR_CN3", cs%RH18_mstar_CN3,&
2130 "MSTAR_N coefficient 3 (exponential decay coefficient). "//&
2131 "The value of -5.0 is given in RH18. Increasing this increases how "//&
2132 "quickly the value of MSTAR decreases as Hf/ust increases.", &
2133 units=
"nondim", default=-5.0, do_not_log=(cs%mstar_scheme/=mstar_from_rh18))
2134 call get_param(param_file, mdl,
"RH18_MSTAR_CS1", cs%RH18_mstar_cs1,&
2135 "MSTAR_S coefficient for RH18 in stabilizing limit. "//&
2136 "The value of 0.2 is given in RH18 and increasing it increases "//&
2137 "MSTAR in the presence of a stabilizing surface buoyancy flux.", &
2138 units=
"nondim", default=0.2, do_not_log=(cs%mstar_scheme/=mstar_from_rh18))
2139 call get_param(param_file, mdl,
"RH18_MSTAR_CS2", cs%RH18_mstar_cs2,&
2140 "MSTAR_S exponent for RH18 in stabilizing limit. "//&
2141 "The value of 0.4 is given in RH18 and increasing it increases MSTAR "//&
2142 "exponentially in the presence of a stabilizing surface buoyancy flux.", &
2143 units=
"nondim", default=0.4, do_not_log=(cs%mstar_scheme/=mstar_from_rh18))
2147 call get_param(param_file, mdl,
"NSTAR", cs%nstar, &
2148 "The portion of the buoyant potential energy imparted by "//&
2149 "surface fluxes that is available to drive entrainment "//&
2150 "at the base of mixed layer when that energy is positive.", &
2151 units=
"nondim", default=0.2)
2152 call get_param(param_file, mdl,
"MSTAR_CONV_ADJ", cs%mstar_convect_coef, &
2153 "Coefficient used for reducing mstar during convection "//&
2154 "due to reduction of stable density gradient.", &
2155 units=
"nondim", default=0.0)
2158 call get_param(param_file, mdl,
"USE_MLD_ITERATION", cs%Use_MLD_iteration, &
2159 "A logical that specifies whether or not to use the "//&
2160 "distance to the bottom of the actively turbulent boundary "//&
2161 "layer to help set the EPBL length scale.", default=.true.)
2162 call get_param(param_file, mdl,
"EPBL_TRANSITION_SCALE", cs%transLay_scale, &
2163 "A scale for the mixing length in the transition layer "//&
2164 "at the edge of the boundary layer as a fraction of the "//&
2165 "boundary layer thickness.", units=
"nondim", default=0.1)
2166 if ( cs%Use_MLD_iteration .and. abs(cs%transLay_scale-0.5) >= 0.5)
then 2167 call mom_error(fatal,
"If flag USE_MLD_ITERATION is true, then "//&
2168 "EPBL_TRANSITION should be greater than 0 and less than 1.")
2171 call get_param(param_file, mdl,
"MLD_ITERATION_GUESS", cs%MLD_ITERATION_GUESS, &
2172 "If true, use the previous timestep MLD as a first guess in the MLD iteration, "//&
2173 "otherwise use half the ocean depth as the first guess of the boundary layer "//&
2174 "depth. The default is false to facilitate reproducibility.", &
2175 default=.false., do_not_log=.not.cs%Use_MLD_iteration)
2176 call get_param(param_file, mdl,
"EPBL_MLD_TOLERANCE", cs%MLD_tol, &
2177 "The tolerance for the iteratively determined mixed "//&
2178 "layer depth. This is only used with USE_MLD_ITERATION.", &
2179 units=
"meter", default=1.0, scale=us%m_to_Z, do_not_log=.not.cs%Use_MLD_iteration)
2180 call get_param(param_file, mdl,
"EPBL_MLD_BISECTION", cs%MLD_bisection, &
2181 "If true, use bisection with the iterative determination of the self-consistent "//&
2182 "mixed layer depth. Otherwise use the false position after a maximum and minimum "//&
2183 "bound have been evaluated and the returned value or bisection before this.", &
2184 default=.true., do_not_log=.not.cs%Use_MLD_iteration)
2185 call get_param(param_file, mdl,
"EPBL_MLD_MAX_ITS", cs%max_MLD_its, &
2186 "The maximum number of iterations that can be used to find a self-consistent "//&
2187 "mixed layer depth. If EPBL_MLD_BISECTION is true, the maximum number "//&
2188 "iteractions needed is set by Depth/2^MAX_ITS < EPBL_MLD_TOLERANCE.", &
2189 default=20, do_not_log=.not.cs%Use_MLD_iteration)
2190 if (.not.cs%Use_MLD_iteration) cs%Max_MLD_Its = 1
2191 call get_param(param_file, mdl,
"EPBL_MIN_MIX_LEN", cs%min_mix_len, &
2192 "The minimum mixing length scale that will be used "//&
2193 "by ePBL. The default (0) does not set a minimum.", &
2194 units=
"meter", default=0.0, scale=us%m_to_Z)
2196 call get_param(param_file, mdl,
"MIX_LEN_EXPONENT", cs%MixLenExponent, &
2197 "The exponent applied to the ratio of the distance to the MLD "//&
2198 "and the MLD depth which determines the shape of the mixing length. "//&
2199 "This is only used if USE_MLD_ITERATION is True.", &
2200 units=
"nondim", default=2.0)
2203 call get_param(param_file, mdl,
"EPBL_VEL_SCALE_SCHEME", tmpstr, &
2204 "Selects the method for translating TKE into turbulent velocities. "//&
2205 "Valid values are: \n"//&
2206 "\t CUBE_ROOT_TKE - A constant times the cube root of remaining TKE. \n"//&
2207 "\t REICHL_H18 - Use the scheme based on a combination of w* and v* as \n"//&
2208 "\t documented in Reichl & Hallberg, 2018.", &
2209 default=root_tke_string, do_not_log=.true.)
2210 call get_param(param_file, mdl,
"EPBL_VEL_SCALE_MODE", wt_mode, default=-1)
2211 if (wt_mode == 0)
then 2212 tmpstr = root_tke_string
2213 call mom_error(warning,
"Use EPBL_VEL_SCALE_SCHEME = CUBE_ROOT_TKE instead of the archaic EPBL_VEL_SCALE_MODE = 0.")
2214 elseif (wt_mode == 1)
then 2215 tmpstr = rh18_string
2216 call mom_error(warning,
"Use EPBL_VEL_SCALE_SCHEME = REICHL_H18 instead of the archaic EPBL_VEL_SCALE_MODE = 1.")
2217 elseif (wt_mode >= 2)
then 2218 call mom_error(fatal,
"An unrecognized value of the obsolete parameter EPBL_VEL_SCALE_MODE was specified.")
2220 call log_param(param_file, mdl,
"EPBL_VEL_SCALE_SCHEME", tmpstr, &
2221 "Selects the method for translating TKE into turbulent velocities. "//&
2222 "Valid values are: \n"//&
2223 "\t CUBE_ROOT_TKE - A constant times the cube root of remaining TKE. \n"//&
2224 "\t REICHL_H18 - Use the scheme based on a combination of w* and v* as \n"//&
2225 "\t documented in Reichl & Hallberg, 2018.", &
2226 default=root_tke_string)
2227 tmpstr = uppercase(tmpstr)
2228 select case (tmpstr)
2229 case (root_tke_string)
2230 cs%wT_scheme = wt_from_croot_tke
2232 cs%wT_scheme = wt_from_rh18
2234 call mom_mesg(
'energetic_PBL_init: EPBL_VEL_SCALE_SCHEME ="'//trim(tmpstr)//
'"', 0)
2235 call mom_error(fatal,
"energetic_PBL_init: Unrecognized setting "// &
2236 "EPBL_VEL_SCALE_SCHEME = "//trim(tmpstr)//
" found in input file.")
2239 call get_param(param_file, mdl,
"WSTAR_USTAR_COEF", cs%wstar_ustar_coef, &
2240 "A ratio relating the efficiency with which convectively "//&
2241 "released energy is converted to a turbulent velocity, "//&
2242 "relative to mechanically forced TKE. Making this larger "//&
2243 "increases the BL diffusivity", units=
"nondim", default=1.0)
2244 call get_param(param_file, mdl,
"EPBL_VEL_SCALE_FACTOR", cs%vstar_scale_fac, &
2245 "An overall nondimensional scaling factor for wT. "//&
2246 "Making this larger increases the PBL diffusivity.", &
2247 units=
"nondim", default=1.0)
2248 call get_param(param_file, mdl,
"VSTAR_SURF_FAC", cs%vstar_surf_fac,&
2249 "The proportionality times ustar to set vstar at the surface.", &
2250 units=
"nondim", default=1.2)
2253 call get_param(param_file, mdl,
"USE_LA_LI2016", use_la_windsea, &
2254 "A logical to use the Li et al. 2016 (submitted) formula to "//&
2255 "determine the Langmuir number.", units=
"nondim", default=.false.)
2257 if (use_la_windsea)
then 2260 call get_param(param_file, mdl,
"EPBL_LT", cs%USE_LT, &
2261 "A logical to use a LT parameterization.", &
2262 units=
"nondim", default=.false.)
2265 call get_param(param_file, mdl,
"EPBL_LANGMUIR_SCHEME", tmpstr, &
2266 "EPBL_LANGMUIR_SCHEME selects the method for including Langmuir turbulence. "//&
2267 "Valid values are: \n"//&
2268 "\t NONE - Do not do any extra mixing due to Langmuir turbulence \n"//&
2269 "\t RESCALE - Use a multiplicative rescaling of mstar to account for Langmuir turbulence \n"//&
2270 "\t ADDITIVE - Add a Langmuir turblence contribution to mstar to other contributions", &
2271 default=none_string, do_not_log=.true.)
2272 call get_param(param_file, mdl,
"LT_ENHANCE", lt_enhance, default=-1)
2273 if (lt_enhance == 0)
then 2274 tmpstr = none_string
2275 call mom_error(warning,
"Use EPBL_LANGMUIR_SCHEME = NONE instead of the archaic LT_ENHANCE = 0.")
2276 elseif (lt_enhance == 1)
then 2277 call mom_error(fatal,
"You are using a legacy LT_ENHANCE mode in ePBL that has been phased out. "//&
2278 "If you need to use this setting please report this error. Also use "//&
2279 "EPBL_LANGMUIR_SCHEME to specify the scheme for mstar.")
2280 elseif (lt_enhance == 2)
then 2281 tmpstr = rescaled_string
2282 call mom_error(warning,
"Use EPBL_LANGMUIR_SCHEME = RESCALE instead of the archaic LT_ENHANCE = 2.")
2283 elseif (lt_enhance == 3)
then 2284 tmpstr = additive_string
2285 call mom_error(warning,
"Use EPBL_LANGMUIR_SCHEME = ADDITIVE instead of the archaic LT_ENHANCE = 3.")
2286 elseif (lt_enhance > 3)
then 2287 call mom_error(fatal,
"An unrecognized value of the obsolete parameter LT_ENHANCE was specified.")
2289 call log_param(param_file, mdl,
"EPBL_LANGMUIR_SCHEME", tmpstr, &
2290 "EPBL_LANGMUIR_SCHEME selects the method for including Langmuir turbulence. "//&
2291 "Valid values are: \n"//&
2292 "\t NONE - Do not do any extra mixing due to Langmuir turbulence \n"//&
2293 "\t RESCALE - Use a multiplicative rescaling of mstar to account for Langmuir turbulence \n"//&
2294 "\t ADDITIVE - Add a Langmuir turblence contribution to mstar to other contributions", &
2295 default=none_string)
2296 tmpstr = uppercase(tmpstr)
2297 select case (tmpstr)
2299 cs%LT_enhance_form = no_langmuir
2300 case (rescaled_string)
2301 cs%LT_enhance_form = langmuir_rescale
2302 case (additive_string)
2303 cs%LT_enhance_form = langmuir_add
2305 call mom_mesg(
'energetic_PBL_init: EPBL_LANGMUIR_SCHEME ="'//trim(tmpstr)//
'"', 0)
2306 call mom_error(fatal,
"energetic_PBL_init: Unrecognized setting "// &
2307 "EPBL_LANGMUIR_SCHEME = "//trim(tmpstr)//
" found in input file.")
2310 call get_param(param_file, mdl,
"LT_ENHANCE_COEF", cs%LT_ENHANCE_COEF, &
2311 "Coefficient for Langmuir enhancement of mstar", &
2312 units=
"nondim", default=0.447, do_not_log=(cs%LT_enhance_form==no_langmuir))
2313 call get_param(param_file, mdl,
"LT_ENHANCE_EXP", cs%LT_ENHANCE_EXP, &
2314 "Exponent for Langmuir enhancementt of mstar", &
2315 units=
"nondim", default=-1.33, do_not_log=(cs%LT_enhance_form==no_langmuir))
2316 call get_param(param_file, mdl,
"LT_MOD_LAC1", cs%LaC_MLDoEK, &
2317 "Coefficient for modification of Langmuir number due to "//&
2318 "MLD approaching Ekman depth.", &
2319 units=
"nondim", default=-0.87, do_not_log=(cs%LT_enhance_form==no_langmuir))
2320 call get_param(param_file, mdl,
"LT_MOD_LAC2", cs%LaC_MLDoOB_stab, &
2321 "Coefficient for modification of Langmuir number due to "//&
2322 "MLD approaching stable Obukhov depth.", &
2323 units=
"nondim", default=0.0, do_not_log=(cs%LT_enhance_form==no_langmuir))
2324 call get_param(param_file, mdl,
"LT_MOD_LAC3", cs%LaC_MLDoOB_un, &
2325 "Coefficient for modification of Langmuir number due to "//&
2326 "MLD approaching unstable Obukhov depth.", &
2327 units=
"nondim", default=0.0, do_not_log=(cs%LT_enhance_form==no_langmuir))
2328 call get_param(param_file, mdl,
"LT_MOD_LAC4", cs%Lac_EKoOB_stab, &
2329 "Coefficient for modification of Langmuir number due to "//&
2330 "ratio of Ekman to stable Obukhov depth.", &
2331 units=
"nondim", default=0.95, do_not_log=(cs%LT_enhance_form==no_langmuir))
2332 call get_param(param_file, mdl,
"LT_MOD_LAC5", cs%Lac_EKoOB_un, &
2333 "Coefficient for modification of Langmuir number due to "//&
2334 "ratio of Ekman to unstable Obukhov depth.", &
2335 units=
"nondim", default=0.95, do_not_log=(cs%LT_enhance_form==no_langmuir))
2341 cs%ustar_min = 2e-4*cs%omega*(gv%Angstrom_Z + gv%H_to_Z*gv%H_subroundoff)
2342 call log_param(param_file, mdl,
"!EPBL_USTAR_MIN", cs%ustar_min*us%Z_to_m*us%s_to_T, &
2343 "The (tiny) minimum friction velocity used within the "//&
2344 "ePBL code, derived from OMEGA and ANGSTROM.", units=
"m s-1", &
2345 like_default=.true.)
2349 cs%id_ML_depth = register_diag_field(
'ocean_model',
'ePBL_h_ML', diag%axesT1, &
2350 time,
'Surface boundary layer depth',
'm', conversion=us%Z_to_m, &
2351 cmor_long_name=
'Ocean Mixed Layer Thickness Defined by Mixing Scheme')
2353 cs%id_hML_depth = register_diag_field(
'ocean_model',
'h_ML', diag%axesT1, &
2354 time,
'Surface mixed layer depth based on active turbulence',
'm', conversion=us%Z_to_m)
2355 cs%id_TKE_wind = register_diag_field(
'ocean_model',
'ePBL_TKE_wind', diag%axesT1, &
2356 time,
'Wind-stirring source of mixed layer TKE',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2357 cs%id_TKE_MKE = register_diag_field(
'ocean_model',
'ePBL_TKE_MKE', diag%axesT1, &
2358 time,
'Mean kinetic energy source of mixed layer TKE',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2359 cs%id_TKE_conv = register_diag_field(
'ocean_model',
'ePBL_TKE_conv', diag%axesT1, &
2360 time,
'Convective source of mixed layer TKE',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2361 cs%id_TKE_forcing = register_diag_field(
'ocean_model',
'ePBL_TKE_forcing', diag%axesT1, &
2362 time,
'TKE consumed by mixing surface forcing or penetrative shortwave radation '//&
2363 'through model layers',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2364 cs%id_TKE_mixing = register_diag_field(
'ocean_model',
'ePBL_TKE_mixing', diag%axesT1, &
2365 time,
'TKE consumed by mixing that deepens the mixed layer',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2366 cs%id_TKE_mech_decay = register_diag_field(
'ocean_model',
'ePBL_TKE_mech_decay', diag%axesT1, &
2367 time,
'Mechanical energy decay sink of mixed layer TKE',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2368 cs%id_TKE_conv_decay = register_diag_field(
'ocean_model',
'ePBL_TKE_conv_decay', diag%axesT1, &
2369 time,
'Convective energy decay sink of mixed layer TKE',
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2370 cs%id_Mixing_Length = register_diag_field(
'ocean_model',
'Mixing_Length', diag%axesTi, &
2371 time,
'Mixing Length that is used',
'm', conversion=us%Z_to_m)
2372 cs%id_Velocity_Scale = register_diag_field(
'ocean_model',
'Velocity_Scale', diag%axesTi, &
2373 time,
'Velocity Scale that is used.',
'm s-1', conversion=us%Z_to_m*us%s_to_T)
2374 cs%id_MSTAR_mix = register_diag_field(
'ocean_model',
'MSTAR', diag%axesT1, &
2375 time,
'Total mstar that is used.',
'nondim')
2378 cs%id_LA = register_diag_field(
'ocean_model',
'LA', diag%axesT1, &
2379 time,
'Langmuir number.',
'nondim')
2380 cs%id_LA_mod = register_diag_field(
'ocean_model',
'LA_MOD', diag%axesT1, &
2381 time,
'Modified Langmuir number.',
'nondim')
2382 cs%id_MSTAR_LT = register_diag_field(
'ocean_model',
'MSTAR_LT', diag%axesT1, &
2383 time,
'Increase in mstar due to Langmuir Turbulence.',
'nondim')
2386 call get_param(param_file, mdl,
"ENABLE_THERMODYNAMICS", use_temperature, &
2387 "If true, temperature and salinity are used as state "//&
2388 "variables.", default=.true.)
2390 if (report_avg_its)
then 2391 cs%sum_its(1) = real_to_efp(0.0) ; cs%sum_its(2) = real_to_efp(0.0)
2394 if (max(cs%id_TKE_wind, cs%id_TKE_MKE, cs%id_TKE_conv, &
2395 cs%id_TKE_mixing, cs%id_TKE_mech_decay, cs%id_TKE_forcing, &
2396 cs%id_TKE_conv_decay) > 0)
then 2397 call safe_alloc_alloc(cs%diag_TKE_wind, isd, ied, jsd, jed)
2398 call safe_alloc_alloc(cs%diag_TKE_MKE, isd, ied, jsd, jed)
2399 call safe_alloc_alloc(cs%diag_TKE_conv, isd, ied, jsd, jed)
2400 call safe_alloc_alloc(cs%diag_TKE_forcing, isd, ied, jsd, jed)
2401 call safe_alloc_alloc(cs%diag_TKE_mixing, isd, ied, jsd, jed)
2402 call safe_alloc_alloc(cs%diag_TKE_mech_decay, isd, ied, jsd, jed)
2403 call safe_alloc_alloc(cs%diag_TKE_conv_decay, isd, ied, jsd, jed)
2405 cs%TKE_diagnostics = .true.
2407 if (cs%id_Velocity_Scale>0)
call safe_alloc_alloc(cs%Velocity_Scale, isd, ied, jsd, jed, gv%ke+1)
2408 if (cs%id_Mixing_Length>0)
call safe_alloc_alloc(cs%Mixing_Length, isd, ied, jsd, jed, gv%ke+1)
2410 call safe_alloc_alloc(cs%ML_depth, isd, ied, jsd, jed)
2411 if (max(cs%id_mstar_mix, cs%id_LA, cs%id_LA_mod, cs%id_MSTAR_LT ) >0)
then 2412 call safe_alloc_alloc(cs%Mstar_mix, isd, ied, jsd, jed)
2413 call safe_alloc_alloc(cs%LA, isd, ied, jsd, jed)
2414 call safe_alloc_alloc(cs%LA_MOD, isd, ied, jsd, jed)
2415 call safe_alloc_alloc(cs%MSTAR_LT, isd, ied, jsd, jed)
2418 end subroutine energetic_pbl_init
2421 subroutine energetic_pbl_end(CS)
2425 character(len=256) :: mesg
2428 if (.not.
associated(cs))
return 2430 if (
allocated(cs%ML_depth))
deallocate(cs%ML_depth)
2431 if (
allocated(cs%LA))
deallocate(cs%LA)
2432 if (
allocated(cs%LA_MOD))
deallocate(cs%LA_MOD)
2433 if (
allocated(cs%MSTAR_MIX))
deallocate(cs%MSTAR_MIX)
2434 if (
allocated(cs%MSTAR_LT))
deallocate(cs%MSTAR_LT)
2435 if (
allocated(cs%diag_TKE_wind))
deallocate(cs%diag_TKE_wind)
2436 if (
allocated(cs%diag_TKE_MKE))
deallocate(cs%diag_TKE_MKE)
2437 if (
allocated(cs%diag_TKE_conv))
deallocate(cs%diag_TKE_conv)
2438 if (
allocated(cs%diag_TKE_forcing))
deallocate(cs%diag_TKE_forcing)
2439 if (
allocated(cs%diag_TKE_mixing))
deallocate(cs%diag_TKE_mixing)
2440 if (
allocated(cs%diag_TKE_mech_decay))
deallocate(cs%diag_TKE_mech_decay)
2441 if (
allocated(cs%diag_TKE_conv_decay))
deallocate(cs%diag_TKE_conv_decay)
2442 if (
allocated(cs%Mixing_Length))
deallocate(cs%Mixing_Length)
2443 if (
allocated(cs%Velocity_Scale))
deallocate(cs%Velocity_Scale)
2445 if (report_avg_its)
then 2448 avg_its = efp_to_real(cs%sum_its(1)) / efp_to_real(cs%sum_its(2))
2449 write (mesg,*)
"Average ePBL iterations = ", avg_its
2455 end subroutine energetic_pbl_end
This module implements boundary forcing for MOM6.
A type for conveniently passing around ePBL diagnostics for a column.
Ocean grid type. See mom_grid for details.
Sum a value or 1-d array of values across processors, returning the sums in place.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Wraps the MPP cpu clock functions.
This control structure holds parameters for the MOM_energetic_PBL module.
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Interfaces to non-domain-oriented communication subroutines, including the MOM6 reproducing sums faci...
Interface for surface waves.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Describes the decomposed MOM domain and has routines for communications across PEs.
Routines for error handling and I/O management.
Container for all surface wave related parameters.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Energetically consistent planetary boundary layer parameterization.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Set up a group of halo updates.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Handy functions for manipulating strings.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.
The Extended Fixed Point (EFP) type provides a public interface for doing sums and taking differences...