Skip to content

Commit 7cf0f91

Browse files
Try foreach_scalar
1 parent fe9e66d commit 7cf0f91

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

src/parameterized_tendencies/les_sgs_models/smagorinsky_lilly.jl

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,13 @@ 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 propertynames(Yₜ.c)
111-
if is_tracer_var(ρχ_name) && ρχ_name != :ρe_tot
112-
ᶜρχ = getproperty(Y.c, ρχ_name)
113-
ᶜρχₜ = getproperty(Yₜ.c, ρχ_name)
114-
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
115-
ᶜρχₜ_diffusion = @. lazy(wdivₕ(Y.c.ρ * ᶜD_smag * gradₕ(ᶜχ)))
116-
@. ᶜρχₜ += ᶜρχₜ_diffusion
117-
# Rain and snow does not affect the mass
118-
if ρχ_name == :ρq_tot
119-
@. Yₜ.c.ρ += ᶜρχₜ_diffusion
120-
end
110+
foreach_scalar(Yₜ, Y) do ᶜρχₜ, ᶜρχ, is_ρq_tot
111+
ᶜχ = @. lazy(specific(ᶜρχ, Y.c.ρ))
112+
ᶜρχₜ_diffusion = @. lazy(wdivₕ(Y.c.ρ * ᶜD_smag * gradₕ(ᶜχ)))
113+
@. ᶜρχₜ += ᶜρχₜ_diffusion
114+
# Rain and snow does not affect the mass
115+
if is_ρq_tot
116+
@. Yₜ.c.ρ += ᶜρχₜ_diffusion
121117
end
122118
end
123119

src/utils/variable_manipulations.jl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,64 @@ Arguments:
5151
return ρa == 0 ? ρχ / ρ : weight * ρaχ / ρa + (1 - weight) * ρχ / ρ
5252
end
5353

54+
"""
55+
scalar_names(field)
56+
57+
Filters and returns the names of the variables from a given state
58+
vector component, excluding `ρ`, `ρe_tot`, and `uₕ`
59+
60+
Arguments:
61+
62+
- `field`: A component of the state vector `Y.c`.
63+
64+
Returns:
65+
66+
- A `Tuple` of `ClimaCore.MatrixFields.FieldName`s corresponding to the tracers.
67+
"""
68+
scalar_names(field) =
69+
unrolled_filter(MatrixFields.top_level_names(field)) do name
70+
!(name in (@name(ρ), @name(ρe_tot), @name(uₕ)))
71+
end
72+
73+
"""
74+
foreach_scalar(f::F, Yₜ, Y) where {F}
75+
76+
Applies a given function `f` to each scalar variable (except `ρ` and `ρe_tot`)
77+
in the state `Y` and its corresponding tendency `Yₜ`.
78+
This utility abstracts the process of iterating over all scalars. It uses
79+
`scalar_names` to identify the relevant variables and `unrolled_foreach` to
80+
ensure a performant loop. For each tracer, it calls the provided function `f`
81+
with the tendency field, the state field, and a boolean flag indicating if
82+
the current tracer is `ρq_tot` (to allow for special handling).
83+
84+
Arguments:
85+
86+
- `f`: A function to apply to each scalar. It must have the signature
87+
`f(ᶜρχₜ, ᶜρχ, is_ρq_tot)`, where `ᶜρχₜ` is the tendency field, `ᶜρχ` is
88+
the state field, and `is_ρq_tot` is a `Bool`.
89+
- `Yₜ`: The tendency state vector.
90+
- `Y`: The current state vector.
91+
92+
# Example
93+
94+
```julia
95+
foreach_scalar(Yₜ, Y) do ᶜρχₜ, ᶜρχ, is_ρq_tot
96+
# Apply some operation, e.g., a sponge layer
97+
@. ᶜρχₜ += some_sponge_function(ᶜρχ)
98+
if is_ρq_tot
99+
# Perform an additional operation only for ρq_tot
100+
end
101+
end
102+
```
103+
"""
104+
foreach_scalar(f::F, Yₜ, Y) where {F} =
105+
unrolled_foreach(scalar_names(Y.c)) do scalar_name
106+
ᶜρχₜ = MatrixFields.get_field(Yₜ.c, scalar_name)
107+
ᶜρχ = MatrixFields.get_field(Y.c, scalar_name)
108+
is_ρq_tot = scalar_name == @name(ρq_tot)
109+
f(ᶜρχₜ, ᶜρχ, is_ρq_tot)
110+
end
111+
54112
"""
55113
sgs_weight_function(a, a_half)
56114

0 commit comments

Comments
 (0)