Skip to content

Commit c4189d3

Browse files
authored
Merge pull request #3794 from CliMA/aj/mixing_length_part2
Update turbulent Prandtl number
2 parents 799fb93 + 8644e2c commit c4189d3

File tree

9 files changed

+68
-58
lines changed

9 files changed

+68
-58
lines changed

.buildkite/Manifest-v1.11.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,9 +399,9 @@ version = "0.2.13"
399399

400400
[[deps.ClimaParams]]
401401
deps = ["TOML"]
402-
git-tree-sha1 = "db2d3e069ed4c12c96a4ae071ab5fc37da1019d4"
402+
git-tree-sha1 = "7613d47b4f96307845cbe377dede19efa3256cfb"
403403
uuid = "5c42b081-d73a-476f-9059-fd94b934656c"
404-
version = "0.10.28"
404+
version = "0.10.29"
405405

406406
[[deps.ClimaReproducibilityTests]]
407407
deps = ["OrderedCollections", "PrettyTables"]

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ AtmosphericProfilesLibrary = "0.1.7"
4343
ClimaComms = "0.6.6"
4444
ClimaCore = "0.14.24"
4545
ClimaDiagnostics = "0.2.12"
46-
ClimaParams = "0.10.27"
46+
ClimaParams = "0.10.29"
4747
ClimaTimeSteppers = "0.8.2"
4848
ClimaUtilities = "0.1.22"
4949
CloudMicrophysics = "0.22.9"

reproducibility_tests/ref_counter.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
236
1+
237
22

33
# **README**
44
#
@@ -20,12 +20,16 @@
2020

2121

2222
#=
23+
237
24+
- Changed the formulation of the Richardson and Prandtl numbers. We are now limiting by
25+
Pr_max = 100 instead of Ri_max = 0.25. Different behavior for stable and neutral conditions.
26+
2327
236
24-
- Radiation fluxes in runs with the `deep_atmosphere` configuration now take into account the
28+
- Radiation fluxes in runs with the `deep_atmosphere` configuration now take into account the
2529
column expansion with height. Affects only cases with `DeepSphericalGlobalGeometry`.
2630
2731
235
28-
- Related to #3775, the computation and update of non-orographic gravity wave (NOGW)
32+
- Related to #3775, the computation and update of non-orographic gravity wave (NOGW)
2933
are now separated into callback and tendencies update, affecting the NOGW-related
3034
tests.
3135
@@ -66,7 +70,7 @@
6670
(This only affects prognostic edmf)
6771
6872
225
69-
- Move nonhydrostatic pressure drag calculation to precomputed quantities and
73+
- Move nonhydrostatic pressure drag calculation to precomputed quantities and
7074
remove one reproducibility job
7175
(This only affects prognostic edmf)
7276

src/cache/diagnostic_edmf_precomputed_quantities.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -983,12 +983,9 @@ NVTX.@annotate function set_diagnostic_edmf_precomputed_quantities_env_closures!
983983
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
984984

985985
ᶜprandtl_nvec = p.scratch.ᶜtemp_scalar
986-
@. ᶜprandtl_nvec = turbulent_prandtl_number(
987-
params,
988-
obukhov_length,
989-
ᶜlinear_buoygrad,
990-
ᶜstrain_rate_norm,
991-
)
986+
@. ᶜprandtl_nvec =
987+
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm)
988+
992989
ᶜtke_exch = p.scratch.ᶜtemp_scalar_2
993990
@. ᶜtke_exch = 0
994991
# using ᶜu⁰ would be more correct, but this is more consistent with the

src/cache/prognostic_edmf_precomputed_quantities.jl

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ NVTX.@annotate function set_prognostic_edmf_precomputed_quantities_explicit_clos
466466
)
467467

468468
# The buoyancy term in the nonhydrostatic pressure closure is always applied
469-
# for prognostic edmf. The tendency is combined with the buoyancy term in the
469+
# for prognostic edmf. The tendency is combined with the buoyancy term in the
470470
# updraft momentum equation in `edmfx_sgs_vertical_advection_tendency!`. This
471471
# term is still calculated here as it is used explicitly in the TKE equation.
472472
@. ᶠnh_pressure₃_buoyʲs.:($$j) = ᶠupdraft_nh_pressure_buoyancy(
@@ -501,12 +501,9 @@ NVTX.@annotate function set_prognostic_edmf_precomputed_quantities_explicit_clos
501501
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
502502

503503
ᶜprandtl_nvec = p.scratch.ᶜtemp_scalar
504-
@. ᶜprandtl_nvec = turbulent_prandtl_number(
505-
params,
506-
obukhov_length,
507-
ᶜlinear_buoygrad,
508-
ᶜstrain_rate_norm,
509-
)
504+
@. ᶜprandtl_nvec =
505+
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm)
506+
510507
ᶜtke_exch = p.scratch.ᶜtemp_scalar_2
511508
@. ᶜtke_exch = 0
512509
for j in 1:n

src/parameters/Parameters.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Base.@kwdef struct TurbulenceConvectionParameters{FT, VFT1, VFT2} <: ATCP
3030
static_stab_coeff::FT
3131
Prandtl_number_scale::FT
3232
Prandtl_number_0::FT
33-
Ri_crit::FT
33+
Pr_max::FT
3434
smin_ub::FT
3535
smin_rm::FT
3636
min_updraft_top::FT

src/parameters/create_parameters.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ function TurbulenceConvectionParameters(
202202
:EDMF_max_area => :max_area,
203203
:mixing_length_smin_rm => :smin_rm,
204204
:entr_coeff => :entr_coeff,
205-
:mixing_length_Ri_crit => :Ri_crit,
206205
:detr_coeff => :detr_coeff,
207206
:EDMF_surface_area => :surface_area,
208207
:entr_param_vec => :entr_param_vec,
@@ -219,6 +218,7 @@ function TurbulenceConvectionParameters(
219218
:pressure_normalmode_drag_coeff => :pressure_normalmode_drag_coeff,
220219
:mixing_length_Prandtl_number_scale => :Prandtl_number_scale,
221220
:mixing_length_Prandtl_number_0 => :Prandtl_number_0,
221+
:mixing_length_Prandtl_maximum => :Pr_max,
222222
:mixing_length_static_stab_coeff => :static_stab_coeff,
223223
:pressure_normalmode_buoy_coeff1 =>
224224
:pressure_normalmode_buoy_coeff1,

src/prognostic_equations/edmfx_closures.jl

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -281,42 +281,58 @@ function mixing_length(
281281
end
282282

283283
"""
284-
turbulent_prandtl_number(params, obukhov_length, ᶜRi_grad)
284+
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm)
285285
286286
where:
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)
320336
end
321337

322338
edmfx_filter_tendency!(Yₜ, Y, p, t, turbconv_model) = nothing

src/prognostic_equations/gm_sgs_closures.jl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,8 @@ NVTX.@annotate function compute_gm_mixing_length!(ᶜmixing_length, Y, p)
5151
@. ᶜstrain_rate_norm = norm_sqr(ᶜstrain_rate)
5252

5353
ᶜprandtl_nvec = p.scratch.ᶜtemp_scalar_2
54-
@. ᶜprandtl_nvec = turbulent_prandtl_number(
55-
params,
56-
obukhov_length,
57-
ᶜlinear_buoygrad,
58-
ᶜstrain_rate_norm,
59-
)
54+
@. ᶜprandtl_nvec =
55+
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm)
6056

6157
@. ᶜmixing_length = smagorinsky_lilly_length(
6258
CAP.c_smag(params),

0 commit comments

Comments
 (0)