Skip to content

Commit 87a14ef

Browse files
committed
Jacobian: clip derivative values with respect to tracers to zero when they are negative
1 parent 0116312 commit 87a14ef

File tree

1 file changed

+56
-9
lines changed

1 file changed

+56
-9
lines changed

src/prognostic_equations/implicit/manual_sparse_jacobian.jl

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,13 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
480480

481481
T = @. lazy(TD.air_temperature(thermo_params, ᶜts))
482482
ᶜ∂p∂ρq_tot = p.scratch.ᶜtemp_scalar_2
483-
@. ᶜ∂p∂ρq_tot = ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T
483+
if MatrixFields.has_field(Y, @name(c.ρq_tot))
484+
@. ᶜ∂p∂ρq_tot = ifelse(
485+
Y.c.ρq_tot < 0,
486+
zero(Y.c.ρ),
487+
ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T,
488+
)
489+
end
484490

485491
if use_derivative(topography_flag)
486492
@. ∂ᶜK_∂ᶜuₕ = DiagonalMatrixRow(
@@ -567,9 +573,20 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
567573
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
568574
MatrixFields.has_field(Y, q_name) || continue
569575
∂ᶠu₃_err_∂ᶜρq = matrix[@name(f.u₃), q_name]
576+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
577+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
578+
else
579+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
580+
end
570581
@. ∂ᶠu₃_err_∂ᶜρq =
571582
dtγ * ᶠp_grad_matrix
572-
DiagonalMatrixRow(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T)
583+
DiagonalMatrixRow(
584+
ifelse(
585+
p.scratch.ᶜtemp_scalar_3 < 0,
586+
zero(Y.c.ρ),
587+
ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T,
588+
),
589+
)
573590
end
574591

575592
∂ᶠu₃_err_∂ᶜuₕ = matrix[@name(f.u₃), @name(c.uₕ)]
@@ -722,9 +739,20 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
722739
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
723740
MatrixFields.has_field(Y, q_name) || continue
724741
∂ᶜρe_tot_err_∂ᶜρq = matrix[@name(c.ρe_tot), q_name]
742+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
743+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
744+
else
745+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
746+
end
725747
@. ∂ᶜρe_tot_err_∂ᶜρq +=
726748
dtγ * ᶜdiffusion_h_matrix
727-
DiagonalMatrixRow((ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ)
749+
DiagonalMatrixRow(
750+
ifelse(
751+
p.scratch.ᶜtemp_scalar_3 < 0,
752+
zero(Y.c.ρ),
753+
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
754+
),
755+
)
728756
end
729757

730758
MatrixFields.unrolled_foreach(tracer_info) do (ρχ_name, _, α)
@@ -954,8 +982,20 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
954982
for (qʲ_name, LH, ∂cp∂q, ∂Rm∂q) in sgs_microphysics_tracers
955983
MatrixFields.has_field(Y, qʲ_name) || continue
956984

957-
@. ᶜ∂RmT∂qʲ =
958-
ᶜkappa_mʲ / (ᶜkappa_mʲ + 1) * (LH - ∂cp∂q * (ᶜTʲ - T_0)) + ∂Rm∂q * ᶜTʲ
985+
if qʲ_name == @name(c.sgsʲs.:(1).q_tot)
986+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.sgsʲs.:(1).q_tot
987+
elseif (
988+
qʲ_name == @name(c.sgsʲs.:(1).q_liq) ||
989+
qʲ_name == @name(c.sgsʲs.:(1).q_rai)
990+
)
991+
@. p.scratch.ᶜtemp_scalar_3 =
992+
Y.c.sgsʲs.:(1).q_liq + Y.c.sgsʲs.:(1).q_rai
993+
else
994+
@. p.scratch.ᶜtemp_scalar_3 =
995+
Y.c.sgsʲs.:(1).q_ice + Y.c.sgsʲs.:(1).q_sno
996+
end
997+
@. ᶜ∂RmT∂qʲ = ifelse(p.scratch.ᶜtemp_scalar_3 < 0, zero(Y.c.ρ),
998+
ᶜkappa_mʲ / (ᶜkappa_mʲ + 1) * (LH - ∂cp∂q * (ᶜTʲ - T_0)) + ∂Rm∂q * ᶜTʲ)
959999

9601000
# ∂ᶜρaʲ_err_∂ᶜqʲ through ρʲ variations in vertical transport of ρa
9611001
∂ᶜρaʲ_err_∂ᶜqʲ = matrix[@name(c.sgsʲs.:(1).ρa), qʲ_name]
@@ -1235,16 +1275,16 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
12351275

12361276
T = @. lazy(TD.air_temperature(thermo_params, ᶜts))
12371277
ᶜ∂p∂ρq_tot = p.scratch.ᶜtemp_scalar_2
1238-
@. ᶜ∂p∂ρq_tot =
1239-
ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T
1278+
@. ᶜ∂p∂ρq_tot = ifelse(Y.c.ρq_tot < 0, zero(Y.c.ρ),
1279+
ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T)
12401280

12411281
ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ))
12421282
@. ∂ᶜρe_tot_err_∂ᶜρ +=
12431283
p.scratch.ᶜtridiagonal_matrix_scalar
12441284
DiagonalMatrixRow(
12451285
(
12461286
-(1 + ᶜkappa_m) * ᶜe_tot -
1247-
ᶜkappa_m * ∂e_int_∂q_tot * ᶜq_tot
1287+
ᶜkappa_m * ∂e_int_∂q_tot * max(0, ᶜq_tot)
12481288
) / ᶜρ,
12491289
)
12501290

@@ -1255,10 +1295,17 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
12551295
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
12561296
MatrixFields.has_field(Y, q_name) || continue
12571297
∂ᶜρe_tot_err_∂ᶜρq = matrix[@name(c.ρe_tot), q_name]
1298+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
1299+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
1300+
else
1301+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
1302+
end
12581303
@. ∂ᶜρe_tot_err_∂ᶜρq +=
12591304
p.scratch.ᶜtridiagonal_matrix_scalar
12601305
DiagonalMatrixRow(
1261-
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
1306+
ifelse(p.scratch.ᶜtemp_scalar_3 < 0, zero(Y.c.ρ),
1307+
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
1308+
),
12621309
)
12631310
end
12641311

0 commit comments

Comments
 (0)