Skip to content

Commit

Permalink
Add implict solver for diagnostic EDMF
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisYatunin authored and szy21 committed Dec 1, 2023
1 parent eb82e32 commit 551f230
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 110 deletions.
8 changes: 8 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,14 @@ steps:
agents:
slurm_mem: 20GB

- label: ":genie: Diagnostic EDMFX DYCOMS_RF01 in a box (implicit)"
command: >
julia --color=yes --project=examples examples/hybrid/driver.jl
--config_file $CONFIG_PATH/diagnostic_edmfx_dycoms_rf01_box_implicit.yml
artifact_paths: "diagnostic_edmfx_dycoms_rf01_box_implicit/*"
agents:
slurm_mem: 20GB

- label: ":genie: Diagnostic EDMFX Rico in a box"
command: >
julia --color=yes --project=examples examples/hybrid/driver.jl
Expand Down
2 changes: 1 addition & 1 deletion config/model_configs/diagnostic_edmfx_dycoms_rf01_box.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ z_max: 1500
z_stretch: false
dt: 40secs
t_end: 4hours
dt_save_to_disk: 2mins
dt_save_to_disk: 10mins
toml: [toml/diagnostic_edmfx_box.toml]
30 changes: 30 additions & 0 deletions config/model_configs/diagnostic_edmfx_dycoms_rf01_box_implicit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
job_id: diagnostic_edmfx_dycoms_rf01_box_implicit
initial_condition: DYCOMS_RF01
subsidence: DYCOMS
edmf_coriolis: DYCOMS_RF01
rad: DYCOMS_RF01
surface_setup: DYCOMS_RF01
turbconv: diagnostic_edmfx
implicit_diffusion: true
prognostic_tke: true
edmfx_upwinding: first_order
edmfx_entr_model: "Generalized"
edmfx_detr_model: "Generalized"
edmfx_nh_pressure: true
edmfx_sgs_mass_flux: true
edmfx_sgs_diffusive_flux: true
moist: equil
config: box
hyperdiff: "true"
kappa_4: 1e21
x_max: 1e8
y_max: 1e8
x_elem: 2
y_elem: 2
z_elem: 30
z_max: 1500
z_stretch: false
dt: 40secs
t_end: 4hours
dt_save_to_disk: 10mins
toml: [toml/diagnostic_edmfx_box.toml]
29 changes: 28 additions & 1 deletion src/cache/precomputed_quantities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function precomputed_quantities(Y, atmos)
!(atmos.turbconv_model isa PrognosticEDMFX)
@assert !(atmos.edmfx_detr_model isa ConstantAreaDetrainment) ||
!(atmos.turbconv_model isa DiagnosticEDMFX)
@assert isnothing(atmos.turbconv_model) || isnothing(atmos.vert_diff)
TST = thermo_state_type(atmos.moisture_model, FT)
SCT = SurfaceConditions.surface_conditions_type(atmos, FT)
n = n_mass_flux_subdomains(atmos.turbconv_model)
Expand Down Expand Up @@ -109,13 +110,20 @@ function precomputed_quantities(Y, atmos)
ᶜK_h = similar(Y.c, FT),
ρatke_flux = similar(Fields.level(Y.f, half), C3{FT}),
) : (;)
vert_diff_quantities = if atmos.vert_diff isa VerticalDiffusion
ᶜK_h = similar(Y.c, FT)
(; ᶜK_u = ᶜK_h, ᶜK_h) # ᶜK_u aliases ᶜK_h because they are always equal.
else
(;)
end
precipitation_quantities =
atmos.precip_model isa Microphysics1Moment ?
(; ᶜwᵣ = similar(Y.c, FT), ᶜwₛ = similar(Y.c, FT)) : (;)
return (;
gs_quantities...,
advective_sgs_quantities...,
diagnostic_sgs_quantities...,
vert_diff_quantities...,
precipitation_quantities...,
)
end
Expand Down Expand Up @@ -272,6 +280,13 @@ ts_sgs(thermo_params, moisture_model, specific, K, Φ, p) = thermo_state(
p,
)

function eddy_diffusivity_coefficient(C_E, norm_v_a, z_a, p)
p_pbl = 85000
p_strato = 10000
K_E = C_E * norm_v_a * z_a
return p > p_pbl ? K_E : K_E * exp(-((p_pbl - p) / p_strato)^2)
end

"""
set_precomputed_quantities!(Y, p, t)
Expand All @@ -289,7 +304,7 @@ function instead of recomputing the value yourself. Otherwise, it will be
difficult to ensure that the duplicated computations are consistent.
"""
NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
(; moisture_model, turbconv_model, precip_model) = p.atmos
(; moisture_model, turbconv_model, vert_diff, precip_model) = p.atmos
thermo_params = CAP.thermodynamics_params(p.params)
n = n_mass_flux_subdomains(turbconv_model)
thermo_args = (thermo_params, moisture_model)
Expand Down Expand Up @@ -344,6 +359,18 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
set_diagnostic_edmf_precomputed_quantities_env_closures!(Y, p, t)
end

if vert_diff isa VerticalDiffusion
(; ᶜK_h) = p.precomputed
interior_uₕ = Fields.level(Y.c.uₕ, 1)
ᶜΔz_surface = Fields.Δz_field(interior_uₕ)
@. ᶜK_h = eddy_diffusivity_coefficient(
p.atmos.vert_diff.C_E,
norm(interior_uₕ),
ᶜΔz_surface / 2,
ᶜp,
)
end

if precip_model isa Microphysics1Moment
set_precipitation_precomputed_quantities!(Y, p, t)
end
Expand Down
69 changes: 35 additions & 34 deletions src/prognostic_equations/implicit/implicit_solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,10 @@ function ImplicitEquationJacobian(
(@name(c.ρe_tot), available_tracer_names...),
)...,
(@name(c.uₕ), @name(c.uₕ)) =>
use_derivative(diffusion_flag) &&
diffuse_momentum(atmos.vert_diff) ?
similar(Y.c, TridiagonalRow) : FT(-1) * I,
use_derivative(diffusion_flag) && (
!isnothing(atmos.turbconv_model) ||
diffuse_momentum(atmos.vert_diff)
) ? similar(Y.c, TridiagonalRow) : FT(-1) * I,
MatrixFields.unrolled_map(
name -> (name, name) => FT(-1) * I,
other_available_names,
Expand Down Expand Up @@ -247,6 +248,11 @@ function Wfact!(A, Y, p, dtγ, t)
p.precomputed.ᶠu³,
p.precomputed.ᶜK,
p.precomputed.ᶜp,
p.precomputed.ᶜh_tot,
(
use_derivative(A.diffusion_flag) ?
(; p.precomputed.ᶜK_u, p.precomputed.ᶜK_h) : (;)
)...,
p.core.∂ᶜK_∂ᶠu₃,
p.core.ᶜΦ,
p.core.ᶠgradᵥ_ᶜΦ,
Expand All @@ -256,7 +262,6 @@ function Wfact!(A, Y, p, dtγ, t)
p.scratch.ᶠtemp_scalar,
p.params,
p.atmos,
p.precomputed.ᶜh_tot,
(
rayleigh_sponge isa RayleighSponge ?
(; p.rayleigh_sponge.ᶠβ_rayleigh_w) : (;)
Expand Down Expand Up @@ -511,41 +516,43 @@ function update_implicit_equation_jacobian!(A, Y, p, dtγ, colidx)
∂ᶜK_∂ᶠu₃[colidx] - (I_u₃,)
end

# We can express the implicit diffusion tendency for scalars and horizontal
# velocity as
# ᶜρχₜ = ᶜadvdivᵥ(ᶠρK_E * ᶠgradᵥ(ᶜχ)) and
# ᶜuₕₜ = ᶜadvdivᵥ(ᶠρK_E * ᶠgradᵥ(ᶜuₕ)) / ᶜρ.
# We can express the implicit diffusion tendency for horizontal velocity and
# scalars as
# ᶜuₕₜ = ᶜadvdivᵥ(ᶠinterp(ᶜρ) * ᶠinterp(ᶜK_u) * ᶠgradᵥ(ᶜuₕ)) / ᶜρ and
# ᶜρχₜ = ᶜadvdivᵥ(ᶠinterp(ᶜρ) * ᶠinterp(ᶜK_h) * ᶠgradᵥ(ᶜχ)).
# The implicit diffusion tendency for horizontal velocity actually uses
# 2 * ᶠstrain_rate instead of ᶠgradᵥ(ᶜuₕ), but these are roughly equivalent.
# The implicit diffusion tendency for density is the sum of the ᶜρχₜ's, but
# we approximate the derivative of this sum with respect to ᶜρ as 0.
# This means that
# ∂(ᶜρχₜ)/∂(ᶜρχ) =
# ᶜadvdivᵥ_matrix() ⋅ DiagonalMatrixRow(ᶠρK_E) ⋅ ᶠgradᵥ_matrix() ⋅
# ∂(ᶜχ)/∂(ᶜρχ) and
# ∂(ᶜuₕₜ)/∂(ᶜuₕ) =
# DiagonalMatrixRow(1 / ᶜρ) ⋅ ᶜadvdivᵥ_matrix() ⋅
# DiagonalMatrixRow(ᶠρK_E) ⋅ ᶠgradᵥ_matrix().
# DiagonalMatrixRow(ᶠinterp(ᶜρ) * ᶠinterp(ᶜK_u)) ⋅ ᶠgradᵥ_matrix() and
# ∂(ᶜρχₜ)/∂(ᶜρχ) =
# ᶜadvdivᵥ_matrix() ⋅ DiagonalMatrixRow(ᶠinterp(ᶜρ) * ᶠinterp(ᶜK_h)) ⋅
# ᶠgradᵥ_matrix() ⋅ ∂(ᶜχ)/∂(ᶜρχ).
# In general, ∂(ᶜχ)/∂(ᶜρχ) = DiagonalMatrixRow(1 / ᶜρ), except for the case
# ∂(ᶜh_tot)/∂(ᶜρe_tot) =
# ∂((ᶜρe_tot + ᶜp) / ᶜρ)/∂(ᶜρe_tot) =
# (I + ∂(ᶜp)/∂(ᶜρe_tot)) ⋅ DiagonalMatrixRow(1 / ᶜρ) ≈
# DiagonalMatrixRow((1 + R_d / cv_d) / ᶜρ).
if use_derivative(diffusion_flag)
(; C_E) = p.atmos.vert_diff
ᶠp = ᶠρK_E = p.ᶠtemp_scalar
interior_uₕ = Fields.level(Y.c.uₕ, 1)
ᶜΔz_surface = Fields.Δz_field(interior_uₕ)
@. ᶠp[colidx] = ᶠinterp(ᶜp[colidx])
@. ᶠρK_E[colidx] =
ᶠinterp(Y.c.ρ[colidx]) * eddy_diffusivity_coefficient(
C_E,
norm(interior_uₕ[colidx]),
ᶜΔz_surface[colidx] / 2,
ᶠp[colidx],
)
if (
!isnothing(p.atmos.turbconv_model) ||
diffuse_momentum(p.atmos.vert_diff)
)
∂ᶜuₕ_err_∂ᶜuₕ = matrix[@name(c.uₕ), @name(c.uₕ)]
@. ∂ᶜuₕ_err_∂ᶜuₕ[colidx] =
dtγ * DiagonalMatrixRow(1 / ᶜρ[colidx]) ᶜadvdivᵥ_matrix()
DiagonalMatrixRow(
ᶠinterp(ᶜρ[colidx]) * ᶠinterp(p.ᶜK_u[colidx]),
) ᶠgradᵥ_matrix() - (I,)
end

∂ᶜρe_tot_err_∂ᶜρe_tot = matrix[@name(c.ρe_tot), @name(c.ρe_tot)]
@. ∂ᶜρe_tot_err_∂ᶜρe_tot[colidx] =
dtγ * ᶜadvdivᵥ_matrix() DiagonalMatrixRow(ᶠρK_E[colidx])
dtγ * ᶜadvdivᵥ_matrix()
DiagonalMatrixRow(ᶠinterp(ᶜρ[colidx]) * ᶠinterp(p.ᶜK_h[colidx]))
ᶠgradᵥ_matrix() DiagonalMatrixRow((1 + R_d / cv_d) / ᶜρ[colidx]) -
(I,)

Expand All @@ -560,15 +567,9 @@ function update_implicit_equation_jacobian!(A, Y, p, dtγ, colidx)
MatrixFields.has_field(Y, ρχ_name) || return
∂ᶜρχ_err_∂ᶜρχ = matrix[ρχ_name, ρχ_name]
@. ∂ᶜρχ_err_∂ᶜρχ[colidx] =
dtγ * ᶜadvdivᵥ_matrix() DiagonalMatrixRow(ᶠρK_E[colidx])
ᶠgradᵥ_matrix() DiagonalMatrixRow(1 / ᶜρ[colidx]) - (I,)
end

if diffuse_momentum(p.atmos.vert_diff)
∂ᶜuₕ_err_∂ᶜuₕ = matrix[@name(c.uₕ), @name(c.uₕ)]
@. ∂ᶜuₕ_err_∂ᶜuₕ[colidx] =
dtγ * DiagonalMatrixRow(1 / ᶜρ[colidx]) ᶜadvdivᵥ_matrix()
DiagonalMatrixRow(ᶠρK_E[colidx]) ᶠgradᵥ_matrix() - (I,)
dtγ * ᶜadvdivᵥ_matrix() DiagonalMatrixRow(
ᶠinterp(ᶜρ[colidx]) * ᶠinterp(p.ᶜK_h[colidx]),
) ᶠgradᵥ_matrix() DiagonalMatrixRow(1 / ᶜρ[colidx]) - (I,)
end
end
end
8 changes: 8 additions & 0 deletions src/prognostic_equations/implicit/implicit_tendency.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ NVTX.@annotate function implicit_tendency!(Yₜ, Y, p, t)
colidx,
p.atmos.vert_diff,
)
edmfx_sgs_diffusive_flux_tendency!(
Yₜ,
Y,
p,
t,
colidx,
p.atmos.turbconv_model,
)
end
# NOTE: All ρa tendencies should be applied before calling this function
pressure_work_tendency!(Yₜ, Y, p, t, colidx, p.atmos.turbconv_model)
Expand Down
16 changes: 8 additions & 8 deletions src/prognostic_equations/remaining_tendency.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ NVTX.@annotate function additional_tendency!(Yₜ, Y, p, t)
colidx,
p.atmos.vert_diff,
)
edmfx_sgs_diffusive_flux_tendency!(
Yₜ,
Y,
p,
t,
colidx,
p.atmos.turbconv_model,
)
end

radiation_tendency!(Yₜ, Y, p, t, colidx, p.atmos.radiation_mode)
Expand All @@ -44,14 +52,6 @@ NVTX.@annotate function additional_tendency!(Yₜ, Y, p, t)
colidx,
p.atmos.turbconv_model,
)
edmfx_sgs_diffusive_flux_tendency!(
Yₜ,
Y,
p,
t,
colidx,
p.atmos.turbconv_model,
)
edmfx_nh_pressure_tendency!(Yₜ, Y, p, t, colidx, p.atmos.turbconv_model)
edmfx_tke_tendency!(Yₜ, Y, p, t, colidx, p.atmos.turbconv_model)
precipitation_tendency!(Yₜ, Y, p, t, colidx, p.atmos.precip_model)
Expand Down
Loading

0 comments on commit 551f230

Please sign in to comment.