Skip to content

Commit 838227a

Browse files
committed
Add a simple non-equilibrium cloud formation
1 parent e4906ea commit 838227a

File tree

14 files changed

+169
-35
lines changed

14 files changed

+169
-35
lines changed

.buildkite/pipeline.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ steps:
288288
agents:
289289
slurm_mem: 20GB
290290

291+
- label: ":computer: aquaplanet (ρe_tot) nonequilmoist allsky radiation monin_obukhov varying insolation gravity wave (gfdl_restart) high top with 1-moment micro"
292+
command: >
293+
julia --color=yes --project=examples examples/hybrid/driver.jl
294+
--config_file $CONFIG_PATH/sphere_aquaplanet_rhoe_nonequilmoist_allsky_gw_res.yml
295+
artifact_paths: "sphere_aquaplanet_rhoe_nonequilmoist_allsky_gw_res/output_active/*"
296+
agents:
297+
slurm_mem: 20GB
298+
291299
- label: ":computer: aquaplanet (ρe_tot) equilmoist allsky radiation monin_obukhov varying insolation gravity wave (raw_topo) high top zonally asymmetric"
292300
command: >
293301
julia --color=yes --project=examples examples/hybrid/driver.jl
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
z_elem: 25
2+
z_max: 45000.0
3+
dz_bottom: 300.0
4+
dt: "400secs"
5+
t_end: "18hours"
6+
dt_save_state_to_disk: "18hours"
7+
vert_diff: "FriersonDiffusion"
8+
implicit_diffusion: true
9+
approximate_linear_solve_iters: 2
10+
moist: "nonequil"
11+
precip_model: "nothing"
12+
rad: "allskywithclear"
13+
idealized_insolation: false
14+
rayleigh_sponge: true
15+
non_orographic_gravity_wave: true
16+
orographic_gravity_wave: "gfdl_restart"
17+
surface_setup: "DefaultMoninObukhov"
18+
prescribed_aerosols: ["CB1", "CB2"]
19+
job_id: "sphere_aquaplanet_rhoe_nonequilmoist_allsky_gw_res"
20+
toml: [toml/sphere_aquaplanet_rhoe_equilmoist_allsky_gw_res.toml]
21+
diagnostics:
22+
- short_name: [edt, evu]
23+
reduction_time: average
24+
period: "18hours"

post_processing/ci_plots.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ end
824824

825825
AquaplanetPlots = Union{
826826
Val{:mpi_sphere_aquaplanet_rhoe_equilmoist_clearsky},
827+
Val{:sphere_aquaplanet_rhoe_nonequilmoist_allsky_gw_res},
827828
Val{:longrun_aquaplanet_rhoe_equil_55km_nz63_gray_0M},
828829
Val{:longrun_aquaplanet_rhoe_equil_55km_nz63_clearsky_0M},
829830
Val{:longrun_aquaplanet_rhoe_equil_55km_nz63_clearsky_diagedmf_diffonly_0M},

src/ClimaAtmos.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ include(joinpath("prognostic_equations", "edmfx_precipitation.jl"))
9090
include(
9191
joinpath("parameterized_tendencies", "microphysics", "precipitation.jl"),
9292
)
93+
include(
94+
joinpath("parameterized_tendencies", "microphysics", "cloud_condensate.jl"),
95+
)
9396
include(
9497
joinpath(
9598
"parameterized_tendencies",

src/cache/diagnostic_edmf_precomputed_quantities.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ NVTX.@annotate function set_diagnostic_edmf_precomputed_quantities_do_integral!(
243243
(; ᶠu³⁰, ᶜK⁰, ᶜtke⁰) = p.precomputed
244244

245245
thermo_params = CAP.thermodynamics_params(params)
246-
microphys_params = CAP.microphysics_params(params)
246+
microphys_params = CAP.microphysics_precipitation_params(params)
247247

248248
ᶠΦ = p.scratch.ᶠtemp_scalar
249249
@. ᶠΦ = CAP.grav(params) * ᶠz
@@ -874,7 +874,7 @@ NVTX.@annotate function set_diagnostic_edmf_precomputed_quantities_env_precipita
874874
precip_model::Microphysics0Moment,
875875
)
876876
thermo_params = CAP.thermodynamics_params(p.params)
877-
microphys_params = CAP.microphysics_params(p.params)
877+
microphys_params = CAP.microphysics_precipitation_params(p.params)
878878
(; dt) = p
879879
(; ᶜts, ᶜSqₜᵖ⁰) = p.precomputed
880880
(; q_tot) = p.precomputed.ᶜspecific

src/cache/precipitation_precomputed_quantities.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function set_precipitation_precomputed_quantities!(Y, p, t)
1919

2020
(; ᶜwᵣ, ᶜwₛ, ᶜqᵣ, ᶜqₛ) = p.precomputed
2121

22-
cmp = CAP.microphysics_params(p.params)
22+
cmp = CAP.microphysics_precipitation_params(p.params)
2323

2424
# compute the precipitation specific humidities
2525
@. ᶜqᵣ = qₚ(Y.c.ρq_rai, Y.c.ρ)

src/cache/prognostic_edmf_precomputed_quantities.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ NVTX.@annotate function set_prognostic_edmf_precomputed_quantities_precipitation
363363

364364
(; params, dt) = p
365365
thp = CAP.thermodynamics_params(params)
366-
cmp = CAP.microphysics_params(params)
366+
cmp = CAP.microphysics_precipitation_params(params)
367367
(; ᶜts⁰, ᶜq_tot⁰, ᶜtsʲs, ᶜSqₜᵖʲs, ᶜSqₜᵖ⁰) = p.precomputed
368368

369369
# Sources from the updrafts
@@ -399,7 +399,7 @@ NVTX.@annotate function set_prognostic_edmf_precomputed_quantities_precipitation
399399
(; params, dt) = p
400400
(; ᶜΦ,) = p.core
401401
thp = CAP.thermodynamics_params(params)
402-
cmp = CAP.microphysics_params(params)
402+
cmp = CAP.microphysics_precipitation_params(params)
403403

404404
(; ᶜSeₜᵖʲs, ᶜSqₜᵖʲs, ᶜSqᵣᵖʲs, ᶜSqₛᵖʲs, ᶜρʲs, ᶜtsʲs) = p.precomputed
405405
(; ᶜSeₜᵖ⁰, ᶜSqₜᵖ⁰, ᶜSqᵣᵖ⁰, ᶜSqₛᵖ⁰, ᶜρ⁰, ᶜts⁰) = p.precomputed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#####
2+
##### DryModel, EquilMoistModel
3+
#####
4+
5+
cloud_condensate_tendency!(Yₜ, p, colidx, _) = nothing
6+
7+
#####
8+
##### NonEquilMoistModel
9+
#####
10+
11+
function cloud_condensate_tendency!(Yₜ, p, colidx, ::NonEquilMoistModel)
12+
13+
(; ᶜts) = p.precomputed
14+
(; params, dt) = p
15+
thp = CAP.thermodynamics_params(params)
16+
cmc = CAP.microphysics_cloud_params(params)
17+
18+
@. Yₜ.c.ρq_liq[colidx] += cloud_sources(cmc.liquid, thp, ᶜts[colidx], dt)
19+
@. Yₜ.c.ρq_ice[colidx] += cloud_sources(cmc.ice, thp, ᶜts[colidx], dt)
20+
end

src/parameterized_tendencies/microphysics/microphysics_wrappers.jl

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import Thermodynamics as TD
44
import CloudMicrophysics.Microphysics0M as CM0
5+
import CloudMicrophysics.Microphysics1M as CM1
6+
import CloudMicrophysics.MicrophysicsNonEq as CMNe
7+
import CloudMicrophysics.Parameters as CMP
58

69
# define some aliases and functions to make the code more readable
710
const Iₗ = TD.internal_energy_liquid
@@ -10,12 +13,64 @@ const Lf = TD.latent_heat_fusion
1013
const Tₐ = TD.air_temperature
1114
const PP = TD.PhasePartition
1215
const qᵥ = TD.vapor_specific_humidity
16+
qₜ(thp, ts) = TD.PhasePartition(thp, ts).tot
1317
qₗ(thp, ts) = TD.PhasePartition(thp, ts).liq
1418
qᵢ(thp, ts) = TD.PhasePartition(thp, ts).ice
1519

1620
# helper function to limit the tendency
17-
function limit(q::FT, dt::FT) where {FT}
18-
return q / dt / 5
21+
function limit(q::FT, dt::FT, n::Int) where {FT}
22+
return q / dt / n
23+
end
24+
25+
"""
26+
cloud_sources(cm_params, thp, ts, dt)
27+
28+
- cm_params - CloudMicrophysics parameters struct for cloud water or ice condensate
29+
- thp - Thermodynamics parameters struct
30+
- ts - thermodynamics state
31+
- dt - model time step
32+
33+
Returns the condensation/evaporation or deposition/sublimation rate for
34+
non-equilibrium cloud formation.
35+
"""
36+
function cloud_sources(cm_params::CMP.CloudLiquid{FT}, thp, ts, dt) where {FT}
37+
38+
λ = TD.liquid_fraction(thp, Tₐ(thp, ts), TD.PhaseEquil)
39+
qᵥ_ex_liquid = λ * (qₜ(thp, ts) - TD.q_vap_saturation_liquid(thp, ts))
40+
41+
# Ideally the logic whether to apply this source term, and what relaxation
42+
# timescale to use, should be based on the availability of CCNs and INPs.
43+
# We need a 2-moment microphysics scheme for that.
44+
45+
# Additionally, to approximate the partitioning between the condensation/evaporation
46+
# and deposition/sublimation, we are scaling down the excess q by the liquid fraction.
47+
# This needs more thought.
48+
S = CMNe.conv_q_vap_to_q_liq_ice(
49+
cm_params,
50+
PP(FT(0), qᵥ_ex_liquid, FT(0)),
51+
PP(thp, ts),
52+
)
53+
return ifelse(
54+
S > FT(0),
55+
min(S, limit(qᵥ(thp, ts), dt, 2)),
56+
-min(abs(S), limit(qₗ(thp, ts), dt, 2)),
57+
)
58+
end
59+
function cloud_sources(cm_params::CMP.CloudIce{FT}, thp, ts, dt) where {FT}
60+
61+
λ = TD.liquid_fraction(thp, Tₐ(thp, ts), TD.PhaseEquil)
62+
qᵥ_ex_ice = (1 - λ) * (qₜ(thp, ts) - TD.q_vap_saturation_ice(thp, ts))
63+
64+
S = CMNe.conv_q_vap_to_q_liq_ice(
65+
cm_params,
66+
PP(FT(0), FT(0), qᵥ_ex_ice),
67+
PP(thp, ts),
68+
)
69+
return ifelse(
70+
S > FT(0),
71+
min(S, limit(qᵥ(thp, ts), dt, 2)),
72+
-min(abs(S), limit(qᵢ(thp, ts), dt, 2)),
73+
)
1974
end
2075

2176
"""
@@ -114,7 +169,7 @@ function compute_precipitation_sources!(
114169
#! format: off
115170
# rain autoconversion: q_liq -> q_rain
116171
@. Sᵖ = min(
117-
limit(qₗ(thp, ts), dt),
172+
limit(qₗ(thp, ts), dt, 5),
118173
CM1.conv_q_liq_to_q_rai(mp.pr.acnv1M, qₗ(thp, ts), true),
119174
)
120175
@. Sqₜᵖ -= Sᵖ
@@ -123,7 +178,7 @@ function compute_precipitation_sources!(
123178

124179
# snow autoconversion assuming no supersaturation: q_ice -> q_snow
125180
@. Sᵖ = min(
126-
limit(qᵢ(thp, ts), dt),
181+
limit(qᵢ(thp, ts), dt, 5),
127182
CM1.conv_q_ice_to_q_sno_no_supersat(mp.ps.acnv1M, qᵢ(thp, ts), true),
128183
)
129184
@. Sqₜᵖ -= Sᵖ
@@ -132,7 +187,7 @@ function compute_precipitation_sources!(
132187

133188
# accretion: q_liq + q_rain -> q_rain
134189
@. Sᵖ = min(
135-
limit(qₗ(thp, ts), dt),
190+
limit(qₗ(thp, ts), dt, 5),
136191
CM1.accretion(mp.cl, mp.pr, mp.tv.rain, mp.ce, qₗ(thp, ts), qᵣ, ρ),
137192
)
138193
@. Sqₜᵖ -= Sᵖ
@@ -141,7 +196,7 @@ function compute_precipitation_sources!(
141196

142197
# accretion: q_ice + q_snow -> q_snow
143198
@. Sᵖ = min(
144-
limit(qᵢ(thp, ts), dt),
199+
limit(qᵢ(thp, ts), dt, 5),
145200
CM1.accretion(mp.ci, mp.ps, mp.tv.snow, mp.ce, qᵢ(thp, ts), qₛ, ρ),
146201
)
147202
@. Sqₜᵖ -= Sᵖ
@@ -151,7 +206,7 @@ function compute_precipitation_sources!(
151206
# accretion: q_liq + q_sno -> q_sno or q_rai
152207
# sink of cloud water via accretion cloud water + snow
153208
@. Sᵖ = min(
154-
limit(qₗ(thp, ts), dt),
209+
limit(qₗ(thp, ts), dt, 5),
155210
CM1.accretion(mp.cl, mp.ps, mp.tv.snow, mp.ce, qₗ(thp, ts), qₛ, ρ),
156211
)
157212
# if T < T_freeze cloud droplets freeze to become snow
@@ -160,7 +215,7 @@ function compute_precipitation_sources!(
160215
@. Sᵖ_snow = ifelse(
161216
Tₐ(thp, ts) < mp.ps.T_freeze,
162217
Sᵖ,
163-
FT(-1) * min(Sᵖ * α(thp, ts), limit(qₛ, dt)),
218+
FT(-1) * min(Sᵖ * α(thp, ts), limit(qₛ, dt, 5)),
164219
)
165220
@. Sqₛᵖ += Sᵖ_snow
166221
@. Sqₜᵖ -= Sᵖ
@@ -173,15 +228,15 @@ function compute_precipitation_sources!(
173228

174229
# accretion: q_ice + q_rai -> q_sno
175230
@. Sᵖ = min(
176-
limit(qᵢ(thp, ts), dt),
231+
limit(qᵢ(thp, ts), dt, 5),
177232
CM1.accretion(mp.ci, mp.pr, mp.tv.rain, mp.ce, qᵢ(thp, ts), qᵣ, ρ),
178233
)
179234
@. Sqₜᵖ -= Sᵖ
180235
@. Sqₛᵖ += Sᵖ
181236
@. Seₜᵖ -= Sᵖ * (Iᵢ(thp, ts) + Φ)
182237
# sink of rain via accretion cloud ice - rain
183238
@. Sᵖ = min(
184-
limit(qᵣ, dt),
239+
limit(qᵣ, dt, 5),
185240
CM1.accretion_rain_sink(mp.pr, mp.ci, mp.tv.rain, mp.ce, qᵢ(thp, ts), qᵣ, ρ),
186241
)
187242
@. Sqᵣᵖ -= Sᵖ
@@ -192,11 +247,11 @@ function compute_precipitation_sources!(
192247
@. Sᵖ = ifelse(
193248
Tₐ(thp, ts) < mp.ps.T_freeze,
194249
min(
195-
limit(qᵣ, dt),
250+
limit(qᵣ, dt, 5),
196251
CM1.accretion_snow_rain(mp.ps, mp.pr, mp.tv.rain, mp.tv.snow, mp.ce, qₛ, qᵣ, ρ),
197252
),
198253
-min(
199-
limit(qₛ, dt),
254+
limit(qₛ, dt, 5),
200255
CM1.accretion_snow_rain(mp.pr, mp.ps, mp.tv.snow, mp.tv.rain, mp.ce, qᵣ, qₛ, ρ),
201256
),
202257
)
@@ -245,7 +300,7 @@ function compute_precipitation_sinks!(
245300
#! format: off
246301
# evaporation: q_rai -> q_vap
247302
@. Sᵖ = -min(
248-
limit(qᵣ, dt),
303+
limit(qᵣ, dt, 5),
249304
-CM1.evaporation_sublimation(rps..., PP(thp, ts), qᵣ, ρ, Tₐ(thp, ts)),
250305
)
251306
@. Sqₜᵖ -= Sᵖ
@@ -254,7 +309,7 @@ function compute_precipitation_sinks!(
254309

255310
# melting: q_sno -> q_rai
256311
@. Sᵖ = min(
257-
limit(qₛ, dt),
312+
limit(qₛ, dt, 5),
258313
CM1.snow_melt(sps..., qₛ, ρ, Tₐ(thp, ts)),
259314
)
260315
@. Sqᵣᵖ += Sᵖ
@@ -265,8 +320,8 @@ function compute_precipitation_sinks!(
265320
@. Sᵖ = CM1.evaporation_sublimation(sps..., PP(thp, ts), qₛ, ρ, Tₐ(thp, ts))
266321
@. Sᵖ = ifelse(
267322
Sᵖ > FT(0),
268-
min(limit(qᵥ(thp, ts), dt), Sᵖ),
269-
-min(limit(qₛ, dt), FT(-1) * Sᵖ),
323+
min(limit(qᵥ(thp, ts), dt, 5), Sᵖ),
324+
-min(limit(qₛ, dt, 5), FT(-1) * Sᵖ),
270325
)
271326
@. Sqₜᵖ -= Sᵖ
272327
@. Sqₛᵖ += Sᵖ

src/parameterized_tendencies/microphysics/precipitation.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function compute_precipitation_cache!(Y, p, colidx, ::Microphysics0Moment, _)
4545
(; ᶜts) = p.precomputed
4646
(; ᶜS_ρq_tot, ᶜS_ρe_tot) = p.precipitation
4747
(; ᶜΦ) = p.core
48-
cm_params = CAP.microphysics_params(params)
48+
cm_params = CAP.microphysics_precipitation_params(params)
4949
thermo_params = CAP.thermodynamics_params(params)
5050
@. ᶜS_ρq_tot[colidx] =
5151
Y.c.ρ[colidx] * q_tot_precipitation_sources(
@@ -215,7 +215,7 @@ function compute_precipitation_cache!(Y, p, colidx, ::Microphysics1Moment, _)
215215

216216
# get thermodynamics and 1-moment microphysics params
217217
(; params) = p
218-
cmp = CAP.microphysics_params(params)
218+
cmp = CAP.microphysics_precipitation_params(params)
219219
thp = CAP.thermodynamics_params(params)
220220

221221
# compute precipitation source terms on the grid mean
@@ -273,7 +273,7 @@ function compute_precipitation_cache!(
273273

274274
# get thermodynamics and 1-moment microphysics params
275275
(; params) = p
276-
cmp = CAP.microphysics_params(params)
276+
cmp = CAP.microphysics_precipitation_params(params)
277277
thp = CAP.thermodynamics_params(params)
278278

279279
# zero out the helper source terms

0 commit comments

Comments
 (0)