@@ -281,42 +281,58 @@ function mixing_length(
281281end
282282
283283"""
284- turbulent_prandtl_number(params, obukhov_length, ᶜRi_grad )
284+ turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm )
285285
286286where:
287- - `params`: set with model parameters
288- - `obukhov_length`: surface Monin Obukhov length
289- - `ᶜRi_grad`: gradient Richardson number
287+ - `params`: Parameters set
288+ - `ᶜlinear_buoygrad`: N^2, Brunt-Väisälä frequency squared [1/s^2].
289+ - `ᶜstrain_rate_norm`: Frobenius norm of strain rate tensor, |S| [1/s].
290+
291+ Returns the turbulent Prandtl number based on the gradient Richardson number.
292+
293+ The formula implemented is from Li et al. (JAS 2015, DOI: 10.1175/JAS-D-14-0335.1, their Eq. 39),
294+ with a reformulation and correction of an algebraic error in their expression:
295+
296+ Pr_t(Ri) = (X + sqrt(max(X^2 - 4*Pr_n*Ri, 0))) / 2
290297
291- Returns the turbulent Prandtl number give the obukhov length sign and
292- the gradient Richardson number, which is calculated from the linearized
293- buoyancy gradient and shear production.
298+ where X = Pr_n + ω_pr * Ri and Ri = N^2 / max(2*|S|, eps)
299+ using parameters Pr_n = Prandtl_number_0, ω_pr = Prandtl_number_scale.
300+ This formula applies in both stable (Ri > 0) and unstable (Ri < 0) conditions.
301+ The returned turbulent Prandtl number is limited by Pr_max parameter.
294302"""
295- function turbulent_prandtl_number (
296- params,
297- obukhov_length,
298- ᶜlinear_buoygrad,
299- ᶜstrain_rate_norm,
300- )
303+ function turbulent_prandtl_number (params, ᶜlinear_buoygrad, ᶜstrain_rate_norm)
301304 FT = eltype (params)
302305 turbconv_params = CAP. turbconv_params (params)
303- Ri_c = CAP. Ri_crit (turbconv_params)
304- ω_pr = CAP. Prandtl_number_scale (turbconv_params)
305- Pr_n = CAP. Prandtl_number_0 (turbconv_params)
306- ᶜRi_grad = min (ᶜlinear_buoygrad / max (2 * ᶜstrain_rate_norm, eps (FT)), Ri_c)
307- if obukhov_length > 0 && ᶜRi_grad > 0 # stable
308- # CSB (Dan Li, 2019, eq. 75), where ω_pr = ω_1 + 1 = 53.0 / 13.0
309- prandtl_nvec =
310- Pr_n * (
311- 2 * ᶜRi_grad / (
312- 1 + ω_pr * ᶜRi_grad -
313- sqrt ((1 + ω_pr * ᶜRi_grad)^ 2 - 4 * ᶜRi_grad)
314- )
315- )
316- else
317- prandtl_nvec = Pr_n
318- end
319- return prandtl_nvec
306+ eps_FT = eps (FT)
307+
308+ # Parameters from CliMAParams
309+ Pr_n = CAP. Prandtl_number_0 (turbconv_params) # Neutral Prandtl number
310+ ω_pr = CAP. Prandtl_number_scale (turbconv_params) # Prandtl number scale coefficient
311+ Pr_max = CAP. Pr_max (turbconv_params) # Maximum Prandtl number limit
312+
313+ # Calculate the raw gradient Richardson number
314+ # Using the definition Ri = N^2 / (2*|S|)
315+ ᶜshear_term_safe = max (2 * ᶜstrain_rate_norm, eps_FT)
316+ ᶜRi_grad = ᶜlinear_buoygrad / ᶜshear_term_safe
317+
318+ # --- Apply the Pr_t(Ri) formula valid for stable and unstable conditions ---
319+
320+ # Calculate the intermediate term X = Pr_n + ω_pr * Ri
321+ X = Pr_n + ω_pr * ᶜRi_grad
322+
323+ # Calculate the discriminant term: (Pr_n + ω_pr*Ri)^2 - 4*Pr_n*Ri = X^2 - 4*Pr_n*Ri
324+ discriminant = X * X - 4 * Pr_n * ᶜRi_grad
325+ # Ensure the discriminant is non-negative before taking the square root
326+ discriminant_safe = max (discriminant, FT (0 ))
327+
328+ # Calculate the Prandtl number using the positive root solution of the quadratic eq.
329+ # Pr_t = ( X + sqrt(discriminant_safe) ) / 2
330+ prandtl_nvec = (X + sqrt (discriminant_safe)) / 2
331+
332+ # Optional safety: ensure Pr_t is not excessively small or negative,
333+ # though the formula should typically yield positive values if Pr_n > 0.
334+ # Also ensure that it's not larger than the Pr_max parameter.
335+ return min (max (prandtl_nvec, eps_FT), Pr_max)
320336end
321337
322338edmfx_filter_tendency! (Yₜ, Y, p, t, turbconv_model) = nothing
0 commit comments