Skip to content

Commit cf307ce

Browse files
author
Olivia Alcabes
committed
adding noneq flags and blocks
1 parent 7c8c26b commit cf307ce

File tree

2 files changed

+205
-11
lines changed

2 files changed

+205
-11
lines changed

src/prognostic_equations/implicit/approx_jacobian.jl

Lines changed: 204 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use_derivative(::IgnoreDerivative) = false
1717
sgs_entr_detr_flag,
1818
sgs_mass_flux_flag,
1919
sgs_nh_pressure_flag,
20+
noneq_cloud_formation_flag,
2021
approximate_solve_iters,
2122
)
2223
@@ -40,16 +41,19 @@ setting their `DerivativeFlag`s to either `UseDerivative` or `IgnoreDerivative`.
4041
subgrid-scale mass flux tendency should be computed
4142
- `sgs_nh_pressure_flag::DerivativeFlag`: whether the derivatives of the
4243
subgrid-scale non-hydrostatic pressure drag tendency should be computed
44+
- `noneq_cloud_formation_flag::DerivativeFlag`: whether the derivatives
45+
of the nonequilibrium cloud formation sources should be computed
4346
- `approximate_solve_iters::Int`: number of iterations to take for the
4447
approximate linear solve required when the `diffusion_flag` is `UseDerivative`
4548
"""
46-
struct ApproxJacobian{F1, F2, F3, F4, F5, F6} <: JacobianAlgorithm
49+
struct ApproxJacobian{F1, F2, F3, F4, F5, F6, F7} <: JacobianAlgorithm
4750
topography_flag::F1
4851
diffusion_flag::F2
4952
sgs_advection_flag::F3
5053
sgs_entr_detr_flag::F4
5154
sgs_mass_flux_flag::F5
5255
sgs_nh_pressure_flag::F6
56+
noneq_cloud_formation_flag::F7
5357
approximate_solve_iters::Int
5458
end
5559

@@ -59,6 +63,7 @@ function jacobian_cache(alg::ApproxJacobian, Y, atmos)
5963
diffusion_flag,
6064
sgs_advection_flag,
6165
sgs_mass_flux_flag,
66+
noneq_cloud_formation_flag,
6267
) = alg
6368
FT = Spaces.undertype(axes(Y.c))
6469
CTh = CTh_vector_type(axes(Y.c))
@@ -82,14 +87,12 @@ function jacobian_cache(alg::ApproxJacobian, Y, atmos)
8287
is_in_Y(@name(c.sgs⁰.ρatke)) ? (@name(c.sgs⁰.ρatke),) : ()
8388
sfc_if_available = is_in_Y(@name(sfc)) ? (@name(sfc),) : ()
8489

85-
tracer_names = (
86-
@name(c.ρq_tot),
87-
@name(c.ρq_liq),
88-
@name(c.ρq_ice),
89-
@name(c.ρq_rai),
90-
@name(c.ρq_sno),
91-
)
92-
available_tracer_names = MatrixFields.unrolled_filter(is_in_Y, tracer_names)
90+
condensate_names =
91+
(@name(c.ρq_liq), @name(c.ρq_ice), @name(c.ρq_rai), @name(c.ρq_sno))
92+
available_condensate_names =
93+
MatrixFields.unrolled_filter(is_in_Y, condensate_names)
94+
available_tracer_names =
95+
(ρq_tot_if_available..., available_condensate_names...)
9396

9497
sgs_tracer_names = (
9598
@name(c.sgsʲs.:(1).q_tot),
@@ -139,6 +142,17 @@ function jacobian_cache(alg::ApproxJacobian, Y, atmos)
139142
(@name(f.u₃), @name(f.u₃)) => similar(Y.f, TridiagonalRow_C3xACT3),
140143
)
141144

145+
condensate_blocks =
146+
if atmos.moisture_model isa NonEquilMoistModel &&
147+
use_derivative(noneq_cloud_formation_flag)
148+
(
149+
(@name(c.ρq_liq), @name(c.ρq_tot)) => similar(Y.c, DiagonalRow),
150+
(@name(c.ρq_ice), @name(c.ρq_tot)) => similar(Y.c, DiagonalRow),
151+
)
152+
else
153+
()
154+
end
155+
142156
diffused_scalar_names = (@name(c.ρe_tot), available_tracer_names...)
143157
diffusion_blocks = if use_derivative(diffusion_flag)
144158
(
@@ -253,6 +267,7 @@ function jacobian_cache(alg::ApproxJacobian, Y, atmos)
253267
identity_blocks...,
254268
sgs_advection_blocks...,
255269
advection_blocks...,
270+
condensate_blocks...,
256271
diffusion_blocks...,
257272
sgs_massflux_blocks...,
258273
)
@@ -318,7 +333,7 @@ function jacobian_cache(alg::ApproxJacobian, Y, atmos)
318333
temp_matrix_column = similar(first_column(temp_matrix))
319334

320335
return (;
321-
matrix = MatrixFields.FieldMatrixWithSolver(matrix, Y, solver_alg),
336+
matrix = MatrixFields.FieldMatrixWithSolver(matrix, Y, full_alg),
322337
temp_matrix,
323338
temp_matrix_column,
324339
)
@@ -348,8 +363,9 @@ function update_jacobian!(alg::ApproxJacobian, cache, Y, p, dtγ, t)
348363
diffusion_flag,
349364
sgs_advection_flag,
350365
sgs_entr_detr_flag,
351-
sgs_nh_pressure_flag,
352366
sgs_mass_flux_flag,
367+
sgs_nh_pressure_flag,
368+
noneq_cloud_formation_flag,
353369
) = alg
354370
(; matrix) = cache
355371
(; params) = p
@@ -555,6 +571,183 @@ function update_jacobian!(alg::ApproxJacobian, cache, Y, p, dtγ, t)
555571

556572
end
557573

574+
if p.atmos.moisture_model isa NonEquilMoistModel &&
575+
use_derivative(noneq_flag)
576+
p_vapₛₗ(tps, ts) = TD.saturation_vapor_pressure(tps, ts, TD.Liquid())
577+
p_vapₛᵢ(tps, ts) = TD.saturation_vapor_pressure(tps, ts, TD.Ice())
578+
579+
function ∂p_vapₛₗ_∂T(tps, ts)
580+
T = TD.air_temperature(tps, ts)
581+
Rᵥ = TD.Parameters.R_v(tps)
582+
Lᵥ = TD.latent_heat_vapor(tps, ts)
583+
return p_vapₛₗ(tps, ts) * Lᵥ / (Rᵥ * T^2)
584+
end
585+
function ∂p_vapₛᵢ_∂T(tps, ts)
586+
T = TD.air_temperature(tps, ts)
587+
Rᵥ = TD.Parameters.R_v(tps)
588+
Lₛ = TD.latent_heat_sublim(tps, ts)
589+
return p_vapₛᵢ(tps, ts) * Lₛ / (Rᵥ * T^2)
590+
end
591+
592+
function ∂qₛₗ_∂T(tps, ts)
593+
T = TD.air_temperature(tps, ts)
594+
Rᵥ = TD.Parameters.R_v(tps)
595+
Lᵥ = TD.latent_heat_vapor(tps, ts)
596+
qᵥ_sat_liq = TD.q_vap_saturation_liquid(tps, ts)
597+
return qᵥ_sat_liq * (Lᵥ / (Rᵥ * T^2) - 1 / T)
598+
end
599+
function ∂qₛᵢ_∂T(tps, ts)
600+
T = TD.air_temperature(tps, ts)
601+
Rᵥ = TD.Parameters.R_v(tps)
602+
Lₛ = TD.latent_heat_sublim(tps, ts)
603+
qᵥ_sat_ice = TD.q_vap_saturation_ice(tps, ts)
604+
return qᵥ_sat_ice * (Lₛ / (Rᵥ * T^2) - 1 / T)
605+
end
606+
607+
function Γₗ(tps, ts)
608+
cₚ_air = TD.cp_m(tps, ts)
609+
Lᵥ = TD.latent_heat_vapor(tps, ts)
610+
return 1 + (Lᵥ / cₚ_air) * ∂qₛₗ_∂T(tps, ts)
611+
end
612+
function Γᵢ(tps, ts)
613+
cₚ_air = TD.cp_m(tps, ts)
614+
Lₛ = TD.latent_heat_sublim(tps, ts)
615+
return 1 + (Lₛ / cₚ_air) * ∂qₛᵢ_∂T(tps, ts)
616+
end
617+
618+
cmc = CAP.microphysics_cloud_params(params)
619+
τₗ = cmc.liquid.τ_relax
620+
τᵢ = cmc.ice.τ_relax
621+
function limit(q, dt, n::Int)
622+
return q / float(dt) / n
623+
end
624+
625+
function ∂ρqₗ_err_∂ρqᵪ(tps, ts, cmc, dt, deriv, limit_deriv)
626+
FT_inner = eltype(tps)
627+
q = TD.PhasePartition(tps, ts)
628+
ρ = TD.air_density(tps, ts)
629+
630+
S = CMNe.conv_q_vap_to_q_liq_ice_MM2015(cmc.liquid, thp, q, ρ, Tₐ(tps, ts))
631+
632+
if S > FT_inner(0)
633+
if S <= limit(qᵥ(tps, ts), dt, 2)
634+
if TD.vapor_specific_humidity(q) + TD.liquid_specific_humidity(q) > FT_inner(0)
635+
return deriv
636+
else
637+
return FT_inner(0)
638+
end
639+
else
640+
return limit_deriv
641+
end
642+
else
643+
if abs(S) <= limit(qₗ(tps, ts, qₚ(qᵣ)), dt, 2)
644+
if TD.vapor_specific_humidity(q) + TD.liquid_specific_humidity(q) > FT_inner(0)
645+
return -deriv
646+
else
647+
return FT_inner(0)
648+
end
649+
else
650+
return -limit_deriv
651+
end
652+
end
653+
end
654+
655+
function ∂ρqᵢ_err_∂ρqᵪ(tps, ts, cmc, dt, deriv, limit_deriv)
656+
FT_inner = eltype(tps)
657+
q = TD.PhasePartition(tps, ts)
658+
ρ = TD.air_density(tps, ts)
659+
660+
S = CMNe.conv_q_vap_to_q_liq_ice_MM2015(cmc.ice, thp, q, ρ, Tₐ(tps, ts))
661+
662+
if S > FT_inner(0)
663+
if S <= limit(qᵥ(tps, ts), dt, 2)
664+
if TD.vapor_specific_humidity(q) + TD.ice_specific_humidity(q) > FT_inner(0)
665+
return deriv
666+
else
667+
return FT_inner(0)
668+
end
669+
else
670+
return limit_deriv
671+
end
672+
else
673+
if abs(S) <= limit(qᵢ(thp, ts, qₚ(qₛ)), dt, 2)
674+
if TD.vapor_specific_humidity(q) + TD.ice_specific_humidity(q) > FT_inner(0)
675+
return -deriv
676+
else
677+
return FT_inner(0)
678+
end
679+
else
680+
return -limit_deriv
681+
end
682+
end
683+
end
684+
685+
686+
∂ᶜρqₗ_err_∂ᶜρqₗ = matrix[@name(c.ρq_liq), @name(c.ρq_liq)]
687+
∂ᶜρqᵢ_err_∂ᶜρqᵢ = matrix[@name(c.ρq_ice), @name(c.ρq_ice)]
688+
689+
∂ᶜρqₗ_err_∂ᶜρqₜ = matrix[@name(c.ρq_liq), @name(c.ρq_tot)]
690+
∂ᶜρqᵢ_err_∂ᶜρqₜ = matrix[@name(c.ρq_ice), @name(c.ρq_tot)]
691+
692+
#@. ∂ᶜρqₗ_err_∂ᶜρqₗ -=
693+
# DiagonalMatrixRow(1 / (τₗ * Γₗ(thermo_params, ᶜts)))
694+
@. ∂ᶜρqₗ_err_∂ᶜρqₗ +=
695+
DiagonalMatrixRow(
696+
∂ρqₗ_err_∂ρqᵪ(
697+
thermo_params, ᶜts, cmc, dt, (-1 / (τₗ * Γₗ(thermo_params, ᶜts))), (1/(2*float(dt))),
698+
)
699+
)
700+
701+
#@. ∂ᶜρqᵢ_err_∂ᶜρqᵢ -=
702+
# DiagonalMatrixRow(1 / (τᵢ * Γᵢ(thermo_params, ᶜts)))
703+
704+
@. ∂ᶜρqᵢ_err_∂ᶜρqᵢ +=
705+
DiagonalMatrixRow(
706+
∂ρqᵢ_err_∂ρqᵪ(
707+
thermo_params, ᶜts, cmc, dt, (-1 / (τᵢ * Γᵢ(thermo_params, ᶜts))), (1/(2*float(dt))),
708+
)
709+
)
710+
711+
ᶜp = @. lazy(TD.air_pressure(thermo_params, ᶜts))
712+
ᶜ∂T_∂p = @. lazy(1 / (ᶜρ * TD.gas_constant_air(thermo_params, ᶜts)))
713+
714+
# qₛₗ = p_vapₛₗ / p, qₛᵢ = p_vapₛᵢ / p
715+
ᶜ∂qₛₗ_∂p = @. lazy(
716+
-p_vapₛₗ(thermo_params, ᶜts) / ᶜp^2 +
717+
∂p_vapₛₗ_∂T(thermo_params, ᶜts) * ᶜ∂T_∂p / ᶜp,
718+
)
719+
ᶜ∂qₛᵢ_∂p = @. lazy(
720+
-p_vapₛᵢ(thermo_params, ᶜts) / ᶜp^2 +
721+
∂p_vapₛᵢ_∂T(thermo_params, ᶜts) * ᶜ∂T_∂p / ᶜp,
722+
)
723+
724+
ᶜ∂p_∂ρqₜ = @. lazy(
725+
ᶜkappa_m * ∂e_int_∂q_tot +
726+
ᶜ∂kappa_m∂q_tot * (
727+
cp_d * T_0 + ᶜspecific.e_tot - ᶜK - ᶜΦ +
728+
∂e_int_∂q_tot * ᶜspecific.q_tot
729+
),
730+
)
731+
732+
#@. ∂ᶜρqₗ_err_∂ᶜρqₜ = DiagonalMatrixRow(
733+
# (1 - ᶜρ * ᶜ∂qₛₗ_∂p * ᶜ∂p_∂ρqₜ) / (τₗ * Γₗ(thermo_params, ᶜts)),
734+
#)
735+
@. ∂ᶜρqₗ_err_∂ᶜρqₜ = DiagonalMatrixRow(
736+
∂ρqₗ_err_∂ρqᵪ(
737+
thermo_params, ts, cmc, dt, ((1 - ᶜρ * ᶜ∂qₛₗ_∂p * ᶜ∂p_∂ρqₜ) / (τₗ * Γₗ(thermo_params, ᶜts))), FT(0)
738+
)
739+
)
740+
741+
#@. ∂ᶜρqᵢ_err_∂ᶜρqₜ = DiagonalMatrixRow(
742+
# (1 - ᶜρ * ᶜ∂qₛᵢ_∂p * ᶜ∂p_∂ρqₜ) / (τᵢ * Γᵢ(thermo_params, ᶜts)),
743+
#)
744+
@. ∂ᶜρqᵢ_err_∂ᶜρqₜ = DiagonalMatrixRow(
745+
∂ρqᵢ_err_∂ρqᵪ(
746+
thermo_params, ts, cmc, dt, ((1 - ᶜρ * ᶜ∂qₛᵢ_∂p * ᶜ∂p_∂ρqₜ) / (τᵢ * Γᵢ(thermo_params, ᶜts))), FT(0)
747+
)
748+
)
749+
end
750+
558751
if use_derivative(diffusion_flag)
559752
α_vert_diff_tracer = CAP.α_vert_diff_tracer(params)
560753
(; ᶜK_h, ᶜK_u) = p.precomputed

src/solver/type_getters.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ get_jacobian(ode_algo, Y, atmos, parsed_args, output_dir) =
423423
DerivativeFlag(atmos.sgs_entr_detr_mode),
424424
DerivativeFlag(atmos.sgs_mf_mode),
425425
DerivativeFlag(atmos.sgs_nh_pressure_mode),
426+
DerivativeFlag(atmos.noneq_cloud_formation_mode),
426427
parsed_args["approximate_linear_solve_iters"],
427428
)
428429
use_exact_jacobian = parsed_args["use_exact_jacobian"]

0 commit comments

Comments
 (0)