Skip to content

Commit 52dac3d

Browse files
committed
add P3 collisions sub-parameterizations
* dry freeze rate, from Musil (1970) * local rime density, from Cober and List (1993)
1 parent 2c2d29e commit 52dac3d

File tree

4 files changed

+226
-0
lines changed

4 files changed

+226
-0
lines changed

docs/bibliography.bib

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,19 @@ @article{Choletteetal2019
141141
pages= {561--582}
142142
}
143143

144+
145+
@article{CoberList1993,
146+
title = {Measurements of the Heat and Mass Transfer Parameters Characterizing Conical Graupel Growth},
147+
volume = {50},
148+
doi = {10.1175/1520-0469(1993)050<1591:MOTHAM>2.0.CO;2},
149+
pages = {1591--1609},
150+
number = {11},
151+
journal = {Journal of the Atmospheric Sciences},
152+
author = {Cober, Stewart G. and List, Roland},
153+
year = {1993},
154+
}
155+
156+
144157
@article{Desai2019,
145158
title = {Aerosol-Mediated Glaciation of Mixed-Phase Clouds: Steady-State Laboratory Measurements},
146159
author = {Desai, Neel and Chandrakar, KK and Kinney, G and Cantrell, W and Shaw, RA},
@@ -549,6 +562,19 @@ @article{Murray2012
549562
doi = {10.1039/C2CS35200A}
550563
}
551564

565+
566+
@article{Musil1970,
567+
title = {Computer Modeling of Hailstone Growth in Feeder Clouds},
568+
volume = {27},
569+
doi = {10.1175/1520-0469(1970)027<0474:CMOHGI>2.0.CO;2},
570+
pages = {474--482},
571+
number = {3},
572+
journal = {Journal of the Atmospheric Sciences},
573+
author = {Musil, Dennis J.},
574+
year = {1970},
575+
}
576+
577+
552578
@article{Ogura1971,
553579
title = {Numerical simulation of the life cycle of a thunderstorm cell},
554580
author = {Ogura, Yoshimitsu and Takahashi, Tsutomu},

docs/src/API.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,27 @@ P3Scheme.D_m
167167
P3Scheme.ice_particle_terminal_velocity
168168
P3Scheme.ice_terminal_velocity_number_weighted
169169
P3Scheme.ice_terminal_velocity_mass_weighted
170+
```
171+
172+
### Processes
173+
174+
#### Heterogeneous ice nucleation
175+
```@docs
170176
P3Scheme.het_ice_nucleation
177+
```
178+
179+
#### Ice melting
180+
```@docs
171181
P3Scheme.ice_melt
172182
```
173183

184+
#### Collisions with liquid droplets
185+
Supporting methods:
186+
```@docs
187+
P3Scheme.compute_max_freeze_rate
188+
P3Scheme.compute_local_rime_density
189+
```
190+
174191
### Supporting integral methods
175192

176193
```@docs

src/P3_processes.jl

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,131 @@ function ice_melt(
9999
dLdt = min(dLdt, L_ice / dt)
100100
return (; dNdt, dLdt)
101101
end
102+
103+
"""
104+
compute_max_freeze_rate(state, aps, tps, velocity_params, ρₐ, Tₐ)
105+
106+
Returns a function `max_freeze_rate(Dᵢ)` that returns the maximum possible freezing rate [kg/s]
107+
for an ice particle of diameter `Dᵢ` [m]. Evaluates to 0 if T ≥ T_freeze.
108+
109+
# Arguments
110+
- `state`: [`P3State`](@ref)
111+
- `aps`: [`CMP.AirProperties`](@ref)
112+
- `tps`: `TDP.ThermodynamicsParameters`
113+
- `velocity_params`: The velocity parameterization, e.g. [`CMP.Chen2022VelType`](@ref)
114+
- `ρₐ`: air density [kg/m³]
115+
- `Tₐ`: air temperature [K]
116+
117+
This rate represents the thermodynamic upper limit to collisional freezing,
118+
which occurs when the heat transfer from the ice particle to the environment is
119+
balanced by the latent heat of fusion.
120+
121+
From Eq (A7) in Musil (1970), [Musil1970](@cite).
122+
"""
123+
function compute_max_freeze_rate(state, aps, tps, velocity_params, ρₐ, Tₐ)
124+
(; D_vapor, K_therm) = aps
125+
cp_l = TDP.cp_l(tps)
126+
T_frz = TDP.T_freeze(tps)
127+
Lᵥ = TD.latent_heat_vapor(tps, Tₐ)
128+
L_f = TD.latent_heat_fusion(tps, Tₐ)
129+
Tₛ = T_frz # the surface of the ice particle is assumed to be at the freezing temperature
130+
ΔT = Tₛ - Tₐ # temperature difference between the surface of the ice particle and the air
131+
Δρᵥ_sat =
132+
ρₐ * ( # saturation vapor density difference between the surface of the ice particle and the air
133+
TD.q_vap_saturation(tps, Tₛ, ρₐ, TD.PhaseNonEquil) -
134+
TD.q_vap_saturation(tps, Tₐ, ρₐ, TD.PhaseNonEquil)
135+
)
136+
v_term = ice_particle_terminal_velocity(state, velocity_params, ρₐ)
137+
F_v = CO.ventilation_factor(state.params.vent, aps, v_term)
138+
function max_freeze_rate(Dᵢ)
139+
Tₐ T_frz && return zero(Dᵢ) # No collisional freezing above the freezing temperature
140+
return 2 ** Dᵢ) * F_v(Dᵢ) * (K_therm * ΔT + Lᵥ * D_vapor * Δρᵥ_sat) / (L_f - cp_l * ΔT)
141+
end
142+
return max_freeze_rate
143+
end
144+
145+
"""
146+
compute_local_rime_density(state, velocity_params, ρₐ, T)
147+
148+
Provides a function `ρ′ᵣ(Dᵢ, Dₗ)` that computes the local rime density [kg/m³]
149+
for a given ice particle diameter `Dᵢ` [m] and liquid particle diameter `Dₗ` [m].
150+
151+
From Cober and List (1993).
152+
153+
# Arguments
154+
- `state`: a [`P3State`](@ref) object
155+
- `velocity_params`: The velocity parameterization, e.g. [`CMP.Chen2022VelType`](@ref)
156+
- `ρₐ`: air density [kg/m³]
157+
- `T`: temperature [K]
158+
159+
# Returns
160+
A function that computes the local rime density [kg/m³] using the equation:
161+
162+
```math
163+
ρ′_r = 51 + 114 R_i - 5.5 R_i^2
164+
```
165+
where
166+
```math
167+
R_i = ( D_{liq} ⋅ |v_{liq} - v_{ice}| ) / ( 2 T_{sfc} )
168+
```
169+
and ``T_{sfc}`` is the surface temperature [°C], ``D_{liq}`` is the liquid particle
170+
diameter [m], ``v_{liq/ice}`` is the particle terminal velocity [m/s].
171+
So the units of ``R_i`` are [m² s⁻¹ °C⁻¹]. The units of ``ρ′_r`` are [kg/m³].
172+
173+
They assume for simplicity that `T_sfc` equals `T`, the ambient air temperature.
174+
For real graupel, `T_sfc` is slightly higher than `T` due to latent heat release
175+
of freezing liquid particles onto the ice particle. MM13 found little sensitivity
176+
to "realistic" increases in `T_sfc`.
177+
178+
Implementation follows Cober and List (1993), Eq. 16 and 17.
179+
See also the P3 fortran code, microphy_p3.f90, Line 3315-3323,
180+
which extends the range of the calculation to Rᵢ ≤ 12, the upper limit of which
181+
then equals the solid bulk ice density, ``ρ^⭒ = 900 kg/m^3``.
182+
183+
Note that MM15 only uses this parameterization for collisions with cloud droplets.
184+
For rain drops, they use the solid bulk ice density, ``ρ^* = 900 kg/m^3``.
185+
We do not consider this distinction, and use this parameterization for all liquid particles.
186+
"""
187+
function compute_local_rime_density(state, velocity_params, ρₐ, T)
188+
(; T_freeze) = state.params
189+
T°C = T - T_freeze # Convert to °C
190+
191+
v_ice = ice_particle_terminal_velocity(state, velocity_params, ρₐ)
192+
v_liq = CO.particle_terminal_velocity(velocity_params.rain, ρₐ)
193+
function ρ′ᵣ(Dᵢ, Dₗ)
194+
v_term = abs(v_ice(Dᵢ) - v_liq(Dₗ))
195+
Rᵢ = (Dₗ * v_term) / (2 * T°C) # Eq. 16 in Cober and List (1993). Note: no `-` due to absolute value in v_term
196+
return ρ′ᵣ_P3(Rᵢ)
197+
end
198+
return ρ′ᵣ
199+
end
200+
201+
"""
202+
ρ′ᵣ_P3(Rᵢ)
203+
204+
Returns the local rime density [kg/m³] for a given Rᵢ [m² s⁻¹ °C⁻¹].
205+
206+
Based on Cober and List (1993), Eq. 16 and 17 (valid for 1 ≤ Rᵢ ≤ 8).
207+
For 8 < Rᵢ ≤ 12, linearly interpolate between ρ′ᵣ(8) ≡ 611 kg/m³ and ρ⭒ = 900 kg/m³.
208+
See also the P3 fortran code
209+
"""
210+
function ρ′ᵣ_P3(Rᵢ)
211+
# TODO: Externalize these parameters
212+
a, b, c = 51, 114, -11 // 2 # coeffs for Eq. 17 in Cober and List (1993), converted to [kg / m³]
213+
ρ⭒ = 900 # ρ^⭒: density of solid bulk ice
214+
215+
Rᵢ = clamp(Rᵢ, 1, 12) # P3 fortran code, microphy_p3.f90, Line 3315 clamps to 1 ≤ Rᵢ ≤ 12
216+
217+
ρ′ᵣ_CL93(Rᵢ) = a + b * Rᵢ + c * Rᵢ^2 # Eq. 17 in Cober and List (1993), in [kg / m³], valid for 1 ≤ Rᵢ ≤ 8
218+
ρ′ᵣ = if Rᵢ 8
219+
ρ′ᵣ_CL93(Rᵢ)
220+
else
221+
# following P3 fortran code, microphy_p3.f90, Line 3323
222+
# https://github.com/P3-microphysics/P3-microphysics/blob/main/src/microphy_p3.f90#L3323
223+
# for 8 < Rᵢ ≤ 12, linearly interpolate between ρ′ᵣ(8) ≡ 611 kg/m³ and ρ⭒ = 900 kg/m³
224+
ρ′ᵣ8 = ρ′ᵣ_CL93(8)
225+
f_ρ⭒ = (Rᵢ - 8) / (12 - 8)
226+
(1 - f_ρ⭒) * ρ′ᵣ8 + f_ρ⭒ * ρ⭒ # Linear interpolation beyond 8.
227+
end
228+
return float(ρ′ᵣ)
229+
end

test/p3_tests.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,58 @@ function test_p3_melting(FT)
561561
end
562562
end
563563

564+
function test_p3_bulk_liquid_ice_collisions(FT)
565+
params = CMP.ParametersP3(FT)
566+
vel_params = CMP.Chen2022VelType(FT)
567+
aps = CMP.AirProperties(FT)
568+
tps = TD.Parameters.ThermodynamicsParameters(FT)
569+
570+
(; T_freeze) = params
571+
572+
ρₐ = FT(1.2)
573+
qᵢ = FT(1e-4)
574+
Lᵢ = qᵢ * ρₐ
575+
Nᵢ = FT(2e5) * ρₐ
576+
F_rim = FT(0.8)
577+
ρ_rim = FT(800)
578+
579+
state = P3.get_state(params; F_rim, ρ_rim, L_ice = Lᵢ, N_ice = Nᵢ)
580+
logλ = P3.get_distribution_logλ(state)
581+
= exp(-logλ)
582+
583+
@testset "maximum dry freezing rate" begin
584+
# Below freezing, max freeze rate is non-zero (check against reference value)
585+
Tₐ = T_freeze - 1 // 10
586+
max_rate = P3.compute_max_freeze_rate(state, aps, tps, vel_params, ρₐ, Tₐ)
587+
@test max_rate(D̄) FT(8.819134467143614e-13) rtol = 1e-4
588+
589+
# At freezing, max freeze rate is zero
590+
Tₐ = T_freeze
591+
max_rate = P3.compute_max_freeze_rate(state, aps, tps, vel_params, ρₐ, Tₐ)
592+
@test iszero(max_rate(D̄))
593+
594+
# Above freezing, max freeze rate is zero
595+
Tₐ = T_freeze + 1 // 10
596+
max_rate = P3.compute_max_freeze_rate(state, aps, tps, vel_params, ρₐ, Tₐ)
597+
@test iszero(max_rate(D̄))
598+
end
599+
600+
@testset "local rime density" begin
601+
Tₐ = T_freeze - 1 // 10
602+
ρ′ᵣ = P3.compute_local_rime_density(state, vel_params, ρₐ, Tₐ)
603+
@test ρ′ᵣ(D̄, D̄) FT(159.5) rtol = 1e-6
604+
605+
a, b, c = 51, 114, -11 // 2 # coeffs for Eq. 17 in Cober and List (1993), converted to [kg / m³]
606+
ρ′ᵣ_CL93(Rᵢ) = a + b * Rᵢ + c * Rᵢ^2 # Eq. 17 in Cober and List (1993), in [kg / m³], valid for 1 ≤ Rᵢ ≤ 8
607+
ρ⭒ = FT(900) # ρ^⭒: density of solid bulk ice
608+
609+
@test P3.ρ′ᵣ_P3(FT(1)) == ρ′ᵣ_CL93(FT(1))
610+
@test P3.ρ′ᵣ_P3(FT(8)) == ρ′ᵣ_CL93(FT(8))
611+
@test P3.ρ′ᵣ_P3(FT(12)) == ρ⭒
612+
end
613+
614+
end
615+
564616

565617
for FT in [Float32, Float64]
566618
@info("Testing " * string(FT))
@@ -580,4 +632,7 @@ for FT in [Float32, Float64]
580632
# processes
581633
test_p3_het_freezing(FT)
582634
test_p3_melting(FT)
635+
636+
# bulk liquid-ice collisions and related processes
637+
test_p3_bulk_liquid_ice_collisions(FT)
583638
end

0 commit comments

Comments
 (0)