Skip to content

Richardson-number stability weight on the geometric SGS variance term - #4837

Merged
szy21 merged 1 commit into
mainfrom
zs/sgs_ri_weight
Sep 19, 2026
Merged

szy21 merged 1 commit into
mainfrom
zs/sgs_ri_weight

Conversation

@szy21

@szy21 szy21 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Purpose

Multiply the horizontal resolved-gradient (geometric) SGS variance term of #4802 by w = Ri₊² / (Ri₊² + Ri₀²), Ri₊ = max(N², 0) / max(2 S², ε), Ri₀ = k Ri_crit, with N² the saturated moist buoyancy gradient in every cell and S² the cached strain-rate norm. The term then acts only in air that is absolutely stable to a saturated displacement and not turbulent, where the turbulence closure cannot carry the variance.

Note: This is a temporary solution. It helps with the boundary layer and tropical RH, but the physical explanation is not entirely clear. A more physical solution may be some maximum length scale for the horizontal mixing length that depends on stability.

To-do

Content


  • I have read and checked the items on the review checklist.

@github-actions

Copy link
Copy Markdown
Contributor

📖 Docs preview for this PR: https://clima.github.io/ClimaAtmos.jl/previews/PR4837/

@szy21
szy21 marked this pull request as ready for review September 18, 2026 02:42
@szy21
szy21 force-pushed the zs/sgs_ri_weight branch 2 times, most recently from ba1c3f2 to e03c7b5 Compare September 18, 2026 02:53
@szy21 szy21 added the Launch Buildkite Add to launch buildkite run label Sep 18, 2026
Multiply the horizontal resolved-gradient (geometric) SGS variance term of
Ri₀ = k Ri_crit, with N² the saturated moist buoyancy gradient in every cell
(the cached buoyancy-gradient coefficients evaluated with cloud fraction 1)
and S² the cached strain-rate norm. The term then acts only in air that is
absolutely stable to a saturated displacement and not turbulent, where the
turbulence closure cannot carry the variance; in mixed and conditionally
unstable layers it is faded out instead of being counted on top of the
closure.

- new provisional parameter `sgs_variance_geometric_Ri_factor` (k; default 0
  → weight exactly 1, default path bitwise identical to main)
- the applied weight is cached in `p.precomputed.ᶜgeo_weight` (1 = term on and
  unweighted, 0 = term off) and exposed as the `sgs_geo_weight` diagnostic
- evaluated after `materialized_mixing_length!`, which fills
  `ᶜstrain_rate_norm` on the non-EDMF path
- pointwise tests of the weight, parameter and diagnostic test entries, NEWS,
  closures docs table

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@szy21
szy21 enabled auto-merge September 18, 2026 18:30
@szy21
szy21 added this pull request to the merge queue Sep 19, 2026
Merged via the queue into main with commit 5e71833 Sep 19, 2026
32 of 33 checks passed
@szy21
szy21 deleted the zs/sgs_ri_weight branch September 19, 2026 03:37
szy21 added a commit that referenced this pull request Sep 19, 2026
…tion for the geometric SGS variance term

Options on the horizontal resolved-gradient (geometric) SGS variance term, all
defaulting to the merged behaviour (default and unweighted `tq` paths unchanged):

- `sgs_variance_horizontal_form: isentropic` (IsentropicHorizontalVariance): q′q′
  gains geo_h |∇_h q_tot − r ∇_h θ_li|², the squared gradient of q_tot along the
  θ_li surface, with r = clamp((∂q/∂z)(∂θ/∂z)/((∂θ/∂z)² + θz_min²), ±r_cap) the
  regularised, capped vertical q/θ_li ratio (`sgs_variance_isentropic_min_dtheta_dz`
  = 1e-3 K/m, `sgs_variance_isentropic_slope_cap` = 5e-4 kg/kg/K). No θ′θ′
  geometric term. The term carries the validity weight 1[N² > 0] on the saturated
  moist N² of the Richardson weight, so it vanishes where the layer is
  moist-neutral or unstable. The three DSS'd gradient invariants come from one
  evaluation of each gradient (`hgrad_invariants_pair!`, second C12 scratch buffer
  allocated for this form only); θz_min > 0 is checked at configuration time.
- `sgs_variance_element_filter: linear` (ElementLinearFilter): the gradient
  invariants are replaced by their element-linear (lumped GLL{2}) restriction
  (`element_linear!`), removing the element-boundary enhancement of the nodal
  spectral-element gradient while conserving each element's WJ-weighted mean.
- `sgs_variance_geometric_tke_scale` (tke₀, default 0 = off): the term is
  multiplied by tke₀/(tke₀ + max(tke, 0)) on the prognostic EDMF TKE
  (`sgs_geometric_tke_weight`), fading it where the closure reports an active
  turbulent layer. Requires prognostic TKE (checked in `get_atmos` and in
  `set_covariance_cache!`); multiplies the Richardson weight when both are set.
- `tq_correlation_model: diagnosed` (DiagnosedTqCorrelation): the T–q correlation
  sampled by the quadrature is diagnosed per cell from the gradient covariance
  T′q′ (the vertical closure's cross term plus the geometric cross term
  ∇_h θ_li · ∇_h q_tot with the same weight and element filter as the variances),
  clamped to ±`sgs_correlation_max` (default 1) and rescaled with the σ_q bound so
  the correlation is invariant under it; the prescribed value is the fallback
  where the variances vanish. The correlation the quadrature samples now lives
  in `p.precomputed.ᶜcorr_Tq` (constant model: filled with the prescribed value),
  and the `env_q_tot_temperature_{covariance,correlation}` diagnostics report it.
  Requires the `tq` form and a nonzero `sgs_variance_horizontal_scale_factor`
  (configuration-time checks; the vertical closure alone gives exactly ±1).

The Richardson and TKE weights (and the isentropic validity step) are now
materialized once per call into the persistent `p.precomputed.ᶜgeo_weight`
(1 = term on and unweighted, 0 = inactive), replacing the lazy per-use
`ᶜsgs_geo_weight` broadcast, and exported as the `sgs_geo_weight` diagnostic.

Squashed rebase of zs/sgs_variance_rh onto main after #4837 merged its
Richardson weight; the RH form of the original branch is dropped.

Validation: `ClimaAtmos` precompiles; `test/parameter_tests.jl` and
`test/parameterized_tendencies/microphysics/cloud_fraction.jl` pass; coarse
prognostic-EDMF aquaplanet smoke (h_elem 4, 3 steps) of the `tq` + TKE-weight
path and the isentropic + element-filter + TKE-weight path solves with finite
variances and ᶜgeo_weight in [0, 1]; the TKE weight without prognostic TKE is
rejected at configuration time. The diagnosed-correlation path solves with
|ᶜcorr_Tq| ≤ sgs_correlation_max, and its two invalid combinations (with the
isentropic form; without the geometric term) are rejected at configuration time.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Launch Buildkite Add to launch buildkite run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants