Skip to content

Commit ee61e90

Browse files
authored
Modify supersaturation equation to include preexisting droplets; update alpha and gamma per Korolev & Mazin; update parcel example and docs (#615)
1 parent 15ddc71 commit ee61e90

14 files changed

+475
-41
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "CloudMicrophysics"
22
uuid = "6a9e3e04-43cd-43ba-94b9-e8782df3c71b"
33
authors = ["Climate Modeling Alliance"]
4-
version = "0.26.0"
4+
version = "0.26.1"
55

66
[deps]
77
ClimaParams = "5c42b081-d73a-476f-9059-fd94b934656c"

docs/src/AerosolActivation.md

Lines changed: 113 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,9 @@ where:
140140

141141
## Maximum Supersaturation
142142

143-
Maximum supersaturation reached by the system ``S_{max}`` governs
144-
what aerosol sizes are activated and what aren't.
145-
We estimate ``S_{max}`` by considering a parcel of air raising adiabatically
146-
with a constant velocity, see for example [Rogers1975](@cite).
147-
The time rate of change of ``S`` is given by eq (10) in [Rogers1975](@cite)
143+
Maximum supersaturation reached by the system ``S_{max}`` governs what aerosol sizes are activated and what aren't.
144+
We estimate ``S_{max}`` by considering a parcel of air raising adiabatically with a constant velocity, see for example [KorolevMazin2003](@cite).
145+
The time rate of change of ``S`` is given by eq (A11) in [KorolevMazin2003](@cite)
148146

149147
```math
150148
\begin{equation}
@@ -157,25 +155,24 @@ where:
157155
- ``d\chi / dt`` is the water condensation rate during aerosol activation and growth,
158156
- ``\alpha`` and ``\gamma`` are coefficients that do not depend on aerosol properties.
159157

160-
The parameters ``\alpha`` and ``\gamma`` are defined by eq. (11) and (12)
161-
in [Abdul-Razzaketal1998](@cite) .
162-
Here, they are implemented following the [Rogers1975](@cite) eq. (10):
158+
The parameters ``\alpha`` and ``\gamma`` are defined similarly to eq. (11) and (12) in [Abdul-Razzaketal1998](@cite), but we follow the full formulation from [KorolevMazin2003](@cite) eq. (A11), without assuming ``S + 1 ≈ 1``. While the difference is often small, we retain the full expressions for completeness and consistency with our implementation. The parameters are:
163159
```math
164160
\begin{equation}
165-
\alpha = \frac{L_v \, g \, \epsilon}{R_m \, c_{pm} \, T^2} - \frac{g}{R_m \, T}
161+
\alpha = \frac{p_{vap}}{p_{vap}^{sat}}\left[\frac{L_v \, g}{R_v \, c_{pm} \, T^2} - \frac{g}{R_m \, T}\right]
166162
\end{equation}
167163
```
168164
```math
169165
\begin{equation}
170-
\gamma = \frac{R_m T}{\epsilon \, p_{vap}^{sat}} + \frac{\epsilon \, L_v^2}{c_{pm} \, T \, p}
166+
\gamma = \frac{R_v T}{p_{vap}^{sat}} + \frac{p_{vap}}{p_{vap}^{sat}}\frac{R_m \, L_v^2}{R_v \, c_{pm} \, T \, p}
171167
\end{equation}
172168
```
173169
where:
174170
- ``L_v`` is the latent heat of vaporization,
175171
- ``g`` is gravitational acceleration,
176-
- ``\epsilon`` is the ratio of water molar mass to dry air molar mass,
172+
- ``R_v`` is the gas constant of vapor,
177173
- ``R_m`` is the gas constant of air (dry air and moisture)
178174
- ``c_{pm}`` is the specific heat of air (dry air and moisture),
175+
- ``p_{vap}`` is the vapor pressure,
179176
- ``p_{vap}^{sat}`` is the saturation vapor pressure,
180177
- ``p`` is the total air pressure.
181178

@@ -285,3 +282,108 @@ The CloudMicrophysics package offers an advanced feature for predicting the aero
285282
In addition, we provide functionality and a demonstration for re-training the free parameters of the traditional ARG activation scheme using Ensemble Kalman Processes. This functionality is showcased in `test/aerosol_activation_calibration.jl`.
286283

287284
Using ML emulators or calibration with Ensemble Kalman Processes for predicting aerosol activation is provided through an extension to the main package. This extension will be loaded with `CloudMicrophysics.jl` if both `MLJ.jl`, `DataFrames.jl`, and `EnsembleKalmanProcesses.jl` are loaded by the user as well.
285+
286+
## Modification for Local Supersaturation with Preexisting Hydrometeors
287+
288+
The original ARG activation scheme assumes adiabatic ascent with no preexisting cloud or ice particles, which is a valid approximation near cloud base. As a result, the ARG formulation is traditionally applied only at cloud base, where no vapor has yet condensed and no hydrometeors exist to affect the supersaturation evolution.
289+
290+
However, in many applications—such as large-eddy simulations or cloud-resolving models—it is desirable to apply the activation scheme locally, throughout the vertical extent of the cloud. In such cases, preexisting cloud droplets and ice crystals act as persistent vapor sinks, suppressing supersaturation and inhibiting further activation.
291+
292+
To relax the cloud-base-only constraint and extend ARG into a local operator, we propose modifying the supersaturation tendency equation by incorporating the effects of these preexisting hydrometeors.
293+
When coupling this approach to a full model, additional clipping may be needed: the modified ARG should only be applied when the local supersaturation does not exceed the predicted maximum, and when the number concentration of hydrometeors remains below the potential activation of aerosols.
294+
295+
296+
### Modified Supersaturation Budget
297+
298+
We modify the supersaturation tendency equation to include additional vapor sink terms:
299+
300+
```math
301+
\frac{dS}{dt} = \alpha w - \gamma \frac{d\chi}{dt}_{\text{activation}} - \gamma \frac{d\chi}{dt}_{\text{liquid}} - \gamma_i \frac{d\chi}{dt}_{\text{ice}},
302+
```
303+
304+
where the thermodynamic coefficient ``\gamma_i`` is defined as
305+
```math
306+
\begin{equation}
307+
\gamma_i = \frac{R_v T}{p_{vap}^{sat}} + \frac{p_{vap}}{p_{vap}^{sat}}\frac{R_m \, L_v L_s}{R_v \, c_{pm} \, T \, p}
308+
\end{equation}
309+
```
310+
where ``L_s`` is the latent heat of sublimation. The new sink terms are:
311+
312+
- Liquid sink:
313+
```math
314+
\frac{d\chi}{dt}_{\text{liquid}} = 4 \pi \rho_w N_l r_l G_l S,
315+
```
316+
317+
- Ice sink:
318+
```math
319+
\frac{d\chi}{dt}_{\text{ice}} = 4 \pi \rho_i N_i r_i G_i S_i,
320+
```
321+
322+
with
323+
```math
324+
S_i = \xi (S + 1) - 1, \quad \xi = \frac{e_{s,\ell}}{e_{s,i}}.
325+
```
326+
327+
Here:
328+
329+
- ``N_l``, ``r_l``, and ``G_l`` are the number concentration, radius, and condensational growth coefficient of liquid droplets,
330+
- ``N_i``, ``r_i``, and ``G_i`` are the corresponding values for ice crystals,
331+
- ``\rho_w`` and ``\rho_i`` are the densities of liquid water and ice.
332+
333+
We define:
334+
```math
335+
K_l = 4 \pi \rho_w N_l r_l G_l \gamma, \quad K_i = 4 \pi \rho_i N_i r_i G_i \gamma_i,
336+
```
337+
338+
yielding the modified supersaturation equation at peak supersaturation:
339+
```math
340+
0 = \alpha w - \gamma f(S_{max}) - K_l S_{max} - K_i \big[ \xi (S_{max} + 1) - 1 \big].
341+
```
342+
343+
### Approximate Solution
344+
345+
Let ``S_0`` be the ARG solution obtained by solving:
346+
```math
347+
\alpha w = \gamma f(S_0),
348+
```
349+
and approximate the nonlinear sink function ``f(S)`` as linear between 0 and ``S_0``:
350+
```math
351+
f(S) \approx f(S_0) \cdot \frac{S}{S_0}.
352+
```
353+
354+
Substituting into the modified budget and solving for ``S_1``:
355+
```math
356+
\alpha w = \gamma f(S_0) \cdot \frac{S_1}{S_0} + K_l S_1 + K_i \big[\xi (S_1 + 1) - 1 \big],
357+
```
358+
yields:
359+
```math
360+
S_1 = \frac{(\alpha w - K_i (\xi - 1)) S_0}{\alpha w + (K_l + K_i \xi) S_0}.
361+
```
362+
363+
The final expression for the modified supersaturation becomes:
364+
```math
365+
S_{\text{max}}^{\text{modified}} = \frac{(\alpha w - K_i (\xi - 1)) S_{\text{max}}^{\text{ARG}}}{\alpha w + (K_l + K_i \xi) S_{\text{max}}^{\text{ARG}}}.
366+
```
367+
368+
- When ``K_l = K_i = 0``, the formula reduces to the original ARG solution.
369+
- Larger values of $K_l$ or $K_i$ reduce the supersaturation due to vapor uptake by preexisting hydrometeors.
370+
- This extension allows the ARG activation scheme to be applied at any vertical level, making it suitable for use as a local operator in models that resolve cloud-scale dynamics.
371+
372+
### Example
373+
374+
To illustrate the behavior of the modified ARG scheme, we compare the maximum supersaturation it predicts against that from a detailed parcel model in four idealized scenarios:
375+
376+
- Varying the liquid droplet number concentration with no ice particles present,
377+
- Varying the ice crystal number concentration with no liquid droplets present,
378+
- Varying the initial droplet radius with no ice particles present,
379+
- Varying the initial ice particle radius with no liquid droplets present.
380+
381+
In all cases, the parcel model assumes an initial zero supersaturation and includes activation, condensational growth, and depositional growth during adiabatic ascent. A background population of sulfate aerosol with an initial concentration of 500 cm⁻³ is present in all scenarios. For simplicity, ice particles are assumed to be monodisperse. Liquid droplets formed through activation and those present initially are represented as two separate monodisperse populations.
382+
383+
The figure below shows the ratio of the maximum supersaturation reached in the parcel model to that predicted by the modified ARG scheme. This comparison highlights the conditions under which the modified ARG provides a good approximation to the more detailed parcel-model results.
384+
385+
```@example
386+
include("plots/ARGmodified_plots.jl")
387+
```
388+
![](parcel_vs_modifiedARG_aerosol_activation.svg)
389+

docs/src/IceNucleationParcel0D.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,7 @@ The crux of the problem is modeling the ``\frac{dq_l}{dt}`` and ``\frac{dq_i}{dt
122122
for different homogeneous and heterogeneous ice nucleation paths.
123123

124124
## Supported size distributions
125-
Currently the parcel model supports monodisperse and gamma size distributions of cloud droplets and ice crystals,
126-
and solves prognostic equations for the cloud water and cloud ice specific contents
127-
``q_l``, ``q_i`` and number concentrations ``N_l``, ``N_i``.
125+
Currently, the parcel model supports monodisperse and gamma size distributions of cloud droplets and ice crystals, and solves prognostic equations for the cloud water and cloud ice specific contents (`q_l`, `q_i`) and number concentrations (`N_l`, `N_i`). Additionally, a `monodisperseMix` option is now supported for cloud liquid droplets. This allows representing the droplet population as a mixture of two monodisperse modes: one corresponding to an initial set of preexisting droplets, and the other representing droplets formed through activation during the simulation. This feature enables more realistic treatment of scenarios involving preexisting hydrometeors.
128126

129127
For a monodisperse size distribution of cloud droplets or ice crystals
130128
```math
@@ -167,15 +165,10 @@ As a result
167165
## Supported source terms
168166
### Aerosol Activation
169167
Aerosol activation is described by ([see discussion](https://clima.github.io/CloudMicrophysics.jl/dev/AerosolActivation/#Number-and-mass-of-activated-particles)).
170-
It is inherently assumed that the aerosols have a lognormal size distribution.
171-
For simplicity, the parcel accepts one mode and one aerosol type at a time, therefore,
172-
internal mixing is not needed. The maxiumum supersaturation as described in the above
173-
mentioned documentation is replaced by the liquid supersaturation in the parcel as
174-
it evolves over time.
168+
It is inherently assumed that the aerosols have a lognormal size distribution. For simplicity, the parcel accepts one mode and one aerosol type at a time, therefore, internal mixing is not needed. The maxiumum supersaturation as described in the above mentioned documentation is replaced by the liquid supersaturation in the parcel as it evolves over time.
175169

176170
!!! note
177-
Standard deviation and r_{mean} of the aerosol size distribution may change as aerosols activate.
178-
For now, we will neglect these effects.
171+
The standard deviation and $r_{\text{mean}}$ of the aerosol size distribution represent the initial (pre-activation) aerosol population and are assumed to remain fixed throughout the simulation. They do not evolve as aerosols activate.
179172

180173
### Condensation growth
181174

docs/src/plots/ARGmodified_plots.jl

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import OrdinaryDiffEq as ODE
2+
import CairoMakie as MK
3+
4+
import ClimaParams as CP
5+
import CloudMicrophysics as CM
6+
import CloudMicrophysics.Parameters as CMP
7+
import CloudMicrophysics.ThermodynamicsInterface as TDI
8+
9+
# definition of the ODE problem for parcel model
10+
include(joinpath(pkgdir(CM), "parcel", "Parcel.jl"))
11+
12+
function run_parcel_model(Nₐ, Nₗ, Nᵢ, rₗ, rᵢ, w, FT)
13+
14+
# Get free parameters
15+
tps = TDI.TD.Parameters.ThermodynamicsParameters(FT)
16+
wps = CMP.WaterProperties(FT)
17+
18+
# Initial conditions
19+
T₀ = FT(230)
20+
cᵥ₀ = FT(5 * 1e-5)
21+
ln_INPC = FT(0)
22+
23+
# Constants
24+
ρₗ = wps.ρw
25+
ρᵢ = wps.ρi
26+
ϵₘ = TDI.Rd_over_Rv(tps)
27+
eₛ = TDI.saturation_vapor_pressure_over_liquid(tps, T₀)
28+
qᵥ = ϵₘ / (ϵₘ - 1 + 1 / cᵥ₀)
29+
Sₗ = FT(1.0)
30+
e = Sₗ * eₛ
31+
p₀ = e / cᵥ₀
32+
ρ_air = TDI.air_density(tps, T₀, p₀, qᵥ, FT(0), FT(0))
33+
qₗ = Nₗ * FT(4 / 3 * π) * (rₗ)^3 * ρₗ / ρ_air
34+
qᵢ = Nᵢ * FT(4 / 3 * π) * (rᵢ)^3 * ρᵢ / ρ_air
35+
IC = [Sₗ, p₀, T₀, qᵥ, qₗ, qᵢ, Nₐ, Nₗ, Nᵢ, ln_INPC, qₗ, Nₗ]
36+
37+
# Simulation parameters passed into ODE solver
38+
const_dt = FT(1e-2) # model timestep
39+
t_max = FT(60) # total time
40+
aerosol = CMP.Sulfate(FT)
41+
42+
condensation_growth = "Condensation"
43+
deposition_growth = "Deposition"
44+
aerosol_act = "AeroAct" # turn on aerosol activation
45+
aero_σ_g = FT(2.3)
46+
r_nuc = FT(4e-8)
47+
48+
params = parcel_params{FT}(
49+
w = w,
50+
const_dt = const_dt,
51+
aerosol_act = aerosol_act,
52+
aerosol = aerosol,
53+
aero_σ_g = aero_σ_g,
54+
r_nuc = r_nuc,
55+
condensation_growth = condensation_growth,
56+
deposition_growth = deposition_growth,
57+
Nₐ = Nₐ,
58+
liq_size_distribution = "MonodisperseMix",
59+
)
60+
61+
# solve ODE
62+
sol = run_parcel(IC, FT(0), t_max, params)
63+
64+
S_max = maximum(sol[1, :]) - FT(1)
65+
66+
# ARG results
67+
ad = AM.Mode_κ(
68+
params.r_nuc,
69+
params.aero_σ_g,
70+
params.Nₐ,
71+
(FT(1.0),),
72+
(FT(1.0),),
73+
(params.aerosol.M,),
74+
(params.aerosol.κ,),
75+
)
76+
all_ad = AM.AerosolDistribution((ad,))
77+
S_max_ARG = AA.max_supersaturation(params.aap, all_ad, params.aps, params.tps, T₀, p₀, w, qᵥ + qₗ + qᵢ, qₗ, qᵢ)
78+
S_max_mod =
79+
AA.max_supersaturation(params.aap, all_ad, params.aps, params.tps, T₀, p₀, w, qᵥ + qₗ + qᵢ, qₗ, qᵢ, Nₗ, Nᵢ)
80+
81+
return S_max / S_max_ARG, S_max_mod / S_max_ARG
82+
end
83+
84+
85+
FT = Float32
86+
Nₐ = FT(5e8)
87+
Nₗ = FT(1e8)
88+
Nᵢ = FT(1e6)
89+
rₗ = FT(20e-6)
90+
rᵢ = FT(20e-6)
91+
w = FT(1.2) # updraft speed
92+
93+
n_points = 10
94+
Nₗ_range = range(FT(0), stop = FT(1e8), length = n_points)
95+
Nᵢ_range = range(FT(0), stop = FT(1e6), length = n_points)
96+
rₗ_range = range(FT(0e-6), stop = FT(25e-6), length = n_points)
97+
rᵢ_range = range(FT(0e-6), stop = FT(25e-6), length = n_points)
98+
99+
S_max_parcel_Nₗ = zeros(n_points)
100+
S_max_ARGmod_Nₗ = zeros(n_points)
101+
S_max_parcel_Nᵢ = zeros(n_points)
102+
S_max_ARGmod_Nᵢ = zeros(n_points)
103+
S_max_parcel_rₗ = zeros(n_points)
104+
S_max_ARGmod_rₗ = zeros(n_points)
105+
S_max_parcel_rᵢ = zeros(n_points)
106+
S_max_ARGmod_rᵢ = zeros(n_points)
107+
for i in 1:n_points
108+
S_max_parcel_Nₗ[i], S_max_ARGmod_Nₗ[i] = run_parcel_model.(Nₐ, Nₗ_range[i], FT(0), rₗ, rᵢ, w, FT)
109+
S_max_parcel_Nᵢ[i], S_max_ARGmod_Nᵢ[i] = run_parcel_model.(Nₐ, FT(0), Nᵢ_range[i], rₗ, rᵢ, w, FT)
110+
S_max_parcel_rₗ[i], S_max_ARGmod_rₗ[i] = run_parcel_model.(Nₐ, Nₗ, FT(0), rₗ_range[i], rᵢ, w, FT)
111+
S_max_parcel_rᵢ[i], S_max_ARGmod_rᵢ[i] = run_parcel_model.(Nₐ, FT(0), Nᵢ, rₗ, rᵢ_range[i], w, FT)
112+
end
113+
114+
# Plot results
115+
fig = MK.Figure(size = (800, 600), fontsize = 20)
116+
ax1 = MK.Axis(fig[1, 1], ylabel = "S_max / S_max_ARG", xlabel = "Nₗ [cm⁻³]", title = "No ice particle, rₗ=20 μm")
117+
ax2 = MK.Axis(fig[1, 2], ylabel = "S_max / S_max_ARG", xlabel = "Nᵢ [cm⁻³]", title = "No liquid droplets, rᵢ=20 μm")
118+
ax3 = MK.Axis(fig[2, 1], ylabel = "S_max / S_max_ARG", xlabel = "rₗ [μm]", title = "No ice particle, Nₗ=100 cm⁻³")
119+
ax4 = MK.Axis(fig[2, 2], ylabel = "S_max / S_max_ARG", xlabel = "rᵢ [μm]", title = "No liquid droplets, Nᵢ=1 cm⁻³")
120+
121+
MK.lines!(ax1, Nₗ_range * 1e-6, S_max_parcel_Nₗ, label = "Parcel", linewidth = 2, color = :blue)
122+
MK.lines!(ax1, Nₗ_range * 1e-6, S_max_ARGmod_Nₗ, label = "Modified ARG", linewidth = 2, color = :red)
123+
MK.lines!(ax2, Nᵢ_range * 1e-6, S_max_parcel_Nᵢ, label = "Parcel", linewidth = 2, color = :blue)
124+
MK.lines!(ax2, Nᵢ_range * 1e-6, S_max_ARGmod_Nᵢ, label = "Modified ARG", linewidth = 2, color = :red)
125+
MK.lines!(ax3, rₗ_range * 1e6, S_max_parcel_rₗ, label = "Parcel", linewidth = 2, color = :blue)
126+
MK.lines!(ax3, rₗ_range * 1e6, S_max_ARGmod_rₗ, label = "Modified ARG", linewidth = 2, color = :red)
127+
MK.lines!(ax4, rᵢ_range * 1e6, S_max_parcel_rᵢ, label = "Parcel", linewidth = 2, color = :blue)
128+
MK.lines!(ax4, rᵢ_range * 1e6, S_max_ARGmod_rᵢ, label = "Modified ARG", linewidth = 2, color = :red)
129+
130+
MK.ylims!(ax1, -0.05, 1.1)
131+
MK.ylims!(ax3, -0.05, 1.1)
132+
MK.axislegend(ax1, framevisible = false, labelsize = 16, position = :rc)
133+
MK.axislegend(ax2, framevisible = false, labelsize = 16, position = :rc)
134+
MK.axislegend(ax3, framevisible = false, labelsize = 16, position = :rc)
135+
MK.axislegend(ax4, framevisible = false, labelsize = 16, position = :rc)
136+
137+
MK.save("parcel_vs_modifiedARG_aerosol_activation.svg", fig)

papers/ice_nucleation_2024/calibration_setup.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ function perf_model_IC(FT, IN_mode)
135135
e = eᵥ(qᵥ, p₀, Rₐ, R_v)
136136
Sₗ = FT(e / eₛ)
137137
end
138-
return [Sₗ, p₀, T₀, qᵥ, qₗ, qᵢ, Nₐ, Nₗ, Nᵢ, FT(0)]
138+
return [Sₗ, p₀, T₀, qᵥ, qₗ, qᵢ, Nₐ, Nₗ, Nᵢ, FT(0), FT(0)]
139139
end
140140

141141
function perf_model_pseudo_data(FT, IN_mode, params, IC)

parcel/Example_AerosolActivation.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ params = parcel_params{FT}(
5858
aero_σ_g = aero_σ_g,
5959
r_nuc = r_nuc,
6060
condensation_growth = condensation_growth,
61+
Nₐ = Nₐ,
6162
)
6263

6364
# solve ODE

parcel/ParcelCommon.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,13 @@ function AIDA_rate(model_t, data_t, data)
2121
return 0
2222
end
2323
end
24+
25+
# Return activated particle radius. See below eq. 19 in [Abdul-Razzaketal1998](@cite)
26+
function get_particle_activation_radius(
27+
ap::CMP.AerosolActivationParameters,
28+
T::FT,
29+
S::FT,
30+
) where {FT}
31+
A::FT = AA.coeff_of_curvature(ap, T)
32+
return FT(2 / 3) * A / S
33+
end

0 commit comments

Comments
 (0)