Skip to content

Commit e2ebbe9

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

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

src/prognostic_equations/implicit/manual_sparse_jacobian.jl

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,11 @@ 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+
@. ᶜ∂p∂ρq_tot = ifelse(
484+
Y.c.ρq_tot < 0,
485+
zero(Y.c.ρ),
486+
ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T,
487+
)
484488

485489
if use_derivative(topography_flag)
486490
@. ∂ᶜK_∂ᶜuₕ = DiagonalMatrixRow(
@@ -567,9 +571,20 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
567571
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
568572
MatrixFields.has_field(Y, q_name) || continue
569573
∂ᶠu₃_err_∂ᶜρq = matrix[@name(f.u₃), q_name]
574+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
575+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
576+
else
577+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
578+
end
570579
@. ∂ᶠu₃_err_∂ᶜρq =
571580
dtγ * ᶠp_grad_matrix
572-
DiagonalMatrixRow(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T)
581+
DiagonalMatrixRow(
582+
ifelse(
583+
p.scratch.ᶜtemp_scalar_3 < 0,
584+
zero(Y.c.ρ),
585+
ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T,
586+
),
587+
)
573588
end
574589

575590
∂ᶠu₃_err_∂ᶜuₕ = matrix[@name(f.u₃), @name(c.uₕ)]
@@ -722,9 +737,20 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
722737
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
723738
MatrixFields.has_field(Y, q_name) || continue
724739
∂ᶜρe_tot_err_∂ᶜρq = matrix[@name(c.ρe_tot), q_name]
740+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
741+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
742+
else
743+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
744+
end
725745
@. ∂ᶜρe_tot_err_∂ᶜρq +=
726746
dtγ * ᶜdiffusion_h_matrix
727-
DiagonalMatrixRow((ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ)
747+
DiagonalMatrixRow(
748+
ifelse(
749+
p.scratch.ᶜtemp_scalar_3 < 0,
750+
zero(Y.c.ρ),
751+
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
752+
),
753+
)
728754
end
729755

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

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

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

12361274
T = @. lazy(TD.air_temperature(thermo_params, ᶜts))
12371275
ᶜ∂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
1276+
@. ᶜ∂p∂ρq_tot = ifelse(Y.c.ρq_tot < 0, zero(Y.c.ρ),
1277+
ᶜkappa_m * (-e_int_v0 - R_d * T_0 - Δcv_v * (T - T_0)) + ΔR_v * T)
12401278

12411279
ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ))
12421280
@. ∂ᶜρe_tot_err_∂ᶜρ +=
12431281
p.scratch.ᶜtridiagonal_matrix_scalar
12441282
DiagonalMatrixRow(
12451283
(
12461284
-(1 + ᶜkappa_m) * ᶜe_tot -
1247-
ᶜkappa_m * ∂e_int_∂q_tot * ᶜq_tot
1285+
ᶜkappa_m * ∂e_int_∂q_tot * max(0, ᶜq_tot)
12481286
) / ᶜρ,
12491287
)
12501288

@@ -1255,10 +1293,17 @@ function update_jacobian!(alg::ManualSparseJacobian, cache, Y, p, dtγ, t)
12551293
for (q_name, e_int_q, ∂cv∂q) in microphysics_tracers
12561294
MatrixFields.has_field(Y, q_name) || continue
12571295
∂ᶜρe_tot_err_∂ᶜρq = matrix[@name(c.ρe_tot), q_name]
1296+
if (q_name == @name(c.ρq_liq) || q_name == @name(c.ρq_rai))
1297+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_liq + Y.c.ρq_rai
1298+
else
1299+
@. p.scratch.ᶜtemp_scalar_3 = Y.c.ρq_ice + Y.c.ρq_sno
1300+
end
12581301
@. ∂ᶜρe_tot_err_∂ᶜρq +=
12591302
p.scratch.ᶜtridiagonal_matrix_scalar
12601303
DiagonalMatrixRow(
1261-
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
1304+
ifelse(p.scratch.ᶜtemp_scalar_3 < 0, zero(Y.c.ρ),
1305+
(ᶜkappa_m * (e_int_q - ∂cv∂q * (T - T_0)) - R_v * T) / ᶜρ,
1306+
),
12621307
)
12631308
end
12641309

0 commit comments

Comments
 (0)