MOM6
mom_energetic_pbl Module Reference

Data Types

type  energetic_pbl_cs
 

Functions/Subroutines

subroutine, public energetic_pbl (h_3d, u_3d, v_3d, tv, fluxes, dt, Kd_int, G, GV, CS, dSV_dT, dSV_dS, TKE_forced, Buoy_Flux, dt_diag, last_call, dT_expected, dS_expected)
 This subroutine determines the diffusivities from the integrated energetics mixed layer model. It assumes that heating, cooling and freshwater fluxes have already been applied. All calculations are done implicitly, and there is no stability limit on the time step. More...
 
subroutine find_pe_chg (Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, dT_to_dPE_a, dS_to_dPE_a, dT_to_dPE_b, dS_to_dPE_b, pres, dT_to_dColHt_a, dS_to_dColHt_a, dT_to_dColHt_b, dS_to_dColHt_b, PE_chg, dPEc_dKd, dPE_max, dPEc_dKd_0, ColHt_cor)
 This subroutine calculates the change in potential energy and or derivatives for several changes in an interfaces's diapycnal diffusivity times a timestep. More...
 
subroutine find_pe_chg_orig (Kddt_h, h_k, b_den_1, dTe_term, dSe_term, dT_km1_t2, dS_km1_t2, dT_to_dPE_k, dS_to_dPE_k, dT_to_dPEa, dS_to_dPEa, pres, dT_to_dColHt_k, dS_to_dColHt_k, dT_to_dColHta, dS_to_dColHta, PE_chg, dPEc_dKd, dPE_max, dPEc_dKd_0)
 This subroutine calculates the change in potential energy and or derivatives for several changes in an interfaces's diapycnal diffusivity times a timestep using the original form used in the first version of ePBL. More...
 
subroutine, public energetic_pbl_get_mld (CS, MLD, G)
 Copies the ePBL active mixed layer depth into MLD. More...
 
subroutine ust_2_u10_coare3p5 (USTair, U10, GV)
 Computes wind speed from ustar_air based on COARE 3.5 Cd relationship. More...
 
subroutine get_la_windsea (ustar, hbl, GV, LA)
 
subroutine, public energetic_pbl_init (Time, G, GV, param_file, diag, CS)
 
subroutine, public energetic_pbl_end (CS)
 

Variables

integer num_msg = 0
 
integer max_msg = 2
 

Function/Subroutine Documentation

◆ energetic_pbl()

subroutine, public mom_energetic_pbl::energetic_pbl ( real, dimension(szi_(g),szj_(g),szk_(gv)), intent(inout)  h_3d,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(in)  u_3d,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(in)  v_3d,
type(thermo_var_ptrs), intent(inout)  tv,
type(forcing), intent(inout)  fluxes,
real, intent(in)  dt,
real, dimension(szi_(g),szj_(g),szk_(gv)+1), intent(out)  Kd_int,
type(ocean_grid_type), intent(inout)  G,
type(verticalgrid_type), intent(in)  GV,
type(energetic_pbl_cs), pointer  CS,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(in)  dSV_dT,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(in)  dSV_dS,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(in)  TKE_forced,
real, dimension(szi_(g),szj_(g)), intent(in)  Buoy_Flux,
real, intent(in), optional  dt_diag,
logical, intent(in), optional  last_call,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(out), optional  dT_expected,
real, dimension(szi_(g),szj_(g),szk_(gv)), intent(out), optional  dS_expected 
)

This subroutine determines the diffusivities from the integrated energetics mixed layer model. It assumes that heating, cooling and freshwater fluxes have already been applied. All calculations are done implicitly, and there is no stability limit on the time step.

Parameters
[in,out]gThe ocean's grid structure.
[in]gvThe ocean's vertical grid structure.
[in,out]h_3dLayer thickness, in m or kg m-2.
[in]u_3dZonal velocities interpolated to h points,
[in]v_3dZonal velocities interpolated to h points,
[in]dsv_dtThe partial derivative of in-situ specific
[in]dsv_dsThe partial derivative of in-situ specific
[in]tke_forcedThe forcing requirements to homogenize the
[in,out]tvA structure containing pointers to any available thermodynamic fields. Absent fields have NULL ptrs.
[in,out]fluxesA structure containing pointers to any possible forcing fields. Unused fields have NULL ptrs.
[in]dtTime increment, in s.
[out]kd_intThe diagnosed diffusivities at interfaces,
csThe control structure returned by a previous call to mixedlayer_init.
[in]buoy_fluxThe surface buoyancy flux. in m2/s3.
[in]dt_diagThe diagnostic time step, which may be less than dt if there are two callse to mixedlayer, in s.
[in]last_callIf true, this is the last call to mixedlayer in the current time step, so diagnostics will be written. The default is .true.

Definition at line 237 of file MOM_energetic_PBL.F90.

References find_pe_chg(), find_pe_chg_orig(), get_la_windsea(), and mom_error_handler::mom_error().

237  type(ocean_grid_type), intent(inout) :: g !< The ocean's grid structure.
238  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
239  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
240  intent(inout) :: h_3d !< Layer thickness, in m or kg m-2.
241  !! (Intent in/out) The units of h are referred
242  !! to as H below.
243  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
244  intent(in) :: u_3d !< Zonal velocities interpolated to h points,
245  !! m s-1.
246  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
247  intent(in) :: v_3d !< Zonal velocities interpolated to h points,
248  !! m s-1.
249  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
250  intent(in) :: dsv_dt !< The partial derivative of in-situ specific
251  !! volume with potential temperature,
252  !! in m3 kg-1 K-1.
253  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
254  intent(in) :: dsv_ds !< The partial derivative of in-situ specific
255  !! volume with salinity, in m3 kg-1 ppt-1.
256  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
257  intent(in) :: tke_forced !< The forcing requirements to homogenize the
258  !! forcing that has been applied to each layer
259  !! through each layer, in J m-2.
260  type(thermo_var_ptrs), intent(inout) :: tv !< A structure containing pointers to any
261  !! available thermodynamic fields. Absent fields
262  !! have NULL ptrs.
263  type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
264  !! possible forcing fields. Unused fields have
265  !! NULL ptrs.
266  real, intent(in) :: dt !< Time increment, in s.
267  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), &
268  intent(out) :: kd_int !< The diagnosed diffusivities at interfaces,
269  !! in m2 s-1.
270  type(energetic_pbl_cs), pointer :: cs !< The control structure returned by a previous
271  !! call to mixedlayer_init.
272  real, dimension(SZI_(G),SZJ_(G)), &
273  intent(in) :: buoy_flux !< The surface buoyancy flux. in m2/s3.
274  real, optional, intent(in) :: dt_diag !< The diagnostic time step, which may be less
275  !! than dt if there are two callse to
276  !! mixedlayer, in s.
277  logical, optional, intent(in) :: last_call !< If true, this is the last call to
278  !! mixedlayer in the current time step, so
279  !! diagnostics will be written. The default
280  !! is .true.
281  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
282  optional, intent(out) :: dt_expected, ds_expected
283 
284 ! This subroutine determines the diffusivities from the integrated energetics
285 ! mixed layer model. It assumes that heating, cooling and freshwater fluxes
286 ! have already been applied. All calculations are done implicitly, and there
287 ! is no stability limit on the time step.
288 !
289 ! For each interior interface, first discard the TKE to account for mixing
290 ! of shortwave radiation through the next denser cell. Next drive mixing based
291 ! on the local? values of ustar + wstar, subject to available energy. This
292 ! step sets the value of Kd(K). Any remaining energy is then subject to decay
293 ! before being handed off to the next interface. mech_TKE and conv_PErel are treated
294 ! separately for the purposes of decay, but are used proportionately to drive
295 ! mixing.
296 !
297 ! The key parameters for the mixed layer are found in the control structure.
298 ! These include mstar, nstar, TKE_decay, and conv_decay. For the Oberhuber (1993) mixed layer,
299 ! the values of these are:
300 ! mstar = 1.25, nstar = 1, TKE_decay = 2.5, conv_decay = 0.5
301 ! TKE_decay is 1/kappa in eq. 28 of Oberhuber (1993), while
302 ! conv_decay is 1/mu.
303 ! For a traditional Kraus-Turner mixed layer, the values are:
304 ! mstar = 1.25, nstar = 0.4, TKE_decay = 0.0, conv_decay = 0.0
305 
306 ! Arguments: h_3d - Layer thickness, in m or kg m-2. (Intent in/out)
307 ! The units of h are referred to as H below.
308 ! (in) u_3d - Zonal velocities interpolated to h points, m s-1.
309 ! (in) v_3d - Zonal velocities interpolated to h points, m s-1.
310 ! (in/out) tv - A structure containing pointers to any available
311 ! thermodynamic fields. Absent fields have NULL ptrs.
312 ! (in) fluxes - A structure containing pointers to any possible
313 ! forcing fields. Unused fields have NULL ptrs.
314 ! (in) dt - Time increment, in s.
315 ! (out) Kd_int - The diagnosed diffusivities at interfaces, in m2 s-1.
316 ! (in) G - The ocean's grid structure.
317 ! (in) GV - The ocean's vertical grid structure.
318 ! (in) CS - The control structure returned by a previous call to
319 ! mixedlayer_init.
320 ! (in) dSV_dT - The partial derivative of in-situ specific volume with
321 ! potential temperature, in m3 kg-1 K-1.
322 ! (in) dSV_dS - The partial derivative of in-situ specific volume with
323 ! salinity, in m3 kg-1 ppt-1.
324 ! (in) TKE_forced - The forcing requirements to homogenize the forcing
325 ! that has been applied to each layer through each layer, in J m-2.
326 ! (in) Buoy_Flux - The surface buoyancy flux. in m2/s3.
327 ! (in,opt) dt_diag - The diagnostic time step, which may be less than dt
328 ! if there are two callse to mixedlayer, in s.
329 ! (in,opt) last_call - if true, this is the last call to mixedlayer in the
330 ! current time step, so diagnostics will be written.
331 ! The default is .true.
332 
333  real, dimension(SZI_(G),SZK_(GV)) :: &
334  h, & ! The layer thickness, in H (usually m or kg m-2).
335  t, & ! The layer temperatures, in deg C.
336  s, & ! The layer salinities, in psu.
337  u, & ! The zonal velocity, in m s-1.
338  v ! The meridional velocity, in m s-1.
339  real, dimension(SZI_(G),SZK_(GV)+1) :: &
340  kd, & ! The diapycnal diffusivity, in m2 s-1.
341  pres, & ! Interface pressures in Pa.
342  hb_hs ! The distance from the bottom over the thickness of the
343  ! water column, nondim.
344  real, dimension(SZI_(G)) :: &
345  mech_tke, & ! The mechanically generated turbulent kinetic energy
346  ! available for mixing over a time step, in J m-2 = kg s-2.
347  conv_perel, & ! The potential energy that has been convectively released
348  ! during this timestep, in J m-2 = kg s-2. A portion nstar_FC
349  ! of conv_PErel is available to drive mixing.
350  htot, & ! The total depth of the layers above an interface, in H.
351  uhtot, & ! The depth integrated zonal and meridional velocities in the
352  vhtot, & ! layers above, in H m s-1.
353  mech_tke_top, & ! The value of mech_TKE at the top of the column, in J m-2.
354  conv_perel_top, & ! The value of conv_PErel at the top of the column, in J m-2.
355 
356  idecay_len_tke, & ! The inverse of a turbulence decay length scale, in H-1.
357  h_sum, & ! The total thickness of the water column, in H.
358  absf ! The absolute value of f, in s-1.
359 
360 
361  real, dimension(SZI_(G),SZK_(GV)) :: &
362  dt_to_dcolht, & ! Partial derivatives of the total column height with the temperature
363  ds_to_dcolht, & ! and salinity changes within a layer, in m K-1 and m ppt-1.
364  dt_to_dpe, & ! Partial derivatives of column potential energy with the temperature
365  ds_to_dpe, & ! and salinity changes within a layer, in J m-2 K-1 and J m-2 ppt-1.
366  dt_to_dcolht_a, & ! Partial derivatives of the total column height with the temperature
367  ds_to_dcolht_a, & ! and salinity changes within a layer, including the implicit effects
368  ! of mixing with layers higher in the water colun, in m K-1 and m ppt-1.
369  dt_to_dpe_a, & ! Partial derivatives of column potential energy with the temperature
370  ds_to_dpe_a ! and salinity changes within a layer, including the implicit effects
371  ! of mixing with layers higher in the water column, in
372  ! units of J m-2 K-1 and J m-2 ppt-1.
373  real, dimension(SZK_(GV)) :: &
374  t0, s0, & ! Initial values of T and S in the column, in K and ppt.
375  te, se, & ! Estimated final values of T and S in the column, in K and ppt.
376  c1, & ! c1 is used by the tridiagonal solver, ND.
377  dte, dse ! Running (1-way) estimates of temperature and salinity change.
378  real, dimension(SZK_(GV)) :: &
379  th_a, & ! An effective temperature times a thickness in the layer above,
380  ! including implicit mixing effects with other yet higher layers, in K H.
381  sh_a, & ! An effective salinity times a thickness in the layer above,
382  ! including implicit mixing effects with other yet higher layers, in K H.
383  th_b, & ! An effective temperature times a thickness in the layer below,
384  ! including implicit mixing effects with other yet lower layers, in K H.
385  sh_b ! An effective salinity times a thickness in the layer below,
386  ! including implicit mixing effects with other yet lower layers, in K H.
387  real, dimension(SZI_(G)) :: &
388  hp_a ! An effective pivot thickness of the layer including the effects
389  ! of coupling with layers above, in H. This is the first term
390  ! in the denominator of b1 in a downward-oriented tridiagonal solver.
391  real, dimension(SZK_(GV)+1) :: &
392  mixlen_shape, & ! A nondimensional shape factor for the mixing length that
393  ! gives it an appropriate assymptotic value at the bottom of
394  ! the boundary layer.
395  kddt_h ! The diapycnal diffusivity times a timestep divided by the
396  ! average thicknesses around a layer, in H (m or kg m-2).
397  real :: b1 ! b1 is inverse of the pivot used by the tridiagonal solver, in H-1.
398  real :: h_neglect ! A thickness that is so small it is usually lost
399  ! in roundoff and can be neglected, in H.
400  real :: dmass ! The mass per unit area within a layer, in kg m-2.
401  real :: dpres ! The hydrostatic pressure change across a layer, in Pa.
402  real :: dmke_max ! The maximum amount of mean kinetic energy that could be
403  ! converted to turbulent kinetic energy if the velocity in
404  ! the layer below an interface were homogenized with all of
405  ! the water above the interface, in J m-2 = kg s-2.
406  real :: mke2_hharm ! Twice the inverse of the harmonic mean of the thickness
407  ! of a layer and the thickness of the water above, used in
408  ! the MKE conversion equation, in H-1.
409 
410  real :: dt_h ! The timestep divided by the averages of the thicknesses around
411  ! a layer, times a thickness conversion factor, in H s m-2.
412  real :: h_bot ! The distance from the bottom, in H.
413  real :: h_rsum ! The running sum of h from the top, in H.
414  real :: i_hs ! The inverse of h_sum, in H-1.
415  real :: i_mld ! The inverse of the current value of MLD, in H-1.
416  real :: h_tt ! The distance from the surface or up to the next interface
417  ! that did not exhibit turbulent mixing from this scheme plus
418  ! a surface mixing roughness length given by h_tt_min, in H.
419  real :: h_tt_min ! A surface roughness length, in H.
420 
421  real :: c1_3 ! = 1/3.
422  real :: vonkar ! The vonKarman constant.
423  real :: i_dtrho ! 1.0 / (dt * Rho0) in m3 kg-1 s-1. This is
424  ! used convert TKE back into ustar^3.
425  real :: u_star ! The surface friction velocity, in m s-1.
426  real :: u_star_mean ! The surface friction without gustiness in m s-1.
427  real :: vstar ! An in-situ turbulent velocity, in m s-1.
428  real :: enhance_m ! An enhancement factor for vstar, based here on Langmuir impact.
429  real :: la ! The Langmuir number (non-dim)
430  real :: lamod ! A modified Langmuir number accounting for other parameters.
431  real :: hbs_here ! The local minimum of hb_hs and MixLen_shape, times a
432  ! conversion factor from H to M, in m H-1.
433  real :: nstar_fc ! The fraction of conv_PErel that can be converted to mixing, nondim.
434  real :: tke_reduc ! The fraction by which TKE and other energy fields are
435  ! reduced to support mixing, nondim. between 0 and 1.
436  real :: tot_tke ! The total TKE available to support mixing at interface K, in J m-2.
437  real :: tke_here ! The total TKE at this point in the algorithm, in J m-2.
438  real :: dt_km1_t2 ! A diffusivity-independent term related to the temperature
439  ! change in the layer above the interface, in K.
440  real :: ds_km1_t2 ! A diffusivity-independent term related to the salinity
441  ! change in the layer above the interface, in ppt.
442  real :: dte_term ! A diffusivity-independent term related to the temperature
443  ! change in the layer below the interface, in K H.
444  real :: dse_term ! A diffusivity-independent term related to the salinity
445  ! change in the layer above the interface, in ppt H.
446  real :: dte_t2 ! A part of dTe_term, in K H.
447  real :: dse_t2 ! A part of dSe_term, in ppt H.
448  real :: dpe_conv ! The convective change in column potential energy, in J m-2.
449  real :: mke_src ! The mean kinetic energy source of TKE due to Kddt_h(K), in J m-2.
450  real :: dmke_src_dk ! The partial derivative of MKE_src with Kddt_h(K), in J m-2 H-1.
451  real :: kd_guess0, pe_chg_g0, dpea_dkd_g0, kddt_h_g0
452  real :: pe_chg_max ! The maximum PE change for very large values of Kddt_h(K).
453  real :: dpec_dkd_kd0 ! The partial derivative of PE change with Kddt_h(K)
454  ! for very small values of Kddt_h(K), in J m-2 H-1.
455  real :: pe_chg ! The change in potential energy due to mixing at an
456  ! interface, in J m-2, positive for the column increasing
457  ! in potential energy (i.e., consuming TKE).
458  real :: tke_left ! The amount of turbulent kinetic energy left for the most
459  ! recent guess at Kddt_h(K), in J m-2.
460  real :: dpec_dkd ! The partial derivative of PE_chg with Kddt_h(K), in J m-2 H-1.
461  real :: tke_left_min, tke_left_max, kddt_h_max, kddt_h_min
462  real :: kddt_h_guess ! A guess at the value of Kddt_h(K), in H.
463  real :: kddt_h_next ! The next guess at the value of Kddt_h(K), in H.
464  real :: dkddt_h ! The change between guesses at Kddt_h(K), in H.
465  real :: dkddt_h_newt ! The change between guesses at Kddt_h(K) with Newton's method, in H.
466  real :: kddt_h_newt ! The Newton's method next guess for Kddt_h(K), in H.
467  real :: exp_kh ! The nondimensional decay of TKE across a layer, ND.
468  logical :: use_newt ! Use Newton's method for the next guess at Kddt_h(K).
469  logical :: convectively_stable
470  logical, dimension(SZI_(G)) :: &
471  sfc_connected ! If true the ocean is actively turbulent from the present
472  ! interface all the way up to the surface.
473  logical :: sfc_disconnect ! If true, any turbulence has become disconnected
474  ! from the surface.
475 
476 ! The following is only used as a diagnostic.
477  real :: dt__diag ! A copy of dt_diag (if present) or dt, in s.
478  real :: idtdr0 ! = 1.0 / (dt__diag * Rho0), in m3 kg-1 s-1.
479  real, dimension(SZI_(G),SZJ_(G)) :: &
480  hsfc_used ! The thickness of the surface region after buffer layer
481  logical :: write_diags ! If true, write out diagnostics with this step.
482  logical :: reset_diags ! If true, zero out the accumulated diagnostics.
483  ! detrainment, in units of m.
484  ! Local column copies of energy change diagnostics, all in J m-2.
485  real :: dtke_conv, dtke_forcing, dtke_mixing
486  real :: dtke_mke, dtke_mech_decay, dtke_conv_decay
487  !----------------------------------------------------------------------
488  !/BGR added Aug24,2016 for adding iteration to get boundary layer depth
489  ! - needed to compute new mixing length.
490  real :: mld_guess, mld_found ! Mixing Layer depth guessed/found for iteration, in m.
491  real :: max_mld, min_mld ! Iteration bounds, in m, which are adjusted at each step
492  ! - These are initialized based on surface/bottom
493  ! 1. The iteration guesses a value (possibly from
494  ! prev step or neighbor).
495  ! 2. The iteration checks if value is converged,
496  ! too shallow, or too deep.
497  ! 3. Based on result adjusts the Max/Min
498  ! and searches through the water column.
499  ! - If using an accurate guess the iteration
500  ! is very quick (e.g. if MLD doesn't change
501  ! over timestep). Otherwise it takes 5-10
502  ! passes, but has a high convergence rate.
503  ! Other iteration may be tried, but this
504  ! method seems to rarely fail and the added
505  ! cost is likely not significant. Additionally,
506  ! when it fails it does so in a reasonable
507  ! manner giving a usable guess. When it
508  ! does fail, it is due to convection within
509  ! the boundary. Likely, a new method e.g.
510  ! surface_disconnect, can improve this.
511  logical :: first_obl ! Flag for computing "found" Mixing layer depth
512  logical :: obl_converged ! Flag for convergence of MLD
513  integer :: obl_it ! Iteration counter
514 !### These need to be made into run-time parameters.
515  integer :: max_obl_it=20 ! Set maximum number of iterations. Probably
516  ! best as an input parameter, but then may want
517  ! to use allocatable arrays if storing
518  ! guess/found (as diagnostic); skipping for now.
519  ! In reality, the maximum number of guesses
520  ! needed is set by:
521  ! DEPTH/2^M < DZ
522  ! where M is the number of guesses
523  ! e.g. M=12 for DEPTH=4000m and DZ=1m
524  real, dimension(SZK_(GV)+1) :: vstar_used, & ! 1D arrays used to store
525  mixing_length_used ! Vstar and Mixing_Length
526  !/BGR - remaining variables are related to tracking iteration statistics.
527  logical :: obl_it_stats=.false. ! Flag for computing OBL iteration statistics
528  REAL :: itguess(20), itresult(20),itmax(20),itmin(20) ! Flag for storing guess/result
529  ! should have dim=MAX_OBL_IT
530  integer, save :: maxit=0 ! Stores maximum number of iterations
531  integer, save :: minit=1e8 ! Stores minimum number of iterations
532  integer, save :: sumit=0 ! Stores total iterations (summed over all)
533  integer, save :: numit=0 ! Stores number of times iterated
534  !e.g. Average iterations = SUMIT/NUMIT
535  integer, save :: converged!
536  integer, save :: notconverged!
537  !-End BGR iteration parameters-----------------------------------------
538  real :: n2_dissipation
539  real :: bf_stable ! Buoyancy flux, capped at 0 (negative only)
540  real :: bf_unstable ! Buoyancy flux, floored at 0 (positive only)
541  real :: stab_scale ! Composite of Stabilizing length scales:
542  ! Ekman scale and Monin-Obukhov scale.
543  real :: il_ekman ! Inverse of Ekman length scale
544  real :: il_obukhov ! Inverse of Obukhov length scale
545  real :: mld_o_ekman ! >
546  real :: mld_o_obukhov_stab ! Ratios of length scales where MLD is boundary layer depth
547  real :: ekman_o_obukhov_stab ! >
548  real :: mld_o_obukhov_un ! Ratios of length scales where MLD is boundary layer depth
549  real :: ekman_o_obukhov_un ! >
550 
551  real :: c_mo = 1. ! Constant in STAB_SCALE for Monin-Obukhov
552  real :: c_ek = 2. ! Constant in STAB_SCALE for Ekman length
553  real :: mld_over_stab ! Mixing layer depth divided by STAB_SCALE
554  real :: mstar_mix! The value of mstar (Proportionality of TKE to drive mixing to ustar
555  ! cubed) which is computed as a function of latitude, boundary layer depth,
556  ! and the Monin-Obukhov depth.
557  real :: mstar_lt ! The added mstar contribution due to Langmuir turbulence
558  real :: mstar_conv_adj ! Adjustment made to mstar due to convection reducing mechanical mixing.
559  real :: mstar_stab, mstar_rot ! Mstar in each limit, max is used.
560  logical :: debug=.false. ! Change this hard-coded value for debugging.
561 ! The following arrays are used only for debugging purposes.
562  real :: dpe_debug, mixing_debug, taux2, tauy2
563  real, dimension(20) :: tke_left_itt, pe_chg_itt, kddt_h_itt, dpea_dkd_itt, mke_src_itt
564  real, dimension(SZI_(G),SZK_(GV)) :: &
565  mech_tke_k, conv_perel_k
566  real, dimension(SZK_(GV)) :: nstar_k
567  integer, dimension(SZK_(GV)) :: num_itts
568 
569  integer :: i, j, k, is, ie, js, je, nz, itt, max_itt
570 
571  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
572 
573  if (.not. associated(cs)) call mom_error(fatal, "energetic_PBL: "//&
574  "Module must be initialized before it is used.")
575 
576  if (.not. ASSOCIATED(tv%eqn_of_state)) call mom_error(fatal, &
577  "energetic_PBL: Temperature, salinity and an equation of state "//&
578  "must now be used.")
579  if (.NOT. ASSOCIATED(fluxes%ustar)) call mom_error(fatal, &
580  "energetic_PBL: No surface TKE fluxes (ustar) defined in mixedlayer!")
581  if (present(dt_expected) .or. present(ds_expected)) debug = .true.
582 
583  h_neglect = gv%H_subroundoff
584 
585  if(.not.cs%Use_MLD_Iteration) max_obl_it=1
586  c1_3 = 1.0 / 3.0
587  dt__diag = dt ; if (present(dt_diag)) dt__diag = dt_diag
588  idtdr0 = 1.0 / (dt__diag * gv%Rho0)
589  write_diags = .true. ; if (present(last_call)) write_diags = last_call
590  max_itt = 20
591 
592  h_tt_min = 0.0
593  vonkar = 0.41
594  mstar_mix=cs%MSTAR!Initialize to mstar
595  i_dtrho = 0.0 ; if (dt*gv%Rho0 > 0.0) i_dtrho = 1.0 / (dt*gv%Rho0)
596 
597  ! Determine whether to zero out diagnostics before accumulation.
598  reset_diags = .true.
599  if (present(dt_diag) .and. write_diags .and. (dt__diag > dt)) &
600  reset_diags = .false. ! This is the second call to mixedlayer.
601 
602  if (reset_diags) then
603 !!OMP parallel default(none) shared(is,ie,js,je,CS)
604  if (cs%TKE_diagnostics) then
605 !!OMP do
606  do j=js,je ; do i=is,ie
607  cs%diag_TKE_wind(i,j) = 0.0 ; cs%diag_TKE_MKE(i,j) = 0.0
608  cs%diag_TKE_conv(i,j) = 0.0 ; cs%diag_TKE_forcing(i,j) = 0.0
609  cs%diag_TKE_mixing(i,j) = 0.0 ; cs%diag_TKE_mech_decay(i,j) = 0.0
610  cs%diag_TKE_conv_decay(i,j) = 0.0 !; CS%diag_TKE_unbalanced_forcing(i,j) = 0.0
611  enddo ; enddo
612  endif
613  if (cs%Mixing_Diagnostics) then
614  cs%Mixing_Length(:,:,:) = 0.0
615  cs%Velocity_Scale(:,:,:) = 0.0
616  endif
617 !!OMP end parallel
618  endif
619 
620 
621 !!OMP parallel do default(none) shared(js,je,nz,is,ie,h_3d,u_3d,v_3d,tv,dt, &
622 !!OMP CS,G,GV,fluxes,IdtdR0, &
623 !!OMP TKE_forced,debug,H_neglect,dSV_dT, &
624 !!OMP dSV_dS,I_dtrho,C1_3,h_tt_min,vonKar, &
625 !!OMP max_itt,Kd_int) &
626 !!OMP private(i,j,k,h,u,v,T,S,Kd,mech_TKE_k,conv_PErel_k, &
627 !!OMP U_Star,absf,mech_TKE,conv_PErel,nstar_k, &
628 !!OMP h_sum,I_hs,h_bot,hb_hs,T0,S0,num_itts, &
629 !!OMP pres,dMass,dPres,dT_to_dPE,dS_to_dPE, &
630 !!OMP dT_to_dColHt,dS_to_dColHt,Kddt_h,hp_a, &
631 !!OMP Th_a,Sh_a,Th_b,Sh_b,dT_to_dPE_a,htot, &
632 !!OMP dT_to_dColHt_a,dS_to_dColHt_a,uhtot,vhtot, &
633 !!OMP Idecay_len_TKE,exp_kh,nstar_FC,tot_TKE, &
634 !!OMP TKE_reduc,dTe_t2,dSe_t2,dTe,dSe,dt_h, &
635 !!OMP Convectively_stable,sfc_disconnect,b1, &
636 !!OMP c1,dT_km1_t2,dS_km1_t2,dTe_term, &
637 !!OMP dSe_term,MKE2_Hharm,vstar,h_tt,h_rsum, &
638 !!OMP Kd_guess0,Kddt_h_g0,dPEc_dKd_Kd0, &
639 !!OMP PE_chg_max,dPEa_dKd_g0,PE_chg_g0, &
640 !!OMP MKE_src,dPE_conv,Kddt_h_max,Kddt_h_min, &
641 !!OMP dTKE_conv, dTKE_forcing, dTKE_mixing, &
642 !!OMP dTKE_MKE,dTKE_mech_decay,dTKE_conv_decay,&
643 !!OMP TKE_left_max,TKE_left_min,Kddt_h_guess, &
644 !!OMP TKE_left_itt,dPEa_dKd_itt,PE_chg_itt, &
645 !!OMP MKE_src_itt,Kddt_h_itt,dPEc_dKd,PE_chg, &
646 !!OMP dMKE_src_dK,TKE_left,use_Newt, &
647 !!OMP dKddt_h_Newt,Kddt_h_Newt,Kddt_h_next, &
648 !!OMP dKddt_h,Te,Se,Hsfc_used,dS_to_dPE_a, &
649 !!OMP dMKE_max,sfc_connected,TKE_here)
650  do j=js,je
651  ! Copy the thicknesses and other fields to 2-d arrays.
652  do k=1,nz ; do i=is,ie
653  h(i,k) = h_3d(i,j,k) + h_neglect ; u(i,k) = u_3d(i,j,k) ; v(i,k) = v_3d(i,j,k)
654  t(i,k) = tv%T(i,j,k) ; s(i,k) = tv%S(i,j,k)
655  kd(i,k) = 0.0
656  enddo ; enddo
657  do i=is,ie
658  cs%ML_depth(i,j) = h(i,1)*gv%H_to_m
659  !CS%ML_depth2(i,j) = h(i,1)*GV%H_to_m
660  sfc_connected(i) = .true.
661  enddo
662 
663  if (debug) then
664  mech_tke_k(:,:) = 0.0 ; conv_perel_k(:,:) = 0.0
665  endif
666 
667  ! Determine the initial mech_TKE and conv_PErel, including the energy required
668  ! to mix surface heating through the topmost cell, the energy released by mixing
669  ! surface cooling & brine rejection down through the topmost cell, and
670  ! homogenizing the shortwave heating within that cell. This sets the energy
671  ! and ustar and wstar available to drive mixing at the first interior
672  ! interface.
673  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
674 
675 
676  u_star = fluxes%ustar(i,j)
677  taux2 = 0.
678  if ((g%mask2dCu(i-1,j) + g%mask2dCu(i,j)) > 0) &
679  taux2 = (g%mask2dCu(i-1,j)*fluxes%taux(i-1,j)**2 + &
680  g%mask2dCu(i,j)*fluxes%taux(i,j)**2) / (g%mask2dCu(i-1,j) + g%mask2dCu(i,j))
681  tauy2 = 0.0
682  if ((g%mask2dCv(i,j-1) + g%mask2dCv(i,j)) > 0) &
683  tauy2 = (g%mask2dCv(i,j-1)*fluxes%tauy(i,j-1)**2 + &
684  g%mask2dCv(i,j)*fluxes%tauy(i,j)**2) / (g%mask2dCv(i,j-1) + g%mask2dCv(i,j))
685  u_star_mean = sqrt(sqrt(taux2 + tauy2)/gv%rho0)
686  if (associated(fluxes%ustar_shelf) .and. associated(fluxes%frac_shelf_h)) then
687  if (fluxes%frac_shelf_h(i,j) > 0.0) &
688  u_star = (1.0 - fluxes%frac_shelf_h(i,j)) * u_star + &
689  fluxes%frac_shelf_h(i,j) * fluxes%ustar_shelf(i,j)
690  endif
691  if (u_star < cs%ustar_min) u_star = cs%ustar_min
692  ! Computing Bf w/ limiters.
693  bf_stable = max(0.0,buoy_flux(i,j)) ! Positive for stable
694  bf_unstable = min(0.0,buoy_flux(i,j)) ! Negative for unstable
695  if (cs%omega_frac >= 1.0) then ; absf(i) = 2.0*cs%omega
696  else
697  absf(i) = 0.25*((abs(g%CoriolisBu(i,j)) + abs(g%CoriolisBu(i-1,j-1))) + &
698  (abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i-1,j))))
699  if (cs%omega_frac > 0.0) &
700  absf(i) = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf(i)**2)
701  endif
702  ! Computing stability scale which correlates with TKE for mixing, where
703  ! TKE for mixing = TKE production minus TKE dissipation
704  stab_scale = u_star**2 / ( vonkar * ( c_mo * bf_stable/u_star - c_ek * u_star * absf(i)))
705  ! Inverse of Ekman and Obukhov
706  il_ekman = absf(i)/u_star
707  il_obukhov = buoy_flux(i,j)*vonkar/u_star**3
708 
709  if (cs%Mstar_Mode.eq.cs%CONST_MSTAR) then
710  mech_tke(i) = (dt*cs%mstar*gv%Rho0)*((u_star**3))
711  conv_perel(i) = 0.0
712 
713  if (cs%TKE_diagnostics) then
714  cs%diag_TKE_wind(i,j) = cs%diag_TKE_wind(i,j) + mech_tke(i) * idtdr0
715  if (tke_forced(i,j,1) <= 0.0) then
716  cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + &
717  max(-mech_tke(i), tke_forced(i,j,1)) * idtdr0
718  ! CS%diag_TKE_unbalanced_forcing(i,j) = CS%diag_TKE_unbalanced_forcing(i,j) + &
719  ! min(0.0, TKE_forced(i,j,1) + mech_TKE(i)) * IdtdR0
720  else
721  cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + cs%nstar*tke_forced(i,j,1) * idtdr0
722  endif
723  endif
724 
725  if (tke_forced(i,j,1) <= 0.0) then
726  mech_tke(i) = mech_tke(i) + tke_forced(i,j,1)
727  if (mech_tke(i) < 0.0) mech_tke(i) = 0.0
728  else
729  conv_perel(i) = conv_perel(i) + tke_forced(i,j,1)
730  endif
731 
732  endif
733 
734 ! endif ; enddo
735 
736 ! do i=is,ie ; if (G%mask2dT(i,j) > 0.5) then
737 
738  h_sum(i) = h_neglect ; do k=1,nz ; h_sum(i) = h_sum(i) + h(i,k) ; enddo
739  i_hs = 0.0 ; if (h_sum(i) > 0.0) i_hs = 1.0 / h_sum(i)
740 
741  h_bot = 0.0 ; hb_hs(i,nz+1) = 0.0
742  do k=nz,1,-1
743  h_bot = h_bot + h(i,k)
744  hb_hs(i,k) = h_bot * i_hs
745  enddo
746 
747  pres(i,1) = 0.0
748  do k=1,nz
749  dmass = gv%H_to_kg_m2 * h(i,k)
750  dpres = gv%g_Earth * dmass
751  dt_to_dpe(i,k) = (dmass * (pres(i,k) + 0.5*dpres)) * dsv_dt(i,j,k)
752  ds_to_dpe(i,k) = (dmass * (pres(i,k) + 0.5*dpres)) * dsv_ds(i,j,k)
753  dt_to_dcolht(i,k) = dmass * dsv_dt(i,j,k)
754  ds_to_dcolht(i,k) = dmass * dsv_ds(i,j,k)
755 
756  pres(i,k+1) = pres(i,k) + dpres
757  enddo
758 
759 ! endif ; enddo
760 
761  ! Note the outer i-loop and inner k-loop loop order!!!
762 ! do i=is,ie ; if (G%mask2dT(i,j) > 0.5) then
763  do k=1,nz ; t0(k) = t(i,k) ; s0(k) = s(i,k) ; enddo
764 
765  ! Store the initial mechanical TKE and convectively released PE to
766  ! enable multiple iterations.
767  mech_tke_top(i) = mech_tke(i) ; conv_perel_top(i) = conv_perel(i)
768 
769  !/The following lines are for the iteration over MLD
770  !{
771  ! max_MLD will initialized as ocean bottom depth
772  max_mld = 0.0 ; do k=1,nz ; max_mld = max_mld + h(i,k)*gv%H_to_m ; enddo
773  min_mld = 0.0 !min_MLD will initialize as 0.
774  !/BGR: May add user-input bounds for max/min MLD
775 
776  !/BGR: Add MLD_guess based on stored previous value.
777  ! note that this is different from ML_Depth already
778  ! computed by EPBL, need to figure out why.
779  if (cs%MLD_iteration_guess .and. cs%ML_Depth2(i,j) > 1.) then
780  !If prev value is present use for guess.
781  mld_guess=cs%ML_Depth2(i,j)
782  else
783  !Otherwise guess middle of water column (or stab_scale if smaller).
784  mld_guess = 0.5 * (min_mld+max_mld)
785  endif
786 
787  ! Iterate up to MAX_OBL_IT times to determine a converged EPBL depth.
788  obl_converged = .false.
789  ! Initialize ENHANCE_M to 1 and mstar_lt to 0
790  enhance_m=1.e0
791  mstar_lt = 0.0
792  do obl_it=1,max_obl_it ; if (.not. obl_converged) then
793 
794  ! Reset ML_depth
795  cs%ML_depth(i,j) = h(i,1)*gv%H_to_m
796  !CS%ML_depth2(i,j) = h(i,1)*GV%H_to_m
797 
798  sfc_connected(i) = .true.
799 
800  if (cs%Mstar_Mode.gt.0) then
801  ! Note the value of mech_TKE(i) now must be iterated over, so it is moved here
802  ! First solve for the TKE to PE length scale
803  if (cs%MSTAR_MODE.eq.cs%MLD_o_OBUKHOV) then
804  mld_over_stab = mld_guess / stab_scale - cs%MSTAR_XINT
805  if ((mld_over_stab) .le. 0.0) then
806  !Asymptote to 0 as MLD_over_Stab -> -infinity (always)
807  mstar_mix = (cs%MSTAR_B*(mld_over_stab)+cs%MSTAR_A)**(cs%MSTAR_N)
808  else
809  if (cs%MSTAR_CAP>=0.) then
810  if (cs%MSTAR_FLATCAP .OR. (mld_over_stab .le.cs%MSTAR_XINT_UP)) then
811  !If using flat cap (or if using asymptotic cap
812  ! but within linear regime we can make use of same code)
813  mstar_mix = min(cs%MSTAR_CAP, &
814  cs%MSTAR_SLOPE*(mld_over_stab)+cs%MSTAR_AT_XINT)
815  else
816  !Asymptote to MSTAR_CAP as MLD_over_Stab -> infinity
817  mstar_mix = cs%MSTAR_CAP - &
818  (cs%MSTAR_B2*(mld_over_stab-cs%MSTAR_XINT_UP)&
819  +cs%MSTAR_A2)**(cs%MSTAR_N)
820  endif
821  else
822  !No cap if negative cap value given.
823  mstar_mix = cs%MSTAR_SLOPE*(mld_over_stab)+cs%MSTAR_AT_XINT
824  endif
825  endif
826  elseif (cs%MSTAR_MODE.eq.cs%EKMAN_o_OBUKHOV) then
827  mstar_stab = cs%MSTAR_COEF*sqrt(bf_stable/u_star**2/(absf(i)+1.e-10))
828  mstar_rot = cs%C_EK*log(max(1.,u_star/(absf(i)+1.e-10)/mld_guess))
829  if ( cs%MSTAR_CAP.le.0.0) then !No cap.
830  mstar_mix = max(mstar_stab,& ! 1st term if balance of rotation and stabilizing
831  ! the balance is f(L_Ekman,L_Obukhov)
832  min(& ! 2nd term for forced stratification limited
833  1.25,& !.5/von Karman (Obukhov limit)
834  ! 3rd term for rotation (Ekman length) limited
835  mstar_rot))
836  else
837  mstar_mix = min( & ! Sets a cap. The cap should be large and just
838  ! meant to be a safety net.
839  cs%MSTAR_CAP, &
840  max(mstar_stab,& ! 1st term if balance of rotation and stabilizing
841  ! the balance is f(L_Ekman,L_Obukhov)
842  min(& ! 2nd term for forced stratification limited
843  1.25,& !.5/von Karman (Obukhov limit)
844  ! 3rd term for rotation (Ekman length) limited
845  mstar_rot)))
846  endif!cap for mstar_mode==2
847  endif!mstar_mode==1 or ==2
848  ! Adjustment for unstable buoyancy flux.
849  ! Convection reduces mechanical mixing because there
850  ! is less density gradient to mix. (Statically unstable near surface)
851  mstar_conv_adj = 1. - cs%CNV_MST_FAC * (-bf_unstable+1.e-10) / &
852  ( (-bf_unstable+1.e-10)+ &
853  2. *mstar_mix *u_star**3 / mld_guess )
854  if (cs%Use_LA_windsea) then
855  ! 1. Get LA
856  call get_la_windsea( u_star_mean, mld_guess*cs%LaDepthRatio, gv, la)
857  ! 2. Get parameters for modified LA
858  mld_o_ekman = abs(mld_guess*il_ekman)
859  mld_o_obukhov_stab = abs(max(0.,mld_guess*il_obukhov))
860  mld_o_obukhov_un = abs(min(0.,mld_guess*il_obukhov))
861  ekman_o_obukhov_stab = abs(max(0.,il_obukhov/(il_ekman+1.e-10)))
862  ekman_o_obukhov_un = abs(min(0.,il_obukhov/(il_ekman+1.e-10)))
863  ! 3. Adjust LA based on various parameters.
864  ! Assumes linear factors based on length scale ratios to adjust LA
865  ! Note when these coefficients are set to 0 recovers simple LA.
866  lamod = la * (1.0 + max(-0.5,cs%LaC_MLDoEK * mld_o_ekman) + &
867  cs%LaC_EKoOB_stab * ekman_o_obukhov_stab + &
868  cs%LaC_EKoOB_un * ekman_o_obukhov_un + &
869  cs%LaC_MLDoOB_stab * mld_o_obukhov_stab + &
870  cs%LaC_MLDoOB_un * mld_o_obukhov_un )
871  if (cs%LT_Enhance_Form==1) then
872  !Original w'/ust scaling w/ Van Roekel's scaling
873  enhance_m = (1+(1.4*la)**(-2)+(5.4*la)**(-4))**(1.5)
874  elseif (cs%LT_Enhance_Form==2) then
875  ! Enhancement is multiplied (added mst_lt set to 0)
876  enhance_m = min(cs%Max_Enhance_M,(1.+cs%LT_ENHANCE_COEF*lamod**cs%LT_ENHANCE_EXP))
877  mstar_lt = 0.0
878  elseif (cs%LT_ENHANCE_Form == 3) then
879  ! or Enhancement is additive (multiplied enhance_m set to 1)
880  mstar_lt = cs%LT_ENHANCE_COEF * lamod**cs%LT_ENHANCE_EXP
881  enhance_m = 1.0
882  endif
883  endif
884  !Reset mech_tke and conv_perel values (based on new mstar)
885  mech_tke(i) = ( mstar_mix * mstar_conv_adj * enhance_m + mstar_lt) * (dt*gv%Rho0*u_star**3)
886  conv_perel(i) = 0.0
887  if (cs%TKE_diagnostics) then
888  cs%diag_TKE_wind(i,j) = cs%diag_TKE_wind(i,j) + mech_tke(i) * idtdr0
889  if (tke_forced(i,j,1) <= 0.0) then
890  cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + &
891  max(-mech_tke(i), tke_forced(i,j,1)) * idtdr0
892  ! CS%diag_TKE_unbalanced_forcing(i,j) = CS%diag_TKE_unbalanced_forcing(i,j) + &
893  ! min(0.0, TKE_forced(i,j,1) + mech_TKE(i)) * IdtdR0
894  else
895  cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + cs%nstar*tke_forced(i,j,1) * idtdr0
896  endif
897  endif
898 
899  if (tke_forced(i,j,1) <= 0.0) then
900  mech_tke(i) = mech_tke(i) + tke_forced(i,j,1)
901  if (mech_tke(i) < 0.0) mech_tke(i) = 0.0
902  else
903  conv_perel(i) = conv_perel(i) + tke_forced(i,j,1)
904  endif
905  else
906  mech_tke(i) = mech_tke_top(i)*enhance_m ; conv_perel(i) = conv_perel_top(i)
907  endif
908 
909  if (cs%TKE_diagnostics) then
910  dtke_conv = 0.0 ; dtke_forcing = 0.0 ; dtke_mixing = 0.0
911  dtke_mke = 0.0 ; dtke_mech_decay = 0.0 ; dtke_conv_decay = 0.0
912  endif
913 
914  ! Store in 1D arrays cleared out each iteration. Only write in
915  ! 3D arrays after convergence.
916  do k=1,nz
917  vstar_used(k) = 0.0 ; mixing_length_used(k) = 0.0
918  enddo
919  if (.not.cs%Use_MLD_Iteration) obl_converged = .true.
920 
921  if ((.not.cs%Use_MLD_Iteration) .or. &
922  (cs%transLay_scale >= 1.0) .or. (cs%transLay_scale < 0.0) ) then
923  do k=1,nz+1 ; mixlen_shape(k) = 1.0 ; enddo
924  elseif (mld_guess <= 0.0) then
925  if (cs%transLay_scale > 0.0) then
926  do k=1,nz+1 ; mixlen_shape(k) = cs%transLay_scale ; enddo
927  else
928  do k=1,nz+1 ; mixlen_shape(k) = 1.0 ; enddo
929  endif
930  else
931  ! Reduce the mixing length based on MLD, with a quadratic
932  ! expression that follows KPP.
933  i_mld = 1.0 / mld_guess ; h_rsum = 0.0
934  mixlen_shape(1) = 1.0
935  do k=2,nz+1
936  h_rsum = h_rsum + h(i,k-1)
937  if (cs%MixLenExponent==2.0)then
938  mixlen_shape(k) = cs%transLay_scale + (1.0 - cs%transLay_scale) * &
939  (max(0.0, (mld_guess - h_rsum)*i_mld) )**2!CS%MixLenExponent
940  else
941  mixlen_shape(k) = cs%transLay_scale + (1.0 - cs%transLay_scale) * &
942  (max(0.0, (mld_guess - h_rsum)*i_mld) )**cs%MixLenExponent
943  endif
944  enddo
945  endif
946 
947 
948  kd(i,1) = 0.0 ; kddt_h(1) = 0.0
949  hp_a(i) = h(i,1)
950  dt_to_dpe_a(i,1) = dt_to_dpe(i,1) ; dt_to_dcolht_a(i,1) = dt_to_dcolht(i,1)
951  ds_to_dpe_a(i,1) = ds_to_dpe(i,1) ; ds_to_dcolht_a(i,1) = ds_to_dcolht(i,1)
952 
953  htot(i) = h(i,1) ; uhtot(i) = u(i,1)*h(i,1) ; vhtot(i) = v(i,1)*h(i,1)
954 
955  if (debug) then
956  mech_tke_k(i,1) = mech_tke(i) ; conv_perel_k(i,1) = conv_perel(i)
957  nstar_k(:) = 0.0 ; nstar_k(1) = cs%nstar ; num_itts(:) = -1
958  endif
959 
960  do k=2,nz
961  ! Apply dissipation to the TKE, here applied as an exponential decay
962  ! due to 3-d turbulent energy being lost to inefficient rotational modes.
963 
964  ! There should be several different "flavors" of TKE that decay at
965  ! different rates. The following form is often used for mechanical
966  ! stirring from the surface, perhaps due to breaking surface gravity
967  ! waves and wind-driven turbulence.
968  idecay_len_tke(i) = (cs%TKE_decay * absf(i) / u_star) * gv%H_to_m
969  exp_kh = 1.0
970  if (idecay_len_tke(i) > 0.0) exp_kh = exp(-h(i,k-1)*idecay_len_tke(i))
971  if (cs%TKE_diagnostics) &
972  dtke_mech_decay = dtke_mech_decay + (exp_kh-1.0) * mech_tke(i) * idtdr0
973  mech_tke(i) = mech_tke(i) * exp_kh
974 
975  ! Accumulate any convectively released potential energy to contribute
976  ! to wstar and to drive penetrating convection.
977  if (tke_forced(i,j,k) > 0.0) then
978  conv_perel(i) = conv_perel(i) + tke_forced(i,j,k)
979  if (cs%TKE_diagnostics) &
980  dtke_forcing = dtke_forcing + cs%nstar*tke_forced(i,j,k) * idtdr0
981  endif
982 
983  if (debug) then
984  mech_tke_k(i,k) = mech_tke(i) ; conv_perel_k(i,k) = conv_perel(i)
985  endif
986 
987  ! Determine the total energy
988  nstar_fc = cs%nstar
989  if (cs%nstar * conv_perel(i) > 0.0) then
990  ! Here nstar is a function of the natural Rossby number 0.2/(1+0.2/Ro), based
991  ! on a curve fit from the data of Wang (GRL, 2003).
992  ! Note: Ro = 1.0 / sqrt(0.5 * dt * Rho0 * (absf*htot(i))**3 / conv_PErel(i))
993  nstar_fc = cs%nstar * conv_perel(i) / (conv_perel(i) + 0.2 * &
994  sqrt(0.5 * dt * gv%Rho0 * (absf(i)*(htot(i)*gv%H_to_m))**3 * conv_perel(i)))
995  endif
996  if (debug) nstar_k(k) = nstar_fc
997 
998  tot_tke = mech_tke(i) + nstar_fc * conv_perel(i)
999 
1000  ! For each interior interface, first discard the TKE to account for
1001  ! mixing of shortwave radiation through the next denser cell.
1002  if (tke_forced(i,j,k) < 0.0) then
1003  if (tke_forced(i,j,k) + tot_tke < 0.0) then
1004  ! The shortwave requirements deplete all the energy in this layer.
1005  if (cs%TKE_diagnostics) then
1006  dtke_mixing = dtke_mixing + tot_tke * idtdr0
1007  dtke_forcing = dtke_forcing - tot_tke * idtdr0
1008  ! dTKE_unbalanced_forcing = dTKE_unbalanced_forcing + &
1009  ! (TKE_forced(i,j,k) + tot_TKE) * IdtdR0
1010  dtke_conv_decay = dtke_conv_decay + &
1011  (cs%nstar-nstar_fc) * conv_perel(i) * idtdr0
1012  endif
1013  tot_tke = 0.0 ; mech_tke(i) = 0.0 ; conv_perel(i) = 0.0
1014  else
1015  ! Reduce the mechanical and convective TKE proportionately.
1016  tke_reduc = (tot_tke + tke_forced(i,j,k)) / tot_tke
1017  if (cs%TKE_diagnostics) then
1018  dtke_mixing = dtke_mixing - tke_forced(i,j,k) * idtdr0
1019  dtke_forcing = dtke_forcing + tke_forced(i,j,k) * idtdr0
1020  dtke_conv_decay = dtke_conv_decay + &
1021  (1.0-tke_reduc)*(cs%nstar-nstar_fc) * conv_perel(i) * idtdr0
1022  endif
1023  tot_tke = tke_reduc*tot_tke ! = tot_TKE + TKE_forced(i,j,k)
1024  mech_tke(i) = tke_reduc*mech_tke(i)
1025  conv_perel(i) = tke_reduc*conv_perel(i)
1026  endif
1027  endif
1028 
1029  ! Precalculate some temporary expressions that are independent of Kddt_h(K).
1030  if (cs%orig_PE_calc) then
1031  if (k==2) then
1032  dte_t2 = 0.0 ; dse_t2 = 0.0
1033  else
1034  dte_t2 = kddt_h(k-1) * ((t0(k-2) - t0(k-1)) + dte(k-2))
1035  dse_t2 = kddt_h(k-1) * ((s0(k-2) - s0(k-1)) + dse(k-2))
1036  endif
1037  endif
1038  dt_h = (gv%m_to_H**2*dt) / max(0.5*(h(i,k-1)+h(i,k)), 1e-15*h_sum(i))
1039 
1040  ! This tests whether the layers above and below this interface are in
1041  ! a convetively stable configuration, without considering any effects of
1042  ! mixing at higher interfaces. It is an approximation to the more
1043  ! complete test dPEc_dKd_Kd0 >= 0.0, that would include the effects of
1044  ! mixing across interface K-1. The dT_to_dColHt here are effectively
1045  ! mass-weigted estimates of dSV_dT.
1046  convectively_stable = ( 0.0 <= &
1047  ( (dt_to_dcolht(i,k) + dt_to_dcolht(i,k-1) ) * (t0(k-1)-t0(k)) + &
1048  (ds_to_dcolht(i,k) + ds_to_dcolht(i,k-1) ) * (s0(k-1)-s0(k)) ) )
1049 
1050  if ((mech_tke(i) + conv_perel(i)) <= 0.0 .and. convectively_stable) then
1051  ! Energy is already exhausted, so set Kd = 0 and cycle or exit?
1052  tot_tke = 0.0 ; mech_tke(i) = 0.0 ; conv_perel(i) = 0.0
1053  kd(i,k) = 0.0 ; kddt_h(k) = 0.0
1054  sfc_disconnect = .true.
1055  ! if (.not.debug) exit
1056 
1057  ! The estimated properties for layer k-1 can be calculated, using
1058  ! greatly simplified expressions when Kddt_h = 0. This enables the
1059  ! tridiagonal solver for the whole column to be completed for debugging
1060  ! purposes, and also allows for something akin to convective adjustment
1061  ! in unstable interior regions?
1062  b1 = 1.0 / hp_a(i)
1063  c1(k) = 0.0
1064  if (cs%orig_PE_calc) then
1065  dte(k-1) = b1 * ( dte_t2 )
1066  dse(k-1) = b1 * ( dse_t2 )
1067  endif
1068 
1069  hp_a(i) = h(i,k)
1070  dt_to_dpe_a(i,k) = dt_to_dpe(i,k)
1071  ds_to_dpe_a(i,k) = ds_to_dpe(i,k)
1072  dt_to_dcolht_a(i,k) = dt_to_dcolht(i,k)
1073  ds_to_dcolht_a(i,k) = ds_to_dcolht(i,k)
1074 
1075  else ! tot_TKE > 0.0 or this is a potentially convectively unstable profile.
1076  sfc_disconnect = .false.
1077 
1078  ! Precalculate some more temporary expressions that are independent of
1079  ! Kddt_h(K).
1080  if (cs%orig_PE_calc) then
1081  if (k==2) then
1082  dt_km1_t2 = (t0(k)-t0(k-1))
1083  ds_km1_t2 = (s0(k)-s0(k-1))
1084  else
1085  dt_km1_t2 = (t0(k)-t0(k-1)) - &
1086  (kddt_h(k-1) / hp_a(i)) * ((t0(k-2) - t0(k-1)) + dte(k-2))
1087  ds_km1_t2 = (s0(k)-s0(k-1)) - &
1088  (kddt_h(k-1) / hp_a(i)) * ((s0(k-2) - s0(k-1)) + dse(k-2))
1089  endif
1090  dte_term = dte_t2 + hp_a(i) * (t0(k-1)-t0(k))
1091  dse_term = dse_t2 + hp_a(i) * (s0(k-1)-s0(k))
1092  else
1093  if (k<=2) then
1094  th_a(k-1) = h(i,k-1) * t0(k-1) ; sh_a(k-1) = h(i,k-1) * s0(k-1)
1095  else
1096  th_a(k-1) = h(i,k-1) * t0(k-1) + kddt_h(k-1) * te(k-2)
1097  sh_a(k-1) = h(i,k-1) * s0(k-1) + kddt_h(k-1) * se(k-2)
1098  endif
1099  th_b(k) = h(i,k) * t0(k) ; sh_b(k) = h(i,k) * s0(k)
1100  endif
1101 
1102  ! Using Pr=1 and the diffusivity at the bottom interface (once it is
1103  ! known), determine how much resolved mean kinetic energy (MKE) will be
1104  ! extracted within a timestep and add a fraction CS%MKE_to_TKE_effic of
1105  ! this to the mTKE budget available for mixing in the next layer.
1106 
1107  if ((cs%MKE_to_TKE_effic > 0.0) .and. (htot(i)*h(i,k) > 0.0)) then
1108  ! This is the energy that would be available from homogenizing the
1109  ! velocities between layer k and the layers above.
1110  dmke_max = (gv%H_to_kg_m2 * cs%MKE_to_TKE_effic) * 0.5 * &
1111  (h(i,k) / ((htot(i) + h(i,k))*htot(i))) * &
1112  ((uhtot(i)-u(i,k)*htot(i))**2 + (vhtot(i)-v(i,k)*htot(i))**2)
1113  ! A fraction (1-exp(Kddt_h*MKE2_Hharm)) of this energy would be
1114  ! extracted by mixing with a finite viscosity.
1115  mke2_hharm = (htot(i) + h(i,k) + 2.0*h_neglect) / &
1116  ((htot(i)+h_neglect) * (h(i,k)+h_neglect))
1117  else
1118  dmke_max = 0.0 ; mke2_hharm = 0.0
1119  endif
1120 
1121  ! At this point, Kddt_h(K) will be unknown because its value may depend
1122  ! on how much energy is available. mech_TKE might be negative due to
1123  ! contributions from TKE_forced.
1124  h_tt = htot(i) + h_tt_min
1125  tke_here = mech_tke(i) + cs%wstar_ustar_coef*conv_perel(i)
1126  if (tke_here > 0.0) then
1127  vstar = cs%vstar_scale_fac * (i_dtrho*tke_here)**c1_3
1128  hbs_here = gv%H_to_m * min(hb_hs(i,k), mixlen_shape(k))
1129  mixing_length_used(k) = max(cs%min_mix_len,((h_tt*hbs_here)*vstar) / &
1130  ((cs%Ekman_scale_coef * absf(i)) * (h_tt*hbs_here) + vstar))
1131  !Note setting Kd_guess0 to Mixing_Length_Used(K) here will
1132  ! change the answers. Therefore, skipping that.
1133  if (.not.cs%Use_MLD_Iteration) then
1134  kd_guess0 = vstar * vonkar * ((h_tt*hbs_here)*vstar) / &
1135  ((cs%Ekman_scale_coef * absf(i)) * (h_tt*hbs_here) + vstar)
1136  else
1137  kd_guess0 = vstar * vonkar * mixing_length_used(k)
1138  endif
1139  else
1140  vstar = 0.0 ; kd_guess0 = 0.0
1141  endif
1142  vstar_used(k) = vstar ! Track vstar
1143  kddt_h_g0 = kd_guess0*dt_h
1144 
1145  if (cs%orig_PE_calc) then
1146  call find_pe_chg_orig(kddt_h_g0, h(i,k), hp_a(i), dte_term, dse_term, &
1147  dt_km1_t2, ds_km1_t2, dt_to_dpe(i,k), ds_to_dpe(i,k), &
1148  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), &
1149  pres(i,k), dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1150  dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1151  pe_chg=pe_chg_g0, dpec_dkd=dpea_dkd_g0, dpe_max=pe_chg_max, &
1152  dpec_dkd_0=dpec_dkd_kd0 )
1153  else
1154  call find_pe_chg(0.0, kddt_h_g0, hp_a(i), h(i,k), &
1155  th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1156  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), dt_to_dpe(i,k), ds_to_dpe(i,k), &
1157  pres(i,k), dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1158  dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1159  pe_chg=pe_chg_g0, dpec_dkd=dpea_dkd_g0, dpe_max=pe_chg_max, &
1160  dpec_dkd_0=dpec_dkd_kd0 )
1161  endif
1162 
1163  mke_src = dmke_max*(1.0 - exp(-kddt_h_g0 * mke2_hharm))
1164 
1165  if (pe_chg_g0 .gt. 0.0) then
1166  !Negative buoyancy (increases PE)
1167  n2_dissipation = 1.+cs%N2_DISSIPATION_SCALE_NEG
1168  else
1169  !Positive buoyancy (decreases PE)
1170  n2_dissipation = 1.+cs%N2_DISSIPATION_SCALE_POS
1171  endif
1172 
1173  if ((pe_chg_g0 < 0.0) .or. ((vstar == 0.0) .and. (dpec_dkd_kd0 < 0.0))) then
1174  ! This column is convectively unstable.
1175  if (pe_chg_max <= 0.0) then
1176  ! Does MKE_src need to be included in the calculation of vstar here?
1177  tke_here = mech_tke(i) + cs%wstar_ustar_coef*(conv_perel(i)-pe_chg_max)
1178  if (tke_here > 0.0) then
1179  vstar = cs%vstar_scale_fac * (i_dtrho*tke_here)**c1_3
1180  hbs_here = gv%H_to_m * min(hb_hs(i,k), mixlen_shape(k))
1181  mixing_length_used(k) = max(cs%min_mix_len,((h_tt*hbs_here)*vstar) / &
1182  ((cs%Ekman_scale_coef * absf(i)) * (h_tt*hbs_here) + vstar))
1183  if (.not.cs%Use_MLD_Iteration) then
1184  ! Note again (as prev) that using Mixing_Length_Used here
1185  ! instead of redoing the computation will change answers...
1186  kd(i,k) = vstar * vonkar * ((h_tt*hbs_here)*vstar) / &
1187  ((cs%Ekman_scale_coef * absf(i)) * (h_tt*hbs_here) + vstar)
1188  else
1189  kd(i,k) = vstar * vonkar * mixing_length_used(k)
1190  endif
1191  else
1192  vstar = 0.0 ; kd(i,k) = 0.0
1193  endif
1194  vstar_used(k) = vstar
1195 
1196  if (cs%orig_PE_calc) then
1197  call find_pe_chg_orig(kd(i,k)*dt_h, h(i,k), hp_a(i), dte_term, dse_term, &
1198  dt_km1_t2, ds_km1_t2, dt_to_dpe(i,k), ds_to_dpe(i,k), &
1199  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), &
1200  pres(i,k), dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1201  dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1202  pe_chg=dpe_conv)
1203  else
1204  call find_pe_chg(0.0, kd(i,k)*dt_h, hp_a(i), h(i,k), &
1205  th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1206  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), dt_to_dpe(i,k), ds_to_dpe(i,k), &
1207  pres(i,k), dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1208  dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1209  pe_chg=dpe_conv)
1210  endif
1211  ! Should this be iterated to convergence for Kd?
1212  if (dpe_conv > 0.0) then
1213  kd(i,k) = kd_guess0 ; dpe_conv = pe_chg_g0
1214  else
1215  mke_src = dmke_max*(1.0 - exp(-(kd(i,k)*dt_h) * mke2_hharm))
1216  endif
1217  else
1218  ! The energy change does not vary monotonically with Kddt_h. Find the maximum?
1219  kd(i,k) = kd_guess0 ; dpe_conv = pe_chg_g0
1220  endif
1221  conv_perel(i) = conv_perel(i) - dpe_conv
1222  mech_tke(i) = mech_tke(i) + mke_src
1223  if (cs%TKE_diagnostics) then
1224  dtke_conv = dtke_conv - cs%nstar*dpe_conv * idtdr0
1225  dtke_mke = dtke_mke + mke_src * idtdr0
1226  endif
1227  if (sfc_connected(i)) then
1228  cs%ML_depth(i,j) = cs%ML_depth(i,j) + gv%H_to_m * h(i,k)
1229  !CS%ML_depth2(i,j) = CS%ML_depth2(i,J) + GV%H_to_m * h(i,k)
1230  endif
1231 
1232  kddt_h(k) = kd(i,k)*dt_h
1233  elseif (tot_tke + (mke_src - n2_dissipation*pe_chg_g0) >= 0.0) then
1234  ! There is energy to support the suggested mixing. Keep that estimate.
1235  kd(i,k) = kd_guess0
1236  kddt_h(k) = kddt_h_g0
1237 
1238  ! Reduce the mechanical and convective TKE proportionately.
1239  tot_tke = tot_tke + mke_src
1240  tke_reduc = 0.0 ! tot_TKE could be 0 if Convectively_stable is false.
1241  if (tot_tke > 0.0) tke_reduc = (tot_tke - n2_dissipation*pe_chg_g0) &
1242  / tot_tke
1243  if (cs%TKE_diagnostics) then
1244  dtke_mixing = dtke_mixing - pe_chg_g0 * idtdr0
1245  dtke_mke = dtke_mke + mke_src * idtdr0
1246  dtke_conv_decay = dtke_conv_decay + &
1247  (1.0-tke_reduc)*(cs%nstar-nstar_fc) * conv_perel(i) * idtdr0
1248  endif
1249  tot_tke = tke_reduc*tot_tke
1250  mech_tke(i) = tke_reduc*(mech_tke(i) + mke_src)
1251  conv_perel(i) = tke_reduc*conv_perel(i)
1252  if (sfc_connected(i)) then
1253  cs%ML_depth(i,j) = cs%ML_depth(i,j) + gv%H_to_m * h(i,k)
1254  !CS%ML_depth2(i,J) = CS%ML_depth2(i,J) + GV%H_to_m * h(i,k)
1255  endif
1256  elseif (tot_tke == 0.0) then
1257  ! This can arise if nstar_FC = 0.
1258  kd(i,k) = 0.0 ; kddt_h(k) = 0.0
1259  tot_tke = 0.0 ; conv_perel(i) = 0.0 ; mech_tke(i) = 0.0
1260  sfc_disconnect = .true.
1261  else
1262  ! There is not enough energy to support the mixing, so reduce the
1263  ! diffusivity to what can be supported.
1264  kddt_h_max = kddt_h_g0 ; kddt_h_min = 0.0
1265  tke_left_max = tot_tke + (mke_src - n2_dissipation*pe_chg_g0) ;
1266  tke_left_min = tot_tke
1267 
1268  ! As a starting guess, take the minimum of a false position estimate
1269  ! and a Newton's method estimate starting from Kddt_h = 0.0.
1270  kddt_h_guess = tot_tke * kddt_h_max / max( n2_dissipation*pe_chg_g0 &
1271  - mke_src, kddt_h_max * (dpec_dkd_kd0 - dmke_max * &
1272  mke2_hharm) )
1273  ! The above expression is mathematically the same as the following
1274  ! except it is not susceptible to division by zero when
1275  ! dPEc_dKd_Kd0 = dMKE_max = 0 .
1276  ! Kddt_h_guess = tot_TKE * min( Kddt_h_max / (PE_chg_g0 - MKE_src), &
1277  ! 1.0 / (dPEc_dKd_Kd0 - dMKE_max * MKE2_Hharm) )
1278  if (debug) then
1279  tke_left_itt(:) = 0.0 ; dpea_dkd_itt(:) = 0.0 ; pe_chg_itt(:) = 0.0
1280  mke_src_itt(:) = 0.0 ; kddt_h_itt(:) = 0.0
1281  endif
1282  do itt=1,max_itt
1283  if (cs%orig_PE_calc) then
1284  call find_pe_chg_orig(kddt_h_guess, h(i,k), hp_a(i), dte_term, dse_term, &
1285  dt_km1_t2, ds_km1_t2, dt_to_dpe(i,k), ds_to_dpe(i,k), &
1286  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), &
1287  pres(i,k), dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1288  dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1289  pe_chg=pe_chg, dpec_dkd=dpec_dkd )
1290  else
1291  call find_pe_chg(0.0, kddt_h_guess, hp_a(i), h(i,k), &
1292  th_a(k-1), sh_a(k-1), th_b(k), sh_b(k), &
1293  dt_to_dpe_a(i,k-1), ds_to_dpe_a(i,k-1), dt_to_dpe(i,k), ds_to_dpe(i,k), &
1294  pres(i,k), dt_to_dcolht_a(i,k-1), ds_to_dcolht_a(i,k-1), &
1295  dt_to_dcolht(i,k), ds_to_dcolht(i,k), &
1296  pe_chg=dpe_conv)
1297  endif
1298  mke_src = dmke_max * (1.0 - exp(-mke2_hharm * kddt_h_guess))
1299  dmke_src_dk = dmke_max * mke2_hharm * exp(-mke2_hharm * kddt_h_guess)
1300 
1301  tke_left = tot_tke + (mke_src - n2_dissipation*pe_chg)
1302  if (debug) then
1303  kddt_h_itt(itt) = kddt_h_guess ; mke_src_itt(itt) = mke_src
1304  pe_chg_itt(itt) = n2_dissipation*pe_chg
1305  tke_left_itt(itt) = tke_left
1306  dpea_dkd_itt(itt) = dpec_dkd
1307  endif
1308  ! Store the new bounding values, bearing in mind that min and max
1309  ! here refer to Kddt_h and dTKE_left/dKddt_h < 0:
1310  if (tke_left >= 0.0) then
1311  kddt_h_min = kddt_h_guess ; tke_left_min = tke_left
1312  else
1313  kddt_h_max = kddt_h_guess ; tke_left_max = tke_left
1314  endif
1315 
1316  ! Try to use Newton's method, but if it would go outside the bracketed
1317  ! values use the false-position method instead.
1318  use_newt = .true.
1319  if (dpec_dkd*n2_dissipation - dmke_src_dk <= 0.0) then
1320  use_newt = .false.
1321  else
1322  dkddt_h_newt = tke_left / (dpec_dkd*n2_dissipation - dmke_src_dk)
1323  kddt_h_newt = kddt_h_guess + dkddt_h_newt
1324  if ((kddt_h_newt > kddt_h_max) .or. (kddt_h_newt < kddt_h_min)) &
1325  use_newt = .false.
1326  endif
1327 
1328  if (use_newt) then
1329  kddt_h_next = kddt_h_guess + dkddt_h_newt
1330  dkddt_h = dkddt_h_newt
1331  else
1332  kddt_h_next = (tke_left_max * kddt_h_min - kddt_h_max * tke_left_min) / &
1333  (tke_left_max - tke_left_min)
1334  dkddt_h = kddt_h_next - kddt_h_guess
1335  endif
1336 
1337  if ((abs(dkddt_h) < 1e-9*kddt_h_guess) .or. (itt==max_itt)) then
1338  ! Use the old value so that the energy calculation does not need to be repeated.
1339  if (debug) num_itts(k) = itt
1340  exit
1341  else
1342  kddt_h_guess = kddt_h_next
1343  endif
1344  enddo
1345  kd(i,k) = kddt_h_guess / dt_h ; kddt_h(k) = kd(i,k)*dt_h
1346 
1347  ! All TKE should have been consumed.
1348  if (cs%TKE_diagnostics) then
1349  dtke_mixing = dtke_mixing - (tot_tke + mke_src) * idtdr0
1350  dtke_mke = dtke_mke + mke_src * idtdr0
1351  dtke_conv_decay = dtke_conv_decay + &
1352  (cs%nstar-nstar_fc) * conv_perel(i) * idtdr0
1353  endif
1354 
1355  if (sfc_connected(i)) cs%ML_depth(i,j) = cs%ML_depth(i,j) + &
1356  (pe_chg / pe_chg_g0) * gv%H_to_m * h(i,k)
1357  tot_tke = 0.0 ; mech_tke(i) = 0.0 ; conv_perel(i) = 0.0
1358  sfc_disconnect = .true.
1359  endif
1360 
1361  kddt_h(k) = kd(i,k)*dt_h
1362  ! At this point, the final value of Kddt_h(K) is known, so the
1363  ! estimated properties for layer k-1 can be calculated.
1364  b1 = 1.0 / (hp_a(i) + kddt_h(k))
1365  c1(k) = kddt_h(k) * b1
1366  if (cs%orig_PE_calc) then
1367  dte(k-1) = b1 * ( kddt_h(k)*(t0(k)-t0(k-1)) + dte_t2 )
1368  dse(k-1) = b1 * ( kddt_h(k)*(s0(k)-s0(k-1)) + dse_t2 )
1369  endif
1370 
1371  hp_a(i) = h(i,k) + (hp_a(i) * b1) * kddt_h(k)
1372  dt_to_dpe_a(i,k) = dt_to_dpe(i,k) + c1(k)*dt_to_dpe_a(i,k-1)
1373  ds_to_dpe_a(i,k) = ds_to_dpe(i,k) + c1(k)*ds_to_dpe_a(i,k-1)
1374  dt_to_dcolht_a(i,k) = dt_to_dcolht(i,k) + c1(k)*dt_to_dcolht_a(i,k-1)
1375  ds_to_dcolht_a(i,k) = ds_to_dcolht(i,k) + c1(k)*ds_to_dcolht_a(i,k-1)
1376 
1377  endif ! tot_TKT > 0.0 branch. Kddt_h(K) has been set.
1378 
1379  ! Store integrated velocities and thicknesses for MKE conversion calculations.
1380  if (sfc_disconnect) then
1381  ! There is no turbulence at this interface, so zero out the running sums.
1382  uhtot(i) = u(i,k)*h(i,k)
1383  vhtot(i) = v(i,k)*h(i,k)
1384  htot(i) = h(i,k)
1385  sfc_connected(i) = .false.
1386  else
1387  uhtot(i) = uhtot(i) + u(i,k)*h(i,k)
1388  vhtot(i) = vhtot(i) + v(i,k)*h(i,k)
1389  htot(i) = htot(i) + h(i,k)
1390  endif
1391 
1392  if (debug) then
1393  if (k==2) then
1394  te(1) = b1*(h(i,1)*t0(1))
1395  se(1) = b1*(h(i,1)*s0(1))
1396  else
1397  te(k-1) = b1 * (h(i,k-1) * t0(k-1) + kddt_h(k-1) * te(k-2))
1398  se(k-1) = b1 * (h(i,k-1) * s0(k-1) + kddt_h(k-1) * se(k-2))
1399  endif
1400  endif
1401  enddo
1402  kd(i,nz+1) = 0.0
1403 
1404  if (debug) then
1405  ! Complete the tridiagonal solve for Te.
1406  b1 = 1.0 / hp_a(i)
1407  te(nz) = b1 * (h(i,nz) * t0(nz) + kddt_h(nz) * te(nz-1))
1408  se(nz) = b1 * (h(i,nz) * s0(nz) + kddt_h(nz) * se(nz-1))
1409  do k=nz-1,1,-1
1410  te(k) = te(k) + c1(k+1)*te(k+1)
1411  se(k) = se(k) + c1(k+1)*se(k+1)
1412  enddo
1413  endif
1414  if (present(dt_expected)) then
1415  do k=1,nz ; dt_expected(i,j,k) = te(k) - t0(k) ; enddo
1416  endif
1417  if (present(ds_expected)) then
1418  do k=1,nz ; ds_expected(i,j,k) = se(k) - s0(k) ; enddo
1419  endif
1420  if (debug) then
1421  dpe_debug = 0.0
1422  do k=1,nz
1423  dpe_debug = dpe_debug + (dt_to_dpe(i,k) * (te(k) - t0(k)) + &
1424  ds_to_dpe(i,k) * (se(k) - s0(k)))
1425  enddo
1426  mixing_debug = dpe_debug * idtdr0
1427  endif
1428  k = nz ! This is here to allow a breakpoint to be set.
1429  !/BGR
1430  ! The following lines are used for the iteration
1431  ! note the iteration has been altered to use the value predicted by
1432  ! the TKE threshold (ML_DEPTH). This is because the MSTAR
1433  ! is now dependent on the ML, and therefore the ML needs to be estimated
1434  ! more precisely than the grid spacing.
1435  !/
1436  itmax(obl_it) = max_mld ! Track max }
1437  itmin(obl_it) = min_mld ! Track min } For debug purpose
1438  itguess(obl_it) = mld_guess ! Track guess }
1439  !/
1440  mld_found=0.0 ; first_obl=.true.
1441  if (cs%Orig_MLD_iteration) then
1442  !This is how the iteration was original conducted
1443  do k=2,nz
1444  if (first_obl) then !Breaks when OBL found
1445  if (vstar_used(k) > 1.e-10 .and. k < nz) then
1446  mld_found = mld_found+h(i,k-1)*gv%H_to_m
1447  else
1448  first_obl = .false.
1449  if (mld_found-cs%MLD_tol > mld_guess) then
1450  min_mld = mld_guess
1451  elseif ((mld_guess-mld_found) < max(cs%MLD_tol,h(i,k-1)*gv%H_to_m)) then
1452  obl_converged = .true.!Break convergence loop
1453  if (obl_it_stats) then !Compute iteration statistics
1454  maxit = max(maxit,obl_it)
1455  minit = min(minit,obl_it)
1456  sumit = sumit+obl_it
1457  numit = numit+1
1458  print*,maxit,minit,sumit/numit
1459  endif
1460  cs%ML_Depth2(i,j) = mld_guess
1461  else
1462  max_mld = mld_guess !We know this guess was too deep
1463  endif
1464  endif
1465  endif
1466  enddo
1467  else
1468  !New method uses ML_DEPTH as computed in ePBL routine
1469  mld_found=cs%ML_DEPTH(i,j)
1470  if (mld_found-cs%MLD_tol > mld_guess) then
1471  min_mld = mld_guess
1472  elseif (abs(mld_guess-mld_found) < (cs%MLD_tol)) then
1473  obl_converged = .true.!Break convergence loop
1474  if (obl_it_stats) then !Compute iteration statistics
1475  maxit = max(maxit,obl_it)
1476  minit = min(minit,obl_it)
1477  sumit = sumit+obl_it
1478  numit = numit+1
1479  print*,maxit,minit,sumit/numit
1480  endif
1481  cs%ML_Depth2(i,j) = mld_guess
1482  else
1483  max_mld = mld_guess !We know this guess was too deep
1484  endif
1485  endif
1486  ! For next pass, guess average of minimum and maximum values.
1487  mld_guess = min_mld*0.5 + max_mld*0.5
1488  itresult(obl_it) = mld_found
1489  endif ; enddo ! Iteration loop for converged boundary layer thickness.
1490  if (.not.obl_converged) then
1491  !/Temp output, warn that EPBL didn't converge
1492  !/Print guess/found for every iteration step
1493  !print*,'EPBL MLD DID NOT CONVERGE'
1494  notconverged=notconverged+1
1495  !do obl_it=1,max_obl_it
1496  ! print*,ITmin(obl_it),ITmax(obl_it)
1497  ! print*,obl_it,ITguess(obl_it),ITresult(obl_it)
1498  !enddo
1499  !Activate to print out some output when not converged
1500  !{
1501  !print*,'Min/Max: ',ITmin(50),ITmax(50)
1502  !print*,'Guess/result: ',ITguess(50),ITresult(50)
1503  !print*,'Stats on CPU: ',CONVERGED,NOTCONVERGED,&
1504  ! real(NOTCONVERGED)/real(CONVERGED)
1505  !}
1506  !stop !Kill if not converged during testing.
1507  else
1508  converged=converged+1
1509  endif
1510 
1511  if (cs%TKE_diagnostics) then
1512  cs%diag_TKE_MKE(i,j) = cs%diag_TKE_MKE(i,j) + dtke_mke
1513  cs%diag_TKE_conv(i,j) = cs%diag_TKE_conv(i,j) + dtke_conv
1514  cs%diag_TKE_forcing(i,j) = cs%diag_TKE_forcing(i,j) + dtke_forcing
1515  cs%diag_TKE_mixing(i,j) = cs%diag_TKE_mixing(i,j) + dtke_mixing
1516  cs%diag_TKE_mech_decay(i,j) = cs%diag_TKE_mech_decay(i,j) + dtke_mech_decay
1517  cs%diag_TKE_conv_decay(i,j) = cs%diag_TKE_conv_decay(i,j) + dtke_conv_decay
1518  ! CS%diag_TKE_unbalanced_forcing(i,j) = CS%diag_TKE_unbalanced_forcing(i,j) + dTKE_unbalanced
1519  endif
1520  if (cs%Mixing_Diagnostics) then
1521  !Write to 3-D for outputing Mixing length and
1522  ! velocity scale.
1523  do k=1,nz
1524  cs%Mixing_Length(i,j,k) = mixing_length_used(k)
1525  cs%Velocity_Scale(i,j,k) = vstar_used(k)
1526  enddo
1527  endif
1528  if (allocated(cs%Enhance_M)) cs%Enhance_M(i,j) = enhance_m
1529  if (allocated(cs%mstar_mix)) cs%mstar_mix(i,j) = mstar_mix
1530  if (allocated(cs%MLD_Obukhov)) cs%MLD_Obukhov(i,j) = (mld_guess*il_obukhov)
1531  if (allocated(cs%MLD_Ekman)) cs%MLD_Ekman(i,j) = (mld_guess*il_ekman)
1532  if (allocated(cs%Ekman_Obukhov)) cs%Ekman_Obukhov(i,j) = (il_obukhov/(il_ekman+1.e-10))
1533  if (allocated(cs%La)) cs%La(i,j) = la
1534  if (allocated(cs%La_mod)) cs%La_mod(i,j) = lamod
1535  else
1536  ! For masked points, Kd_int must still be set (to 0) because it has intent(out).
1537  do k=1,nz+1
1538  kd(i,k) = 0.
1539  enddo
1540  if (present(dt_expected)) then
1541  do k=1,nz ; dt_expected(i,j,k) = 0.0 ; enddo
1542  endif
1543  if (present(ds_expected)) then
1544  do k=1,nz ; ds_expected(i,j,k) = 0.0 ; enddo
1545  endif
1546  endif ; enddo ; ! Close of i-loop - Note unusual loop order!
1547 
1548  if (cs%id_Hsfc_used > 0) then
1549  do i=is,ie ; hsfc_used(i,j) = h(i,1)*gv%H_to_m ; enddo
1550  do k=2,nz ; do i=is,ie
1551  if (kd(i,k) > 0.0) hsfc_used(i,j) = hsfc_used(i,j) + h(i,k)*gv%H_to_m
1552  enddo ; enddo
1553  endif
1554 
1555  do k=1,nz+1 ; do i=is,ie
1556  kd_int(i,j,k) = kd(i,k)
1557  enddo ; enddo
1558 
1559  enddo ! j-loop
1560 
1561  if (write_diags) then
1562  if (cs%id_ML_depth > 0) &
1563  call post_data(cs%id_ML_depth, cs%ML_depth, cs%diag)
1564  if (cs%id_TKE_wind > 0) &
1565  call post_data(cs%id_TKE_wind, cs%diag_TKE_wind, cs%diag)
1566  if (cs%id_TKE_MKE > 0) &
1567  call post_data(cs%id_TKE_MKE, cs%diag_TKE_MKE, cs%diag)
1568  if (cs%id_TKE_conv > 0) &
1569  call post_data(cs%id_TKE_conv, cs%diag_TKE_conv, cs%diag)
1570  if (cs%id_TKE_forcing > 0) &
1571  call post_data(cs%id_TKE_forcing, cs%diag_TKE_forcing, cs%diag)
1572  if (cs%id_TKE_mixing > 0) &
1573  call post_data(cs%id_TKE_mixing, cs%diag_TKE_mixing, cs%diag)
1574  if (cs%id_TKE_mech_decay > 0) &
1575  call post_data(cs%id_TKE_mech_decay, cs%diag_TKE_mech_decay, cs%diag)
1576  if (cs%id_TKE_conv_decay > 0) &
1577  call post_data(cs%id_TKE_conv_decay, cs%diag_TKE_conv_decay, cs%diag)
1578  if (cs%id_Hsfc_used > 0) &
1579  call post_data(cs%id_Hsfc_used, hsfc_used, cs%diag)
1580  if (cs%id_Mixing_Length > 0) &
1581  call post_data(cs%id_Mixing_Length, cs%Mixing_Length, cs%diag)
1582  if (cs%id_Velocity_Scale >0) &
1583  call post_data(cs%id_Velocity_Scale, cs%Velocity_Scale, cs%diag)
1584  if (cs%id_OSBL >0) &
1585  call post_data(cs%id_OSBL, cs%ML_Depth2, cs%diag)
1586  if (cs%id_LT_Enhancement >0) &
1587  call post_data(cs%id_LT_Enhancement, cs%Enhance_M, cs%diag)
1588  if (cs%id_MSTAR_MIX >0) &
1589  call post_data(cs%id_MSTAR_MIX, cs%MSTAR_MIX, cs%diag)
1590  if (cs%id_MLD_OBUKHOV >0) &
1591  call post_data(cs%id_MLD_Obukhov, cs%MLD_OBUKHOV, cs%diag)
1592  if (cs%id_MLD_EKMAN >0) &
1593  call post_data(cs%id_MLD_Ekman, cs%MLD_EKMAN, cs%diag)
1594  if (cs%id_Ekman_Obukhov >0) &
1595  call post_data(cs%id_Ekman_Obukhov, cs%Ekman_Obukhov, cs%diag)
1596  if (cs%id_LA >0) &
1597  call post_data(cs%id_LA, cs%LA, cs%diag)
1598  if (cs%id_LA_MOD >0) &
1599  call post_data(cs%id_LA_MOD, cs%LA_MOD, cs%diag)
1600 
1601  endif
1602 
Here is the call graph for this function:

◆ energetic_pbl_end()

subroutine, public mom_energetic_pbl::energetic_pbl_end ( type(energetic_pbl_cs), pointer  CS)

Definition at line 2371 of file MOM_energetic_PBL.F90.

2371  type(energetic_pbl_cs), pointer :: cs
2372 
2373  if (.not.associated(cs)) return
2374 
2375  if (allocated(cs%ML_depth)) deallocate(cs%ML_depth)
2376  if (allocated(cs%ML_depth2)) deallocate(cs%ML_depth2)
2377  if (allocated(cs%Enhance_M)) deallocate(cs%Enhance_M)
2378  if (allocated(cs%MLD_EKMAN)) deallocate(cs%MLD_EKMAN)
2379  if (allocated(cs%MLD_OBUKHOV)) deallocate(cs%MLD_OBUKHOV)
2380  if (allocated(cs%EKMAN_OBUKHOV)) deallocate(cs%EKMAN_OBUKHOV)
2381  if (allocated(cs%LA)) deallocate(cs%LA)
2382  if (allocated(cs%LA_mod)) deallocate(cs%LA_mod)
2383  if (allocated(cs%MSTAR_MIX)) deallocate(cs%MSTAR_MIX)
2384  if (allocated(cs%diag_TKE_wind)) deallocate(cs%diag_TKE_wind)
2385  if (allocated(cs%diag_TKE_MKE)) deallocate(cs%diag_TKE_MKE)
2386  if (allocated(cs%diag_TKE_conv)) deallocate(cs%diag_TKE_conv)
2387  if (allocated(cs%diag_TKE_forcing)) deallocate(cs%diag_TKE_forcing)
2388  if (allocated(cs%diag_TKE_mixing)) deallocate(cs%diag_TKE_mixing)
2389  if (allocated(cs%diag_TKE_mech_decay)) deallocate(cs%diag_TKE_mech_decay)
2390  if (allocated(cs%diag_TKE_conv_decay)) deallocate(cs%diag_TKE_conv_decay)
2391  if (allocated(cs%Mixing_Length)) deallocate(cs%Mixing_Length)
2392  if (allocated(cs%Velocity_Scale)) deallocate(cs%Velocity_Scale)
2393 
2394  deallocate(cs)
2395 

◆ energetic_pbl_get_mld()

subroutine, public mom_energetic_pbl::energetic_pbl_get_mld ( type(energetic_pbl_cs), pointer  CS,
real, dimension(szi_(g),szj_(g)), intent(out)  MLD,
type(ocean_grid_type), intent(in)  G 
)

Copies the ePBL active mixed layer depth into MLD.

Parameters
csControl structure for ePBL
[in]gGrid structure
[out]mldDepth of ePBL active mixing layer

Definition at line 1908 of file MOM_energetic_PBL.F90.

Referenced by mom_diabatic_driver::diabatic().

1908  type(energetic_pbl_cs), pointer :: cs !< Control structure for ePBL
1909  type(ocean_grid_type), intent(in) :: g !< Grid structure
1910  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: mld !< Depth of ePBL active mixing layer
1911  ! Local variables
1912  integer :: i,j
1913  do j = g%jsc, g%jec ; do i = g%isc, g%iec
1914  mld(i,j) = cs%ML_depth(i,j)
1915  enddo ; enddo
Here is the caller graph for this function:

◆ energetic_pbl_init()

subroutine, public mom_energetic_pbl::energetic_pbl_init ( type(time_type), intent(in), target  Time,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout), target  diag,
type(energetic_pbl_cs), pointer  CS 
)
Parameters
[in]gThe ocean's grid structure
[in]gvThe ocean's vertical grid structure
[in]param_fileA structure to parse for run-time parameters

Definition at line 2056 of file MOM_energetic_PBL.F90.

2056  type(time_type), target, intent(in) :: time
2057  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
2058  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
2059  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
2060  type(diag_ctrl), target, intent(inout) :: diag
2061  type(energetic_pbl_cs), pointer :: cs
2062 ! Arguments: Time - The current model time.
2063 ! (in) G - The ocean's grid structure.
2064 ! (in) GV - The ocean's vertical grid structure.
2065 ! (in) param_file - A structure indicating the open file to parse for
2066 ! model parameter values.
2067 ! (in) diag - A structure that is used to regulate diagnostic output.
2068 ! (in/out) CS - A pointer that is set to point to the control structure
2069 ! for this module
2070 ! This include declares and sets the variable "version".
2071 #include "version_variable.h"
2072  character(len=40) :: mdl = "MOM_energetic_PBL" ! This module's name.
2073  real :: omega_frac_dflt
2074  integer :: isd, ied, jsd, jed
2075  logical :: use_temperature, use_omega
2076  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2077 
2078  if (associated(cs)) then
2079  call mom_error(warning, "mixedlayer_init called with an associated"// &
2080  "associated control structure.")
2081  return
2082  else ; allocate(cs) ; endif
2083 
2084  cs%diag => diag
2085  cs%Time => time
2086 
2087 ! Set default, read and log parameters
2088  call log_version(param_file, mdl, version, "")
2089 
2090  call get_param(param_file, mdl, "MSTAR_MODE", cs%mstar_mode, &
2091  "An integer switch for how to compute MSTAR. \n"//&
2092  " 0 for constant MSTAR\n"//&
2093  " 1 for MSTAR w/ MLD in stabilizing limit\n"//&
2094  " 2 for MSTAR w/ L_E/L_O in stabilizing limit.",&
2095  "units=nondim",default=0)
2096  call get_param(param_file, mdl, "MSTAR", cs%mstar, &
2097  "The ratio of the friction velocity cubed to the TKE \n"//&
2098  "input to the mixed layer.", "units=nondim", default=1.2)
2099  call get_param(param_file, mdl, "MIX_LEN_EXPONENT", cs%MixLenExponent, &
2100  "The exponent applied to the ratio of the distance to the MLD \n"//&
2101  "and the MLD depth which determines the shape of the mixing length.",&
2102  "units=nondim", default=2.0)
2103  call get_param(param_file, mdl, "MSTAR_CAP", cs%mstar_cap, &
2104  "Maximum value of mstar allowed in model if non-negative\n"//&
2105  "(used if MSTAR_MODE>0).",&
2106  "units=nondim", default=-1.0)
2107  call get_param(param_file, mdl, "MSTAR_CONV_ADJ", cs%cnv_mst_fac, &
2108  "Factor used for reducing mstar during convection \n"//&
2109  " due to reduction of stable density gradient.",&
2110  "units=nondim", default=0.0)
2111  call get_param(param_file, mdl, "MSTAR_SLOPE", cs%mstar_slope, &
2112  "The slope of the linear relationship between mstar \n"//&
2113  "and the length scale ratio (used if MSTAR_MODE=1).",&
2114  "units=nondim", default=0.85)
2115  call get_param(param_file, mdl, "MSTAR_XINT", cs%mstar_xint, &
2116  "The value of the length scale ratio where the mstar \n"//&
2117  "is linear above (used if MSTAR_MODE=1).",&
2118  "units=nondim", default=-0.3)
2119  call get_param(param_file, mdl, "MSTAR_AT_XINT", cs%mstar_at_xint, &
2120  "The value of mstar at MSTAR_XINT \n"//&
2121  "(used if MSTAR_MODE=1).",&
2122  "units=nondim", default=0.095)
2123  call get_param(param_file, mdl, "MSTAR_FLATCAP", cs%MSTAR_FLATCAP, &
2124  "Set false to use asymptotic cap, defaults to true.\n"//&
2125  "(used only if MSTAR_MODE=1)"&
2126  ,"units=nondim",default=.true.)
2127  call get_param(param_file, mdl, "MSTAR2_COEF1", cs%MSTAR_COEF, &
2128  "Coefficient in computing mstar when rotation and \n"//&
2129  " stabilizing effects are both important (used if MSTAR_MODE=2)"&
2130  ,"units=nondim",default=0.3)
2131  call get_param(param_file, mdl, "MSTAR2_COEF2", cs%C_EK, &
2132  "Coefficient in computing mstar when only rotation limits \n"//&
2133  " the total mixing. (used only if MSTAR_MODE=2)"&
2134  ,"units=nondim",default=0.085)
2135  call get_param(param_file, mdl, "NSTAR", cs%nstar, &
2136  "The portion of the buoyant potential energy imparted by \n"//&
2137  "surface fluxes that is available to drive entrainment \n"//&
2138  "at the base of mixed layer when that energy is positive.", &
2139  units="nondim", default=0.2)
2140  call get_param(param_file, mdl, "MKE_TO_TKE_EFFIC", cs%MKE_to_TKE_effic, &
2141  "The efficiency with which mean kinetic energy released \n"//&
2142  "by mechanically forced entrainment of the mixed layer \n"//&
2143  "is converted to turbulent kinetic energy.", units="nondim", &
2144  default=0.0)
2145  call get_param(param_file, mdl, "TKE_DECAY", cs%TKE_decay, &
2146  "TKE_DECAY relates the vertical rate of decay of the \n"//&
2147  "TKE available for mechanical entrainment to the natural \n"//&
2148  "Ekman depth.", units="nondim", default=2.5)
2149 ! call get_param(param_file, mdl, "HMIX_MIN", CS%Hmix_min, &
2150 ! "The minimum mixed layer depth if the mixed layer depth \n"//&
2151 ! "is determined dynamically.", units="m", default=0.0)
2152 
2153  call get_param(param_file, mdl, "OMEGA",cs%omega, &
2154  "The rotation rate of the earth.", units="s-1", &
2155  default=7.2921e-5)
2156  call get_param(param_file, mdl, "ML_USE_OMEGA", use_omega, &
2157  "If true, use the absolute rotation rate instead of the \n"//&
2158  "vertical component of rotation when setting the decay \n"// &
2159  "scale for turbulence.", default=.false., do_not_log=.true.)
2160  omega_frac_dflt = 0.0
2161  if (use_omega) then
2162  call mom_error(warning, "ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
2163  omega_frac_dflt = 1.0
2164  endif
2165  call get_param(param_file, mdl, "ML_OMEGA_FRAC", cs%omega_frac, &
2166  "When setting the decay scale for turbulence, use this \n"// &
2167  "fraction of the absolute rotation rate blended with the \n"//&
2168  "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
2169  units="nondim", default=omega_frac_dflt)
2170  call get_param(param_file, mdl, "WSTAR_USTAR_COEF", cs%wstar_ustar_coef, &
2171  "A ratio relating the efficiency with which convectively \n"//&
2172  "released energy is converted to a turbulent velocity, \n"// &
2173  "relative to mechanically forced TKE. Making this larger \n"//&
2174  "increases the BL diffusivity", units="nondim", default=1.0)
2175  call get_param(param_file, mdl, "VSTAR_SCALE_FACTOR", cs%vstar_scale_fac, &
2176  "An overall nondimensional scaling factor for v*. \n"// &
2177  "Making this larger decreases the PBL diffusivity.", &
2178  units="nondim", default=1.0)
2179  call get_param(param_file, mdl, "EKMAN_SCALE_COEF", cs%Ekman_scale_coef, &
2180  "A nondimensional scaling factor controlling the inhibition \n"// &
2181  "of the diffusive length scale by rotation. Making this larger \n"//&
2182  "decreases the PBL diffusivity.", units="nondim", default=1.0)
2183  call get_param(param_file, mdl, "USE_MLD_ITERATION", cs%USE_MLD_ITERATION, &
2184  "A logical that specifies whether or not to use the \n"// &
2185  "distance to the bottom of the actively turblent boundary \n"//&
2186  "layer to help set the EPBL length scale.", default=.false.)
2187  call get_param(param_file, mdl, "ORIG_MLD_ITERATION", cs%ORIG_MLD_ITERATION, &
2188  "A logical that specifies whether or not to use the \n"// &
2189  "old method for determining MLD depth in iteration, which \n"//&
2190  "is limited to resolution.", default=.true.)
2191  call get_param(param_file, mdl, "MLD_ITERATION_GUESS", cs%MLD_ITERATION_GUESS, &
2192  "A logical that specifies whether or not to use the \n"// &
2193  "previous timestep MLD as a first guess in the MLD iteration.\n"// &
2194  "The default is false to facilitate reproducibility.", default=.false.)
2195  call get_param(param_file, mdl, "EPBL_MLD_TOLERANCE", cs%MLD_tol, &
2196  "The tolerance for the iteratively determined mixed \n"// &
2197  "layer depth. This is only used with USE_MLD_ITERATION.", &
2198  units="meter", default=1.0)
2199  call get_param(param_file, mdl, "EPBL_MIN_MIX_LEN", cs%min_mix_len, &
2200  "The minimum mixing length scale that will be used \n"//&
2201  "by ePBL. The default (0) does not set a minimum.", &
2202  units="meter", default=0.0)
2203  call get_param(param_file, mdl, "EPBL_ORIGINAL_PE_CALC", cs%orig_PE_calc, &
2204  "If true, the ePBL code uses the original form of the \n"// &
2205  "potential energy change code. Otherwise, the newer \n"// &
2206  "version that can work with successive increments to the \n"// &
2207  "diffusivity in upward or downward passes is used.", default=.true.)
2208  call get_param(param_file, mdl, "EPBL_TRANSITION_SCALE", cs%transLay_scale, &
2209  "A scale for the mixing length in the transition layer \n"// &
2210  "at the edge of the boundary layer as a fraction of the \n"//&
2211  "boundary layer thickness. The default is 0.1.", &
2212  units="nondim", default=0.1)
2213  if ( cs%USE_MLD_ITERATION .and. abs(cs%transLay_scale-0.5).ge.0.5) then
2214  call mom_error(fatal, "If flag USE_MLD_ITERATION is true, then "// &
2215  "EPBL_TRANSITION should be greater than 0 and less than 1.")
2216  endif
2217  call get_param(param_file, mdl, "N2_DISSIPATION_POS", cs%N2_Dissipation_Scale_Pos, &
2218  "A scale for the dissipation of TKE due to stratification \n"// &
2219  "in the boundary layer, applied when local stratification \n"// &
2220  "is positive. The default is 0, but should probably be ~0.4.", &
2221  units="nondim", default=0.0)
2222  call get_param(param_file, mdl, "N2_DISSIPATION_NEG", cs%N2_Dissipation_Scale_Neg,&
2223  "A scale for the dissipation of TKE due to stratification \n"// &
2224  "in the boundary layer, applied when local stratification \n"// &
2225  "is negative. The default is 0, but should probably be ~1.", &
2226  units="nondim", default=0.0)
2227  call get_param(param_file, mdl, "USE_LA_LI2016", cs%USE_LA_Windsea, &
2228  "A logical to use the Li et al. 2016 (submitted) formula to \n"//&
2229  " determine the Langmuir number.", &
2230  units="nondim", default=.false.)
2231  call get_param(param_file, mdl, "LA_DEPTH_RATIO", cs%LaDepthRatio, &
2232  "The depth (normalized by BLD) to average Stokes drift over in \n"//&
2233  " Lanmguir number calculation, where La = sqrt(ust/Stokes).", &
2234  units="nondim",default=0.04)
2235  call get_param(param_file, mdl, "LT_ENHANCE", cs%LT_ENHANCE_FORM, &
2236  "Integer for Langmuir number mode. \n"// &
2237  " *Requires USE_LA_LI2016 to be set to True. \n"// &
2238  "Options: 0 - No Langmuir \n"// &
2239  " 1 - Van Roekel et al. 2014/Li et al., 2016 \n"//&
2240  " 2 - Multiplied w/ adjusted La. \n"// &
2241  " 3 - Added w/ adjusted La.", &
2242  units="nondim", default=0)
2243  call get_param(param_file, mdl, "LT_ENHANCE_COEF", cs%LT_ENHANCE_COEF, &
2244  "Coefficient for Langmuir enhancement if LT_ENHANCE > 1",&
2245  units="nondim", default=0.447)
2246  call get_param(param_file, mdl, "LT_ENHANCE_EXP", cs%LT_ENHANCE_EXP, &
2247  "Exponent for Langmuir enhancement if LT_ENHANCE > 1", &
2248  units="nondim", default=-1.33)
2249  call get_param(param_file, mdl, "LT_MOD_LAC1", cs%LaC_MLDoEK, &
2250  "Coefficient for modification of Langmuir number due to\n"//&
2251  " MLD approaching Ekman depth if LT_ENHANCE=2.", &
2252  units="nondim", default=-0.87)
2253  call get_param(param_file, mdl, "LT_MOD_LAC2", cs%LaC_MLDoOB_stab, &
2254  "Coefficient for modification of Langmuir number due to\n"//&
2255  " MLD approaching stable Obukhov depth if LT_ENHANCE=2.", &
2256  units="nondim", default=0.0)
2257  call get_param(param_file, mdl, "LT_MOD_LAC3", cs%LaC_MLDoOB_un, &
2258  "Coefficient for modification of Langmuir number due to\n"//&
2259  " MLD approaching unstable Obukhov depth if LT_ENHANCE=2.", &
2260  units="nondim", default=0.0)
2261  call get_param(param_file, mdl, "LT_MOD_LAC4", cs%Lac_EKoOB_stab, &
2262  "Coefficient for modification of Langmuir number due to\n"//&
2263  " ratio of Ekman to stable Obukhov depth if LT_ENHANCE=2.", &
2264  units="nondim", default=0.95)
2265  call get_param(param_file, mdl, "LT_MOD_LAC5", cs%Lac_EKoOB_un, &
2266  "Coefficient for modification of Langmuir number due to\n"// &
2267  " ratio of Ekman to unstable Obukhov depth if LT_ENHANCE=2.",&
2268  units="nondim", default=0.95)
2269  if (cs%LT_ENHANCE_FORM.gt.0 .and. (.not.cs%USE_LA_Windsea)) then
2270  call mom_error(fatal, "If flag USE_LA_LI2016 is false, then "//&
2271  " LT_ENHANCE must be 0.")
2272  endif
2273  ! This gives a minimum decay scale that is typically much less than Angstrom.
2274  cs%ustar_min = 2e-4*cs%omega*(gv%Angstrom_z + gv%H_to_m*gv%H_subroundoff)
2275  call log_param(param_file, mdl, "EPBL_USTAR_MIN", cs%ustar_min, &
2276  "The (tiny) minimum friction velocity used within the \n"//&
2277  "ePBL code, derived from OMEGA and ANGSTROM.", units="meter second-1")
2278 
2279  cs%id_ML_depth = register_diag_field('ocean_model', 'ePBL_h_ML', diag%axesT1, &
2280  time, 'Surface mixed layer depth', 'meter')
2281  cs%id_TKE_wind = register_diag_field('ocean_model', 'ePBL_TKE_wind', diag%axesT1, &
2282  time, 'Wind-stirring source of mixed layer TKE', 'meter3 second-3')
2283  cs%id_TKE_MKE = register_diag_field('ocean_model', 'ePBL_TKE_MKE', diag%axesT1, &
2284  time, 'Mean kinetic energy source of mixed layer TKE', 'meter3 second-3')
2285  cs%id_TKE_conv = register_diag_field('ocean_model', 'ePBL_TKE_conv', diag%axesT1, &
2286  time, 'Convective source of mixed layer TKE', 'meter3 second-3')
2287  cs%id_TKE_forcing = register_diag_field('ocean_model', 'ePBL_TKE_forcing', diag%axesT1, &
2288  time, 'TKE consumed by mixing surface forcing or penetrative shortwave radation'//&
2289  ' through model layers', 'meter3 second-3')
2290  cs%id_TKE_mixing = register_diag_field('ocean_model', 'ePBL_TKE_mixing', diag%axesT1, &
2291  time, 'TKE consumed by mixing that deepens the mixed layer', 'meter3 second-3')
2292  cs%id_TKE_mech_decay = register_diag_field('ocean_model', 'ePBL_TKE_mech_decay', diag%axesT1, &
2293  time, 'Mechanical energy decay sink of mixed layer TKE', 'meter3 second-3')
2294  cs%id_TKE_conv_decay = register_diag_field('ocean_model', 'ePBL_TKE_conv_decay', diag%axesT1, &
2295  time, 'Convective energy decay sink of mixed layer TKE', 'meter3 second-3')
2296  cs%id_Hsfc_used = register_diag_field('ocean_model', 'ePBL_Hs_used', diag%axesT1, &
2297  time, 'Surface region thickness that is used', 'meter')
2298  cs%id_Mixing_Length = register_diag_field('ocean_model', 'Mixing_Length', diag%axesTi, &
2299  time, 'Mixing Length that is used', 'meter')
2300  cs%id_Velocity_Scale = register_diag_field('ocean_model', 'Velocity_Scale', diag%axesTi, &
2301  time, 'Velocity Scale that is used.', 'meter second-1')
2302  cs%id_LT_enhancement = register_diag_field('ocean_model', 'LT_Enhancement', diag%axesT1, &
2303  time, 'LT enhancement that is used.', 'non-dim')
2304  cs%id_MSTAR_mix = register_diag_field('ocean_model', 'MSTAR', diag%axesT1, &
2305  time, 'MSTAR that is used.', 'non-dim')
2306  cs%id_OSBL = register_diag_field('ocean_model', 'ePBL_OSBL', diag%axesT1, &
2307  time, 'Boundary layer depth from the iteration.', 'meter')
2308  cs%id_mld_ekman = register_diag_field('ocean_model', 'MLD_EKMAN', diag%axesT1, &
2309  time, 'Boundary layer depth over Ekman length.', 'meter')
2310  cs%id_mld_obukhov = register_diag_field('ocean_model', 'MLD_OBUKHOV', diag%axesT1, &
2311  time, 'Boundary layer depth over Obukhov length.', 'meter')
2312  cs%id_ekman_obukhov = register_diag_field('ocean_model', 'EKMAN_OBUKHOV', diag%axesT1, &
2313  time, 'Ekman length over Obukhov length.', 'meter')
2314  cs%id_LA = register_diag_field('ocean_model', 'LA', diag%axesT1, &
2315  time, 'Langmuir number.', 'non-dim')
2316  cs%id_LA_mod = register_diag_field('ocean_model', 'LA_MOD', diag%axesT1, &
2317  time, 'Modified Langmuir number.', 'non-dim')
2318 
2319 
2320  call get_param(param_file, mdl, "ENABLE_THERMODYNAMICS", use_temperature, &
2321  "If true, temperature and salinity are used as state \n"//&
2322  "variables.", default=.true.)
2323 
2324  if (max(cs%id_TKE_wind, cs%id_TKE_MKE, cs%id_TKE_conv, &
2325  cs%id_TKE_mixing, cs%id_TKE_mech_decay, cs%id_TKE_forcing, &
2326  cs%id_TKE_conv_decay) > 0) then
2327  call safe_alloc_alloc(cs%diag_TKE_wind, isd, ied, jsd, jed)
2328  call safe_alloc_alloc(cs%diag_TKE_MKE, isd, ied, jsd, jed)
2329  call safe_alloc_alloc(cs%diag_TKE_conv, isd, ied, jsd, jed)
2330  call safe_alloc_alloc(cs%diag_TKE_forcing, isd, ied, jsd, jed)
2331  call safe_alloc_alloc(cs%diag_TKE_mixing, isd, ied, jsd, jed)
2332  call safe_alloc_alloc(cs%diag_TKE_mech_decay, isd, ied, jsd, jed)
2333  call safe_alloc_alloc(cs%diag_TKE_conv_decay, isd, ied, jsd, jed)
2334 
2335  cs%TKE_diagnostics = .true.
2336  endif
2337  if ((cs%id_Mixing_Length>0) .or. (cs%id_Velocity_Scale>0)) then
2338  call safe_alloc_alloc(cs%Velocity_Scale,isd,ied,jsd,jed,gv%ke+1)
2339  call safe_alloc_alloc(cs%Mixing_Length,isd,ied,jsd,jed,gv%ke+1)
2340  cs%Velocity_Scale(:,:,:) = 0.0
2341  cs%Mixing_Length(:,:,:) = 0.0
2342  cs%mixing_diagnostics = .true.
2343  endif
2344  call safe_alloc_alloc(cs%ML_depth, isd, ied, jsd, jed)
2345  call safe_alloc_alloc(cs%ML_depth2, isd, ied, jsd, jed)
2346  if (max(cs%id_LT_Enhancement, cs%id_mstar_mix,cs%id_mld_ekman, &
2347  cs%id_ekman_obukhov, cs%id_mld_obukhov, cs%id_LA, cs%id_LA_mod)>0) then
2348  call safe_alloc_alloc(cs%Mstar_mix, isd, ied, jsd, jed)
2349  call safe_alloc_alloc(cs%Enhance_M, isd, ied, jsd, jed)
2350  call safe_alloc_alloc(cs%MLD_EKMAN, isd, ied, jsd, jed)
2351  call safe_alloc_alloc(cs%MLD_OBUKHOV, isd, ied, jsd, jed)
2352  call safe_alloc_alloc(cs%EKMAN_OBUKHOV, isd, ied, jsd, jed)
2353  call safe_alloc_alloc(cs%LA, isd, ied, jsd, jed)
2354  call safe_alloc_alloc(cs%LA_MOD, isd, ied, jsd, jed)
2355  endif
2356 
2357  !Fitting coefficients to asymptote twoard 0 as MLD -> Ekman depth
2358  cs%MSTAR_A = cs%MSTAR_AT_XINT**(1./cs%MSTAR_N)
2359  cs%MSTAR_B = cs%MSTAR_SLOPE / (cs%MSTAR_N*cs%MSTAR_A**(cs%MSTAR_N-1.))
2360  !Fitting coefficients to asymptote toward MSTAR_CAP
2361  !*Fixed to begin asymptote at MSTAR_CAP-0.5 toward MSTAR_CAP
2362  cs%MSTAR_A2 = 0.5**(1./cs%MSTAR_N)
2363  cs%MSTAR_B2 = -cs%MSTAR_SLOPE / (cs%MSTAR_N*cs%MSTAR_A2**(cs%MSTAR_N-1))
2364  !Compute value of X (referenced to MSTAR_XINT) where transition
2365  ! to asymptotic regime based on value of X where MSTAR=MSTAR_CAP-0.5
2366  cs%MSTAR_XINT_UP = (cs%MSTAR_CAP-0.5-cs%MSTAR_AT_XINT)/cs%MSTAR_SLOPE
2367 

◆ find_pe_chg()

subroutine mom_energetic_pbl::find_pe_chg ( real, intent(in)  Kddt_h0,
real, intent(in)  dKddt_h,
real, intent(in)  hp_a,
real, intent(in)  hp_b,
real, intent(in)  Th_a,
real, intent(in)  Sh_a,
real, intent(in)  Th_b,
real, intent(in)  Sh_b,
real, intent(in)  dT_to_dPE_a,
real, intent(in)  dS_to_dPE_a,
real, intent(in)  dT_to_dPE_b,
real, intent(in)  dS_to_dPE_b,
real, intent(in)  pres,
real, intent(in)  dT_to_dColHt_a,
real, intent(in)  dS_to_dColHt_a,
real, intent(in)  dT_to_dColHt_b,
real, intent(in)  dS_to_dColHt_b,
real, intent(out), optional  PE_chg,
real, intent(out), optional  dPEc_dKd,
real, intent(out), optional  dPE_max,
real, intent(out), optional  dPEc_dKd_0,
real, intent(out), optional  ColHt_cor 
)
private

This subroutine calculates the change in potential energy and or derivatives for several changes in an interfaces's diapycnal diffusivity times a timestep.

Parameters
[in]kddt_h0The previously used diffusivity at an interface times the time step and divided by the average of the thicknesses around the interface, in units of H (m or kg-2).
[in]dkddt_hThe trial change in the diffusivity at an interface times the time step and divided by the average of the thicknesses around the interface, in units of H (m or kg-2).
[in]hp_aThe effective pivot thickness of the layer above the interface, given by h_k plus a term that is a fraction (determined from the tridiagonal solver) of Kddt_h for the interface above, in H.
[in]hp_bThe effective pivot thickness of the layer below the interface, given by h_k plus a term that is a fraction (determined from the tridiagonal solver) of Kddt_h for the interface above, in H.
[in]th_aAn effective temperature times a thickness in the layer above, including implicit mixing effects with other yet higher layers, in K H.
[in]sh_aAn effective salinity times a thickness in the layer above, including implicit mixing effects with other yet higher layers, in K H.
[in]th_bAn effective temperature times a thickness in the layer below, including implicit mixing effects with other yet lower layers, in K H.
[in]sh_bAn effective salinity times a thickness in the layer below, including implicit mixing effects with other yet lower layers, in K H.
[in]dt_to_dpe_aA factor (pres_lay*mass_lay*dSpec_vol/dT) relating a layer's temperature change to the change in column potential energy, including all implicit diffusive changes in the temperatures of all the layers above, in J m-2 K-1.
[in]ds_to_dpe_aA factor (pres_lay*mass_lay*dSpec_vol/dS) relating a layer's salinity change to the change in column potential energy, including all implicit diffusive changes in the salinities of all the layers above, in J m-2 ppt-1.
[in]dt_to_dpe_bA factor (pres_lay*mass_lay*dSpec_vol/dT) relating a layer's temperature change to the change in column potential energy, including all implicit diffusive changes in the temperatures of all the layers below, in J m-2 K-1.
[in]ds_to_dpe_bA factor (pres_lay*mass_lay*dSpec_vol/dS) relating a layer's salinity change to the change in column potential energy, including all implicit diffusive changes in the salinities of all the layers below, in J m-2 ppt-1.
[in]presThe hydrostatic interface pressure, which is used to relate the changes in column thickness to the energy that is radiated as gravity waves and unavailable to drive mixing, in Pa.
[in]dt_to_dcolht_aA factor (mass_lay*dSColHtc_vol/dT) relating a layer's temperature change to the change in column height, including all implicit diffusive changes in the temperatures of all the layers above, in m K-1.
[in]ds_to_dcolht_aA factor (mass_lay*dSColHtc_vol/dS) relating a layer's salinity change to the change in column height, including all implicit diffusive changes in the salinities of all the layers above, in m ppt-1.
[in]dt_to_dcolht_bA factor (mass_lay*dSColHtc_vol/dT) relating a layer's temperature change to the change in column height, including all implicit diffusive changes in the temperatures of all the layers below, in m K-1.
[in]ds_to_dcolht_bA factor (mass_lay*dSColHtc_vol/dS) relating a layer's salinity change to the change in column height, including all implicit diffusive changes in the salinities of all the layers below, in m ppt-1.
[out]pe_chgThe change in column potential energy from applying Kddt_h at the present interface, in J m-2.
[out]dpec_dkdThe partial derivative of PE_chg with Kddt_h, in units of J m-2 H-1.
[out]dpe_maxThe maximum change in column potential energy that could be realizedd by applying a huge value of Kddt_h at the present interface, in J m-2.
[out]dpec_dkd_0The partial derivative of PE_chg with Kddt_h in the limit where Kddt_h = 0, in J m-2 H-1.
[out]colht_corThe correction to PE_chg that is made due to a net change in the column height, in J m-2.

Definition at line 1611 of file MOM_energetic_PBL.F90.

Referenced by energetic_pbl().

1611  real, intent(in) :: kddt_h0 !< The previously used diffusivity at an interface times
1612  !! the time step and divided by the average of the
1613  !! thicknesses around the interface, in units of H (m or kg-2).
1614  real, intent(in) :: dkddt_h !< The trial change in the diffusivity at an interface times
1615  !! the time step and divided by the average of the
1616  !! thicknesses around the interface, in units of H (m or kg-2).
1617  real, intent(in) :: hp_a !< The effective pivot thickness of the layer above the
1618  !! interface, given by h_k plus a term that
1619  !! is a fraction (determined from the tridiagonal solver) of
1620  !! Kddt_h for the interface above, in H.
1621  real, intent(in) :: hp_b !< The effective pivot thickness of the layer below the
1622  !! interface, given by h_k plus a term that
1623  !! is a fraction (determined from the tridiagonal solver) of
1624  !! Kddt_h for the interface above, in H.
1625  real, intent(in) :: th_a !< An effective temperature times a thickness in the layer
1626  !! above, including implicit mixing effects with other
1627  !! yet higher layers, in K H.
1628  real, intent(in) :: sh_a !< An effective salinity times a thickness in the layer
1629  !! above, including implicit mixing effects with other
1630  !! yet higher layers, in K H.
1631  real, intent(in) :: th_b !< An effective temperature times a thickness in the layer
1632  !! below, including implicit mixing effects with other
1633  !! yet lower layers, in K H.
1634  real, intent(in) :: sh_b !< An effective salinity times a thickness in the layer
1635  !! below, including implicit mixing effects with other
1636  !! yet lower layers, in K H.
1637  real, intent(in) :: dt_to_dpe_a !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating
1638  !! a layer's temperature change to the change in column
1639  !! potential energy, including all implicit diffusive changes
1640  !! in the temperatures of all the layers above, in J m-2 K-1.
1641  real, intent(in) :: ds_to_dpe_a !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating
1642  !! a layer's salinity change to the change in column
1643  !! potential energy, including all implicit diffusive changes
1644  !! in the salinities of all the layers above, in J m-2 ppt-1.
1645  real, intent(in) :: dt_to_dpe_b !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating
1646  !! a layer's temperature change to the change in column
1647  !! potential energy, including all implicit diffusive changes
1648  !! in the temperatures of all the layers below, in J m-2 K-1.
1649  real, intent(in) :: ds_to_dpe_b !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating
1650  !! a layer's salinity change to the change in column
1651  !! potential energy, including all implicit diffusive changes
1652  !! in the salinities of all the layers below, in J m-2 ppt-1.
1653  real, intent(in) :: pres !< The hydrostatic interface pressure, which is used to relate
1654  !! the changes in column thickness to the energy that is radiated
1655  !! as gravity waves and unavailable to drive mixing, in Pa.
1656  real, intent(in) :: dt_to_dcolht_a !< A factor (mass_lay*dSColHtc_vol/dT) relating
1657  !! a layer's temperature change to the change in column
1658  !! height, including all implicit diffusive changes
1659  !! in the temperatures of all the layers above, in m K-1.
1660  real, intent(in) :: ds_to_dcolht_a !< A factor (mass_lay*dSColHtc_vol/dS) relating
1661  !! a layer's salinity change to the change in column
1662  !! height, including all implicit diffusive changes
1663  !! in the salinities of all the layers above, in m ppt-1.
1664  real, intent(in) :: dt_to_dcolht_b !< A factor (mass_lay*dSColHtc_vol/dT) relating
1665  !! a layer's temperature change to the change in column
1666  !! height, including all implicit diffusive changes
1667  !! in the temperatures of all the layers below, in m K-1.
1668  real, intent(in) :: ds_to_dcolht_b !< A factor (mass_lay*dSColHtc_vol/dS) relating
1669  !! a layer's salinity change to the change in column
1670  !! height, including all implicit diffusive changes
1671  !! in the salinities of all the layers below, in m ppt-1.
1672 
1673  real, optional, intent(out) :: pe_chg !< The change in column potential energy from applying
1674  !! Kddt_h at the present interface, in J m-2.
1675  real, optional, intent(out) :: dpec_dkd !< The partial derivative of PE_chg with Kddt_h,
1676  !! in units of J m-2 H-1.
1677  real, optional, intent(out) :: dpe_max !< The maximum change in column potential energy that could
1678  !! be realizedd by applying a huge value of Kddt_h at the
1679  !! present interface, in J m-2.
1680  real, optional, intent(out) :: dpec_dkd_0 !< The partial derivative of PE_chg with Kddt_h in the
1681  !! limit where Kddt_h = 0, in J m-2 H-1.
1682  real, optional, intent(out) :: colht_cor !< The correction to PE_chg that is made due to a net
1683  !! change in the column height, in J m-2.
1684 
1685  real :: hps ! The sum of the two effective pivot thicknesses, in H.
1686  real :: bdt1 ! A product of the two pivot thicknesses plus a diffusive term, in H2.
1687  real :: dt_c ! The core term in the expressions for the temperature changes, in K H2.
1688  real :: ds_c ! The core term in the expressions for the salinity changes, in psu H2.
1689  real :: pec_core ! The diffusivity-independent core term in the expressions
1690  ! for the potential energy changes, J m-3.
1691  real :: colht_core ! The diffusivity-independent core term in the expressions
1692  ! for the column height changes, J m-3.
1693  real :: colht_chg ! The change in the column height, in m.
1694  real :: y1 ! A local temporary term, in units of H-3 or H-4 in various contexts.
1695 
1696  ! The expression for the change in potential energy used here is derived
1697  ! from the expression for the final estimates of the changes in temperature
1698  ! and salinities, and then extensively manipulated to get it into its most
1699  ! succint form. The derivation is not necessarily obvious, but it demonstrably
1700  ! works by comparison with separate calculations of the energy changes after
1701  ! the tridiagonal solver for the final changes in temperature and salinity are
1702  ! applied.
1703 
1704  hps = hp_a + hp_b
1705  bdt1 = hp_a * hp_b + kddt_h0 * hps
1706  dt_c = hp_a * th_b - hp_b * th_a
1707  ds_c = hp_a * sh_b - hp_b * sh_a
1708  pec_core = hp_b * (dt_to_dpe_a * dt_c + ds_to_dpe_a * ds_c) - &
1709  hp_a * (dt_to_dpe_b * dt_c + ds_to_dpe_b * ds_c)
1710  colht_core = hp_b * (dt_to_dcolht_a * dt_c + ds_to_dcolht_a * ds_c) - &
1711  hp_a * (dt_to_dcolht_b * dt_c + ds_to_dcolht_b * ds_c)
1712 
1713  if (present(pe_chg)) then
1714  ! Find the change in column potential energy due to the change in the
1715  ! diffusivity at this interface by dKddt_h.
1716  y1 = dkddt_h / (bdt1 * (bdt1 + dkddt_h * hps))
1717  pe_chg = pec_core * y1
1718  colht_chg = colht_core * y1
1719  if (colht_chg < 0.0) pe_chg = pe_chg - pres * colht_chg
1720  if (present(colht_cor)) colht_cor = -pres * min(colht_chg, 0.0)
1721  else if (present(colht_cor)) then
1722  y1 = dkddt_h / (bdt1 * (bdt1 + dkddt_h * hps))
1723  colht_cor = -pres * min(colht_core * y1, 0.0)
1724  endif
1725 
1726  if (present(dpec_dkd)) then
1727  ! Find the derivative of the potential energy change with dKddt_h.
1728  y1 = 1.0 / (bdt1 + dkddt_h * hps)**2
1729  dpec_dkd = pec_core * y1
1730  colht_chg = colht_core * y1
1731  if (colht_chg < 0.0) dpec_dkd = dpec_dkd - pres * colht_chg
1732  endif
1733 
1734  if (present(dpe_max)) then
1735  ! This expression is the limit of PE_chg for infinite dKddt_h.
1736  y1 = 1.0 / (bdt1 * hps)
1737  dpe_max = pec_core * y1
1738  colht_chg = colht_core * y1
1739  if (colht_chg < 0.0) dpe_max = dpe_max - pres * colht_chg
1740  endif
1741 
1742  if (present(dpec_dkd_0)) then
1743  ! This expression is the limit of dPEc_dKd for dKddt_h = 0.
1744  y1 = 1.0 / bdt1**2
1745  dpec_dkd_0 = pec_core * y1
1746  colht_chg = colht_core * y1
1747  if (colht_chg < 0.0) dpec_dkd_0 = dpec_dkd_0 - pres * colht_chg
1748  endif
1749 
Here is the caller graph for this function:

◆ find_pe_chg_orig()

subroutine mom_energetic_pbl::find_pe_chg_orig ( real, intent(in)  Kddt_h,
real, intent(in)  h_k,
real, intent(in)  b_den_1,
real, intent(in)  dTe_term,
real, intent(in)  dSe_term,
real, intent(in)  dT_km1_t2,
real, intent(in)  dS_km1_t2,
real, intent(in)  dT_to_dPE_k,
real, intent(in)  dS_to_dPE_k,
real, intent(in)  dT_to_dPEa,
real, intent(in)  dS_to_dPEa,
real, intent(in)  pres,
real, intent(in)  dT_to_dColHt_k,
real, intent(in)  dS_to_dColHt_k,
real, intent(in)  dT_to_dColHta,
real, intent(in)  dS_to_dColHta,
real, intent(out), optional  PE_chg,
real, intent(out), optional  dPEc_dKd,
real, intent(out), optional  dPE_max,
real, intent(out), optional  dPEc_dKd_0 
)
private

This subroutine calculates the change in potential energy and or derivatives for several changes in an interfaces's diapycnal diffusivity times a timestep using the original form used in the first version of ePBL.

Parameters
[in]kddt_hThe diffusivity at an interface times the time step and divided by the average of the thicknesses around the interface, in units of H (m or kg-2).
[in]h_kThe thickness of the layer below the interface, in H.
[in]b_den_1The first term in the denominator of the pivot for the tridiagonal solver, given by h_k plus a term that is a fraction (determined from the tridiagonal solver) of Kddt_h for the interface above, in H.
[in]dte_termA diffusivity-independent term related to the temperature change in the layer below the interface, in K H.
[in]dse_termA diffusivity-independent term related to the salinity change in the layer below the interface, in ppt H.
[in]dt_km1_t2A diffusivity-independent term related to the temperature change in the layer above the interface, in K.
[in]ds_km1_t2A diffusivity-independent term related to the salinity change in the layer above the interface, in ppt.
[in]presThe hydrostatic interface pressure, which is used to relate the changes in column thickness to the energy that is radiated as gravity waves and unavailable to drive mixing, in Pa.
[in]dt_to_dpe_kA factor (pres_lay*mass_lay*dSpec_vol/dT) relating a layer's temperature change to the change in column potential energy, including all implicit diffusive changes in the temperatures of all the layers below, in J m-2 K-1.
[in]ds_to_dpe_kA factor (pres_lay*mass_lay*dSpec_vol/dS) relating a layer's salinity change to the change in column potential energy, including all implicit diffusive changes in the salinities of all the layers below, in J m-2 ppt-1.
[in]dt_to_dpeaA factor (pres_lay*mass_lay*dSpec_vol/dT) relating a layer's temperature change to the change in column potential energy, including all implicit diffusive changes in the temperatures of all the layers above, in J m-2 K-1.
[in]ds_to_dpeaA factor (pres_lay*mass_lay*dSpec_vol/dS) relating a layer's salinity change to the change in column potential energy, including all implicit diffusive changes in the salinities of all the layers above, in J m-2 ppt-1.
[in]dt_to_dcolht_kA factor (mass_lay*dSColHtc_vol/dT) relating a layer's temperature change to the change in column height, including all implicit diffusive changes in the temperatures of all the layers below, in m K-1.
[in]ds_to_dcolht_kA factor (mass_lay*dSColHtc_vol/dS) relating a layer's salinity change to the change in column height, including all implicit diffusive changes in the salinities of all the layers below, in m ppt-1.
[in]dt_to_dcolhtaA factor (mass_lay*dSColHtc_vol/dT) relating a layer's temperature change to the change in column height, including all implicit diffusive changes in the temperatures of all the layers above, in m K-1.
[in]ds_to_dcolhtaA factor (mass_lay*dSColHtc_vol/dS) relating a layer's salinity change to the change in column height, including all implicit diffusive changes in the salinities of all the layers above, in m ppt-1.
[out]pe_chgThe change in column potential energy from applying Kddt_h at the present interface, in J m-2.
[out]dpec_dkdThe partial derivative of PE_chg with Kddt_h, in units of J m-2 H-1.
[out]dpe_maxThe maximum change in column potential energy that could be realizedd by applying a huge value of Kddt_h at the present interface, in J m-2.
[out]dpec_dkd_0The partial derivative of PE_chg with Kddt_h in the limit where Kddt_h = 0, in J m-2 H-1.

Definition at line 1760 of file MOM_energetic_PBL.F90.

Referenced by energetic_pbl().

1760  real, intent(in) :: kddt_h !< The diffusivity at an interface times the time step and
1761  !! divided by the average of the thicknesses around the
1762  !! interface, in units of H (m or kg-2).
1763  real, intent(in) :: h_k !< The thickness of the layer below the interface, in H.
1764  real, intent(in) :: b_den_1 !< The first term in the denominator of the pivot
1765  !! for the tridiagonal solver, given by h_k plus a term that
1766  !! is a fraction (determined from the tridiagonal solver) of
1767  !! Kddt_h for the interface above, in H.
1768  real, intent(in) :: dte_term !< A diffusivity-independent term related to the
1769  !! temperature change in the layer below the interface, in K H.
1770  real, intent(in) :: dse_term !< A diffusivity-independent term related to the
1771  !! salinity change in the layer below the interface, in ppt H.
1772  real, intent(in) :: dt_km1_t2 !< A diffusivity-independent term related to the
1773  !! temperature change in the layer above the interface, in K.
1774  real, intent(in) :: ds_km1_t2 !< A diffusivity-independent term related to the
1775  !! salinity change in the layer above the interface, in ppt.
1776  real, intent(in) :: pres !< The hydrostatic interface pressure, which is used to relate
1777  !! the changes in column thickness to the energy that is radiated
1778  !! as gravity waves and unavailable to drive mixing, in Pa.
1779  real, intent(in) :: dt_to_dpe_k !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating
1780  !! a layer's temperature change to the change in column
1781  !! potential energy, including all implicit diffusive changes
1782  !! in the temperatures of all the layers below, in J m-2 K-1.
1783  real, intent(in) :: ds_to_dpe_k !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating
1784  !! a layer's salinity change to the change in column
1785  !! potential energy, including all implicit diffusive changes
1786  !! in the salinities of all the layers below, in J m-2 ppt-1.
1787  real, intent(in) :: dt_to_dpea !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating
1788  !! a layer's temperature change to the change in column
1789  !! potential energy, including all implicit diffusive changes
1790  !! in the temperatures of all the layers above, in J m-2 K-1.
1791  real, intent(in) :: ds_to_dpea !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating
1792  !! a layer's salinity change to the change in column
1793  !! potential energy, including all implicit diffusive changes
1794  !! in the salinities of all the layers above, in J m-2 ppt-1.
1795  real, intent(in) :: dt_to_dcolht_k !< A factor (mass_lay*dSColHtc_vol/dT) relating
1796  !! a layer's temperature change to the change in column
1797  !! height, including all implicit diffusive changes
1798  !! in the temperatures of all the layers below, in m K-1.
1799  real, intent(in) :: ds_to_dcolht_k !< A factor (mass_lay*dSColHtc_vol/dS) relating
1800  !! a layer's salinity change to the change in column
1801  !! height, including all implicit diffusive changes
1802  !! in the salinities of all the layers below, in m ppt-1.
1803  real, intent(in) :: dt_to_dcolhta !< A factor (mass_lay*dSColHtc_vol/dT) relating
1804  !! a layer's temperature change to the change in column
1805  !! height, including all implicit diffusive changes
1806  !! in the temperatures of all the layers above, in m K-1.
1807  real, intent(in) :: ds_to_dcolhta !< A factor (mass_lay*dSColHtc_vol/dS) relating
1808  !! a layer's salinity change to the change in column
1809  !! height, including all implicit diffusive changes
1810  !! in the salinities of all the layers above, in m ppt-1.
1811 
1812  real, optional, intent(out) :: pe_chg !< The change in column potential energy from applying
1813  !! Kddt_h at the present interface, in J m-2.
1814  real, optional, intent(out) :: dpec_dkd !< The partial derivative of PE_chg with Kddt_h,
1815  !! in units of J m-2 H-1.
1816  real, optional, intent(out) :: dpe_max !< The maximum change in column potential energy that could
1817  !! be realizedd by applying a huge value of Kddt_h at the
1818  !! present interface, in J m-2.
1819  real, optional, intent(out) :: dpec_dkd_0 !< The partial derivative of PE_chg with Kddt_h in the
1820  !! limit where Kddt_h = 0, in J m-2 H-1.
1821 
1822 ! This subroutine determines the total potential energy change due to mixing
1823 ! at an interface, including all of the implicit effects of the prescribed
1824 ! mixing at interfaces above. Everything here is derived by careful manipulation
1825 ! of the robust tridiagonal solvers used for tracers by MOM6. The results are
1826 ! positive for mixing in a stably stratified environment.
1827 ! The comments describing these arguments are for a downward mixing pass, but
1828 ! this routine can also be used for an upward pass with the sense of direction
1829 ! reversed.
1830 
1831  real :: b1 ! b1 is used by the tridiagonal solver, in H-1.
1832  real :: b1kd ! Temporary array (nondim.)
1833  real :: colht_chg ! The change in column thickness in m.
1834  real :: dcolht_max ! The change in column thickess for infinite diffusivity, in m.
1835  real :: dcolht_dkd ! The partial derivative of column thickess with diffusivity, in s m-1.
1836  real :: dt_k, dt_km1 ! Temporary arrays in K.
1837  real :: ds_k, ds_km1 ! Temporary arrays in ppt.
1838  real :: i_kr_denom, dkr_dkd ! Temporary arrays in H-2 and nondim.
1839  real :: ddt_k_dkd, ddt_km1_dkd ! Temporary arrays in K H-1.
1840  real :: dds_k_dkd, dds_km1_dkd ! Temporary arrays in ppt H-1.
1841 
1842  b1 = 1.0 / (b_den_1 + kddt_h)
1843  b1kd = kddt_h*b1
1844 
1845  ! Start with the temperature change in layer k-1 due to the diffusivity at
1846  ! interface K without considering the effects of changes in layer k.
1847 
1848  ! Calculate the change in PE due to the diffusion at interface K
1849  ! if Kddt_h(K+1) = 0.
1850  i_kr_denom = 1.0 / (h_k*b_den_1 + (b_den_1 + h_k)*kddt_h)
1851 
1852  dt_k = (kddt_h*i_kr_denom) * dte_term
1853  ds_k = (kddt_h*i_kr_denom) * dse_term
1854 
1855  if (present(pe_chg)) then
1856  ! Find the change in energy due to diffusion with strength Kddt_h at this interface.
1857  ! Increment the temperature changes in layer k-1 due the changes in layer k.
1858  dt_km1 = b1kd * ( dt_k + dt_km1_t2 )
1859  ds_km1 = b1kd * ( ds_k + ds_km1_t2 )
1860  pe_chg = (dt_to_dpe_k * dt_k + dt_to_dpea * dt_km1) + &
1861  (ds_to_dpe_k * ds_k + ds_to_dpea * ds_km1)
1862  colht_chg = (dt_to_dcolht_k * dt_k + dt_to_dcolhta * dt_km1) + &
1863  (ds_to_dcolht_k * ds_k + ds_to_dcolhta * ds_km1)
1864  if (colht_chg < 0.0) pe_chg = pe_chg - pres * colht_chg
1865  endif
1866 
1867  if (present(dpec_dkd)) then
1868  ! Find the derivatives of the temperature and salinity changes with Kddt_h.
1869  dkr_dkd = (h_k*b_den_1) * i_kr_denom**2
1870 
1871  ddt_k_dkd = dkr_dkd * dte_term
1872  dds_k_dkd = dkr_dkd * dse_term
1873  ddt_km1_dkd = (b1**2 * b_den_1) * ( dt_k + dt_km1_t2 ) + b1kd * ddt_k_dkd
1874  dds_km1_dkd = (b1**2 * b_den_1) * ( ds_k + ds_km1_t2 ) + b1kd * dds_k_dkd
1875 
1876  ! Calculate the partial derivative of Pe_chg with Kddt_h.
1877  dpec_dkd = (dt_to_dpe_k * ddt_k_dkd + dt_to_dpea * ddt_km1_dkd) + &
1878  (ds_to_dpe_k * dds_k_dkd + ds_to_dpea * dds_km1_dkd)
1879  dcolht_dkd = (dt_to_dcolht_k * ddt_k_dkd + dt_to_dcolhta * ddt_km1_dkd) + &
1880  (ds_to_dcolht_k * dds_k_dkd + ds_to_dcolhta * dds_km1_dkd)
1881  if (dcolht_dkd < 0.0) dpec_dkd = dpec_dkd - pres * dcolht_dkd
1882  endif
1883 
1884  if (present(dpe_max)) then
1885  ! This expression is the limit of PE_chg for infinite Kddt_h.
1886  dpe_max = (dt_to_dpea * dt_km1_t2 + ds_to_dpea * ds_km1_t2) + &
1887  ((dt_to_dpe_k + dt_to_dpea) * dte_term + &
1888  (ds_to_dpe_k + ds_to_dpea) * dse_term) / (b_den_1 + h_k)
1889  dcolht_max = (dt_to_dcolhta * dt_km1_t2 + ds_to_dcolhta * ds_km1_t2) + &
1890  ((dt_to_dcolht_k + dt_to_dcolhta) * dte_term + &
1891  (ds_to_dcolht_k + ds_to_dcolhta) * dse_term) / (b_den_1 + h_k)
1892  if (dcolht_max < 0.0) dpe_max = dpe_max - pres*dcolht_max
1893  endif
1894 
1895  if (present(dpec_dkd_0)) then
1896  ! This expression is the limit of dPEc_dKd for Kddt_h = 0.
1897  dpec_dkd_0 = (dt_to_dpea * dt_km1_t2 + ds_to_dpea * ds_km1_t2) / (b_den_1) + &
1898  (dt_to_dpe_k * dte_term + ds_to_dpe_k * dse_term) / (h_k*b_den_1)
1899  dcolht_dkd = (dt_to_dcolhta * dt_km1_t2 + ds_to_dcolhta * ds_km1_t2) / (b_den_1) + &
1900  (dt_to_dcolht_k * dte_term + ds_to_dcolht_k * dse_term) / (h_k*b_den_1)
1901  if (dcolht_dkd < 0.0) dpec_dkd_0 = dpec_dkd_0 - pres*dcolht_dkd
1902  endif
1903 
Here is the caller graph for this function:

◆ get_la_windsea()

subroutine mom_energetic_pbl::get_la_windsea ( real, intent(in)  ustar,
real, intent(in)  hbl,
type(verticalgrid_type), intent(in)  GV,
real, intent(out)  LA 
)
private
Parameters
[in]gvThe ocean's vertical grid structure

Definition at line 1962 of file MOM_energetic_PBL.F90.

References ust_2_u10_coare3p5().

Referenced by energetic_pbl().

1962 ! Original description:
1963 ! This function returns the enhancement factor, given the 10-meter
1964 ! wind (m/s), friction velocity (m/s) and the boundary layer depth (m).
1965 ! Update (Jan/25):
1966 ! Converted from function to subroutine, now returns Langmuir number.
1967 ! Computs 10m wind internally, so only ustar and hbl need passed to
1968 ! subroutine.
1969 !
1970 ! Qing Li, 160606
1971 ! BGR port from CVMix to MOM6 Jan/25/2017
1972 ! BGR change output to LA from Efactor
1973 ! BGR remove u10 input
1974 
1975 ! Input
1976  real, intent(in) :: &
1977  ! water-side surface friction velocity (m/s)
1978  ustar, &
1979  ! boundary layer depth (m)
1980  hbl
1981  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
1982  real, intent(out) :: la
1983 ! Local variables
1984  ! parameters
1985  real, parameter :: &
1986  ! ratio of U19.5 to U10 (Holthuijsen, 2007)
1987  u19p5_to_u10 = 1.075, &
1988  ! ratio of mean frequency to peak frequency for
1989  ! Pierson-Moskowitz spectrum (Webb, 2011)
1990  fm_to_fp = 1.296, &
1991  ! ratio of surface Stokes drift to U10
1992  us_to_u10 = 0.0162, &
1993  ! loss ratio of Stokes transport
1994  r_loss = 0.667
1995  real :: us, hm0, fm, fp, vstokes, kphil, kstar
1996  real :: z0, z0i, r1, r2, r3, r4, tmp, us_sl, lasl_sqr_i
1997  real :: pi, u10
1998  pi = 4.0*atan(1.0)
1999  ! Computing u10 based on u_star and COARE 3.5 relationships
2000  call ust_2_u10_coare3p5(ustar*sqrt(gv%Rho0/1.225),u10,gv)
2001  if (u10 .gt. 0.0 .and. ustar .gt. 0.0) then
2002  ! surface Stokes drift
2003  us = us_to_u10*u10
2004  !
2005  ! significant wave height from Pierson-Moskowitz
2006  ! spectrum (Bouws, 1998)
2007  hm0 = 0.0246 *u10**2
2008  !
2009  ! peak frequency (PM, Bouws, 1998)
2010  tmp = 2.0 * pi * u19p5_to_u10 * u10
2011  fp = 0.877 * gv%g_Earth / tmp
2012  !
2013  ! mean frequency
2014  fm = fm_to_fp * fp
2015  !
2016  ! total Stokes transport (a factor r_loss is applied to account
2017  ! for the effect of directional spreading, multidirectional waves
2018  ! and the use of PM peak frequency and PM significant wave height
2019  ! on estimating the Stokes transport)
2020  vstokes = 0.125 * pi * r_loss * fm * hm0**2
2021  !
2022  ! the general peak wavenumber for Phillips' spectrum
2023  ! (Breivik et al., 2016) with correction of directional spreading
2024  kphil = 0.176 * us / vstokes
2025  !
2026  ! surface layer averaged Stokes dirft with Stokes drift profile
2027  ! estimated from Phillips' spectrum (Breivik et al., 2016)
2028  ! the directional spreading effect from Webb and Fox-Kemper, 2015
2029  ! is also included
2030  kstar = kphil * 2.56
2031  ! surface layer
2032  !z0 = 0.2 * abs(hbl)
2033  !BGR hbl now adjusted by averaging ratio before function call.
2034  z0 = abs(hbl)
2035  z0i = 1.0 / z0
2036  ! term 1 to 4
2037  r1 = ( 0.151 / kphil * z0i -0.84 ) &
2038  * ( 1.0 - exp(-2.0 * kphil * z0) )
2039  r2 = -( 0.84 + 0.0591 / kphil * z0i ) &
2040  *sqrt( 2.0 * pi * kphil * z0 ) &
2041  *erfc( sqrt( 2.0 * kphil * z0 ) )
2042  r3 = ( 0.0632 / kstar * z0i + 0.125 ) &
2043  * (1.0 - exp(-2.0 * kstar * z0) )
2044  r4 = ( 0.125 + 0.0946 / kstar * z0i ) &
2045  *sqrt( 2.0 * pi *kstar * z0) &
2046  *erfc( sqrt( 2.0 * kstar * z0 ) )
2047  us_sl = us * (0.715 + r1 + r2 + r3 + r4)
2048  !
2049  la = sqrt(ustar / us_sl)
2050  else
2051  la=1.e8
2052  endif
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ust_2_u10_coare3p5()

subroutine mom_energetic_pbl::ust_2_u10_coare3p5 ( real, intent(in)  USTair,
real, intent(out)  U10,
type(verticalgrid_type), intent(in)  GV 
)
private

Computes wind speed from ustar_air based on COARE 3.5 Cd relationship.

Parameters
[in]gvThe ocean's vertical grid structure

Definition at line 1920 of file MOM_energetic_PBL.F90.

Referenced by get_la_windsea().

1920  real, intent(in) :: ustair
1921  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
1922  real, intent(out) :: u10
1923  real, parameter :: vonkar = 0.4
1924  real, parameter :: nu=1e-6
1925  real :: z0sm, z0, z0rough, u10a, alpha, cd
1926  integer :: ct
1927 
1928  ! Uses empirical formula for z0 to convert ustar_air to u10 based on the
1929  ! COARE 3.5 paper (Edson et al., 2013)
1930  !alpha=m*U10+b
1931  !Note in Edson et al. 2013, eq. 13 m is given as 0.017. However,
1932  ! m=0.0017 reproduces the curve in their figure 6.
1933 
1934  z0sm = 0.11 * nu / ustair; !Compute z0smooth from ustar guess
1935  u10 = ustair/sqrt(0.001); !Guess for u10
1936  u10a = 1000;
1937 
1938  ct=0
1939  do while (abs(u10a/u10-1.)>0.001)
1940  ct=ct+1
1941  u10a = u10
1942  alpha = min(0.028,0.0017 * u10 - 0.005)
1943  z0rough = alpha * ustair**2/gv%g_Earth ! Compute z0rough from ustar guess
1944  z0=z0sm+z0rough
1945  cd = ( vonkar / log(10/z0) )**2 ! Compute CD from derived roughness
1946  u10 = ustair/sqrt(cd);!Compute new u10 from derived CD, while loop
1947  ! ends and checks for convergence...CT counter
1948  ! makes sure loop doesn't run away if function
1949  ! doesn't converge. This code was produced offline
1950  ! and converged rapidly (e.g. 2 cycles)
1951  ! for ustar=0.0001:0.0001:10.
1952  if (ct>20) then
1953  u10 = ustair/sqrt(0.0015) ! I don't expect to get here, but just
1954  ! in case it will output a reasonable value.
1955  exit
1956  endif
1957  enddo
1958  return
Here is the caller graph for this function:

Variable Documentation

◆ max_msg

integer mom_energetic_pbl::max_msg = 2
private

Definition at line 226 of file MOM_energetic_PBL.F90.

◆ num_msg

integer mom_energetic_pbl::num_msg = 0

Definition at line 226 of file MOM_energetic_PBL.F90.

226 integer :: num_msg = 0, max_msg = 2