Skip to content

Commit 7bfbc57

Browse files
committed
wip p3 collisions
1 parent 30d9141 commit 7bfbc57

File tree

8 files changed

+203
-10
lines changed

8 files changed

+203
-10
lines changed

src/Common/equation_types.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export Precipitation0M
1818
export Precipitation1M
1919
export Precipitation2M
2020
export PrecipitationP3
21+
export IcePrecipitationP3
22+
export Precipitation2M_P3
2123
export CloudyPrecip
2224

2325
abstract type AbstractStyle end
@@ -59,3 +61,12 @@ struct PrecipitationP3{P3, CH, PT, B} <: AbstractPrecipitationStyle
5961
p3_boundary_condition::B
6062
end
6163
struct CloudyPrecip <: AbstractPrecipitationStyle end
64+
# New P3 structs
65+
struct IcePrecipitationP3{P3, ST} <: AbstractPrecipitationStyle
66+
params::P3
67+
sedimentation::ST
68+
end
69+
struct Precipitation2M_P3{LP, IP} <: AbstractPrecipitationStyle
70+
liq_precip::LP # The rain scheme. For now: Precipitation2M
71+
ice_precip::IP # The ice scheme. For now: IcePrecipitationP3
72+
end

src/Common/helper_functions.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ function get_precipitation_type(
8686
Chen2022 = CMP.Chen2022VelType(FT)
8787
sb2006 = CMP.SB2006(toml_dict)
8888
precip = PrecipitationP3(p3_params, Chen2022, sb2006, boundary)
89+
elseif precipitation_choice == "Precipitation2M_P3"
90+
@assert sedimentation_choice == "Chen2022"
91+
@assert rain_formation_choice == "SB2006"
92+
params = CMP.ParametersP3(toml_dict; slope_law = :constant)
93+
liq_sedimentation = CMP.Chen2022VelTypeRain(toml_dict)
94+
ice_sedimentation = CMP.Chen2022VelType(toml_dict)
95+
liq_precip = Precipitation2M(CMP.SB2006(toml_dict), liq_sedimentation)
96+
ice_precip = IcePrecipitationP3(params, ice_sedimentation)
97+
precip = Precipitation2M_P3(liq_precip, ice_precip)
8998
else
9099
error("Invalid precipitation choice: $precipitation_choice")
91100
end

src/Common/initial_condition.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ function initial_condition_1d(
162162
ρq_ice,
163163
ρq_rai,
164164
ρq_sno,
165+
ρq_rim,
165166
ρq_vap,
166167
q_tot,
167168
q_liq,
@@ -175,6 +176,10 @@ function initial_condition_1d(
175176
N_rai,
176177
N_aer,
177178
zero,
179+
# P3 variables
180+
F_rim = FT(0),
181+
ρ_rim = FT(0),
182+
logλ = FT(0),
178183
)
179184
end
180185

src/Common/ode_utils.jl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ function initialise_state(::MoistureP3, ::PrecipitationP3, initial_profiles)
4747
:N_liq, :N_rai, :N_ice, :N_aer, :q_vap, :ρq_vap, :q_rai,
4848
)}.(initial_profiles)
4949
end
50+
function initialise_state(::NonEquilibriumMoisture, ::Precipitation2M_P3, initial_profiles)
51+
warm_state = NamedTuple{(:ρq_tot, :ρq_liq, :ρq_rai, :N_liq, :N_rai, :N_aer)}.(initial_profiles)
52+
cold_state = NamedTuple{(:ρq_ice, :N_ice, :ρq_rim, :B_rim)}.(initial_profiles)
53+
tmp = NamedTuple{(:ρq_sno,)}.(initial_profiles) # only needed to use existing `Precipitation2M` code, should always be zero.
54+
return merge.(warm_state, cold_state, tmp)
55+
end
5056
function initialise_state(::CloudyMoisture, ::CloudyPrecip, initial_profiles)
5157
return NamedTuple{(:ρq_vap, :N_aer, :moments)}.(initial_profiles)
5258
end
@@ -115,11 +121,21 @@ function initialise_aux(
115121
velocities = zero_nt(NamedTuple{(:term_vel_rai, :term_vel_sno)})
116122
precip_sources = zero_nt(NamedTuple{(:q_tot, :q_liq, :q_ice, :q_rai, :q_sno)})
117123
activation_sources = nothing
118-
elseif precip isa Precipitation2M
124+
elseif precip isa Precipitation2M || precip isa Precipitation2M_P3
119125
microph_variables = merge.(microph_variables, NamedTuple{(:q_rai, :q_sno, :N_liq, :N_rai, :N_aer)}.(ip))
120126
velocities = zero_nt(NamedTuple{(:term_vel_N_rai, :term_vel_rai)})
121127
precip_sources = zero_nt(NamedTuple{(:q_tot, :q_liq, :q_rai, :N_aer, :N_liq, :N_rai)})
122128
activation_sources = zero_nt(NamedTuple{(:N_aer, :N_liq)})
129+
if precip isa Precipitation2M_P3
130+
# NOTE: `q_sno` from above is not used in the P3 code, but is needed to use existing `Precipitation2M` code.
131+
ice_microph_variables = NamedTuple{(:F_rim, :ρ_rim, :logλ)}.(ip) # variables needed to be precomputed
132+
ice_output_variables = NamedTuple{(:N_ice, :ρq_rim, :B_rim)}.(ip) # variables for netCDF output
133+
microph_variables = merge.(microph_variables, ice_microph_variables, ice_output_variables)
134+
ice_velocities = zero_nt(NamedTuple{(:term_vel_N_ice, :term_vel_q_ice)})
135+
velocities = merge.(velocities, ice_velocities) # precompute ice terminal velocities
136+
ice_precip_sources = zero_nt(NamedTuple{(:q_ice, :q_rim, :N_ice, :B_rim)})
137+
precip_sources = merge.(precip_sources, ice_precip_sources)
138+
end
123139
elseif precip isa PrecipitationP3
124140
microph_variables =
125141
NamedTuple{(

src/Common/tendency.jl

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ end
160160
@. term_vel_rai = CM1.terminal_velocity(ps.rain, ps.sedimentation.rain, ρ, q_rai)
161161
@. term_vel_sno = CM1.terminal_velocity(ps.snow, ps.sedimentation.snow, ρ, q_sno)
162162
end
163-
@inline function precompute_aux_precip!(ps::Precipitation2M, Y, aux)
163+
@inline function precompute_aux_precip!(ps::Precipitation2M, Y, aux) # called by `make_rhs_function`
164164

165165
FT = eltype(Y.ρq_rai)
166166
sb2006 = ps.rain_formation
@@ -177,6 +177,42 @@ end
177177
@. term_vel_N_rai = getindex(CM2.rain_terminal_velocity(sb2006, vel_scheme, q_rai, ρ, N_rai), 1)
178178
@. term_vel_rai = getindex(CM2.rain_terminal_velocity(sb2006, vel_scheme, q_rai, ρ, N_rai), 2)
179179
end
180+
@inline function precompute_aux_precip!(ps::IcePrecipitationP3, Y, aux)
181+
# State, `Y`, includes: ρq_ice, ρq_rim, N_ice, B_rim
182+
183+
# update state variables
184+
(; sedimentation, params) = ps
185+
(; ρq_ice, ρq_rim, N_ice, B_rim) = Y
186+
(; ρ) = aux.thermo_variables
187+
(; F_rim, ρ_rim, logλ) = aux.microph_variables
188+
(; term_vel_N_ice, term_vel_q_ice) = aux.velocities
189+
190+
# Calculate derived rime quantities
191+
# @. F_rim = ifelse(Y.ρq_ice < eps(FT), FT(0), Y.ρq_rim / Y.ρq_ice)
192+
# @. ρ_rim = ifelse(Y.B_rim < eps(FT), FT(0), Y.ρq_rim / Y.B_rim)
193+
194+
@. F_rim = ifelse(isnan(ρq_rim / ρq_ice), zero(ρq_rim), ρq_rim / ρq_ice)
195+
@. ρ_rim = ifelse(isnan(ρq_rim / B_rim), zero(ρq_rim), ρq_rim / B_rim)
196+
# Calculate distribution parameters
197+
@. logλ = CMP3.get_distribution_logλ(CMP3.P3State(params, ρq_ice, N_ice, F_rim, ρ_rim))
198+
199+
# Calculate terminal velocities
200+
use_aspect_ratio = true
201+
@. term_vel_N_ice = CMP3.ice_terminal_velocity_number_weighted(
202+
sedimentation, ρ, CMP3.P3State(params, ρq_ice, N_ice, F_rim, ρ_rim), logλ; use_aspect_ratio
203+
)
204+
@. term_vel_q_ice = CMP3.ice_terminal_velocity_mass_weighted(
205+
sedimentation, ρ, CMP3.P3State(params, ρq_ice, N_ice, F_rim, ρ_rim), logλ; use_aspect_ratio
206+
)
207+
# args = (ps.sedimentation, ρ, ps.params, ρq_ice, N_ice, F_rim, ρ_rim, logλ)
208+
# @. term_vel_N_ice = CMP3.ice_terminal_velocity_number_weighted(args...; use_aspect_ratio)
209+
# @. term_vel_q_ice = CMP3.ice_terminal_velocity_mass_weighted(args...; use_aspect_ratio)
210+
211+
end
212+
function precompute_aux_precip!(ps::Precipitation2M_P3, Y, aux)
213+
precompute_aux_precip!(ps.liq_precip, Y, aux)
214+
precompute_aux_precip!(ps.ice_precip, Y, aux)
215+
end
180216
@inline function precompute_aux_precip!(ps::PrecipitationP3, Y, aux)
181217

182218
# update state variables
@@ -580,6 +616,13 @@ end
580616
end
581617
end
582618

619+
@inline function precompute_aux_precip_sources!(ps::IcePrecipitationP3, Y, aux)
620+
621+
# TODO: So far, implemented directly in precip_sources_tendency!
622+
623+
return nothing
624+
end
625+
583626
@inline function precompute_aux_precip_sources!(ps::PrecipitationP3, aux)
584627
# TODO [P3]
585628
return nothing
@@ -670,7 +713,7 @@ end
670713
@inline function cloud_sources_tendency!(::EquilibriumMoisture, dY, Y, aux, t) end
671714
@inline function cloud_sources_tendency!(ms::NonEquilibriumMoisture, dY, Y, aux, t)
672715

673-
precompute_aux_moisture_sources!(ms, aux)
716+
precompute_aux_moisture_sources!(ms, aux) # defined in `Common/tendency.jl`
674717

675718
@. dY.ρq_liq += aux.thermo_variables.ρ * aux.cloud_sources.q_liq
676719
@. dY.ρq_ice += aux.thermo_variables.ρ * aux.cloud_sources.q_ice
@@ -740,6 +783,42 @@ end
740783
@inline function precip_sources_tendency!(ms::MoistureP3, ps::PrecipitationP3, dY, Y, aux, t)
741784
return dY
742785
end
786+
@inline function precip_sources_tendency!(ms::AbstractMoistureStyle, ps::Precipitation2M_P3, dY, Y, aux, t)
787+
precip_sources_tendency!(ms, ps.liq_precip, dY, Y, aux, t)
788+
# TODO [P3]
789+
# precompute_aux_precip_sources!(ps, Y, aux)
790+
791+
#=
792+
function bulk_liquid_ice_collision_sources(
793+
params, logλ, L_ice, F_rim, ρ_rim,
794+
psd_c, psd_r, L_c, N_c, L_r, N_r,
795+
aps, tps, vel, ρₐ, T,
796+
)
797+
=#
798+
(; ρ, ts) = aux.thermo_variables
799+
(; ρq_liq, ρq_rai, ρq_ice, N_liq, N_rai, N_ice) = Y
800+
(; air_params, thermo_params) = aux
801+
(; logλ, F_rim, ρ_rim) = aux.microph_variables
802+
(; pdf_c, pdf_r) = ps.liq_precip.rain_formation
803+
(; ice_precip) = ps
804+
805+
coll_src = @. CMP3.bulk_liquid_ice_collision_sources(
806+
ice_precip.params, logλ, ρq_ice, N_ice, F_rim, ρ_rim,
807+
pdf_c, pdf_r, ρq_liq, N_liq, ρq_rai, N_rai,
808+
air_params, thermo_params, (ice_precip.sedimentation,),
809+
ρ, TD.air_temperature(thermo_params, ts),
810+
)
811+
812+
@. dY.ρq_liq += ρ * coll_src.∂ₜq_c
813+
@. dY.ρq_rai += ρ * coll_src.∂ₜq_r
814+
@. dY.N_liq += coll_src.∂ₜN_c
815+
@. dY.N_rai += coll_src.∂ₜN_r
816+
@. dY.ρq_rim += coll_src.∂ₜL_rim
817+
@. dY.ρq_ice += coll_src.∂ₜL_ice
818+
@. dY.B_rim += coll_src.∂ₜB_rim
819+
820+
return dY
821+
end
743822
@inline function precip_sources_tendency!(ms::CloudyMoisture, ps::CloudyPrecip, dY, Y, aux, t)
744823

745824
precompute_aux_precip_sources!(ps, aux)

src/K1DModel/ode_utils.jl

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,56 @@ end
2828
"""
2929
function make_rhs_function(ms::CO.AbstractMoistureStyle, ps::CO.AbstractPrecipitationStyle)
3030
function rhs!(dY, Y, aux, t)
31-
3231
CO.zero_tendencies!(dY)
3332

33+
# defined in `K1DModel/tendency.jl`
34+
# calc: aux.prescribed_velocity.ρw
3435
precompute_aux_prescribed_velocity!(aux, t)
36+
# defined in `Common/tendency.jl`
37+
# For NonEquilibriumMoisture:
38+
# calc: aux.thermo_variables.{ts, ρ, p, θ_dry, θ_liq_ice}
39+
# calc: aux.microph_variables.{q_tot, q_liq, q_ice}
3540
CO.precompute_aux_thermo!(ms, Y, aux)
36-
CO.precompute_aux_precip!(ps, Y, aux)
37-
38-
precompute_aux_activation!(ps, dY, Y, aux, t)
39-
41+
# defined in `Common/tendency.jl`
42+
# For Precipitation2M:
43+
# calc: aux.microph_variables.{q_rai, q_sno, N_rai, N_liq} <-- NOTE: You can assume `q_sno = ρq_sno = 0`
44+
# calc: aux.velocities.{term_vel_rai, term_vel_N_rai}
45+
# For IcePrecipitationP3:
46+
# calc: aux.microph_variables.{ρq_ice, ρq_rim, N_ice, B_rim} <-- maybe not needed
47+
# calc: aux.velocities.{term_vel_ice, term_vel_N_ice}
48+
CO.precompute_aux_precip!(ps, Y, aux) # <-- calls fn for Precipitation2M
49+
50+
# defined in `K1DModel/tendency.jl`
51+
# calc: aux.activation_sources.{N_aer, N_liq}
52+
precompute_aux_activation!(ps, dY, Y, aux, t) # <-- calls fn for Precipitation2M
53+
54+
# defined in `Common/tendency.jl`
55+
# calls: `precompute_aux_moisture_sources` (defined in `Common/tendency.jl`)
56+
# calc: aux.cloud_sources.{q_liq, q_ice}
57+
# increments: dY.{ρq_liq, ρq_ice} += ρ * aux.cloud_sources.{q_...}
4058
CO.cloud_sources_tendency!(ms, dY, Y, aux, t)
41-
CO.precip_sources_tendency!(ms, ps, dY, Y, aux, t)
59+
# defined in `Common/tendency.jl`
60+
# For Precipitation2M:
61+
# calls: `precompute_aux_precip_sources` (defined in `Common/tendency.jl`)
62+
# calc: aux.precip_sources.{q_tot, q_liq, q_rai, N_liq, N_rai, N_aer}
63+
# increments: dY.{ρq_tot, ρq_rai, ρq_liq, N_liq, N_rai, N_aer}
64+
# += aux.precip_sources.{...}
65+
# and/or += aux.activation_sources.{N_liq, N_aer}
66+
# For Precipitation2M_P3:
67+
# calls: `precompute_aux_precip_sources` (defined in `Common/tendency.jl`)
68+
# TODO: write collisions
69+
CO.precip_sources_tendency!(ms, ps, dY, Y, aux, t) # <-- calls fn for Precipitation2M + write code
4270

4371
for eq_style in [ms, ps]
72+
# defined in `K1DModel/tendency.jl`
73+
# For Precipitation2M:
74+
# increments: dY.{ρq_rai, N_liq, N_rai, N_aer} += ... * aux.velocities.{term_vel_N_rai, term_vel_rai}
75+
# For NonEquilibriumMoisture:
76+
# increments: dY.{ρq_tot, ρq_liq, ρq_ice} += {aux.prescribed_velocity} * {Y.ρq_...}
77+
# For Precipitation2M_P3
78+
# - delegates to `Precipitation2M` (see above) and `IcePrecipitationP3`
79+
# For IcePrecipitationP3:
80+
# increments: dY.{N_ice, B_rim, ρq_rim} += ... * aux.velocities.{term_vel_N_ice, term_vel_q_ice}
4481
advection_tendency!(eq_style, dY, Y, aux, t)
4582
end
4683

src/K1DModel/tendency.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ end
171171
@. aux.activation_sources.N_liq = S_Nl
172172
end
173173

174+
@inline function precompute_aux_activation!(ps::CO.Precipitation2M_P3, dY, Y, aux, t)
175+
precompute_aux_activation!(ps.liq_precip, dY, Y, aux, t)
176+
end
177+
174178
@inline function precompute_aux_activation!(::CO.CloudyPrecip, dY, Y, aux, t)
175179

176180
(; common_params, kid_params, thermo_params, air_params, activation_params, cloudy_params) = aux
@@ -421,6 +425,38 @@ end
421425

422426
return dY
423427
end
428+
@inline function advection_tendency!(::CO.IcePrecipitationP3, dY, Y, aux, t)
429+
FT = eltype(Y.ρq_tot)
430+
# Apply advection tendency to N_ice, B_rim, ρq_rim
431+
(; ρw) = aux.prescribed_velocity
432+
(; ρ) = aux.thermo_variables
433+
(; term_vel_N_ice, term_vel_q_ice) = aux.velocities
434+
435+
If = CC.Operators.InterpolateC2F()
436+
wvec = CC.Geometry.WVector
437+
extrapolate = CC.Operators.Extrapolate()
438+
zero_bc = CC.Operators.SetValue(wvec(FT(0)))
439+
440+
∇_N = CC.Operators.DivergenceF2C(bottom = extrapolate, top = zero_bc)
441+
∇_q = CC.Operators.DivergenceF2C(bottom = zero_bc, top = extrapolate)
442+
443+
@. dY.N_ice += -∇_N((ρw / If(ρ) - wvec(If(term_vel_N_ice))) * If(Y.N_ice))
444+
@. dY.B_rim += -∇_q((ρw / If(ρ) - wvec(If(term_vel_q_ice))) * If(Y.B_rim))
445+
@. dY.ρq_rim += -∇_q((ρw / If(ρ) - wvec(If(term_vel_q_ice))) * If(Y.ρq_rim))
446+
447+
fcc = CC.Operators.FluxCorrectionC2C(bottom = extrapolate, top = extrapolate)
448+
@. dY.N_ice += fcc(ρw / If(ρ) - wvec(If(term_vel_N_ice)), Y.N_ice)
449+
@. dY.B_rim += fcc(ρw / If(ρ) - wvec(If(term_vel_q_ice)), Y.B_rim)
450+
@. dY.ρq_rim += fcc(ρw / If(ρ) - wvec(If(term_vel_q_ice)), Y.ρq_rim)
451+
452+
return dY
453+
end
454+
455+
@inline function advection_tendency!(ps::CO.Precipitation2M_P3, dY, Y, aux, t)
456+
advection_tendency!(ps.liq_precip, dY, Y, aux, t)
457+
advection_tendency!(ps.ice_precip, dY, Y, aux, t)
458+
return dY
459+
end
424460

425461
@inline function advection_tendency!(::CO.PrecipitationP3, dY, Y, aux, t)
426462
FT = eltype(Y.ρq_tot)

test/experiments/KiD_driver/run_KiD_simulation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function run_KiD_simulation(::Type{FT}, opts) where {FT}
2424

2525
# Decide the output folder name based on options
2626
folder = "Output_$(moisture_choice)_$(precipitation_choice)"
27-
if precipitation_choice in ["Precipitation1M", "Precipitation2M"]
27+
if precipitation_choice in ["Precipitation1M", "Precipitation2M", "Precipitation2M_P3"]
2828
folder *= "_$(rain_formation_choice)"
2929
sedimentation_choice == "Chen2022" && (folder *= "_Chen2022")
3030
elseif precipitation_choice == "CloudyPrecip"

0 commit comments

Comments
 (0)