Skip to content

Commit bd07660

Browse files
committed
cleanup and fix division by zero
1 parent ceb64e7 commit bd07660

File tree

2 files changed

+51
-32
lines changed

2 files changed

+51
-32
lines changed

src/prognostic_equations/edmfx_boundary_condition.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ function sgs_scalar_flux_bc(
5050
sfc_local_geometry,
5151
) where {FT}
5252

53+
# when surface-interior difference on the grid mean is zero (negligible),
54+
# return grid mean flux (which is zero or negligible) to avoid division by zero
55+
if abs(χ_sfc - ᶜχ_int) < sqrt(floatmin(FT))
56+
return ρ_flux_χ
57+
end
58+
5359
kinematic_sfc_flux_χ = ρ_flux_χ / ρ_sfc # Convert to kinematic flux [K m/s]
5460

5561
χ_sfc_var = get_scalar_variance(

src/prognostic_equations/surface_flux.jl

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -170,29 +170,32 @@ function edmfx_surface_flux_tendency!(Yₜ, Y, p, t, turbconv_model::PrognosticE
170170
thermo_params = CAP.thermodynamics_params(params)
171171
n = n_mass_flux_subdomains(p.atmos.turbconv_model)
172172

173-
ρ_flux_χʲ = p.scratch.sfc_temp_C3
174-
ᶜaʲ = p.scratch.ᶜtemp_scalar
175-
176-
(; ρ_flux_h_tot, ρ_flux_q_tot, ustar, obukhov_length, ts) =
173+
(; ρ_flux_h_tot, ustar, obukhov_length, ts) =
177174
p.precomputed.sfc_conditions
178175

179-
ρ_flux_h_tot_val = Fields.field_values(ρ_flux_h_tot)
180-
ρ_flux_q_tot_val = Fields.field_values(ρ_flux_q_tot)
176+
ᶜaʲ = p.scratch.ᶜtemp_scalar
177+
ρ_flux_χʲ = p.scratch.sfc_temp_C3
178+
# We need field_values everywhere because we are mixing
179+
# information from surface and first interior inside the
180+
# sgs_scalar_flux_bc call.
181+
ρ_flux_χʲ_val = Fields.field_values(ρ_flux_χʲ)
182+
181183
ustar_val = Fields.field_values(ustar)
182184
obukhov_length_val = Fields.field_values(obukhov_length)
183185
sfc_local_geometry_val = Fields.field_values(
184186
Fields.local_geometry_field(Fields.level(Y.f, Fields.half)),
185187
)
186188

187-
ρ_sfc = @. lazy(TD.air_density(thermo_params, ts))
188-
h_sfc = @. lazy(TD.specific_enthalpy(thermo_params, ts))
189-
q_tot_sfc = @. lazy(TD.total_specific_humidity(thermo_params, ts))
190189
z_sfc_val =
191190
Fields.field_values(Fields.level(Fields.coordinate_field(Y.f).z, Fields.half))
191+
ρ_sfc = @. lazy(TD.air_density(thermo_params, ts))
192192
ρ_sfc_val = Fields.field_values(ρ_sfc)
193-
h_sfc_val = Fields.field_values(h_sfc)
194-
q_tot_sfc_val = Fields.field_values(q_tot_sfc)
195193

194+
# Based on boundary conditions for updrafts we compute
195+
# the tendency due to the surface flux for EDMFX ᶜmseʲ...
196+
ρ_flux_h_tot_val = Fields.field_values(ρ_flux_h_tot)
197+
h_tot_sfc = @. lazy(TD.specific_enthalpy(thermo_params, ts))
198+
h_tot_sfc_val = Fields.field_values(h_tot_sfc)
196199
ᶜh_tot = @. lazy(
197200
TD.total_specific_enthalpy(
198201
thermo_params,
@@ -202,20 +205,16 @@ function edmfx_surface_flux_tendency!(Yₜ, Y, p, t, turbconv_model::PrognosticE
202205
)
203206
ᶜh_tot_int_val = Fields.field_values(Fields.level(ᶜh_tot, 1))
204207
ᶜK_int_val = Fields.field_values(Fields.level(ᶜK, 1))
205-
ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ))
206-
ᶜq_tot_int_val = Fields.field_values(Fields.level(ᶜq_tot, 1))
207-
208-
ρ_flux_χʲ_val = Fields.field_values(ρ_flux_χʲ)
209208

210209
for j in 1:n
211210
@. ᶜaʲ = draft_area(Y.c.sgsʲs.:($$j).ρa, ᶜρʲs.:($$j))
212211
ᶜaʲ_int_val = Fields.field_values(Fields.level(ᶜaʲ, 1))
213-
214212
ᶜmseʲ_int_val = Fields.field_values(Fields.level(Y.c.sgsʲs.:($j).mse, 1))
213+
215214
@. ρ_flux_χʲ_val = sgs_scalar_flux_bc(
216215
z_sfc_val,
217216
ρ_sfc_val,
218-
h_sfc_val,
217+
h_tot_sfc_val,
219218
ᶜh_tot_int_val - ᶜK_int_val,
220219
ᶜaʲ_int_val,
221220
ᶜmseʲ_int_val,
@@ -226,22 +225,36 @@ function edmfx_surface_flux_tendency!(Yₜ, Y, p, t, turbconv_model::PrognosticE
226225
)
227226
btt = boundary_tendency_scalar(Y.c.sgsʲs.:(1).mse, ρ_flux_χʲ)
228227
@. Yₜ.c.sgsʲs.:($$j).mse -= btt / p.precomputed.ᶜρʲs.:($$j)
228+
end
229229

230-
ᶜq_totʲ_int_val = Fields.field_values(Fields.level(Y.c.sgsʲs.:($j).q_tot, 1))
231-
@. ρ_flux_χʲ_val = sgs_scalar_flux_bc(
232-
z_sfc_val,
233-
ρ_sfc_val,
234-
q_tot_sfc_val,
235-
ᶜq_tot_int_val,
236-
ᶜaʲ_int_val,
237-
ᶜq_totʲ_int_val,
238-
ρ_flux_q_tot_val,
239-
ustar_val,
240-
obukhov_length_val,
241-
sfc_local_geometry_val,
242-
)
243-
btt = boundary_tendency_scalar(Y.c.sgsʲs.:(1).q_tot, ρ_flux_χʲ)
244-
@. Yₜ.c.sgsʲs.:($$j).q_tot -= btt / p.precomputed.ᶜρʲs.:($$j)
230+
# ... and the tendency for EDMFX ᶜq_totʲ.
231+
if !(p.atmos.moisture_model isa DryModel)
232+
ρ_flux_q_tot_val = Fields.field_values(p.precomputed.sfc_conditions.ρ_flux_q_tot)
233+
q_tot_sfc = @. lazy(TD.total_specific_humidity(thermo_params, ts))
234+
q_tot_sfc_val = Fields.field_values(q_tot_sfc)
235+
ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ))
236+
ᶜq_tot_int_val = Fields.field_values(Fields.level(ᶜq_tot, 1))
237+
238+
for j in 1:n
239+
@. ᶜaʲ = draft_area(Y.c.sgsʲs.:($$j).ρa, ᶜρʲs.:($$j))
240+
ᶜaʲ_int_val = Fields.field_values(Fields.level(ᶜaʲ, 1))
241+
ᶜq_totʲ_int_val = Fields.field_values(Fields.level(Y.c.sgsʲs.:($j).q_tot, 1))
242+
243+
@. ρ_flux_χʲ_val = sgs_scalar_flux_bc(
244+
z_sfc_val,
245+
ρ_sfc_val,
246+
q_tot_sfc_val,
247+
ᶜq_tot_int_val,
248+
ᶜaʲ_int_val,
249+
ᶜq_totʲ_int_val,
250+
ρ_flux_q_tot_val,
251+
ustar_val,
252+
obukhov_length_val,
253+
sfc_local_geometry_val,
254+
)
255+
btt = boundary_tendency_scalar(Y.c.sgsʲs.:(1).q_tot, ρ_flux_χʲ)
256+
@. Yₜ.c.sgsʲs.:($$j).q_tot -= btt / p.precomputed.ᶜρʲs.:($$j)
257+
end
245258
end
246259

247260
end

0 commit comments

Comments
 (0)