@@ -794,9 +794,9 @@ function update_sedimentation_jacobian!(matrix, Y, p, dtγ)
794794end
795795
796796# Center eddy diffusivity and viscosity for the non-EDMF implicit diffusion
797- # Jacobians . May write to ᶜtemp_scalar_3. AbstractEDMF configurations return
798- # nothing: their grid-mean and updraft diffusion Jacobians both use the
799- # face-native ᶠK_h/ᶠK_u/ᶠK_entr from set_face_diffusivities! (see
797+ # Jacobian . May write to ᶜtemp_scalar_3. AbstractEDMF configurations return
798+ # nothing: their grid-mean diffusion Jacobian uses the face-native
799+ # ᶠK_h/ᶠK_u/ᶠK_entr from set_face_diffusivities! (see
800800# update_diffusion_jacobian! and update_sgs_diffusion_jacobian!).
801801function eddy_diffusivity_coefficients! (Y, p)
802802 (; vertical_diffusion, smagorinsky_lilly) = p. atmos
@@ -1236,63 +1236,75 @@ end
12361236 update_sgs_diffusion_jacobian!(matrix, Y, p, dtγ, diffusion_flag)
12371237
12381238Updates the Jacobian blocks for implicit vertical diffusion of the updraft
1239- scalars. No-op when diffusion is treated explicitly.
1240-
1241- Reuses `ᶜdiffusion_h_matrix` as scratch space, so it must run after
1242- `update_diffusion_jacobian!`.
1239+ scalars under the unified grid-mean tendency. Under the "uniform diffusion
1240+ in the grid box" tendency in `edmfx_sgs_diffusive_flux_tendency!`, each
1241+ subdomain scalar receives the grid-mean specific tendency which strictly
1242+ depends on grid-mean state, not on χⱼ. The exact linearization would
1243+ put off-diagonal (subdomain-column, grid-mean-column) entries into the
1244+ Jacobian, which the current triangular structure of the ClimaAtmos Jacobian
1245+ does not accommodate. We instead use a `χ ≈ χⱼ` self-linearization (frozen-
1246+ coefficient / diagonal approximation): pretend `ᶜρχₜ_diffusion` depends on χⱼ
1247+ via the same divergence-of-K-gradient operator applied to χⱼ. The residual
1248+ still uses the true (grid-mean-derived) tendency; only the Jacobian is
1249+ approximated. This gives implicit stability for the subdomain scalar
1250+ diffusion without introducing off-triangular Jacobian entries.
12431251"""
12441252function update_sgs_diffusion_jacobian! (matrix, Y, p, dtγ, diffusion_flag)
12451253 p. atmos. turbconv_model isa PrognosticEDMFX || return nothing
12461254 use_derivative (diffusion_flag) || return nothing
12471255 # Mirror the gate of the tendency this linearizes
1248- # (edmfx_vertical_diffusion_tendency!): without it, the updraft scalar
1249- # diagonals would carry diffusion terms that have no tendency counterpart.
1250- p. atmos. edmfx_model. vertical_diffusion isa Val{true } || return nothing
1256+ # (`edmfx_sgs_diffusive_flux_tendency!` inside the sgs_diffusive_flux
1257+ # branch): without it, the updraft scalar diagonals would carry
1258+ # diffusion terms that have no tendency counterpart.
1259+ p. atmos. edmfx_model. sgs_diffusive_flux isa Val{true } || return nothing
12511260 (; params) = p
1252- (; ᶜρʲs) = p. precomputed
12531261 (; ᶜdiffusion_h_matrix) = p. scratch
1262+ ᶜρ = Y. c. ρ
12541263
1255- α_vert_diff_microphysics = CAP. α_vert_diff_tracer (params)
1256- # Face-native ᶠK_h, consistent with edmfx_vertical_diffusion_tendency!
1257- # (ᶠK_entr is deliberately excluded there; see that function).
1258- (; ᶠK_h) = p. precomputed
1259- @. ᶜdiffusion_h_matrix =
1260- ᶜadvdivᵥ_matrix () ⋅ DiagonalMatrixRow (ᶠinterp (ᶜρʲs.:(1 )) * ᶠK_h) ⋅
1261- ᶠgradᵥ_matrix ()
1262-
1264+ # mseⱼ and q_totⱼ diagonals: same operator, no tracer factor. Uses the
1265+ # full ρ(K_h + K_entr) diffusion matrix.
12631266 ∂ᶜmseʲ_err_∂ᶜmseʲ =
12641267 matrix[@name (c. sgsʲs.:(1 ). mse), @name (c. sgsʲs.:(1 ). mse)]
12651268 ∂ᶜq_totʲ_err_∂ᶜq_totʲ =
12661269 matrix[@name (c. sgsʲs.:(1 ). q_tot), @name (c. sgsʲs.:(1 ). q_tot)]
12671270 @. ∂ᶜmseʲ_err_∂ᶜmseʲ +=
1268- dtγ * DiagonalMatrixRow (1 / ᶜρʲs.:( 1 ) ) ⋅ ᶜdiffusion_h_matrix
1271+ dtγ * DiagonalMatrixRow (1 / ᶜρ ) ⋅ ᶜdiffusion_h_matrix
12691272 @. ∂ᶜq_totʲ_err_∂ᶜq_totʲ +=
1270- dtγ * DiagonalMatrixRow (1 / ᶜρʲs.:( 1 ) ) ⋅ ᶜdiffusion_h_matrix
1273+ dtγ * DiagonalMatrixRow (1 / ᶜρ ) ⋅ ᶜdiffusion_h_matrix
12711274
1275+ # Auto-discovered SGS tracers. Sedimenting microphysics species are
1276+ # diffused with `α·K_h + K_entr` (matching the tendency); passive
1277+ # tracers keep the full `K_h + K_entr` — so the passive branch reuses
1278+ # `ᶜdiffusion_h_matrix` directly and the sedimenting branch rebuilds the
1279+ # α-scaled matrix in scratch.
12721280 if p. atmos. microphysics_model isa Union{
12731281 NonEquilibriumMicrophysics1M,
12741282 NonEquilibriumMicrophysics2M,
12751283 }
1284+ α_vert_diff_microphysics = CAP. α_vert_diff_tracer (params)
1285+ (; ᶠK_h, ᶠK_entr) = p. precomputed
1286+ ᶜsgs_tracer_diffusion_matrix = p. scratch. ᶜtridiagonal_matrix_scalar
1287+ @. ᶜsgs_tracer_diffusion_matrix =
1288+ ᶜadvdivᵥ_matrix () ⋅ DiagonalMatrixRow (
1289+ ᶠinterp (ᶜρ) * (α_vert_diff_microphysics * ᶠK_h + ᶠK_entr),
1290+ ) ⋅ ᶠgradᵥ_matrix ()
12761291 MatrixFields. unrolled_foreach (
12771292 sedimenting_sgs_tracer_names (Y),
12781293 ) do χ_name
12791294 χ_state_name = sgs_state_name (χ_name)
12801295 ∂ᶜχʲ_err_∂ᶜχʲ = matrix[χ_state_name, χ_state_name]
12811296 @. ∂ᶜχʲ_err_∂ᶜχʲ +=
1282- dtγ * α_vert_diff_microphysics *
1283- DiagonalMatrixRow (1 / ᶜρʲs.:(1 )) ⋅
1284- ᶜdiffusion_h_matrix
1297+ dtγ * DiagonalMatrixRow (1 / ᶜρ) ⋅
1298+ ᶜsgs_tracer_diffusion_matrix
12851299 end
12861300 end
12871301
1288- # Passive SGS tracers are diffused with the unscaled K_h (see
1289- # edmfx_vertical_diffusion_tendency!); their diagonals are initialized by
1290- # update_sgs_advection_jacobian!, so the diffusion term is accumulated.
1302+ # Passive SGS tracers: unscaled ρ(K_h + K_entr), same as mseⱼ / q_totⱼ.
12911303 MatrixFields. unrolled_foreach (passive_sgs_tracer_names (Y)) do χ_name
12921304 χ_state_name = sgs_state_name (χ_name)
12931305 ∂ᶜχʲ_err_∂ᶜχʲ = matrix[χ_state_name, χ_state_name]
12941306 @. ∂ᶜχʲ_err_∂ᶜχʲ +=
1295- dtγ * DiagonalMatrixRow (1 / ᶜρʲs.:( 1 ) ) ⋅ ᶜdiffusion_h_matrix
1307+ dtγ * DiagonalMatrixRow (1 / ᶜρ ) ⋅ ᶜdiffusion_h_matrix
12961308 end
12971309 return nothing
12981310end
0 commit comments