Skip to content

Commit 78f56d3

Browse files
committed
refactor(diffusion): consolidate the TKE eddy-diffusivity pipeline
Extract the TKE -> mixing length -> Prandtl -> eddy viscosity/diffusivity chain, previously duplicated at seven sites, into `eddy_diffusivities!`. Callers supply the mixing-length output field and optional `K_u`/`K_h` output fields, preserving each site's scratch slots and lazy or materialized policy; the closure inputs (`grid_scale`, `buoyancy_gradient`) pass through unchanged. Migrated sites: the vertical and horizontal EDMFX SGS diffusive fluxes, the vertical and horizontal updraft diffusion, the TKE tendency for both EDMF models, and the diffusion Jacobian coefficients.
1 parent 2f58f5e commit 78f56d3

5 files changed

Lines changed: 69 additions & 85 deletions

File tree

src/prognostic_equations/eddy_diffusion_closures.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,53 @@ function ᶜmixing_length(
468468
return @. lazy(get_mixing_length_field(ᶜmixing_length_tuple, property))
469469
end
470470

471+
"""
472+
eddy_diffusivities!(ᶜmixing_length_field, Y, p; grid_scale, buoyancy_gradient, ᶜK_u_field, ᶜK_h_field)
473+
474+
Compute the eddy viscosity `K_u` and eddy diffusivity `K_h` of the TKE-based
475+
closure, materializing the mixing length into `ᶜmixing_length_field`.
476+
477+
# Keyword Arguments
478+
479+
- `grid_scale`: grid-scale limit on the mixing length. By default, the
480+
vertical cell thickness.
481+
- `buoyancy_gradient`: stability input of the mixing length and the turbulent
482+
Prandtl number. By default, the centered `ᶜlinear_buoygrad`.
483+
- `ᶜK_u_field`, `ᶜK_h_field`: output fields for `K_u` and `K_h`. By default
484+
`nothing`, in which case the corresponding value is lazy.
485+
486+
# Returns
487+
488+
- `(; ᶜK_u, ᶜK_h)`.
489+
"""
490+
function eddy_diffusivities!(
491+
ᶜmixing_length_field, Y, p;
492+
grid_scale = Fields.Δz_field(axes(Y.c)),
493+
buoyancy_gradient = p.precomputed.ᶜlinear_buoygrad,
494+
ᶜK_u_field = nothing,
495+
ᶜK_h_field = nothing,
496+
)
497+
(; params) = p
498+
(; ᶜstrain_rate_norm) = p.precomputed
499+
turbconv_params = CAP.turbconv_params(params)
500+
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
501+
ᶜmixing_length_field .= ᶜmixing_length(Y, p; grid_scale, buoyancy_gradient)
502+
ᶜK_u = if isnothing(ᶜK_u_field)
503+
@. lazy(eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field))
504+
else
505+
@. ᶜK_u_field =
506+
eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field)
507+
end
508+
ᶜprandtl_nvec =
509+
@. lazy(turbulent_prandtl_number(params, buoyancy_gradient, ᶜstrain_rate_norm))
510+
ᶜK_h = if isnothing(ᶜK_h_field)
511+
@. lazy(eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec))
512+
else
513+
@. ᶜK_h_field = eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec)
514+
end
515+
return (; ᶜK_u, ᶜK_h)
516+
end
517+
471518
"""
472519
gradient_richardson_number(params, ᶜN²_eff, ᶜstrain_rate_norm)
473520

src/prognostic_equations/edmfx_sgs_flux.jl

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -231,21 +231,8 @@ function edmfx_sgs_diffusive_flux_tendency!(
231231

232232
if p.atmos.edmfx_model.sgs_diffusive_flux isa Val{true}
233233

234-
(; ᶜlinear_buoygrad, ᶜstrain_rate_norm) = p.precomputed
235-
# scratch to prevent GPU Kernel parameter memory error
236234
ᶜmixing_length_field = p.scratch.ᶜtemp_scalar_2
237-
ᶜmixing_length_field .= ᶜmixing_length(Y, p)
238-
ᶜK_u = @. lazy(
239-
eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field),
240-
)
241-
ᶜprandtl_nvec = @. lazy(
242-
turbulent_prandtl_number(
243-
params,
244-
ᶜlinear_buoygrad,
245-
ᶜstrain_rate_norm,
246-
),
247-
)
248-
ᶜK_h = @. lazy(eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec))
235+
(; ᶜK_u, ᶜK_h) = eddy_diffusivities!(ᶜmixing_length_field, Y, p)
249236

250237
ᶠρaK_h = p.scratch.ᶠtemp_scalar
251238
@. ᶠρaK_h = ᶠinterp(Y.c.ρ) * ᶠinterp(ᶜK_h)
@@ -382,25 +369,20 @@ function edmfx_sgs_horizontal_diffusive_flux_tendency!(
382369
return nothing
383370
iscolumn(axes(Y.c)) && return nothing
384371
(; params) = p
385-
turbconv_params = CAP.turbconv_params(params)
386-
(; ᶜlinear_buoygrad, ᶜstrain_rate_norm) = p.precomputed
372+
(; ᶜlinear_buoygrad) = p.precomputed
387373
ᶜρ = Y.c.ρ
388374
ᶜtke = @. lazy(specific(Y.c.ρtke, ᶜρ))
389375

390376
# Mixing length limited by the horizontal node spacing, with the centered
391377
# buoyancy gradient as the stability input
392378
Δx = Spaces.node_horizontal_length_scale(Spaces.horizontal_space(axes(Y.c)))
393-
ᶜmixing_length_h = p.scratch.ᶜtemp_scalar_2
394-
ᶜmixing_length_h .= ᶜmixing_length(
395-
Y, p; grid_scale = Δx, buoyancy_gradient = ᶜlinear_buoygrad,
379+
ᶜK = eddy_diffusivities!(
380+
p.scratch.ᶜtemp_scalar_2, Y, p;
381+
grid_scale = Δx, buoyancy_gradient = ᶜlinear_buoygrad,
382+
ᶜK_u_field = p.scratch.ᶜtemp_scalar_4, ᶜK_h_field = p.scratch.ᶜtemp_scalar,
396383
)
397-
398-
ᶜK_u_h = p.scratch.ᶜtemp_scalar_4
399-
@. ᶜK_u_h = eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_h)
400-
ᶜprandtl_nvec =
401-
@. lazy(turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm))
402-
ᶜK_h_h = p.scratch.ᶜtemp_scalar
403-
@. ᶜK_h_h = eddy_diffusivity(ᶜK_u_h, ᶜprandtl_nvec)
384+
ᶜK_u_h = ᶜK.ᶜK_u
385+
ᶜK_h_h = ᶜK.ᶜK_h
404386

405387
# Total enthalpy, using the dry-static-energy + water-enthalpy
406388
# decomposition; see the matching vertical term in

src/prognostic_equations/edmfx_tke.jl

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,8 @@
2626
edmfx_tke_tendency!(Yₜ, Y, p, t, turbconv_model) = nothing
2727

2828
function edmfx_tke_tendency!(Yₜ, Y, p, t, turbconv_model::EDOnlyEDMFX)
29-
(; params) = p
3029
(; ᶜstrain_rate_norm, ᶜlinear_buoygrad) = p.precomputed
31-
turbconv_params = CAP.turbconv_params(p.params)
32-
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
33-
ᶜmixing_length_field = p.scratch.ᶜtemp_scalar
34-
ᶜmixing_length_field .= ᶜmixing_length(Y, p)
35-
ᶜK_u = @. lazy(eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field))
36-
ᶜprandtl_nvec = @. lazy(
37-
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm),
38-
)
39-
ᶜK_h = @. lazy(eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec))
30+
(; ᶜK_u, ᶜK_h) = eddy_diffusivities!(p.scratch.ᶜtemp_scalar, Y, p)
4031

4132
# shear production
4233
@. Yₜ.c.ρtke += 2 * Y.c.ρ * ᶜK_u * ᶜstrain_rate_norm
@@ -52,23 +43,9 @@ function edmfx_tke_tendency!(
5243
turbconv_model::PrognosticEDMFX,
5344
)
5445
(; ᶜstrain_rate_norm, ᶜlinear_buoygrad) = p.precomputed
55-
turbconv_params = CAP.turbconv_params(p.params)
5646

5747
if use_prognostic_tke(turbconv_model)
58-
ᶜmixing_length_field = p.scratch.ᶜtemp_scalar_2
59-
ᶜmixing_length_field .= ᶜmixing_length(Y, p)
60-
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
61-
ᶜK_u = @. lazy(
62-
eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field),
63-
)
64-
ᶜprandtl_nvec = @. lazy(
65-
turbulent_prandtl_number(
66-
p.params,
67-
ᶜlinear_buoygrad,
68-
ᶜstrain_rate_norm,
69-
),
70-
)
71-
ᶜK_h = @. lazy(eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec))
48+
(; ᶜK_u, ᶜK_h) = eddy_diffusivities!(p.scratch.ᶜtemp_scalar_2, Y, p)
7249

7350
# shear production
7451
@. Yₜ.c.ρtke += 2 * Y.c.ρ * ᶜK_u * ᶜstrain_rate_norm

src/prognostic_equations/implicit/manual_sparse_jacobian.jl

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,7 @@ end
796796
# Eddy diffusivity and viscosity used by both grid-scale and SGS implicit
797797
# diffusion. May write to ᶜtemp_scalar_3, ᶜtemp_scalar_4, and ᶜtemp_scalar_6.
798798
function eddy_diffusivity_coefficients!(Y, p)
799-
(; params) = p
800799
(; turbconv_model, vertical_diffusion, smagorinsky_lilly) = p.atmos
801-
turbconv_params = CAP.turbconv_params(params)
802800
(; ᶜp) = p.precomputed
803801
ᶜK_u = p.scratch.ᶜtemp_scalar_4
804802
ᶜK_h = p.scratch.ᶜtemp_scalar_6
@@ -813,17 +811,12 @@ function eddy_diffusivity_coefficients!(Y, p)
813811
ᶜK_u = p.precomputed.ᶜνₜ_v
814812
ᶜK_h = p.precomputed.ᶜD_v
815813
elseif turbconv_model isa AbstractEDMF
816-
(; ᶜlinear_buoygrad, ᶜstrain_rate_norm) = p.precomputed
817-
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
818-
ᶜmixing_length_field = p.scratch.ᶜtemp_scalar_3
819-
ᶜmixing_length_field .= ᶜmixing_length(Y, p)
820-
ᶜK_u = p.scratch.ᶜtemp_scalar_4
821-
@. ᶜK_u = eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field)
822-
ᶜprandtl_nvec = @. lazy(
823-
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm),
814+
ᶜK = eddy_diffusivities!(
815+
p.scratch.ᶜtemp_scalar_3, Y, p;
816+
ᶜK_u_field = p.scratch.ᶜtemp_scalar_4, ᶜK_h_field = p.scratch.ᶜtemp_scalar_6,
824817
)
825-
ᶜK_h = p.scratch.ᶜtemp_scalar_6
826-
@. ᶜK_h = eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec)
818+
ᶜK_u = ᶜK.ᶜK_u
819+
ᶜK_h = ᶜK.ᶜK_h
827820
end
828821
return (; ᶜK_u, ᶜK_h)
829822
end

src/prognostic_equations/mass_flux_closures.jl

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ function edmfx_vertical_diffusion_tendency!(
175175
(; params) = p
176176
(; ᶜρʲs) = p.precomputed
177177
FT = eltype(p.params)
178-
turbconv_params = CAP.turbconv_params(params)
179178
n = n_mass_flux_subdomains(turbconv_model)
180179
ᶜdivᵥ_mse = Operators.DivergenceF2C(
181180
top = Operators.SetValue(C3(0)),
@@ -186,16 +185,7 @@ function edmfx_vertical_diffusion_tendency!(
186185
bottom = Operators.SetValue(C3(0)),
187186
)
188187

189-
(; ᶜlinear_buoygrad, ᶜstrain_rate_norm) = p.precomputed
190-
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
191-
# scratch to prevent GPU Kernel parameter memory error
192-
ᶜmixing_length_field = p.scratch.ᶜtemp_scalar
193-
ᶜmixing_length_field .= ᶜmixing_length(Y, p)
194-
ᶜK_u = @. lazy(eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_field))
195-
ᶜprandtl_nvec = @. lazy(
196-
turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm),
197-
)
198-
ᶜK_h = @. lazy(eddy_diffusivity(ᶜK_u, ᶜprandtl_nvec))
188+
(; ᶜK_h) = eddy_diffusivities!(p.scratch.ᶜtemp_scalar, Y, p)
199189

200190
for j in 1:n
201191
ᶜρʲ = ᶜρʲs.:($j)
@@ -244,21 +234,16 @@ function edmfx_horizontal_diffusion_tendency!(
244234
p.atmos.edmfx_model.horizontal_diffusion isa Val{true} || return nothing
245235
iscolumn(axes(Y.c)) && return nothing
246236
(; params) = p
247-
(; ᶜρʲs, ᶜlinear_buoygrad, ᶜstrain_rate_norm) = p.precomputed
248-
turbconv_params = CAP.turbconv_params(params)
237+
(; ᶜρʲs, ᶜlinear_buoygrad) = p.precomputed
249238
n = n_mass_flux_subdomains(turbconv_model)
250239

251-
ᶜtke = @. lazy(specific(Y.c.ρtke, Y.c.ρ))
252240
Δx = Spaces.node_horizontal_length_scale(Spaces.horizontal_space(axes(Y.c)))
253-
ᶜmixing_length_h = p.scratch.ᶜtemp_scalar
254-
ᶜmixing_length_h .= ᶜmixing_length(
255-
Y, p; grid_scale = Δx, buoyancy_gradient = ᶜlinear_buoygrad,
241+
ᶜK = eddy_diffusivities!(
242+
p.scratch.ᶜtemp_scalar, Y, p;
243+
grid_scale = Δx, buoyancy_gradient = ᶜlinear_buoygrad,
244+
ᶜK_h_field = p.scratch.ᶜtemp_scalar_2,
256245
)
257-
ᶜK_u_h = @. lazy(eddy_viscosity(turbconv_params, ᶜtke, ᶜmixing_length_h))
258-
ᶜprandtl_nvec =
259-
@. lazy(turbulent_prandtl_number(params, ᶜlinear_buoygrad, ᶜstrain_rate_norm))
260-
ᶜK_h_h = p.scratch.ᶜtemp_scalar_2
261-
@. ᶜK_h_h = eddy_diffusivity(ᶜK_u_h, ᶜprandtl_nvec)
246+
ᶜK_h_h = ᶜK.ᶜK_h
262247

263248
ᶜq_totʲₜ_diffusion = p.scratch.ᶜtemp_scalar_3
264249
for j in 1:n

0 commit comments

Comments
 (0)