Skip to content

Commit 9fda311

Browse files
authored
Merge pull request #3959 from CliMA/he/feat-add-p3-ice-microphysics
feat: add P3 ice microphysics model
2 parents f81c83f + 92a071e commit 9fda311

File tree

15 files changed

+266
-10
lines changed

15 files changed

+266
-10
lines changed

src/cache/precipitation_precomputed_quantities.jl

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import CloudMicrophysics.MicrophysicsNonEq as CMNe
66
import CloudMicrophysics.Microphysics1M as CM1
77
import CloudMicrophysics.Microphysics2M as CM2
8+
import CloudMicrophysics.P3Scheme as CMP3
89

910
import Thermodynamics as TD
1011
import ClimaCore.Operators as Operators
@@ -506,6 +507,68 @@ function set_precipitation_velocities!(
506507
return nothing
507508
end
508509

510+
function set_precipitation_velocities!(
511+
Y, p, ::NonEquilMoistModel, ::Microphysics2MomentP3,
512+
)
513+
## liquid quantities (2M warm rain)
514+
(; ᶜwₗ, ᶜwᵣ, ᶜwnₗ, ᶜwnᵣ, ᶜwₜqₜ, ᶜwₕhₜ, ᶜts, ᶜu) = p.precomputed
515+
(; ᶜΦ) = p.core
516+
517+
(; ρ, ρq_liq, ρn_liq, ρq_rai, ρn_rai) = Y.c
518+
(; sb, rtv, ctv) = p.params.microphysics_2mp3_params.warm
519+
thp = CAP.thermodynamics_params(p.params)
520+
521+
# Number- and mass weighted rain terminal velocity [m/s]
522+
ᶜrai_w_terms = @. lazy(
523+
CM2.rain_terminal_velocity(
524+
sb, rtv,
525+
max(zero(ρ), specific(ρq_rai, ρ)),
526+
ρ, max(zero(ρ), ρn_rai),
527+
),
528+
)
529+
@. ᶜwnᵣ = getindex(ᶜrai_w_terms, 1)
530+
@. ᶜwᵣ = getindex(ᶜrai_w_terms, 2)
531+
# Number- and mass weighted cloud liquid terminal velocity [m/s]
532+
ᶜliq_w_terms = @. lazy(
533+
CM2.cloud_terminal_velocity(
534+
sb.pdf_c, ctv,
535+
max(zero(ρ), specific(ρq_liq, ρ)),
536+
ρ, max(zero(ρ), ρn_liq),
537+
),
538+
)
539+
@. ᶜwnₗ = getindex(ᶜliq_w_terms, 1)
540+
@. ᶜwₗ = getindex(ᶜliq_w_terms, 2)
541+
542+
## Ice quantities
543+
(; ρq_ice, ρn_ice, ρq_rim, ρb_rim) = Y.c
544+
(; ᶜwᵢ) = p.precomputed
545+
(; cold) = CAP.microphysics_2mp3_params(p.params)
546+
547+
# Number- and mass weighted ice terminal velocity [m/s]
548+
# Calculate terminal velocities
549+
(; ᶜlogλ, ᶜwnᵢ) = p.precomputed
550+
use_aspect_ratio = true # TODO: Make a config option
551+
ᶜF_rim = @. lazy(ρq_rim / ρq_ice)
552+
ᶜρ_rim = @. lazy(ρq_rim / ρb_rim)
553+
ᶜstate_p3 = @. lazy(CMP3.P3State(cold.params,
554+
max(0, ρq_ice), max(0, ρn_ice), ᶜF_rim, ᶜρ_rim,
555+
))
556+
@. ᶜlogλ = CMP3.get_distribution_logλ(ᶜstate_p3)
557+
args = (cold.velocity_params, ρ, ᶜstate_p3, ᶜlogλ)
558+
@. ᶜwnᵢ = CMP3.ice_terminal_velocity_number_weighted(args...; use_aspect_ratio)
559+
@. ᶜwᵢ = CMP3.ice_terminal_velocity_mass_weighted(args...; use_aspect_ratio)
560+
561+
# compute their contributions to energy and total water advection
562+
@. ᶜwₜqₜ = Geometry.WVector(ᶜwₗ * ρq_liq + ᶜwᵢ * ρq_ice + ᶜwᵣ * ρq_rai) / ρ
563+
@. ᶜwₕhₜ =
564+
Geometry.WVector(
565+
ᶜwₗ * ρq_liq * (Iₗ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwₗ, ᶜu))) +
566+
ᶜwᵢ * ρq_ice * (Iᵢ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwᵢ, ᶜu))) +
567+
ᶜwᵣ * ρq_rai * (Iₗ(thp, ᶜts) + ᶜΦ + $(Kin(ᶜwᵣ, ᶜu))),
568+
) / ρ
569+
return nothing
570+
end
571+
509572
"""
510573
set_precipitation_cache!(Y, p, microphysics_model, turbconv_model)
511574
@@ -744,6 +807,37 @@ function set_precipitation_cache!(
744807
return nothing
745808
end
746809

810+
function set_precipitation_cache!(Y, p, ::Microphysics2MomentP3, ::Nothing)
811+
### Rainy processes (2M)
812+
(; turbconv_model) = p.atmos
813+
set_precipitation_cache!(Y, p, Microphysics2Moment(), turbconv_model)
814+
# NOTE: the above function sets `ᶜSqᵢᵖ` to `0`. For P3, need to update `ᶜSqᵢᵖ` below!!
815+
816+
### Icy processes (P3)
817+
(; ᶜScoll, ᶜts, ᶜlogλ) = p.precomputed
818+
819+
# get thermodynamics and microphysics params
820+
(; params) = p
821+
params_2mp3 = CAP.microphysics_2mp3_params(params)
822+
thermo_params = CAP.thermodynamics_params(params)
823+
824+
ᶜY_reduced = (;
825+
Y.c.ρ,
826+
# condensate
827+
Y.c.ρq_liq, Y.c.ρn_liq, Y.c.ρq_rai, Y.c.ρn_rai,
828+
# ice
829+
Y.c.ρq_ice, Y.c.ρn_ice, Y.c.ρq_rim, Y.c.ρb_rim,
830+
)
831+
832+
# compute warm precipitation sources on the grid mean (based on SB2006 2M scheme)
833+
compute_cold_precipitation_sources_P3!(
834+
ᶜScoll, params_2mp3, thermo_params, ᶜY_reduced, ᶜts, ᶜlogλ,
835+
)
836+
837+
return nothing
838+
839+
end
840+
747841
"""
748842
set_precipitation_surface_fluxes!(Y, p, precipitation model)
749843
@@ -833,3 +927,8 @@ function set_precipitation_surface_fluxes!(
833927

834928
return nothing
835929
end
930+
931+
function set_precipitation_surface_fluxes!(Y, p, ::Microphysics2MomentP3)
932+
set_precipitation_surface_fluxes!(Y, p, Microphysics2Moment())
933+
# TODO: Figure out what to do for ρn_ice, ρq_rim, ρb_rim
934+
end

src/cache/precomputed_quantities.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ function precomputed_quantities(Y, atmos)
113113
ᶜSqᵣᵖ = similar(Y.c, FT),
114114
ᶜSqₛᵖ = similar(Y.c, FT),
115115
)
116-
elseif atmos.microphysics_model isa Microphysics2Moment
116+
elseif atmos.microphysics_model isa Union{Microphysics2Moment, Microphysics2MomentP3}
117+
# 2-moment microphysics
117118
precipitation_quantities = (;
118119
ᶜwᵣ = similar(Y.c, FT),
119120
ᶜwₛ = similar(Y.c, FT),
@@ -126,6 +127,23 @@ function precomputed_quantities(Y, atmos)
126127
ᶜSnₗᵖ = similar(Y.c, FT),
127128
ᶜSnᵣᵖ = similar(Y.c, FT),
128129
)
130+
# Add additional quantities for 2M + P3
131+
if atmos.microphysics_model isa Microphysics2MomentP3
132+
precipitation_quantities = (;
133+
# liquid quantities (2M warm rain)
134+
precipitation_quantities...,
135+
# ice quantities (P3)
136+
ᶜwᵢ = similar(Y.c, FT),
137+
ᶜwnᵢ = similar(Y.c, FT),
138+
ᶜlogλ = similar(Y.c, FT),
139+
ᶜScoll = similar(Y.c,
140+
@NamedTuple{
141+
∂ₜq_c::FT, ∂ₜq_r::FT, ∂ₜN_c::FT, ∂ₜN_r::FT,
142+
∂ₜL_rim::FT, ∂ₜL_ice::FT, ∂ₜB_rim::FT,
143+
}
144+
),
145+
)
146+
end
129147
else
130148
precipitation_quantities = (;)
131149
end

src/diagnostics/Diagnostics.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import ..NoPrecipitation
3535
import ..Microphysics0Moment
3636
import ..Microphysics1Moment
3737
import ..Microphysics2Moment
38+
import ..Microphysics2MomentP3
3839

3940
# radiation
4041
import ClimaAtmos.RRTMGPInterface as RRTMGPI

src/diagnostics/core_diagnostics.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ function compute_pr!(
738738
Microphysics0Moment,
739739
Microphysics1Moment,
740740
Microphysics2Moment,
741+
Microphysics2MomentP3,
741742
},
742743
)
743744
if isnothing(out)
@@ -774,6 +775,7 @@ function compute_prra!(
774775
Microphysics0Moment,
775776
Microphysics1Moment,
776777
Microphysics2Moment,
778+
Microphysics2MomentP3,
777779
},
778780
)
779781
if isnothing(out)
@@ -807,6 +809,7 @@ function compute_prsn!(
807809
Microphysics0Moment,
808810
Microphysics1Moment,
809811
Microphysics2Moment,
812+
Microphysics2MomentP3,
810813
},
811814
)
812815
if isnothing(out)
@@ -838,7 +841,9 @@ function compute_husra!(
838841
state,
839842
cache,
840843
time,
841-
microphysics_model::Union{Microphysics1Moment, Microphysics2Moment},
844+
microphysics_model::Union{
845+
Microphysics1Moment, Microphysics2Moment, Microphysics2MomentP3,
846+
},
842847
)
843848
if isnothing(out)
844849
return state.c.ρq_rai ./ state.c.ρ
@@ -869,7 +874,9 @@ function compute_hussn!(
869874
state,
870875
cache,
871876
time,
872-
microphysics_model::Union{Microphysics1Moment, Microphysics2Moment},
877+
microphysics_model::Union{
878+
Microphysics1Moment, Microphysics2Moment, Microphysics2MomentP3,
879+
},
873880
)
874881
if isnothing(out)
875882
return state.c.ρq_sno ./ state.c.ρ
@@ -900,7 +907,7 @@ function compute_cdnc!(
900907
state,
901908
cache,
902909
time,
903-
microphysics_model::Microphysics2Moment,
910+
microphysics_model::Union{Microphysics2Moment, Microphysics2MomentP3},
904911
)
905912
if isnothing(out)
906913
return state.c.ρn_liq
@@ -931,7 +938,7 @@ function compute_ncra!(
931938
state,
932939
cache,
933940
time,
934-
microphysics_model::Microphysics2Moment,
941+
microphysics_model::Union{Microphysics2Moment, Microphysics2MomentP3},
935942
)
936943
if isnothing(out)
937944
return state.c.ρn_rai
@@ -1554,7 +1561,7 @@ function compute_rwp!(
15541561
cache,
15551562
time,
15561563
moisture_model::T,
1557-
) where {T <: Union{Microphysics1Moment, Microphysics2Moment}}
1564+
) where {T <: Union{Microphysics1Moment, Microphysics2Moment, Microphysics2MomentP3}}
15581565
if isnothing(out)
15591566
out = zeros(axes(Fields.level(state.f, half)))
15601567
rw = cache.scratch.ᶜtemp_scalar

src/initial_conditions/InitialConditions.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ..NoPrecipitation
88
import ..Microphysics0Moment
99
import ..Microphysics1Moment
1010
import ..Microphysics2Moment
11+
import ..Microphysics2MomentP3
1112
import ..PrescribedSST
1213
import ..SlabOceanSST
1314
import ..ᶜinterp

src/initial_conditions/atmos_state.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ precip_variables(ls, ::Microphysics2Moment) = (;
134134
ρq_sno = ls.ρ * ls.precip_state.q_sno,
135135
)
136136

137+
function precip_variables(ls, ::Microphysics2MomentP3)
138+
(; ρ) = ls
139+
(; n_liq, n_rai, q_rai) = ls.precip_state.warm
140+
(; n_ice, q_ice, q_rim, b_rim) = ls.precip_state.cold
141+
# warm state
142+
ls_warm = (; ρ, precip_state = ls.precip_state.warm)
143+
warm_state = precip_variables(ls_warm, Microphysics2Moment())
144+
# cold state
145+
cold_state = (;
146+
ρq_ice = ρ * q_ice, ρn_ice = ρ * n_ice,
147+
ρq_rim = ρ * q_rim, ρb_rim = ρ * b_rim,
148+
)
149+
return (; warm_state..., cold_state...)
150+
end
151+
137152
# We can use paper-based cases for LES type configurations (no TKE)
138153
# or SGS type configurations (initial TKE needed), so we do not need to assert
139154
# that there is no TKE when there is no turbconv_model.

src/parameterized_tendencies/microphysics/microphysics_wrappers.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,3 +751,30 @@ function compute_warm_precipitation_sources_2M!(
751751
@. Snᵣᵖ += Sᵖ + S₂ᵖ
752752

753753
end
754+
755+
function compute_cold_precipitation_sources_P3!(
756+
ᶜScoll, # NamedTuple-valued Field with P3 liquid-ice collision sources
757+
params_2mp3, # Parameters for 2M and P3 schemes, see `get_microphysics_2m_p3_parameters`
758+
thermo_params, # An instance of `Thermodynamics.Parameters.ThermodynamicsParameters`
759+
ᶜY_reduced, # A reduced set of prognostic variables needed for P3 sources
760+
ᶜts, # Thermodynamic state
761+
ᶜlogλ, # Logarithm of the P3 distribution slope parameter
762+
)
763+
764+
(; warm, cold) = params_2mp3
765+
(; ρ, ρq_liq, ρn_liq, ρq_rai, ρn_rai, ρq_ice, ρn_ice, ρq_rim, ρb_rim) = ᶜY_reduced
766+
767+
ᶜF_rim = @. lazy(ρq_rim / ρq_ice)
768+
ᶜρ_rim = @. lazy(ρq_rim / ρb_rim)
769+
770+
@. ᶜScoll = CMP3.bulk_liquid_ice_collision_sources(cold.params, ᶜlogλ,
771+
ρq_ice, max(0, ρn_ice),
772+
ᶜF_rim, ᶜρ_rim,
773+
warm.sb.pdf_c, warm.sb.pdf_r,
774+
ρq_liq, ρn_liq, ρq_rai, ρn_rai,
775+
warm.aps, thermo_params, (cold.velocity_params,),
776+
ρ, Tₐ(thermo_params, ᶜts),
777+
)
778+
779+
return nothing
780+
end

src/parameterized_tendencies/microphysics/precipitation.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,33 @@ function precipitation_tendency!(
259259
@. Yₜ.c.ρn_rai += Y.c.sgsʲs.:($$j).ρa * ᶜSnᵣᵖʲs.:($$j)
260260
end
261261
end
262+
263+
####
264+
#### 2-moment warm microphysics with P3 scheme
265+
####
266+
267+
function precipitation_tendency!(Yₜ, Y, p, t,
268+
ne::NonEquilMoistModel, ::Microphysics2MomentP3, ::Nothing,
269+
)
270+
(; ᶜSqₗᵖ, ᶜSqᵢᵖ, ᶜSqᵣᵖ, ᶜSqₛᵖ, ᶜScoll) = p.precomputed
271+
(; ᶜSnₗᵖ, ᶜSnᵣᵖ) = p.precomputed
272+
273+
## Update grid mean tendencies
274+
# 2 moment scheme (warm)
275+
precipitation_tendency!(Yₜ, Y, p, t, ne, Microphysics2Moment(), nothing)
276+
277+
# P3 scheme (cold)
278+
# @. Yₜ.c.ρq_ice += Y.c.ρ * ᶜSqᵢᵖ # updated in the above function
279+
# @. Yₜ.c.ρn_ice += Y.c.ρ * ᶜSnᵢᵖ # TODO: Additional sources for `ρn_ice`
280+
281+
# Collisions
282+
@. Yₜ.c.ρq_liq += Y.c.ρ * ᶜScoll.∂ₜq_c
283+
@. Yₜ.c.ρq_rai += Y.c.ρ * ᶜScoll.∂ₜq_r
284+
@. Yₜ.c.ρn_liq += ᶜScoll.∂ₜN_c
285+
@. Yₜ.c.ρn_rai += ᶜScoll.∂ₜN_r
286+
@. Yₜ.c.ρq_rim += ᶜScoll.∂ₜL_rim
287+
@. Yₜ.c.ρq_ice += ᶜScoll.∂ₜL_ice
288+
@. Yₜ.c.ρb_rim += ᶜScoll.∂ₜB_rim
289+
290+
return nothing
291+
end

src/parameters/Parameters.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Base.@kwdef struct ClimaAtmosParameters{
6969
MP0M,
7070
MP1M,
7171
MP2M,
72+
MP2MP3,
7273
SFP,
7374
TCP,
7475
STP,
@@ -82,6 +83,7 @@ Base.@kwdef struct ClimaAtmosParameters{
8283
microphysics_0m_params::MP0M
8384
microphysics_1m_params::MP1M
8485
microphysics_2m_params::MP2M
86+
microphysics_2mp3_params::MP2MP3
8587
surface_fluxes_params::SFP
8688
turbconv_params::TCP
8789
surface_temp_params::STP

0 commit comments

Comments
 (0)