Skip to content

Commit e8efcff

Browse files
committed
updates
1 parent 80687aa commit e8efcff

File tree

7 files changed

+81
-77
lines changed

7 files changed

+81
-77
lines changed

config/default_configs/default_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ vert_diff:
163163
hyperdiff:
164164
help: "Hyperdiffusion. Use `CAM_SE` for sensible default values and ClimaHyperdiffusion for user control. [`CAM_SE` (default), `ClimaHyperdiffusion` (or `true`), `none` (or `false`)]"
165165
value: "CAM_SE"
166-
smagorinsky:
166+
smagorinsky_lilly:
167167
help: "Smagorinsky diffusive closure in the horizontal and vertical [`false` (default), `true`]"
168168
value: false
169169
smagorinsky_horizontal:

src/cache/precomputed_quantities.jl

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,10 @@ function precomputed_quantities(Y, atmos)
245245
precipitation_sgs_quantities...,
246246
diagnostic_precipitation_sgs_quantities...,
247247
) : (;)
248-
smagorinsky_lilly_quantities =
249-
if atmos.smagorinsky_lilly isa SmagorinskyLilly
250-
uvw_vec = UVW(FT(0), FT(0), FT(0))
251-
(;
252-
ᶜτ_smag = similar(Y.c, typeof(uvw_vec * uvw_vec')),
253-
ᶠτ_smag = similar(Y.f, typeof(uvw_vec * uvw_vec')),
254-
ᶜD_smag = similar(Y.c, FT),
255-
ᶠD_smag = similar(Y.f, FT),
256-
)
248+
smagorinsky_quantities =
249+
if atmos.smagorinsky_horizontal isa SmagorinskyLilly ||
250+
atmos.smagorinsky_vertical isa SmagorinskyLilly
251+
(; ᶜL_h = similar(Y.c, FT), ᶜL_v = similar(Y.c, FT))
257252
else
258253
(;)
259254
end
@@ -269,7 +264,7 @@ function precomputed_quantities(Y, atmos)
269264
precipitation_quantities...,
270265
surface_precip_fluxes...,
271266
cloud_diagnostics_tuple,
272-
smagorinsky_lilly_quantities...,
267+
smagorinsky_quantities...,
273268
)
274269
end
275270

@@ -596,7 +591,8 @@ NVTX.@annotate function set_explicit_precomputed_quantities_part2!(Y, p, t)
596591
set_cloud_fraction!(Y, p, moisture_model, cloud_model)
597592
end
598593

599-
if p.atmos.smagorinsky_lilly isa SmagorinskyLilly
594+
if p.atmos.smagorinsky_horizontal isa SmagorinskyLilly ||
595+
p.atmos.smagorinsky_vertical isa SmagorinskyLilly
600596
set_smagorinsky_lilly_precomputed_quantities!(Y, p)
601597
end
602598

src/parameterized_tendencies/les_sgs_models/smagorinsky_lilly.jl

Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import ClimaCore: Geometry
99
"""
1010
set_smagorinsky_lilly_precomputed_quantities!(Y, p)
1111
12-
Compute the Smagorinsky-Lilly diffusivity tensors, `ᶜτ_smag`, `ᶠτ_smag`, `ᶜD_smag`, and `ᶠD_smag`.
12+
Compute the Smagorinsky-Lilly horizontal and vertical length scales `ᶜL_h` and `ᶜL_v`.
1313
Store in the precomputed quantities `p.precomputed`.
1414
1515
The subgrid-scale momentum flux tensor is defined by `τ = -2 νₜ ∘ S`, where `νₜ` is the Smagorinsky-Lilly eddy viscosity
@@ -26,66 +26,33 @@ These quantities are computed for both cell centers and faces, with prefixes `
2626
- `p`: The model parameters, e.g. `AtmosCache`.
2727
"""
2828
function set_smagorinsky_lilly_precomputed_quantities!(Y, p)
29-
30-
(; atmos, precomputed, scratch, params) = p
31-
c_smag = CAP.c_smag(params)
32-
Pr_t = CAP.Prandtl_number_0(CAP.turbconv_params(params))
33-
(; ᶜu, ᶠu³, ᶜts, ᶜτ_smag, ᶠτ_smag, ᶜD_smag, ᶠD_smag) = precomputed
3429
FT = eltype(Y)
35-
grav = CAP.grav(params)
36-
thermo_params = CAP.thermodynamics_params(params)
37-
(; ᶜtemp_UVWxUVW, ᶠtemp_UVWxUVW, ᶜtemp_strain, ᶠtemp_strain) = scratch
38-
(; ᶜtemp_scalar, ᶜtemp_scalar_2, ᶠtemp_scalar, ᶜtemp_UVW, ᶠtemp_UVW) = scratch
39-
40-
∇ᵥuvw_boundary = Geometry.outer(Geometry.WVector(0), UVW(0, 0, 0))
41-
ᶠgradᵥ_uvw = Operators.GradientC2F(
42-
bottom = Operators.SetGradient(∇ᵥuvw_boundary),
43-
top = Operators.SetGradient(∇ᵥuvw_boundary),
44-
)
45-
axis_uvw = (Geometry.UVWAxis(),)
46-
47-
# Compute UVW velocities
48-
ᶜu_uvw = @. ᶜtemp_UVW = UVW(ᶜu)
49-
ᶠu_uvw = @. ᶠtemp_UVW = UVW(ᶠinterp(Y.c.uₕ)) + UVW(ᶠu³)
50-
51-
# Gradients
52-
## cell centers
53-
∇ᶜu_uvw = @. ᶜtemp_UVWxUVW = Geometry.project(axis_uvw, ᶜgradᵥ(ᶠu_uvw)) # vertical component
54-
@. ∇ᶜu_uvw += Geometry.project(axis_uvw, gradₕ(ᶜu_uvw)) # horizontal component
55-
## cell faces
56-
∇ᶠu_uvw = @. ᶠtemp_UVWxUVW = Geometry.project(axis_uvw, ᶠgradᵥ_uvw(ᶜu_uvw)) # vertical component
57-
@. ∇ᶠu_uvw += Geometry.project(axis_uvw, gradₕ(ᶠu_uvw)) # horizontal component
58-
30+
(; ᶠu, ᶜts, ᶜL_h, ᶜL_v) = p.precomputed
31+
c_smag = CAP.c_smag(p.params)
32+
grav = CAP.grav(p.params)
33+
Pr_t = CAP.Prandtl_number_0(CAP.turbconv_params(p.params))
34+
thermo_params = CAP.thermodynamics_params(p.params)
35+
(; ᶜtemp_scalar, ᶜtemp_scalar_2) = p.scratch
36+
5937
# Strain rate tensor
60-
ᶜS = @. ᶜtemp_strain = (∇ᶜu_uvw + adjoint(∇ᶜu_uvw)) / 2
61-
ᶠS = @. ᶠtemp_strain = (∇ᶠu_uvw + adjoint(∇ᶠu_uvw)) / 2
38+
ᶜS = compute_strain_rate_center(ᶠu)
6239

6340
# Stratification correction
64-
ᶜθ_v = @. ᶜtemp_scalar = TD.virtual_pottemp(thermo_params, ᶜts)
41+
ᶜθ_v = @. lazy(TD.virtual_pottemp(thermo_params, ᶜts))
6542
ᶜ∇ᵥθ = @. ᶜtemp_scalar_2 = Geometry.WVector(ᶜgradᵥ(ᶠinterp(ᶜθ_v))).components.data.:1
6643
ᶜN² = @. ᶜtemp_scalar = grav / ᶜθ_v * ᶜ∇ᵥθ
67-
ᶜS_norm = @. ᶜtemp_scalar_2 = (2 * CA.norm_sqr(ᶜS))
44+
ᶜS_norm = @. ᶜtemp_scalar_2 = (2 * norm_sqr(ᶜS))
6845

6946
ᶜRi = @. ᶜtemp_scalar = ᶜN² / (ᶜS_norm^2 + eps(FT)) # Ri = N² / |S|²
7047
ᶜfb = @. ᶜtemp_scalar = ifelse(ᶜRi 0, 1, max(0, 1 - ᶜRi / Pr_t)^(1 / 4))
7148

7249
# filter scale
7350
h_space = Spaces.horizontal_space(axes(Y.c))
74-
Δ_xy = Spaces.node_horizontal_length_scale(h_space)^2 # Δ_x * Δ_y
51+
Δ_h = Spaces.node_horizontal_length_scale(h_space)
7552
ᶜΔ_z = Fields.Δz_field(Y.c)
76-
ᶜΔ = @. ᶜtemp_scalar = (Δ_xy * ᶜΔ_z) * ᶜfb
7753

78-
# Smagorinsky-Lilly eddy viscosity
79-
ᶜνₜ = @. ᶜtemp_scalar = c_smag^2 * ᶜΔ^2 * ᶜS_norm
80-
ᶠνₜ = @. ᶠtemp_scalar = ᶠinterp(ᶜνₜ)
81-
82-
# Subgrid-scale momentum flux tensor, `τ = -2 νₜ ∘ S`
83-
@. ᶜτ_smag = -2 * ᶜνₜ * ᶜS
84-
@. ᶠτ_smag = -2 * ᶠνₜ * ᶠS
85-
86-
# Turbulent diffusivity
87-
@. ᶜD_smag = ᶜνₜ / Pr_t
88-
@. ᶠD_smag = ᶠνₜ / Pr_t
54+
@. ᶜL_v = c_smag * ᶜΔ_z * ᶜfb
55+
@. ᶜL_h = c_smag * Δ_h
8956

9057
nothing
9158
end
@@ -94,11 +61,28 @@ horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::Nothing) = nothing
9461
vertical_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::Nothing) = nothing
9562

9663
function horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::SmagorinskyLilly)
97-
(; ᶜτ_smag, ᶠτ_smag, ᶜD_smag, ᶜts) = p.precomputed
64+
(; ᶜu, ᶠu, ᶜts, ᶜL_h) = p.precomputed
65+
(; ᶜtemp_UVWxUVW, ᶠtemp_UVWxUVW, ᶜtemp_scalar, ᶠtemp_scalar) = p.scratch
9866
thermo_params = CAP.thermodynamics_params(p.params)
67+
Pr_t = CAP.Prandtl_number_0(CAP.turbconv_params(p.params))
9968

10069
## Momentum tendencies
101-
ᶠρ = @. p.scratch.ᶠtemp_scalar = ᶠinterp(Y.c.ρ)
70+
ᶜS = compute_strain_rate_center(ᶠu)
71+
ᶠS = compute_strain_rate_face(ᶜu)
72+
ᶜS_norm = @. lazy((2 * norm_sqr(ᶜS))) # TODO: This should be the UV-components only
73+
74+
# Smagorinsky eddy viscosity
75+
ᶜνₜ_h = @. lazy(ᶜL_h^2 * ᶜS_norm)
76+
ᶠνₜ_h = @. lazy(ᶠinterp(ᶜνₜ_h))
77+
78+
# Turbulent diffusivity
79+
ᶜD_smag = @. ᶜtemp_scalar = ᶜνₜ_h / Pr_t
80+
81+
# Subgrid-scale momentum flux tensor, `τ = -2 νₜ ∘ S`
82+
ᶜτ_smag = @. ᶜtemp_UVWxUVW = -2 * ᶜνₜ_h * ᶜS # TODO: Lazify once we can mix lazy horizontal & vertical operations
83+
ᶠτ_smag = @. ᶠtemp_UVWxUVW = -2 * ᶠνₜ_h * ᶠS
84+
85+
ᶠρ = ᶠtemp_scalar .= face_density(Y)
10286
@. Yₜ.c.uₕ -= C12(wdivₕ(Y.c.ρ * ᶜτ_smag) / Y.c.ρ)
10387
@. Yₜ.f.u₃ -= C3(wdivₕ(ᶠρ * ᶠτ_smag) / ᶠρ)
10488

@@ -121,15 +105,12 @@ function horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::SmagorinskyLill
121105

122106
end
123107

124-
import UnrolledUtilities as UU
125-
126108
function vertical_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::SmagorinskyLilly)
127109
FT = eltype(Y)
128-
(; sfc_temp_C3, ᶠtemp_scalar) = p.scratch
129-
(; ᶜτ_smag, ᶠτ_smag, ᶠD_smag, sfc_conditions) = p.precomputed
130-
(; ρ_flux_uₕ, ρ_flux_h_tot) = sfc_conditions
131-
(; ᶜts) = p.precomputed
110+
(; ᶜu, ᶠu, ᶜts, ᶜL_v) = p.precomputed
111+
(; ᶜtemp_UVWxUVW, ᶠtemp_UVWxUVW, ᶠtemp_scalar, ᶠtemp_scalar_2) = p.scratch
132112
thermo_params = CAP.thermodynamics_params(p.params)
113+
Pr_t = CAP.Prandtl_number_0(CAP.turbconv_params(p.params))
133114

134115
# Define operators
135116
ᶠgradᵥ = Operators.GradientC2F() # apply BCs to ᶜdivᵥ, which wraps ᶠgradᵥ
@@ -146,9 +127,25 @@ function vertical_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::SmagorinskyLilly)
146127
bottom = Operators.SetValue(C3(FT(0))),
147128
)
148129

130+
## Momentum tendencies
131+
ᶜS = compute_strain_rate_center(ᶠu)
132+
ᶠS = compute_strain_rate_face(ᶜu)
133+
ᶜS_norm = @. lazy((2 * norm_sqr(ᶜS))) # TODO: This should be the W-component only
134+
135+
# Smagorinsky eddy viscosity
136+
ᶜνₜ_v = @. lazy(ᶜL_v^2 * ᶜS_norm)
137+
ᶠνₜ_v = @. lazy(ᶠinterp(ᶜνₜ_v))
138+
139+
# Subgrid-scale momentum flux tensor, `τ = -2 νₜ ∘ S`
140+
ᶜτ_smag = @. ᶜtemp_UVWxUVW = -2 * ᶜνₜ_v * ᶜS
141+
ᶠτ_smag = @. ᶠtemp_UVWxUVW = -2 * ᶠνₜ_v * ᶠS
142+
143+
# Turbulent diffusivity
144+
ᶠD_smag = @. ᶠtemp_scalar_2 = ᶠνₜ_v / Pr_t
145+
149146
# Apply to tendencies
150147
## Horizontal momentum tendency
151-
ᶠρ = @. ᶠtemp_scalar = ᶠinterp(Y.c.ρ)
148+
ᶠρ = ᶠtemp_scalar .= face_density(Y)
152149
@. Yₜ.c.uₕ -= C12(ᶜdivᵥ(ᶠρ * ᶠτ_smag) / Y.c.ρ)
153150
## Apply boundary condition for momentum flux
154151
@. Yₜ.c.uₕ -= ᶜdivᵥ_uₕ(-(FT(0) * ᶠgradᵥ(Y.c.uₕ))) / Y.c.ρ

src/prognostic_equations/remaining_tendency.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,8 @@ NVTX.@annotate function additional_tendency!(Yₜ, Y, p, t)
348348
# NOTE: All ρa tendencies should be applied before calling this function
349349
pressure_work_tendency!(Yₜ, Y, p, t, p.atmos.turbconv_model)
350350

351-
sl = p.atmos.smagorinsky_lilly
352-
horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, sl)
353-
vertical_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, sl)
351+
horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, p.atmos.smagorinsky_horizontal)
352+
vertical_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, p.atmos.smagorinsky_vertical)
354353

355354
# NOTE: This will zero out all momentum tendencies in the EDMFX advection test,
356355
# where velocities do not evolve

src/solver/model_getters.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ end
172172
function get_smagorinsky_model(parsed_args; dir)
173173
dir = (; h = "horizontal", v = "vertical")[dir]
174174
smag_dir = parsed_args["smagorinsky_$dir"]
175-
smag = parsed_args["smagorinsky"]
175+
smag = parsed_args["smagorinsky_lilly"] # TODO: Remove "lilly" suffix
176176
@assert smag_dir isa Bool "'smagorinsky_$dir' must be `true` or `false`."
177-
@assert smag isa Bool "'smagorinsky' must be `true` or `false`."
178-
@assert smag smag_dir "Only one of 'smagorinsky' and 'smagorinsky_$dir' can be set to true."
177+
@assert smag isa Bool "'smagorinsky_lilly' must be `true` or `false`."
178+
@assert smag smag_dir "Only one of 'smagorinsky_lilly' and 'smagorinsky_$dir' can be set to true."
179179
return smag_dir || smag ? SmagorinskyLilly() : nothing
180180
end
181181

src/solver/types.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,15 +582,16 @@ end
582582
583583
Groups turbulence convection-related models and types.
584584
"""
585-
Base.@kwdef struct AtmosTurbconv{EDMFX, TCM, SAM, SEDM, SNPM, SVM, SMM, SL}
585+
Base.@kwdef struct AtmosTurbconv{EDMFX, TCM, SAM, SEDM, SNPM, SVM, SMM, SH, SV}
586586
edmfx_model::EDMFX = nothing
587587
turbconv_model::TCM = nothing
588588
sgs_adv_mode::SAM = nothing
589589
sgs_entr_detr_mode::SEDM = nothing
590590
sgs_nh_pressure_mode::SNPM = nothing
591591
sgs_vertdiff_mode::SVM = nothing
592592
sgs_mf_mode::SMM = nothing
593-
smagorinsky_lilly::SL = nothing
593+
smagorinsky_horizontal::SH = nothing
594+
smagorinsky_vertical::SV = nothing
594595
end
595596

596597
"""

src/utils/utilities.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ compute_kinetic(Y::Fields.FieldVector) = compute_kinetic(Y.c.uₕ, Y.f.u₃)
8787
Compute the strain_rate at cell centers from velocity at cell faces.
8888
"""
8989
function compute_strain_rate_center(u::Fields.Field)
90-
@assert eltype(u) <: C123
9190
axis_uvw = Geometry.UVWAxis()
9291
return @. lazy(
9392
(
@@ -119,6 +118,18 @@ function compute_strain_rate_face(u::Fields.Field)
119118
)
120119
end
121120

121+
"""
122+
face_density(Y)
123+
124+
Compute the density at cell faces from the density at cell centers.
125+
"""
126+
function face_density(Y)
127+
ᶠJ = Fields.local_geometry_field(Y.f).J
128+
ᶜJ = Fields.local_geometry_field(Y.c).J
129+
130+
@. lazy(ᶠinterp(Y.c.ρ * ᶜJ) / ᶠJ)
131+
end
132+
122133
"""
123134
g³³_field(space)
124135

0 commit comments

Comments
 (0)