Skip to content

Commit 21c7e39

Browse files
Remove more use of matching_subfields
1 parent a732795 commit 21c7e39

File tree

7 files changed

+90
-81
lines changed

7 files changed

+90
-81
lines changed

src/parameterized_tendencies/les_sgs_models/smagorinsky_lilly.jl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,18 @@ function horizontal_smagorinsky_lilly_tendency!(Yₜ, Y, p, t, ::SmagorinskyLill
107107
@. Yₜ.c.ρe_tot += wdivₕ(Y.c.ρ * ᶜD_smag * gradₕ(ᶜh_tot))
108108

109109
## Tracer diffusion and associated mass changes
110-
for (ᶜρχₜ, ᶜχ, χ_name) in CA.matching_subfields(Yₜ.c, ᶜspecific)
111-
χ_name == :e_tot && continue
112-
ᶜρχₜ_diffusion =
113-
@. p.scratch.ᶜtemp_scalar = wdivₕ(Y.c.ρ * ᶜD_smag * gradₕ(ᶜχ))
114-
@. ᶜρχₜ += ᶜρχₜ_diffusion
115-
# Rain and snow does not affect the mass
116-
if χ_name (:q_rai, :q_sno)
117-
@. Yₜ.c.ρ += ᶜρχₜ_diffusion
110+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
111+
if ρχ_name != :ρe_tot
112+
ᶜρχ = getproperty(Y.c, ρχ_name)
113+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
114+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
115+
ᶜρχₜ_diffusion =
116+
@. p.scratch.ᶜtemp_scalar = wdivₕ(Y.c.ρ * ᶜD_smag * gradₕ(ᶜχ))
117+
@. ᶜρχₜ += ᶜρχₜ_diffusion
118+
# Rain and snow does not affect the mass
119+
if ρχ_name (:ρq_rai, :ρq_sno)
120+
@. Yₜ.c.ρ += ᶜρχₜ_diffusion
121+
end
118122
end
119123
end
120124

src/prognostic_equations/advection.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,14 @@ NVTX.@annotate function explicit_vertical_advection_tendency!(Yₜ, Y, p, t)
213213
ᶜρ = Y.c.ρ
214214

215215
# Full vertical advection of passive tracers (like liq, rai, etc) ...
216-
for (ᶜρχₜ, ᶜχ, χ_name) in matching_subfields(Yₜ.c, ᶜspecific)
217-
χ_name in (:e_tot, :q_tot) && continue
218-
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜχ, float(dt), tracer_upwinding)
219-
@. ᶜρχₜ += vtt
216+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
217+
if !(ρχ_name in (:ρe_tot, :ρq_tot))
218+
ᶜρχ = getproperty(Y.c, ρχ_name)
219+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
220+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
221+
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜχ, float(dt), tracer_upwinding)
222+
@. ᶜρχₜ += vtt
223+
end
220224
end
221225
# ... and upwinding correction of energy and total water.
222226
# (The central advection of energy and total water is done implicitly.)

src/prognostic_equations/hyperdiffusion.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,22 @@ NVTX.@annotate function apply_tracer_hyperdiffusion_tendency!(Yₜ, Y, p, t)
289289
# by the limiter. Is this a significant problem?
290290
# TODO: Figure out why caching the duplicated tendencies in ᶜtemp_scalar
291291
# triggers allocations.
292-
for (ᶜρχₜ, ᶜ∇²χ, χ_name) in matching_subfields(Yₜ.c, ᶜ∇²specific_tracers)
292+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
293+
ᶜρχ = getproperty(Y.c, ρχ_name)
294+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
295+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
296+
293297
ν₄_scalar = ifelse(
294-
χ_name in (:q_rai, :q_sno, :n_rai),
298+
ρχ_name in (:ρq_rai, :ρq_sno, :ρn_rai),
295299
α_hyperdiff_tracer * ν₄_scalar,
296300
ν₄_scalar,
297301
)
302+
ᶜ∇²χ = getproperty(ᶜ∇²specific_tracers, specific_name(ρχ_name))
298303
@. ᶜρχₜ -= ν₄_scalar * wdivₕ(Y.c.ρ * gradₕ(ᶜ∇²χ))
299304

300305
# Exclude contributions from hyperdiffusion of condensate,
301306
# precipitating species from mass tendency.
302-
if χ_name == :q_tot
307+
if ρχ_name == :ρq_tot
303308
@. Yₜ.c.ρ -= ν₄_scalar * wdivₕ(Y.c.ρ * gradₕ(ᶜ∇²χ))
304309
end
305310
end

src/prognostic_equations/remaining_tendency.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,15 @@ NVTX.@annotate function additional_tendency!(Yₜ, Y, p, t)
166166
@. Yₜ.c.ρe_tot += vst_ρe_tot
167167

168168
# TODO: can we write this out explicitly?
169-
for (ᶜρχₜ, ᶜχ, χ_name) in matching_subfields(Yₜ.c, ᶜspecific)
170-
χ_name == :e_tot && continue
171-
vst_tracer = viscous_sponge_tendency_tracer(ᶜρ, ᶜχ, viscous_sponge)
172-
@. ᶜρχₜ += vst_tracer
173-
@. Yₜ.c.ρ += vst_tracer # TODO: This doesn't look right for all tracers here. Remove?
169+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
170+
if ρχ_name != :ρe_tot
171+
ᶜρχ = getproperty(Y.c, ρχ_name)
172+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
173+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
174+
vst_tracer = viscous_sponge_tendency_tracer(ᶜρ, ᶜχ, viscous_sponge)
175+
@. ᶜρχₜ += vst_tracer
176+
@. Yₜ.c.ρ += vst_tracer # TODO: This doesn't look right for all tracers here. Remove?
177+
end
174178
end
175179

176180
# Held Suarez tendencies

src/prognostic_equations/surface_flux.jl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,21 @@ function surface_flux_tendency!(Yₜ, Y, p, t)
115115
btt = boundary_tendency_scalar(ᶜh_tot, sfc_conditions.ρ_flux_h_tot)
116116
@. Yₜ.c.ρe_tot -= btt
117117
ρ_flux_χ = p.scratch.sfc_temp_C3
118-
for (ᶜρχₜ, ᶜχ, χ_name) in matching_subfields(Yₜ.c, ᶜspecific)
119-
χ_name == :e_tot && continue
120-
if χ_name == :q_tot
121-
@. ρ_flux_χ = sfc_conditions.ρ_flux_q_tot
122-
else
123-
@. ρ_flux_χ = C3(FT(0))
124-
end
125-
btt = boundary_tendency_scalar(ᶜχ, ρ_flux_χ)
126-
@. ᶜρχₜ -= btt
127-
if χ_name == :q_tot
128-
@. Yₜ.c.ρ -= btt
118+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
119+
ᶜρχ = getproperty(Y.c, ρχ_name)
120+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
121+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
122+
if ρχ_name != :ρe_tot
123+
if ρχ_name == :ρq_tot
124+
@. ρ_flux_χ = sfc_conditions.ρ_flux_q_tot
125+
else
126+
@. ρ_flux_χ = C3(FT(0))
127+
end
128+
btt = boundary_tendency_scalar(ᶜχ, ρ_flux_χ)
129+
@. ᶜρχₜ -= btt
130+
if ρχ_name == :ρq_tot
131+
@. Yₜ.c.ρ -= btt
132+
end
129133
end
130134
end
131135
end

src/prognostic_equations/vertical_diffusion_boundary_layer.jl

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ This function is dispatched based on the type of the vertical diffusion model
4646
for scalars. Zero-flux boundary conditions are explicitly applied.
4747
- **Note on mass conservation for `q_tot` diffusion**: The current implementation
4848
also modifies the tendency of total moist air density `Yₜ.c.ρ` based on the
49-
diffusion tendency of total specific humidity `ρq_tot`:
49+
diffusion tendency of total specific humidity `ρq_tot`:
5050
`Yₜ.c.ρ -= ᶜρχₜ_diffusion_for_q_tot`.
5151
5252
Arguments for all methods:
@@ -58,7 +58,7 @@ Arguments for all methods:
5858
- `t`: Current simulation time (not directly used in diffusion calculations).
5959
- `vert_diff_model` (for dispatched methods): The specific vertical diffusion model instance.
6060
61-
Modifies components of tendency vector `Yₜ.c` (e.g., `Yₜ.c.uₕ`, `Yₜ.c.ρe_tot`, `Yₜ.c.ρ`, and
61+
Modifies components of tendency vector `Yₜ.c` (e.g., `Yₜ.c.uₕ`, `Yₜ.c.ρe_tot`, `Yₜ.c.ρ`, and
6262
various tracer fields such as `Yₜ.c.ρq_tot`).
6363
"""
6464

@@ -96,24 +96,28 @@ function vertical_diffusion_boundary_layer_tendency!(
9696

9797
ᶜρχₜ_diffusion = p.scratch.ᶜtemp_scalar
9898
ᶜK_h_scaled = p.scratch.ᶜtemp_scalar_2
99-
for (ᶜρχₜ, ᶜχ, χ_name) in matching_subfields(Yₜ.c, ᶜspecific)
100-
χ_name == :e_tot && continue
101-
if χ_name in (:q_rai, :q_sno, :n_rai)
102-
@. ᶜK_h_scaled = α_vert_diff_tracer * ᶜK_h
103-
else
104-
@. ᶜK_h_scaled = ᶜK_h
105-
end
106-
ᶜdivᵥ_ρχ = Operators.DivergenceF2C(
107-
top = Operators.SetValue(C3(0)),
108-
bottom = Operators.SetValue(C3(0)),
109-
)
110-
@. ᶜρχₜ_diffusion =
111-
ᶜdivᵥ_ρχ(-(ᶠinterp(Y.c.ρ) * ᶠinterp(ᶜK_h_scaled) * ᶠgradᵥ(ᶜχ)))
112-
@. ᶜρχₜ -= ᶜρχₜ_diffusion
113-
# Only add contribution from total water diffusion to mass tendency
114-
# (exclude contributions from diffusion of condensate, precipitation)
115-
if χ_name == :q_tot
116-
@. Yₜ.c.ρ -= ᶜρχₜ_diffusion
99+
UU.unrolled_foreach(filter(is_tracer_var, propertynames(Yₜ.c))) do ρχ_name
100+
ᶜρχ = getproperty(Y.c, ρχ_name)
101+
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
102+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
103+
if ρχ_name != :ρe_tot
104+
if χ_name in (:q_rai, :q_sno, :n_rai)
105+
@. ᶜK_h_scaled = α_vert_diff_tracer * ᶜK_h
106+
else
107+
@. ᶜK_h_scaled = ᶜK_h
108+
end
109+
ᶜdivᵥ_ρχ = Operators.DivergenceF2C(
110+
top = Operators.SetValue(C3(0)),
111+
bottom = Operators.SetValue(C3(0)),
112+
)
113+
@. ᶜρχₜ_diffusion =
114+
ᶜdivᵥ_ρχ(-(ᶠinterp(Y.c.ρ) * ᶠinterp(ᶜK_h_scaled) * ᶠgradᵥ(ᶜχ)))
115+
@. ᶜρχₜ -= ᶜρχₜ_diffusion
116+
# Only add contribution from total water diffusion to mass tendency
117+
# (exclude contributions from diffusion of condensate, precipitation)
118+
if χ_name == :q_tot
119+
@. Yₜ.c.ρ -= ᶜρχₜ_diffusion
120+
end
117121
end
118122
end
119123
end

src/utils/variable_manipulations.jl

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ Arguments:
4242
"""
4343
@inline specific(ρχ, ρ) = ρχ / ρ
4444

45+
#! format: off
46+
@inline specific_name(ρχ_name::Symbol) =
47+
if ρχ_name == :ρe_tot; return :e_tot
48+
elseif ρχ_name == :ρq_tot; return :q_tot
49+
elseif ρχ_name == :ρq_liq; return :q_liq
50+
elseif ρχ_name == :ρq_ice; return :q_ice
51+
elseif ρχ_name == :ρq_rai; return :q_rai
52+
elseif ρχ_name == :ρn_liq; return :n_liq
53+
elseif ρχ_name == :ρn_rai; return :q_rai
54+
elseif ρχ_name == :ρq_sno; return :q_sno
55+
else; error("Uncaught name: $ρχ_name")
56+
end
57+
#! format: on
58+
4559
@inline function specific(ρaχ, ρa, ρχ, ρ, turbconv_model)
4660
# TODO: Replace turbconv_model struct by parameters, and include a_half in
4761
# parameters, not in config
@@ -202,36 +216,6 @@ value is assumed to be equal to the value of `ρaχ` in `sgs`.
202216
return :(NamedTuple{$specific_sgs_names}(($(specific_sgs_values...),)))
203217
end
204218

205-
"""
206-
matching_subfields(tendency_field, specific_field)
207-
208-
Given a field that contains the tendencies of variables of the form `ρχ` or
209-
`ρaχ` and another field that contains the values of specific variables `χ`,
210-
returns all tuples `(tendency_field.<ρχ or ρaχ>, specific_field.<χ>, :<χ>)`.
211-
Variables in `tendency_field` that do not have matching variables in
212-
`specific_field` are omitted, as are variables in `specific_field` that do not
213-
have matching variables in `tendency_field`. This function is needed to avoid
214-
allocations due to failures in type inference, which are triggered when the
215-
`propertynames` of these fields are manipulated during runtime in order to pick
216-
out the matching subfields (as of Julia 1.8).
217-
"""
218-
@generated function matching_subfields(tendency_field, specific_field)
219-
tendency_names = Base._nt_names(eltype(tendency_field))
220-
specific_names = Base._nt_names(eltype(specific_field))
221-
prefix = :ρa in tendency_names ? :ρa :
222-
relevant_specific_names =
223-
filter(name -> Symbol(prefix, name) in tendency_names, specific_names)
224-
subfield_tuples = map(
225-
name -> :((
226-
tendency_field.$(Symbol(prefix, name)),
227-
specific_field.$name,
228-
$(QuoteNode(name)),
229-
)),
230-
relevant_specific_names,
231-
)
232-
return :(($(subfield_tuples...),))
233-
end
234-
235219
"""
236220
ρa⁺(gs)
237221

0 commit comments

Comments
 (0)