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)
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
584 real,
optional,
intent(in) :: dt_diag
587 optional,
pointer :: Waves
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)
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)
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