Skip to content

Commit dd2f543

Browse files
Merge pull request #3663 from CliMA/dy/split_precomputed
Split implicit and explicit precomputed quantities
2 parents 8835be9 + ff088a4 commit dd2f543

File tree

5 files changed

+170
-92
lines changed

5 files changed

+170
-92
lines changed

reproducibility_tests/ref_counter.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
219
1+
220
22

33
# **README**
44
#
@@ -20,6 +20,10 @@
2020

2121

2222
#=
23+
220
24+
- Split out cached variables that should be treated implicitly, so that all
25+
other cached variables are no longer updated by the implicit solver
26+
2327
219
2428
- Change the operations order in vertical advection upwinding
2529

src/cache/diagnostic_edmf_precomputed_quantities.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,6 @@ NVTX.@annotate function set_diagnostic_edmf_precomputed_quantities_env_closures!
962962
)
963963
ᶜtke_exch = p.scratch.ᶜtemp_scalar_2
964964
@. ᶜtke_exch = 0
965-
@. ᶜtke⁰ = Y.c.sgs⁰.ρatke / Y.c.ρ
966965
# using ᶜu⁰ would be more correct, but this is more consistent with the
967966
# TKE equation, where using ᶜu⁰ results in allocation
968967
for j in 1:n

src/cache/precomputed_quantities.jl

Lines changed: 129 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,85 @@ import Thermodynamics as TD
55
import ClimaCore: Spaces, Fields
66

77
"""
8-
precomputed_quantities(Y, atmos)
8+
implicit_precomputed_quantities(Y, atmos)
9+
10+
Allocates precomputed quantities that are treated implicitly (i.e., updated
11+
on each iteration of the implicit solver). This includes all quantities related
12+
to velocity and thermodynamics that are used in the implicit tendency.
913
10-
Allocates and returns the precomputed quantities:
11-
- `ᶜspecific`: the specific quantities on cell centers (for every prognostic
14+
The following grid-scale quantities are treated implicitly:
15+
- `ᶜspecific`: specific quantities on cell centers (for every prognostic
1216
quantity `ρχ`, there is a corresponding specific quantity `χ`)
13-
- `ᶜu`: the covariant velocity on cell centers
14-
- `ᶠu³`: the third component of contravariant velocity on cell faces
15-
- `ᶜK`: the kinetic energy on cell centers
16-
- `ᶜts`: the thermodynamic state on cell centers
17-
- `ᶜp`: the air pressure on cell centers
18-
- `sfc_conditions`: the conditions at the surface (at the bottom cell faces)
19-
- `ᶜh_tot`: the total enthalpy on cell centers
20-
21-
If the `turbconv_model` is EDMFX, there also two SGS versions of every quantity
22-
except for `ᶜp` (we assume that the pressure is the same across all subdomains):
23-
- `_⁰`: the value for the environment
24-
- `_ʲs`: a tuple of the values for the mass-flux subdomains
25-
In addition, there are several other SGS quantities for the EDMFX model:
26-
- `ᶜρa⁰`: the area-weighted air density of the environment on cell centers
27-
- `ᶠu₃⁰`: the vertical component of the covariant velocity of the environment
28-
on cell faces
29-
- `ᶜρ⁰`: the air density of the environment on cell centers
17+
- `ᶜu`: covariant velocity on cell centers
18+
- `ᶠu`: contravariant velocity on cell faces
19+
- `ᶜK`: kinetic energy on cell centers
20+
- `ᶜts`: thermodynamic state on cell centers
21+
- `ᶜp`: air pressure on cell centers
22+
- `ᶜh_tot`: total enthalpy on cell centers
23+
If the `turbconv_model` is `PrognosticEDMFX`, there also two SGS versions of
24+
every quantity except for `ᶜp` (which is shared across all subdomains):
25+
- `_⁰`: value for the environment
26+
- `_ʲs`: a tuple of values for the mass-flux subdomains
27+
In addition, there are several other SGS quantities for `PrognosticEDMFX`:
28+
- `ᶜtke⁰`: turbulent kinetic energy of the environment on cell centers
29+
- `ᶜρa⁰`: area-weighted air density of the environment on cell centers
30+
- `ᶜmse⁰`: moist static energy of the environment on cell centers
31+
- `ᶜq_tot⁰`: total specific humidity of the environment on cell centers
32+
- `ᶜρ⁰`: air density of the environment on cell centers
3033
- `ᶜρʲs`: a tuple of the air densities of the mass-flux subdomains on cell
3134
centers
35+
For every other `AbstractEDMF`, only `ᶜtke⁰` is added as a precomputed quantity.
3236
3337
TODO: Rename `ᶜK` to `ᶜκ`.
3438
"""
39+
function implicit_precomputed_quantities(Y, atmos)
40+
(; moisture_model, turbconv_model) = atmos
41+
FT = eltype(Y)
42+
TST = thermo_state_type(moisture_model, FT)
43+
n = n_mass_flux_subdomains(turbconv_model)
44+
gs_quantities = (;
45+
ᶜspecific = specific_gs.(Y.c),
46+
ᶜu = similar(Y.c, C123{FT}),
47+
ᶠu³ = similar(Y.f, CT3{FT}),
48+
ᶠu = similar(Y.f, CT123{FT}),
49+
ᶜK = similar(Y.c, FT),
50+
ᶜts = similar(Y.c, TST),
51+
ᶜp = similar(Y.c, FT),
52+
ᶜh_tot = similar(Y.c, FT),
53+
)
54+
sgs_quantities =
55+
turbconv_model isa AbstractEDMF ? (; ᶜtke⁰ = similar(Y.c, FT)) : (;)
56+
prognostic_sgs_quantities =
57+
turbconv_model isa PrognosticEDMFX ?
58+
(;
59+
ᶜρa⁰ = similar(Y.c, FT),
60+
ᶜmse⁰ = similar(Y.c, FT),
61+
ᶜq_tot⁰ = similar(Y.c, FT),
62+
ᶠu₃⁰ = similar(Y.f, C3{FT}),
63+
ᶜu⁰ = similar(Y.c, C123{FT}),
64+
ᶠu³⁰ = similar(Y.f, CT3{FT}),
65+
ᶜK⁰ = similar(Y.c, FT),
66+
ᶜts⁰ = similar(Y.c, TST),
67+
ᶜρ⁰ = similar(Y.c, FT),
68+
ᶜuʲs = similar(Y.c, NTuple{n, C123{FT}}),
69+
ᶠu³ʲs = similar(Y.f, NTuple{n, CT3{FT}}),
70+
ᶜKʲs = similar(Y.c, NTuple{n, FT}),
71+
ᶠKᵥʲs = similar(Y.f, NTuple{n, FT}),
72+
ᶜtsʲs = similar(Y.c, NTuple{n, TST}),
73+
ᶜρʲs = similar(Y.c, NTuple{n, FT}),
74+
) : (;)
75+
return (; gs_quantities..., sgs_quantities..., prognostic_sgs_quantities...)
76+
end
77+
78+
"""
79+
precomputed_quantities(Y, atmos)
80+
81+
Allocates all precomputed quantities. This includes the quantities treated
82+
implicitly (updated before each tendency evaluation), and also the quantities
83+
treated explicitly (updated only before explicit tendency evaluations).
84+
85+
TODO: Reduce the number of cached values by computing them on the fly.
86+
"""
3587
function precomputed_quantities(Y, atmos)
3688
FT = eltype(Y)
3789
@assert !(atmos.moisture_model isa DryModel) ||
@@ -45,20 +97,12 @@ function precomputed_quantities(Y, atmos)
4597
fspace = axes(Y.f)
4698
n = n_mass_flux_subdomains(atmos.turbconv_model)
4799
gs_quantities = (;
48-
ᶜspecific = specific_gs.(Y.c),
49-
ᶜu = similar(Y.c, C123{FT}),
50-
ᶠu³ = similar(Y.f, CT3{FT}),
51-
ᶠu = similar(Y.f, CT123{FT}),
52100
ᶜwₜqₜ = similar(Y.c, Geometry.WVector{FT}),
53101
ᶜwₕhₜ = similar(Y.c, Geometry.WVector{FT}),
54-
ᶜK = similar(Y.c, FT),
55-
ᶜts = similar(Y.c, TST),
56-
ᶜp = similar(Y.c, FT),
57-
ᶜh_tot = similar(Y.c, FT),
58102
ᶜmixing_length = similar(Y.c, FT),
59103
ᶜlinear_buoygrad = similar(Y.c, FT),
60104
ᶜstrain_rate_norm = similar(Y.c, FT),
61-
sfc_conditions = Fields.Field(SCT, Spaces.level(axes(Y.f), half)),
105+
sfc_conditions = similar(Spaces.level(Y.f, half), SCT),
62106
)
63107
cloud_diagnostics_tuple =
64108
similar(Y.c, @NamedTuple{cf::FT, q_liq::FT, q_ice::FT})
@@ -82,29 +126,13 @@ function precomputed_quantities(Y, atmos)
82126
advective_sgs_quantities =
83127
atmos.turbconv_model isa PrognosticEDMFX ?
84128
(;
85-
ᶜtke⁰ = similar(Y.c, FT),
86-
ᶜρa⁰ = similar(Y.c, FT),
87-
ᶠu₃⁰ = similar(Y.f, C3{FT}),
88-
ᶜu⁰ = similar(Y.c, C123{FT}),
89-
ᶠu³⁰ = similar(Y.f, CT3{FT}),
90-
ᶜK⁰ = similar(Y.c, FT),
91-
ᶜmse⁰ = similar(Y.c, FT),
92-
ᶜq_tot⁰ = similar(Y.c, FT),
93-
ᶜts⁰ = similar(Y.c, TST),
94-
ᶜρ⁰ = similar(Y.c, FT),
95129
ᶜmixing_length_tuple = similar(Y.c, MixingLength{FT}),
96130
ᶜK_u = similar(Y.c, FT),
97131
ᶜK_h = similar(Y.c, FT),
98132
ρatke_flux = similar(Fields.level(Y.f, half), C3{FT}),
99-
ᶜuʲs = similar(Y.c, NTuple{n, C123{FT}}),
100-
ᶠu³ʲs = similar(Y.f, NTuple{n, CT3{FT}}),
101-
ᶜKʲs = similar(Y.c, NTuple{n, FT}),
102-
ᶠKᵥʲs = similar(Y.f, NTuple{n, FT}),
103-
ᶜtsʲs = similar(Y.c, NTuple{n, TST}),
104133
bdmr_l = similar(Y.c, BidiagonalMatrixRow{FT}),
105134
bdmr_r = similar(Y.c, BidiagonalMatrixRow{FT}),
106135
bdmr = similar(Y.c, BidiagonalMatrixRow{FT}),
107-
ᶜρʲs = similar(Y.c, NTuple{n, FT}),
108136
ᶜentrʲs = similar(Y.c, NTuple{n, FT}),
109137
ᶜdetrʲs = similar(Y.c, NTuple{n, FT}),
110138
ᶜturb_entrʲs = similar(Y.c, NTuple{n, FT}),
@@ -149,7 +177,6 @@ function precomputed_quantities(Y, atmos)
149177
ᶠu³⁰ = similar(Y.f, CT3{FT}),
150178
ᶜu⁰ = similar(Y.c, C123{FT}),
151179
ᶜK⁰ = similar(Y.c, FT),
152-
ᶜtke⁰ = similar(Y.c, FT),
153180
ᶜmixing_length_tuple = similar(Y.c, MixingLength{FT}),
154181
ᶜK_u = similar(Y.c, FT),
155182
ᶜK_h = similar(Y.c, FT),
@@ -181,6 +208,7 @@ function precomputed_quantities(Y, atmos)
181208
end
182209

183210
return (;
211+
implicit_precomputed_quantities(Y, atmos)...,
184212
gs_quantities...,
185213
sgs_quantities...,
186214
advective_sgs_quantities...,
@@ -369,37 +397,31 @@ function eddy_diffusivity_coefficient(C_E, norm_v_a, z_a, p)
369397
end
370398

371399
"""
372-
set_precomputed_quantities!(Y, p, t)
400+
set_implicit_precomputed_quantities!(Y, p, t)
373401
374-
Updates the precomputed quantities stored in `p` based on the current state `Y`.
402+
Updates the precomputed quantities that are handled implicitly based on the
403+
current state `Y`. This is called before each evaluation of either
404+
`implicit_tendency!` or `remaining_tendency!`, and it includes quantities used
405+
in both tedencies.
375406
376407
This function also applies a "filter" to `Y` in order to ensure that `ᶠu³` is 0
377408
at the surface (i.e., to enforce the impenetrable boundary condition). If the
378409
`turbconv_model` is EDMFX, the filter also ensures that `ᶠu³⁰` and `ᶠu³ʲs` are 0
379410
at the surface. In the future, we will probably want to move this filtering
380411
elsewhere, but doing it here ensures that it occurs whenever the precomputed
381412
quantities are updated.
382-
383-
Note: If you need to use any of the precomputed quantities, please call this
384-
function instead of recomputing the value yourself. Otherwise, it will be
385-
difficult to ensure that the duplicated computations are consistent.
386413
"""
387-
NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
388-
(; moisture_model, turbconv_model, vert_diff, precip_model, cloud_model) =
389-
p.atmos
390-
(; call_cloud_diagnostics_per_stage) = p.atmos
391-
thermo_params = CAP.thermodynamics_params(p.params)
392-
n = n_mass_flux_subdomains(turbconv_model)
393-
thermo_args = (thermo_params, moisture_model, precip_model)
414+
NVTX.@annotate function set_implicit_precomputed_quantities!(Y, p, t)
415+
(; turbconv_model, moisture_model, precip_model) = p.atmos
394416
(; ᶜΦ) = p.core
395-
(; ᶜspecific, ᶜu, ᶠu³, ᶠu, ᶜK, ᶜts, ᶜp) = p.precomputed
417+
(; ᶜspecific, ᶜu, ᶠu³, ᶠu, ᶜK, ᶜts, ᶜp, ᶜh_tot) = p.precomputed
396418
ᶠuₕ³ = p.scratch.ᶠtemp_CT3
419+
n = n_mass_flux_subdomains(turbconv_model)
420+
thermo_params = CAP.thermodynamics_params(p.params)
421+
thermo_args = (thermo_params, moisture_model, precip_model)
397422

398423
@. ᶜspecific = specific_gs(Y.c)
399-
ᶜρ = Y.c.ρ
400-
ᶜuₕ = Y.c.uₕ
401-
bc_ᶠuₕ³ = compute_ᶠuₕ³(ᶜuₕ, ᶜρ)
402-
@. ᶠuₕ³ = bc_ᶠuₕ³
424+
@. ᶠuₕ³ = $compute_ᶠuₕ³(Y.c.uₕ, Y.c.ρ)
403425

404426
# TODO: We might want to move this to dss! (and rename dss! to something
405427
# like enforce_constraints!).
@@ -426,6 +448,36 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
426448
end
427449
@. ᶜts = ts_gs(thermo_args..., ᶜspecific, ᶜK, ᶜΦ, Y.c.ρ)
428450
@. ᶜp = TD.air_pressure(thermo_params, ᶜts)
451+
@. ᶜh_tot = TD.total_specific_enthalpy(thermo_params, ᶜts, ᶜspecific.e_tot)
452+
453+
if turbconv_model isa PrognosticEDMFX
454+
set_prognostic_edmf_precomputed_quantities_draft!(Y, p, ᶠuₕ³, t)
455+
set_prognostic_edmf_precomputed_quantities_environment!(Y, p, ᶠuₕ³, t)
456+
elseif turbconv_model isa AbstractEDMF
457+
(; ᶜtke⁰) = p.precomputed
458+
@. ᶜtke⁰ = Y.c.sgs⁰.ρatke / Y.c.ρ
459+
end
460+
end
461+
462+
"""
463+
set_explicit_precomputed_quantities!(Y, p, t)
464+
465+
Updates the precomputed quantities that are handled explicitly based on the
466+
current state `Y`. This is only called before each evaluation of
467+
`remaining_tendency!`, though it includes quantities used in both
468+
`implicit_tendency!` and `remaining_tendency!`.
469+
"""
470+
NVTX.@annotate function set_explicit_precomputed_quantities!(Y, p, t)
471+
(; turbconv_model, moisture_model, precip_model, cloud_model) = p.atmos
472+
(; vert_diff, call_cloud_diagnostics_per_stage) = p.atmos
473+
(; ᶜΦ) = p.core
474+
(; ᶜu, ᶜts, ᶜp) = p.precomputed
475+
ᶠuₕ³ = p.scratch.ᶠtemp_CT3 # updated in set_implicit_precomputed_quantities!
476+
thermo_params = CAP.thermodynamics_params(p.params)
477+
478+
if !isnothing(p.sfc_setup)
479+
SurfaceConditions.update_surface_conditions!(Y, p, float(t))
480+
end
429481

430482
if turbconv_model isa AbstractEDMF
431483
@. p.precomputed.ᶜgradᵥ_θ_virt =
@@ -436,13 +488,6 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
436488
ᶜgradᵥ(ᶠinterp(TD.liquid_ice_pottemp(thermo_params, ᶜts)))
437489
end
438490

439-
(; ᶜh_tot) = p.precomputed
440-
@. ᶜh_tot = TD.total_specific_enthalpy(thermo_params, ᶜts, ᶜspecific.e_tot)
441-
442-
if !isnothing(p.sfc_setup)
443-
SurfaceConditions.update_surface_conditions!(Y, p, float(t))
444-
end
445-
446491
# TODO: It is too slow to calculate mixing length at every timestep
447492
# if isnothing(turbconv_model)
448493
# (; ᶜmixing_length) = p.precomputed
@@ -511,8 +556,7 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
511556
end
512557

513558
if turbconv_model isa PrognosticEDMFX
514-
set_prognostic_edmf_precomputed_quantities_draft_and_bc!(Y, p, ᶠuₕ³, t)
515-
set_prognostic_edmf_precomputed_quantities_environment!(Y, p, ᶠuₕ³, t)
559+
set_prognostic_edmf_precomputed_quantities_bottom_bc!(Y, p, t)
516560
set_prognostic_edmf_precomputed_quantities_closures!(Y, p, t)
517561
set_prognostic_edmf_precomputed_quantities_precipitation!(
518562
Y,
@@ -540,12 +584,10 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
540584

541585
if vert_diff isa DecayWithHeightDiffusion
542586
(; ᶜK_h) = p.precomputed
543-
bc_K_h = compute_eddy_diffusivity_coefficient(ᶜρ, vert_diff)
544-
@. ᶜK_h = bc_K_h
587+
@. ᶜK_h = $compute_eddy_diffusivity_coefficient(Y.c.ρ, vert_diff)
545588
elseif vert_diff isa VerticalDiffusion
546589
(; ᶜK_h) = p.precomputed
547-
bc_K_h = compute_eddy_diffusivity_coefficient(Y.c.uₕ, ᶜp, vert_diff)
548-
@. ᶜK_h = bc_K_h
590+
@. ᶜK_h = $compute_eddy_diffusivity_coefficient(Y.c.uₕ, ᶜp, vert_diff)
549591
end
550592

551593
# TODO
@@ -559,3 +601,13 @@ NVTX.@annotate function set_precomputed_quantities!(Y, p, t)
559601

560602
return nothing
561603
end
604+
605+
"""
606+
set_precomputed_quantities!(Y, p, t)
607+
608+
Updates all precomputed quantities based on the current state `Y`.
609+
"""
610+
function set_precomputed_quantities!(Y, p, t)
611+
set_implicit_precomputed_quantities!(Y, p, t)
612+
set_explicit_precomputed_quantities!(Y, p, t)
613+
end

0 commit comments

Comments
 (0)