Skip to content

Commit 580d6b9

Browse files
committed
Add limiter option for NonEq in parcel
1 parent d3a8ae2 commit 580d6b9

File tree

4 files changed

+36
-18
lines changed

4 files changed

+36
-18
lines changed

parcel/Example_NonEq.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ include(joinpath(pkgdir(CM), "parcel", "Parcel.jl"))
1111

1212
# choosing a value for the ice relaxation timescale
1313
τ = FT(10)
14+
limiter = true
1415
@info("using τ value ", τ)
1516
override_file = Dict(
1617
"condensation_evaporation_timescale" =>
@@ -72,6 +73,7 @@ ax6 = MK.Axis(fig[3, 2], xlabel = "Time [s]", ylabel = "q_ice [g/kg]")
7273
params = parcel_params{FT}(
7374
condensation_growth = condensation_growth,
7475
deposition_growth = deposition_growth,
76+
limiter = limiter,
7577
const_dt = const_dt,
7678
w = w,
7779
liquid = liquid,

parcel/ParcelModel.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Base.@kwdef struct parcel_params{FT} <: CMP.ParametersType{FT}
2121
deposition_growth = "None"
2222
liq_size_distribution = "Monodisperse"
2323
ice_size_distribution = "Monodisperse"
24+
limiter = false
2425
aerosol = Empty{FT}()
2526
aero_σ_g = FT(0)
2627
wps = CMP.WaterProperties(FT)
@@ -293,7 +294,7 @@ function run_parcel(IC, t_0, t_end, pp)
293294
elseif pp.condensation_growth == "NonEq_Condensation_simple"
294295
ce_params = NonEqCondParams_simple{FT}(pp.tps, pp.liquid)
295296
elseif pp.condensation_growth == "NonEq_Condensation"
296-
ce_params = NonEqCondParams{FT}(pp.tps, pp.liquid, pp.const_dt)
297+
ce_params = NonEqCondParams{FT}(pp.tps, pp.liquid, pp.limiter, pp.const_dt)
297298
else
298299
throw("Unrecognized condensation growth mode")
299300
end
@@ -306,7 +307,7 @@ function run_parcel(IC, t_0, t_end, pp)
306307
elseif pp.deposition_growth == "NonEq_Deposition_simple"
307308
ds_params = NonEqDepParams_simple{FT}(pp.tps, pp.ice)
308309
elseif pp.deposition_growth == "NonEq_Deposition"
309-
ds_params = NonEqDepParams{FT}(pp.tps, pp.ice, pp.const_dt)
310+
ds_params = NonEqDepParams{FT}(pp.tps, pp.ice, pp.limiter, pp.const_dt)
310311
else
311312
throw("Unrecognized deposition growth mode")
312313
end

parcel/ParcelParameters.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ end
9090
struct NonEqCondParams{FT} <: CMP.ParametersType{FT}
9191
tps::TDP.ThermodynamicsParameters{FT}
9292
liquid::CMP.CloudLiquid{FT}
93+
limiter::Bool
9394
dt::FT
9495
end
9596

@@ -107,5 +108,6 @@ end
107108
struct NonEqDepParams{FT} <: CMP.ParametersType{FT}
108109
tps::TDP.ThermodynamicsParameters{FT}
109110
ice::CMP.CloudIce{FT}
111+
limiter::Bool
110112
dt::FT
111113
end

parcel/ParcelTendencies.jl

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ function limit(q, dt, n::Int)
1212
return q / dt / n
1313
end
1414

15+
# the triangle inequality limiter used in ClimaAtmos
16+
function triangle_inequality_limiter(force, limit)
17+
return force + limit - sqrt(force^2 + limit^2)
18+
end
19+
1520
function aerosol_activation(::Empty, state)
1621
FT = eltype(state)
1722
return FT(0)
@@ -249,23 +254,28 @@ end
249254
function condensation(params::NonEqCondParams, PSD, state, ρ_air)
250255
FT = eltype(state)
251256
(; T, qₗ, qᵥ, qᵢ) = state
252-
(; tps, liquid, dt) = params
253257

254-
if qᵥ + qₗ > FT(0)
258+
(; tps, liquid, limiter, dt) = params
255259

256-
qₜ = qᵥ + qₗ + qᵢ
260+
qₜ = qᵥ + qₗ + qᵢ
257261

258-
cond_rate = MNE.conv_q_vap_to_q_liq_ice_MM2015(liquid, tps, qₜ, qₗ, qᵢ, FT(0), FT(0), ρ_air, T)
262+
cond_rate = MNE.conv_q_vap_to_q_liq_ice_MM2015(liquid, tps, qₜ, qₗ, qᵢ, FT(0), FT(0), ρ_air, T)
259263

260-
# Using same limiter as ClimaAtmos for now
264+
# Using same limiter as ClimaAtmos
265+
if limiter
261266
# Not sure why, but without intermediate storing of the tendencies for the
262267
# if/else branch this code segfaults on julia v1.11 (works fine on v1.10)
268+
263269
cond_limit = min(cond_rate, limit(qᵥ, dt, 1))
264270
evap_limit = min(abs(cond_rate), limit(qₗ, dt, 1))
265-
ret = ifelse(cond_rate > FT(0), cond_limit, -1 * evap_limit)
266-
return ret
271+
272+
return ifelse(
273+
cond_rate > FT(0),
274+
triangle_inequality_limiter(cond_rate, cond_limit),
275+
-triangle_inequality_limiter(abs(cond_rate), evap_limit),
276+
)
267277
else
268-
return FT(0)
278+
return cond_rate
269279
end
270280
end
271281

@@ -307,21 +317,24 @@ function deposition(params::NonEqDepParams, PSD, state, ρ_air)
307317
FT = eltype(state)
308318
(; T, qₗ, qᵥ, qᵢ) = state
309319

310-
(; tps, ice, dt) = params
320+
(; tps, ice, limiter, dt) = params
311321

312-
if qᵥ + qᵢ > FT(0)
313-
qₜ = qᵥ + qₗ + qᵢ
322+
qₜ = qᵥ + qₗ + qᵢ
314323

315-
dep_rate = MNE.conv_q_vap_to_q_liq_ice_MM2015(ice, tps, qₜ, qₗ, qᵢ, FT(0), FT(0), ρ_air, T)
324+
dep_rate = MNE.conv_q_vap_to_q_liq_ice_MM2015(ice, tps, qₜ, qₗ, qᵢ, FT(0), FT(0), ρ_air, T)
316325

317-
# Using same limiter as ClimaAtmos for now
326+
# using same limiter as ClimaAtmos for now
327+
if limiter
318328
# Not sure why, but without intermediate storing of the tendencies for the
319329
# if/else branch this code segfaults on julia v1.11 (works fine on v1.10)
320330
dep_limit = min(dep_rate, limit(qᵥ, dt, 1))
321331
sub_limit = min(abs(dep_rate), limit(qᵢ, dt, 1))
322-
ret = ifelse(dep_rate > FT(0), dep_limit, -1 * sub_limit)
323-
return ret
332+
return ifelse(
333+
dep_rate > FT(0),
334+
triangle_inequality_limiter(dep_rate, dep_limit),
335+
-triangle_inequality_limiter(abs(dep_rate), sub_limit),
336+
)
324337
else
325-
return FT(0)
338+
return dep_rate
326339
end
327340
end

0 commit comments

Comments
 (0)