Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P3 skeleton framework #185

Merged
merged 19 commits into from
Aug 24, 2024
4 changes: 3 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,7 @@ steps:
command: "julia --color=yes --project=test test/experiments/KiD_driver/KiD_driver.jl --moisture_choice=CloudyMoisture --precipitation_choice=CloudyPrecip --n_elem=128 --num_moments=7"
artifact_paths: "test/experiments/KiD_driver/Output_CloudyMoisture_CloudyPrecip_7/figures/*"


- label: ":snowflake: Experiment: P3 Setup"
command: "julia --color=yes --project=test test/experiments/KiD_driver/KiD_driver.jl --moisture_choice=MoistureP3 --precipitation_choice=PrecipitationP3 --n_elem=24 --z_max=3000 --t_end=75 --w1=0 --dt=0.5"
artifact_paths: "test/experiments/KiD_driver/Output_MoistureP3_PrecipitationP3/figures/*"

2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Thermodynamics = "b60c26fb-14c3-4610-9d3e-2d17fe7ff00c"
[compat]
ClimaCore = "0.14"
ClimaParams = "0.10.7"
CloudMicrophysics = "0.22.1"
CloudMicrophysics = "0.22.2"
Cloudy = "0.5.6"
DiffEqBase = "6"
Distributions = "0.25"
Expand Down
1 change: 1 addition & 0 deletions src/Common/Common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const CM1 = CM.Microphysics1M
const CM2 = CM.Microphysics2M
const CMAM = CM.AerosolModel
const CMAA = CM.AerosolActivation
const CMP3 = CM.P3Scheme

include("parameters.jl")
include("equation_types.jl")
Expand Down
9 changes: 5 additions & 4 deletions src/Common/equation_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ struct Precipitation2M{PT, ST} <: AbstractPrecipitationStyle
rain_formation::PT
sedimentation::ST
end
struct PrecipitationP3{PT, ST, P3} <: AbstractPrecipitationStyle
rain_formation::PT
sedimentation::ST
p3_parameters::P3
struct PrecipitationP3{P3, CH, PT, B} <: AbstractPrecipitationStyle
p3_params::P3
Chen2022::CH
sb2006::PT
p3_boundary_condition::B
end
struct CloudyPrecip <: AbstractPrecipitationStyle end
9 changes: 9 additions & 0 deletions src/Common/helper_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ function get_moisture_type(moisture_choice::String, toml_dict)
moisture = NonEquilibriumMoisture(CMP.CloudLiquid(toml_dict), CMP.CloudIce(toml_dict))
elseif moisture_choice == "CloudyMoisture"
moisture = CloudyMoisture()
elseif moisture_choice == "MoistureP3"
moisture = MoistureP3()
else
error("Invalid moisture choice: $moisture_choice")
end
Expand All @@ -22,6 +24,7 @@ function get_precipitation_type(
toml_dict;
rain_formation_choice::Union{Nothing, String} = nothing,
sedimentation_choice::Union{Nothing, String} = nothing,
boundary::Union{Nothing, NamedTuple} = nothing,
)
if precipitation_choice == "NoPrecipitation"
precip = NoPrecipitation()
Expand Down Expand Up @@ -77,6 +80,12 @@ function get_precipitation_type(
end
elseif precipitation_choice == "CloudyPrecip"
precip = CloudyPrecip()
elseif precipitation_choice == "PrecipitationP3"
FT = Float64
p3_params = CMP.ParametersP3(FT)
Chen2022 = CMP.Chen2022VelType(FT)
sb2006 = CMP.SB2006(toml_dict)
precip = PrecipitationP3(p3_params, Chen2022, sb2006, boundary)
else
error("Invalid precipitation choice: $precipitation_choice")
end
Expand Down
114 changes: 114 additions & 0 deletions src/Common/initial_condition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,117 @@ function cloudy_initial_condition(pdists, ip, k = 1)

return merge(ip, (; moments = moments, pdists = pdists, cloudy_moments_zero))
end

function p3_initial_condition(
::Type{FT},
kid_params,
thermo_params,
z;
_q_init = FT(0),
_N_init = FT(0),
_F_rim = FT(0),
_F_liq = FT(0),
_ρ_r = FT(0),
z_top,
ice_start,
dry = false,
) where {FT}

# initialize water vapor profile
# using same setup as initial_condition_1d
q_vap::FT = init_profile(FT, kid_params, thermo_params, z, dry = dry).qv

# if ice_start, start with small ice bump
# otherwise, introduce particles solely through
# the boundary in advection_tendency!()
_z_band = z_top * FT(0.2)
has_ice(z) = ifelse(ice_start, z > (z_top - _z_band), false)
ice_bump(χ, z) = χ * cos(z - (z_top - 0.5 * _z_band))

# P3 state variables (minus B_rim -- computed below)
# (initialized as kg/kg before converting to kg/m3)
q_ice::FT = has_ice(z) ? ice_bump(_q_init, z) : FT(0)
N_ice_kg::FT = has_ice(z) ? ice_bump(_N_init, z) : FT(0)
q_liqonice::FT = _F_liq * q_ice
q_rim::FT = _F_rim * (q_ice - q_liqonice)

# 2M warm rain state variables
q_liq::FT = FT(0)
N_liq::FT = FT(0)
q_rai::FT = FT(0)
N_rai::FT = FT(0)

# q_tot - single p3 category + 2M categories + vapor
q_tot::FT = q_ice + q_liq + q_rai + q_vap

# thermodynamics:
# for Case 1 of Cholette et al 2019 paper
# use approximate temperature values from
# sounding: kin1d/soundings/Tsfc2.txt
# (path in p3 fortran github repo)
T::FT = -0.004 * (z - 500) + 273.15 # temperature
p::FT = 990 - (0.1 * z) # pressure
_q = TD.PhasePartition(q_tot, q_liq, q_ice)
ρ::FT = TD.air_density(thermo_params, T, p, _q) # total density
ρ_dry::FT = TD.air_density(thermo_params, T, p)
ts = TD.PhaseNonEquil_ρTq(thermo_params, ρ, T, _q) # thermodynamic state

# P3 scheme uses L (kg/m3) = ρ * q
# so we compute ρq and pass that to P3
# also we convert N to (1/m3)
# since paper init values are given
# in (kg/kg), (1/kg)
ρq_tot::FT = ρ * q_tot
N_ice::FT = ρ * N_ice_kg
ρq_ice::FT = ρ * q_ice
ρq_rim::FT = ρ * q_rim
ρq_liqonice::FT = ρ * q_liqonice
ρq_rai::FT = ρ * q_rai
ρq_liq::FT = ρ * q_liq
ρq_vap::FT = ρ * q_vap

# also compute B_rim from L_rim, ρ_r
B_rim::FT = ρq_rim / _ρ_r


# unused quantities:
q_sno::FT = FT(0)
ρq_sno::FT = FT(0)
θ_liq_ice::FT = TD.liquid_ice_pottemp(thermo_params, ts)
N_aer::FT = FT(0)
θ_dry::FT = TD.dry_pottemp(thermo_params, T, ρ)

# zero:
zero::FT = FT(0)

return (;
ρ,
ρ_dry,
T,
p,
θ_liq_ice,
θ_dry,
ρq_tot,
ρq_liq,
ρq_ice,
ρq_rai,
ρq_rim,
ρq_sno,
ρq_vap,
ρq_liqonice,
q_tot,
q_liq,
q_ice,
q_rai,
q_sno,
q_rim,
q_liqonice,
q_vap,
B_rim,
N_liq,
N_ice,
N_rai,
N_aer,
zero,
)
end
10 changes: 10 additions & 0 deletions src/Common/netcdf_io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,21 @@ function NetCDFIO_Stats(
:q_tot => "q_tot",
:q_liq => "q_liq",
:q_ice => "q_ice",
:q_rim => "q_rim",
:q_liqonice => "q_liqonice",
:q_rai => "q_rai",
:q_sno => "q_sno",
:q_vap => "q_vap",
:N_aer => "N_aer",
:N_liq => "N_liq",
:N_rai => "N_rai",
:N_ice => "N_ice",
:B_rim => "B_rim",
:ρq_ice => "ρq_ice",
:ρq_rim => "ρq_rim",
:ρq_liqonice => "ρq_liqonice",
:ρq_vap => "ρq_vap",
:ρq_rai => "ρq_rai",
),
)
FT = Float64
Expand Down
42 changes: 39 additions & 3 deletions src/Common/ode_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,15 @@ function initialise_state(::MoistureP3, ::PrecipitationP3, initial_profiles)
ρq_rai = initial_profiles.ρq_rai,
ρq_ice = initial_profiles.ρq_ice,
ρq_rim = initial_profiles.ρq_rim,
ρq_liqonice = initial_profiles.ρq_liqonice,
B_rim = initial_profiles.B_rim,
N_liq = initial_profiles.N_liq,
N_rai = initial_profiles.N_rai,
N_ice = initial_profiles.N_ice,
N_aer = initial_profiles.N_aer,
q_vap = initial_profiles.q_vap,
ρq_vap = initial_profiles.ρq_vap,
q_rai = initial_profiles.q_rai,
)
end
function initialise_state(::CloudyMoisture, ::CloudyPrecip, initial_profiles)
Expand Down Expand Up @@ -116,7 +120,7 @@ function initialise_aux(
if moisture isa EquilibriumMoisture
ts = @. TD.PhaseEquil_ρθq(thermo_params, ip.ρ, ip.θ_liq_ice, ip.q_tot)
cloud_sources = nothing
elseif moisture isa NonEquilibriumMoisture
elseif moisture isa NonEquilibriumMoisture || moisture isa MoistureP3
q = @. TD.PhasePartition(ip.q_tot, ip.q_liq, ip.q_ice)
ts = @. TD.PhaseNonEquil_ρθq(thermo_params, ip.ρ, ip.θ_liq_ice, q)

Expand Down Expand Up @@ -181,11 +185,20 @@ function initialise_aux(
q_rai = ip.q_rai,
q_ice = ip.q_ice,
q_rim = ip.q_rim,
q_liqonice = ip.q_liqonice,
B_rim = ip.B_rim,
N_liq = ip.N_liq,
N_rai = ip.N_rai,
N_ice = ip.N_ice,
N_aer = ip.N_aer,
ρq_tot = ip.ρq_tot,
ρq_liq = ip.ρq_liq,
ρq_rai = ip.ρq_rai,
ρq_ice = ip.ρq_ice,
ρq_rim = ip.ρq_rim,
ρq_liqonice = ip.ρq_liqonice,
q_vap = ip.q_vap,
ρq_vap = ip.ρq_vap,
)
velocities = (;
term_vel_rai = copy(ip.zero),
Expand All @@ -199,6 +212,7 @@ function initialise_aux(
q_rai::FT,
q_ice::FT,
q_rim::FT,
q_liqonice::FT,
N_aer::FT,
N_liq::FT,
N_rai::FT,
Expand All @@ -217,11 +231,31 @@ function initialise_aux(
copy(ip.zero),
copy(ip.zero),
copy(ip.zero),
copy(ip.zero),
),
)
p3_boundary_condition_eltype = @NamedTuple{
ice_start::Bool,
_magnitude::FT,
_q_flux::FT,
_N_flux::FT,
_F_rim::FT,
_F_liq::FT,
_ρ_r_init::FT,
}
p3_boundary_condition = @. p3_boundary_condition_eltype(
tuple(
copy(precip.p3_boundary_condition.ice_start),
copy(precip.p3_boundary_condition._magnitude),
copy(precip.p3_boundary_condition._q_flux),
copy(precip.p3_boundary_condition._N_flux),
copy(precip.p3_boundary_condition._F_rim),
copy(precip.p3_boundary_condition._F_liq),
copy(precip.p3_boundary_condition._ρ_r_init),
),
)

activation_sources = nothing
@assert moisture isa NonEquilibrumMoisture
elseif precip isa CloudyPrecip
microph_variables = (;
q_tot = ip.q_tot,
Expand All @@ -241,7 +275,7 @@ function initialise_aux(
cloudy_variables = (; nm_cloud = Val(cloudy_params.NProgMoms[1]))
scratch = merge(scratch, (; tmp_cloudy = similar(ip.cloudy_moments_zero)))
else
error("Wrong precipitation choise $precip")
error("Wrong precipitation choice $precip")
end

aux = (;
Expand All @@ -262,6 +296,8 @@ function initialise_aux(

if precip isa CloudyPrecip
aux = merge(aux, (; cloudy_params, cloudy_variables))
elseif precip isa PrecipitationP3
aux = merge(aux, (; p3_boundary_condition))
end

return aux
Expand Down
Loading
Loading