Skip to content

Commit aaeb6aa

Browse files
charleskawczynskiCharlie Kawczynski
authored andcommitted
Add some tendencies via columnwise
1 parent de6d9fc commit aaeb6aa

File tree

4 files changed

+207
-47
lines changed

4 files changed

+207
-47
lines changed

src/cache/precipitation_precomputed_quantities.jl

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,76 @@ function Kin(ᶜw_precip, ᶜu_air)
2929
)
3030
end
3131

32+
function compute_precip_velocities(ᶜY, ᶠY, p, t)
33+
cmc = CAP.microphysics_cloud_params(p.params)
34+
cmp = CAP.microphysics_1m_params(p.params)
35+
36+
# compute the precipitation terminal velocity [m/s]
37+
ᶜwᵣ = CM1.terminal_velocity(
38+
cmp.pr,
39+
cmp.tv.rain,
40+
ᶜY.ρ,
41+
max(zero(ᶜY.ρ), ᶜY.ρq_rai / ᶜY.ρ),
42+
)
43+
ᶜwₛ = CM1.terminal_velocity(
44+
cmp.ps,
45+
cmp.tv.snow,
46+
ᶜY.ρ,
47+
max(zero(ᶜY.ρ), ᶜY.ρq_sno / ᶜY.ρ),
48+
)
49+
# compute sedimentation velocity for cloud condensate [m/s]
50+
ᶜwₗ = CMNe.terminal_velocity(
51+
cmc.liquid,
52+
cmc.Ch2022.rain,
53+
ᶜY.ρ,
54+
max(zero(ᶜY.ρ), ᶜY.ρq_liq / ᶜY.ρ),
55+
)
56+
ᶜwᵢ = CMNe.terminal_velocity(
57+
cmc.ice,
58+
cmc.Ch2022.small_ice,
59+
ᶜY.ρ,
60+
max(zero(ᶜY.ρ), ᶜY.ρq_ice / ᶜY.ρ),
61+
)
62+
return (ᶜwᵣ, ᶜwₛ, ᶜwₗ, ᶜwᵢ)
63+
end
64+
65+
66+
compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t) =
67+
compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t, p.atmos.moisture_model, p.atmos.precip_model)
68+
compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t, moisture_model, precip_model) = zero(eltype(ᶜY.ρ))
69+
70+
function compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t,
71+
::NonEquilMoistModel,
72+
::Microphysics1Moment,
73+
)
74+
(ᶜwᵣ, ᶜwₛ, ᶜwₗ, ᶜwᵢ) = compute_precip_velocities(ᶜY, ᶠY, p, t)
75+
# compute their contributions to energy and total water advection
76+
return Geometry.WVector(
77+
ᶜwₗ * ᶜY.ρq_liq +
78+
ᶜwᵢ * ᶜY.ρq_ice +
79+
ᶜwᵣ * ᶜY.ρq_rai +
80+
ᶜwₛ * ᶜY.ρq_sno,
81+
) / ᶜY.ρ
82+
end
83+
84+
compute_ᶜwₕhₜ(ᶜY, ᶠY, p, t) =
85+
compute_ᶜwₕhₜ(ᶜY, ᶠY, p, t, p.atmos.moisture_model, p.atmos.precip_model)
86+
87+
compute_ᶜwₕhₜ(ᶜY, ᶠY, p, t, moisture_model, precip_model) = zero(ᶜY.ρ)
88+
89+
function compute_ᶜwₕhₜ(ᶜY, ᶠY, p, t, ::NonEquilMoistModel, ::Microphysics1Moment)
90+
thp = CAP.thermodynamics_params(p.params)
91+
ᶜts = compute_ᶜts(ᶜY, ᶠY, p, t)
92+
(ᶜwᵣ, ᶜwₛ, ᶜwₗ, ᶜwᵢ) = compute_precip_velocities(ᶜY, ᶠY, p, t)
93+
# compute their contributions to energy and total water advection
94+
return @. lazy(Geometry.WVector(
95+
ᶜwₗ * ᶜY.ρq_liq * (Iₗ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwₗ, ᶜY.ᶜu))) +
96+
ᶜwᵢ * ᶜY.ρq_ice * (Iᵢ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwᵢ, ᶜY.ᶜu))) +
97+
ᶜwᵣ * ᶜY.ρq_rai * (Iₗ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwᵣ, ᶜY.ᶜu))) +
98+
ᶜwₛ * ᶜY.ρq_sno * (Iᵢ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwₛ, ᶜY.ᶜu))),
99+
) / ᶜY.ρ)
100+
end
101+
32102
"""
33103
set_precipitation_velocities!(Y, p, moisture_model, precip_model)
34104

src/prognostic_equations/advection.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -139,19 +139,6 @@ NVTX.@annotate function explicit_vertical_advection_tendency!(Yₜ, Y, p, t)
139139
end
140140
# ... and upwinding correction of energy and total water.
141141
# (The central advection of energy and total water is done implicitly.)
142-
if energy_upwinding != Val(:none)
143-
(; ᶜh_tot) = p.precomputed
144-
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜh_tot, float(dt), energy_upwinding)
145-
vtt_central = vertical_transport(ᶜρ, ᶠu³, ᶜh_tot, float(dt), Val(:none))
146-
@. Yₜ.c.ρe_tot += vtt - vtt_central
147-
end
148-
149-
if !(p.atmos.moisture_model isa DryModel) && tracer_upwinding != Val(:none)
150-
ᶜq_tot = ᶜspecific.q_tot
151-
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, float(dt), tracer_upwinding)
152-
vtt_central = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, float(dt), Val(:none))
153-
@. Yₜ.c.ρq_tot += vtt - vtt_central
154-
end
155142

156143
if isnothing(ᶠf¹²)
157144
# shallow atmosphere

src/prognostic_equations/remaining_tendency.jl

Lines changed: 137 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,84 @@ using ClimaCore.RecursiveApply: rzero
4444
function ᶜremaining_tendency_ρ(ᶜY, ᶠY, p, t)
4545
in propertynames(ᶜY) || return ()
4646
∑tendencies = zero(eltype(ᶜY.ρ))
47-
return (; ρ = ∑tendencies)
47+
ᶜJ = Fields.local_geometry_field(ᶜY).J
48+
ᶠJ = Fields.local_geometry_field(ᶠY).J
49+
50+
if !(p.atmos.moisture_model isa DryModel)
51+
ᶜwₜqₜ = compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t)
52+
∑tendencies = lazy.(∑tendencies .- water_adv(ᶜρ, ᶜJ, ᶠJ, ᶜwₜqₜ))
53+
end
54+
return (;ρ=∑tendencies)
4855
end
4956
function ᶜremaining_tendency_uₕ(ᶜY, ᶠY, p, t)
5057
:uₕ in propertynames(ᶜY) || return ()
5158
∑tendencies = zero(eltype(ᶜY.uₕ))
52-
return (; uₕ = ∑tendencies)
59+
(; viscous_sponge, rayleigh_sponge) = p.atmos
60+
ᶜuₕ = ᶜY.uₕ
61+
∑tendencies = lazy.(∑tendencies .+ viscous_sponge_tendency_uₕ(ᶜuₕ, viscous_sponge))
62+
∑tendencies = lazy.(∑tendencies .+ rayleigh_sponge_tendency_uₕ(ᶜuₕ, rayleigh_sponge))
63+
64+
return (;uₕ=∑tendencies)
5365
end
5466
function ᶜremaining_tendency_ρe_tot(ᶜY, ᶠY, p, t)
5567
:ρe_tot in propertynames(ᶜY) || return ()
5668
∑tendencies = zero(eltype(ᶜY.ρe_tot))
57-
return (; ρe_tot = ∑tendencies)
69+
70+
(; moisture_model, viscous_sponge, precip_model) = p.atmos
71+
(; energy_upwinding) = p.atmos.numerics
72+
thermo_params = CAP.thermodynamics_params(p.params)
73+
thermo_args = (thermo_params, moisture_model, precip_model)
74+
ᶜz = Fields.coordinate_field(ᶜY).z
75+
ᶜρ = ᶜY.ρ
76+
ᶜuₕ = ᶜY.uₕ
77+
ᶜρe_tot = ᶜY.ρe_tot
78+
ᶜts = compute_ᶜts(ᶜY, ᶠY, p, t)
79+
ᶜp = @. lazy(TD.air_pressure(thermo_params, ᶜts))
80+
ᶜe_tot = @. lazy(ᶜρe_tot / ᶜρ)
81+
ᶜh_tot = @. lazy(TD.total_specific_enthalpy(thermo_params, ᶜts, ᶜe_tot))
82+
83+
if !(p.atmos.moisture_model isa DryModel)
84+
ᶜwₕhₜ = compute_ᶜwₕhₜ(ᶜY, ᶠY, p, t)
85+
∑tendencies = lazy.(∑tendencies .- water_adv(ᶜρ, ᶜJ, ᶠJ, ᶜwₕhₜ))
86+
end
87+
if energy_upwinding != Val(:none)
88+
(; dt) = p
89+
ᶠu³ = compute_ᶠu³(ᶜY, ᶠY)
90+
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜh_tot, float(dt), energy_upwinding)
91+
∑tendencies = lazy.(∑tendencies .+ vtt)
92+
vtt_central = vertical_transport(ᶜρ, ᶠu³, ᶜh_tot, float(dt), Val(:none))
93+
# need to improve NullBroadcast support for this.
94+
∑tendencies = lazy.(∑tendencies .+ (-1) .* vtt_central)
95+
end
96+
97+
∑tendencies = lazy.(∑tendencies .+ viscous_sponge_tendency_ρe_tot(ᶜρ, ᶜh_tot, viscous_sponge))
98+
return (;ρe_tot=∑tendencies)
5899
end
59100
function ᶜremaining_tendency_ρq_tot(ᶜY, ᶠY, p, t)
60101
:ρq_tot in propertynames(ᶜY) || return ()
61102
∑tendencies = zero(eltype(ᶜY.ρq_tot))
62-
return (; ρq_tot = ∑tendencies)
103+
ᶜJ = Fields.local_geometry_field(ᶜY).J
104+
ᶠJ = Fields.local_geometry_field(ᶠY).J
105+
ᶜρ = ᶜY.ρ
106+
if !(p.atmos.moisture_model isa DryModel)
107+
ᶜwₜqₜ = compute_ᶜwₜqₜ(ᶜY, ᶠY, p, t)
108+
cmc = CAP.microphysics_cloud_params(p.params)
109+
cmp = CAP.microphysics_1m_params(p.params)
110+
thp = CAP.thermodynamics_params(p.params)
111+
∑tendencies = lazy.(∑tendencies .- water_adv(ᶜρ, ᶜJ, ᶠJ, ᶜwₜqₜ))
112+
end
113+
(; tracer_upwinding) = p.atmos.numerics
114+
if !(p.atmos.moisture_model isa DryModel) && tracer_upwinding != Val(:none)
115+
(; dt) = p
116+
(; ᶜspecific) = p.precomputed
117+
ᶜq_tot = @. lazy(ᶜY.ρq_tot / ᶜY.ρ)
118+
ᶠu³ = compute_ᶠu³(ᶜY, ᶠY)
119+
vtt = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, float(dt), tracer_upwinding)
120+
vtt_central = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, float(dt), Val(:none))
121+
∑tendencies = lazy.(∑tendencies .+ vtt .- vtt_central)
122+
end
123+
124+
return (;ρq_tot=∑tendencies)
63125
end
64126
function ᶜremaining_tendency_ρq_liq(ᶜY, ᶠY, p, t)
65127
:ρq_liq in propertynames(ᶜY) || return ()
@@ -94,7 +156,13 @@ end
94156
function ᶠremaining_tendency_u₃(ᶜY, ᶠY, p, t)
95157
:u₃ in propertynames(ᶠY) || return ()
96158
∑tendencies = zero(eltype(ᶠY.u₃))
97-
return (; u₃ = ∑tendencies)
159+
(; viscous_sponge) = p.atmos
160+
ᶜρ = ᶜY.ρ
161+
ᶜuₕ = ᶜY.uₕ
162+
ᶠuₕ³ = compute_ᶠuₕ³(ᶜuₕ, ᶜρ)
163+
ᶠu₃ = compute_ᶠu₃_with_bcs(ᶠY.u₃, ᶠuₕ³)
164+
∑tendencies = lazy.(∑tendencies .+ viscous_sponge_tendency_u₃(ᶠu₃, viscous_sponge))
165+
return (;u₃=∑tendencies)
98166
end
99167
function ᶠremaining_tendency_sgsʲs(ᶜY, ᶠY, p, t)
100168
:sgsʲs in propertynames(ᶠY) || return ()
@@ -103,6 +171,64 @@ function ᶠremaining_tendency_sgsʲs(ᶜY, ᶠY, p, t)
103171
end
104172

105173

174+
water_adv(ᶜρ, ᶜJ, ᶠJ, ᶜχ) =
175+
@. lazy(ᶜprecipdivᵥ(ᶠinterp(ᶜρ * ᶜJ) / ᶠJ * ᶠright_bias(-(ᶜχ))))
176+
177+
function surface_velocity_full(ᶠu₃, ᶠuₕ³)
178+
assert_eltype(ᶠuₕ³, Geometry.Contravariant3Vector)
179+
assert_eltype(ᶠu₃, Geometry.Covariant3Vector)
180+
ᶠlg = Fields.local_geometry_field(axes(ᶠu₃))
181+
sfc_u₃ = ᶠu₃ # Fields.level(ᶠu₃.components.data.:1, half)
182+
sfc_uₕ³ = ᶠuₕ³ # Fields.level(ᶠuₕ³.components.data.:1, half)
183+
sfc_g³³ = g³³_field(axes(sfc_u₃))
184+
w₃ = @. lazy(- C3(sfc_uₕ³ / sfc_g³³, ᶠlg)) # u³ = uₕ³ + w³ = uₕ³ + w₃ * g³³
185+
assert_eltype(w₃, Geometry.Covariant3Vector)
186+
return w₃
187+
end
188+
189+
function compute_ᶜts(ᶜY, ᶠY, p, t)
190+
(; moisture_model, precip_model) = p.atmos
191+
thermo_params = CAP.thermodynamics_params(p.params)
192+
thermo_args = (thermo_params, moisture_model, precip_model)
193+
ᶜz = Fields.coordinate_field(ᶜY).z
194+
FT = Spaces.undertype(axes(ᶜY))
195+
grav = FT(CAP.grav(p.params))
196+
ᶜΦ = @. lazy(grav * ᶜz)
197+
198+
ᶜρ = ᶜY.ρ
199+
ᶜuₕ = ᶜY.uₕ
200+
ᶠuₕ³ = compute_ᶠuₕ³(ᶜuₕ, ᶜρ)
201+
ᶠu₃ = compute_ᶠu₃_with_bcs(ᶠY.u₃, ᶠuₕ³)
202+
ᶜK = compute_kinetic(ᶜuₕ, ᶠu₃)
203+
ᶜspecific = @. lazy(specific_gs(ᶜY))
204+
return @. lazy(ts_gs(thermo_args..., ᶜspecific, ᶜK, ᶜΦ, ᶜρ))
205+
end
206+
207+
assert_eltype(bc::Base.AbstractBroadcasted, ::Type{T}) where {T} =
208+
assert_eltype(eltype(bc), T)
209+
assert_eltype(f::Fields.Field, ::Type{T}) where {T} =
210+
assert_eltype(Fields.field_values(f), T)
211+
assert_eltype(data::DataLayouts.AbstractData, ::Type{T}) where {T} =
212+
assert_eltype(eltype(data), T)
213+
assert_eltype(::Type{S}, ::Type{T}) where {S, T} =
214+
@assert S <: T "Type $S should be a subtype of $T"
215+
216+
function compute_ᶠu₃_with_bcs(ᶠu₃, ᶠuₕ³)
217+
assert_eltype(ᶠu₃, Geometry.Covariant3Vector)
218+
assert_eltype(ᶠuₕ³, Geometry.Contravariant3Vector)
219+
ᶠz = Fields.coordinate_field(axes(ᶠu₃)).z
220+
sfc_u₃ = surface_velocity_full(ᶠu₃, ᶠuₕ³)
221+
# todo: generalize this with z_min
222+
return @. lazy(ifelse(iszero(ᶠz), sfc_u₃, ᶠu₃))
223+
end
224+
function compute_ᶠu³(ᶜY, ᶠY)
225+
ᶜρ = ᶜY.ρ
226+
ᶜuₕ = ᶜY.uₕ
227+
ᶠuₕ³ = compute_ᶠuₕ³(ᶜuₕ, ᶜρ)
228+
ᶠu₃ = compute_ᶠu₃_with_bcs(ᶠY.u₃, ᶠuₕ³)
229+
return @. lazy(ᶠuₕ³ + CT3(ᶠu₃))
230+
end
231+
106232
NVTX.@annotate function remaining_tendency!(Yₜ, Yₜ_lim, Y, p, t)
107233
Yₜ_lim .= zero(eltype(Yₜ_lim))
108234
device = ClimaComms.device(axes(Y.c))
@@ -111,7 +237,12 @@ NVTX.@annotate function remaining_tendency!(Yₜ, Yₜ_lim, Y, p, t)
111237
else
112238
Val(false), Val(false)
113239
end
114-
p_kernel = (;)
240+
(; moisture_model, viscous_sponge, precip_model) = p.atmos
241+
p_kernel = (;
242+
atmos = p.atmos,
243+
params = p.params,
244+
dt = p.dt,
245+
)
115246
if :sfc in propertynames(Y) # columnwise! does not yet handle .sfc
116247
parent(Yₜ.sfc) .= zero(Spaces.undertype(axes(Y.c)))
117248
end
@@ -133,7 +264,6 @@ NVTX.@annotate function remaining_tendency!(Yₜ, Yₜ_lim, Y, p, t)
133264
horizontal_advection_tendency!(Yₜ, Y, p, t)
134265
hyperdiffusion_tendency!(Yₜ, Yₜ_lim, Y, p, t)
135266
explicit_vertical_advection_tendency!(Yₜ, Y, p, t)
136-
vertical_advection_of_water_tendency!(Yₜ, Y, p, t)
137267
additional_tendency!(Yₜ, Y, p, t)
138268
return Yₜ
139269
end
@@ -161,24 +291,13 @@ NVTX.@annotate function additional_tendency!(Yₜ, Y, p, t)
161291
thermo_params = CAP.thermodynamics_params(params)
162292
(; ᶜp, sfc_conditions, ᶜts) = p.precomputed
163293

164-
vst_uₕ = viscous_sponge_tendency_uₕ(ᶜuₕ, viscous_sponge)
165-
vst_u₃ = viscous_sponge_tendency_u₃(ᶠu₃, viscous_sponge)
166-
vst_ρe_tot = viscous_sponge_tendency_ρe_tot(ᶜρ, ᶜh_tot, viscous_sponge)
167-
rst_uₕ = rayleigh_sponge_tendency_uₕ(ᶜuₕ, rayleigh_sponge)
168294
hs_args = (ᶜuₕ, ᶜp, params, sfc_conditions.ts, moisture_model, forcing_type)
169295
hs_tendency_uₕ = held_suarez_forcing_tendency_uₕ(hs_args...)
170296
hs_tendency_ρe_tot = held_suarez_forcing_tendency_ρe_tot(ᶜρ, hs_args...)
171297
edmf_cor_tend_uₕ = edmf_coriolis_tendency_uₕ(ᶜuₕ, edmf_coriolis)
172298
lsa_args = (ᶜρ, thermo_params, ᶜts, t, ls_adv)
173299
bc_lsa_tend_ρe_tot = large_scale_advection_tendency_ρe_tot(lsa_args...)
174300

175-
# TODO: fuse, once we fix
176-
# https://github.com/CliMA/ClimaCore.jl/issues/2165
177-
@. Yₜ.c.uₕ += vst_uₕ
178-
@. Yₜ.c.uₕ += rst_uₕ
179-
@. Yₜ.f.u₃.components.data.:1 += vst_u₃
180-
@. Yₜ.c.ρe_tot += vst_ρe_tot
181-
182301
# TODO: can we write this out explicitly?
183302
for (ᶜρχₜ, ᶜχ, χ_name) in matching_subfields(Yₜ.c, ᶜspecific)
184303
χ_name == :e_tot && continue
Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,2 @@
11
import ClimaCore: Fields
22

3-
function vertical_advection_of_water_tendency!(Yₜ, Y, p, t)
4-
5-
ᶜJ = Fields.local_geometry_field(Y.c).J
6-
ᶠJ = Fields.local_geometry_field(Y.f).J
7-
(; ᶜwₜqₜ, ᶜwₕhₜ) = p.precomputed
8-
9-
if !(p.atmos.moisture_model isa DryModel)
10-
@. Yₜ.c.ρ -=
11-
ᶜprecipdivᵥ(ᶠinterp(Y.c.ρ * ᶜJ) / ᶠJ * ᶠright_bias(-(ᶜwₜqₜ)))
12-
@. Yₜ.c.ρe_tot -=
13-
ᶜprecipdivᵥ(ᶠinterp(Y.c.ρ * ᶜJ) / ᶠJ * ᶠright_bias(-(ᶜwₕhₜ)))
14-
@. Yₜ.c.ρq_tot -=
15-
ᶜprecipdivᵥ(ᶠinterp(Y.c.ρ * ᶜJ) / ᶠJ * ᶠright_bias(-(ᶜwₜqₜ)))
16-
end
17-
return nothing
18-
end

0 commit comments

Comments
 (0)