Skip to content

Commit b1848a5

Browse files
sriharshakandalaAkshay Sridhar
authored andcommitted
Restructure radiation callbacks.
1 parent 50b0b53 commit b1848a5

File tree

3 files changed

+393
-263
lines changed

3 files changed

+393
-263
lines changed

src/callbacks/callbacks.jl

Lines changed: 2 additions & 262 deletions
Original file line numberDiff line numberDiff line change
@@ -124,278 +124,18 @@ NVTX.@annotate function cloud_fraction_model_callback!(integrator)
124124
set_cloud_fraction!(Y, p, p.atmos.moisture_model, p.atmos.cloud_model)
125125
end
126126

127-
# TODO: Move this somewhere else
128-
update_o3!(_, _, _) = nothing
129-
function update_o3!(p, t, ::PrescribedOzone)
130-
evaluate!(p.tracers.o3, p.tracers.prescribed_o3_timevaryinginput, t)
131-
return nothing
132-
end
133-
134-
update_co2!(_, _, _) = nothing
135-
function update_co2!(p, t, ::MaunaLoaCO2)
136-
evaluate!(p.tracers.co2, p.tracers.prescribed_co2_timevaryinginput, t)
137-
return nothing
138-
end
139-
140-
141127
NVTX.@annotate function rrtmgp_model_callback!(integrator)
142128
Y = integrator.u
143129
p = integrator.p
144130
t = integrator.t
145131

146-
(; ᶜts, ᶜp, cloud_diagnostics_tuple, sfc_conditions) = p.precomputed
147132
(; params) = p
148133
(; ᶠradiation_flux, rrtmgp_model) = p.radiation
149134
(; radiation_mode) = p.atmos
150135

151-
# If we have prescribed ozone or aerosols, we need to update them
152-
update_o3!(p, t, p.atmos.ozone)
153-
update_co2!(p, t, p.atmos.co2)
154-
if :prescribed_aerosols_field in propertynames(p.tracers)
155-
for (key, tv) in pairs(p.tracers.prescribed_aerosol_timevaryinginputs)
156-
field = getproperty(p.tracers.prescribed_aerosols_field, key)
157-
evaluate!(field, tv, t)
158-
end
159-
end
160-
if :prescribed_clouds_field in propertynames(p.radiation)
161-
for (key, tv) in pairs(p.radiation.prescribed_cloud_timevaryinginputs)
162-
field = getproperty(p.radiation.prescribed_clouds_field, key)
163-
evaluate!(field, tv, t)
164-
end
165-
end
166-
167-
FT = Spaces.undertype(axes(Y.c))
168-
thermo_params = CAP.thermodynamics_params(params)
169-
cmc = CAP.microphysics_cloud_params(params)
170-
T_min = CAP.optics_lookup_temperature_min(params)
171-
T_max = CAP.optics_lookup_temperature_max(params)
172-
173-
sfc_ts = sfc_conditions.ts
174-
sfc_T = Fields.array2field(rrtmgp_model.surface_temperature, axes(sfc_ts))
175-
@. sfc_T = TD.air_temperature(thermo_params, sfc_ts)
176-
177-
rrtmgp_model.center_pressure .= Fields.field2array(ᶜp)
178-
ᶜT = Fields.array2field(rrtmgp_model.center_temperature, axes(Y.c))
179-
# TODO: move this to RRTMGP
180-
@. ᶜT =
181-
min(max(TD.air_temperature(thermo_params, ᶜts), FT(T_min)), FT(T_max))
182-
183-
if !(radiation_mode isa RRTMGPI.GrayRadiation)
184-
ᶜrh =
185-
Fields.array2field(rrtmgp_model.center_relative_humidity, axes(Y.c))
186-
ᶜvmr_h2o = Fields.array2field(
187-
rrtmgp_model.center_volume_mixing_ratio_h2o,
188-
axes(Y.c),
189-
)
190-
if radiation_mode.idealized_h2o
191-
# slowly increase the relative humidity from 0 to 0.6 to account for
192-
# the fact that we have a very unrealistic initial condition
193-
max_relative_humidity = FT(0.6)
194-
t_increasing_humidity = FT(60 * 60 * 24 * 30)
195-
if float(t) < t_increasing_humidity
196-
max_relative_humidity *= float(t) / t_increasing_humidity
197-
end
198-
@. ᶜrh = max_relative_humidity
199-
200-
# temporarily store ᶜq_tot in ᶜvmr_h2o
201-
ᶜq_tot = ᶜvmr_h2o
202-
@. ᶜq_tot =
203-
max_relative_humidity * TD.q_vap_saturation(thermo_params, ᶜts)
204-
205-
# filter ᶜq_tot so that it is monotonically decreasing with z
206-
for i in 2:Spaces.nlevels(axes(ᶜq_tot))
207-
level = Fields.field_values(Spaces.level(ᶜq_tot, i))
208-
prev_level = Fields.field_values(Spaces.level(ᶜq_tot, i - 1))
209-
@. level = min(level, prev_level)
210-
end
211-
212-
# assume that ᶜq_vap = ᶜq_tot when computing ᶜvmr_h2o
213-
@. ᶜvmr_h2o = TD.vol_vapor_mixing_ratio(
214-
thermo_params,
215-
TD.PhasePartition(ᶜq_tot),
216-
)
217-
else
218-
@. ᶜvmr_h2o = TD.vol_vapor_mixing_ratio(
219-
thermo_params,
220-
TD.PhasePartition(thermo_params, ᶜts),
221-
)
222-
@. ᶜrh = min(max(TD.relative_humidity(thermo_params, ᶜts), 0), 1)
223-
end
224-
end
136+
RRTMGPI.update_atmospheric_state!(integrator)
225137

226138
set_insolation_variables!(Y, p, t, p.atmos.insolation)
227-
228-
if radiation_mode isa RRTMGPI.AllSkyRadiation ||
229-
radiation_mode isa RRTMGPI.AllSkyRadiationWithClearSkyDiagnostics
230-
if !radiation_mode.idealized_clouds
231-
ᶜΔz = Fields.Δz_field(Y.c)
232-
ᶜlwp = Fields.array2field(
233-
rrtmgp_model.center_cloud_liquid_water_path,
234-
axes(Y.c),
235-
)
236-
ᶜiwp = Fields.array2field(
237-
rrtmgp_model.center_cloud_ice_water_path,
238-
axes(Y.c),
239-
)
240-
ᶜfrac = Fields.array2field(
241-
rrtmgp_model.center_cloud_fraction,
242-
axes(Y.c),
243-
)
244-
ᶜreliq = Fields.array2field(
245-
rrtmgp_model.center_cloud_liquid_effective_radius,
246-
axes(Y.c),
247-
)
248-
ᶜreice = Fields.array2field(
249-
rrtmgp_model.center_cloud_ice_effective_radius,
250-
axes(Y.c),
251-
)
252-
# RRTMGP needs lwp and iwp in g/m^2
253-
kg_to_g_factor = 1000
254-
m_to_um_factor = FT(1e6)
255-
cloud_liquid_water_content =
256-
radiation_mode.cloud isa PrescribedCloudInRadiation ?
257-
p.radiation.prescribed_clouds_field.clwc :
258-
cloud_diagnostics_tuple.q_liq
259-
cloud_ice_water_content =
260-
radiation_mode.cloud isa PrescribedCloudInRadiation ?
261-
p.radiation.prescribed_clouds_field.ciwc :
262-
cloud_diagnostics_tuple.q_ice
263-
cloud_fraction =
264-
radiation_mode.cloud isa PrescribedCloudInRadiation ?
265-
p.radiation.prescribed_clouds_field.cc :
266-
cloud_diagnostics_tuple.cf
267-
@. ᶜlwp =
268-
kg_to_g_factor * Y.c.ρ * cloud_liquid_water_content * ᶜΔz /
269-
max(cloud_fraction, eps(FT))
270-
@. ᶜiwp =
271-
kg_to_g_factor * Y.c.ρ * cloud_ice_water_content * ᶜΔz /
272-
max(cloud_fraction, eps(FT))
273-
@. ᶜfrac = cloud_fraction
274-
# RRTMGP needs effective radius in microns
275-
276-
seasalt_aero_conc = p.scratch.ᶜtemp_scalar
277-
dust_aero_conc = p.scratch.ᶜtemp_scalar_2
278-
SO4_aero_conc = p.scratch.ᶜtemp_scalar_3
279-
@. seasalt_aero_conc = 0
280-
@. dust_aero_conc = 0
281-
@. SO4_aero_conc = 0
282-
# Get aerosol mass concentrations if available
283-
seasalt_names = [:SSLT01, :SSLT02, :SSLT03, :SSLT04, :SSLT05]
284-
dust_names = [:DST01, :DST02, :DST03, :DST04, :DST05]
285-
SO4_names = [:SO4]
286-
if :prescribed_aerosols_field in propertynames(p.tracers)
287-
aerosol_field = p.tracers.prescribed_aerosols_field
288-
for aerosol_name in propertynames(aerosol_field)
289-
if aerosol_name in seasalt_names
290-
data = getproperty(aerosol_field, aerosol_name)
291-
@. seasalt_aero_conc += data
292-
elseif aerosol_name in dust_names
293-
data = getproperty(aerosol_field, aerosol_name)
294-
@. dust_aero_conc += data
295-
elseif aerosol_name in SO4_names
296-
data = getproperty(aerosol_field, aerosol_name)
297-
@. SO4_aero_conc += data
298-
end
299-
end
300-
end
301-
302-
lwp_col = p.scratch.temp_field_level
303-
ᶜliquid_water_mass_concentration =
304-
@. lazy(cloud_liquid_water_content * Y.c.ρ)
305-
Operators.column_integral_definite!(
306-
lwp_col,
307-
ᶜliquid_water_mass_concentration,
308-
)
309-
310-
@. ᶜreliq = ifelse(
311-
cloud_liquid_water_content > FT(0),
312-
CM.CloudDiagnostics.effective_radius_Liu_Hallet_97(
313-
cmc.liquid,
314-
Y.c.ρ,
315-
cloud_liquid_water_content / max(eps(FT), cloud_fraction),
316-
ml_N_cloud_liquid_droplets(
317-
(cmc,),
318-
dust_aero_conc,
319-
seasalt_aero_conc,
320-
SO4_aero_conc,
321-
lwp_col,
322-
),
323-
FT(0),
324-
FT(0),
325-
) * m_to_um_factor,
326-
FT(0),
327-
)
328-
329-
@. ᶜreice = ifelse(
330-
cloud_ice_water_content > FT(0),
331-
CM.CloudDiagnostics.effective_radius_const(cmc.ice) *
332-
m_to_um_factor,
333-
FT(0),
334-
)
335-
end
336-
end
337-
338-
if !(radiation_mode isa RRTMGPI.GrayRadiation)
339-
if radiation_mode.aerosol_radiation
340-
ᶜΔz = Fields.Δz_field(Y.c)
341-
342-
more_aerosols = (
343-
(:center_dust1_column_mass_density, :DST01),
344-
(:center_dust2_column_mass_density, :DST02),
345-
(:center_dust3_column_mass_density, :DST03),
346-
(:center_dust4_column_mass_density, :DST04),
347-
(:center_dust5_column_mass_density, :DST05),
348-
(:center_ss1_column_mass_density, :SSLT01),
349-
(:center_ss2_column_mass_density, :SSLT02),
350-
(:center_ss3_column_mass_density, :SSLT03),
351-
(:center_ss4_column_mass_density, :SSLT04),
352-
(:center_ss5_column_mass_density, :SSLT05),
353-
)
354-
355-
aerosol_names_pair = [
356-
more_aerosols...,
357-
(:center_so4_column_mass_density, :SO4),
358-
(:center_bcpi_column_mass_density, :CB2),
359-
(:center_bcpo_column_mass_density, :CB1),
360-
(:center_ocpi_column_mass_density, :OC2),
361-
(:center_ocpo_column_mass_density, :OC1),
362-
]
363-
364-
for (rrtmgp_aerosol_name, prescribed_aerosol_name) in
365-
aerosol_names_pair
366-
ᶜaero_conc = Fields.array2field(
367-
getproperty(rrtmgp_model, rrtmgp_aerosol_name),
368-
axes(Y.c),
369-
)
370-
if prescribed_aerosol_name in
371-
propertynames(p.tracers.prescribed_aerosols_field)
372-
aerosol_field = getproperty(
373-
p.tracers.prescribed_aerosols_field,
374-
prescribed_aerosol_name,
375-
)
376-
@. ᶜaero_conc = aerosol_field * Y.c.ρ * ᶜΔz
377-
else
378-
@. ᶜaero_conc = 0
379-
end
380-
end
381-
382-
end
383-
if :o3 in propertynames(p.tracers)
384-
ᶜvmr_o3 = Fields.array2field(
385-
rrtmgp_model.center_volume_mixing_ratio_o3,
386-
axes(Y.c),
387-
)
388-
@. ᶜvmr_o3 = p.tracers.o3
389-
end
390-
if :co2 in propertynames(p.tracers)
391-
if pkgversion(ClimaUtilities) < v"0.1.21"
392-
rrtmgp_model.volume_mixing_ratio_co2 .= p.tracers.co2
393-
else
394-
rrtmgp_model.volume_mixing_ratio_co2 .= p.tracers.co2[]
395-
end
396-
end
397-
end
398-
399139
set_surface_albedo!(Y, p, t, p.atmos.surface_albedo)
400140

401141
RRTMGPI.update_fluxes!(rrtmgp_model, UInt32(floor(t / integrator.p.dt)))
@@ -483,7 +223,7 @@ function set_insolation_variables!(Y, p, t, tvi::TimeVaryingInsolation)
483223
current_datetime,
484224
date0,
485225
insolation_params,
486-
)
226+
),
487227
)
488228
bottom_coords = Fields.coordinate_field(Spaces.level(Y.c, 1))
489229
cos_zenith =

src/parameterized_tendencies/radiation/RRTMGPInterface.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import Adapt
1010
import ClimaComms
1111
using NVTX
1212
using Random
13-
1413
# TODO: Move this file to RRTMGP.jl, once the interface has been settled.
1514
# It will be faster to do interface development in the same repo as experiment
1615
# development, but, since this is just a user-friendly wrapper for RRTMGP.jl, we
@@ -1025,6 +1024,7 @@ NVTX.@annotate function update_fluxes!(model, seedval)
10251024
model.radiation_mode.add_isothermal_boundary_layer &&
10261025
update_boundary_layer!(model)
10271026
clip_values!(model)
1027+
# TODO : update_concentrations as part of update_atmospheric_state!
10281028
update_concentrations!(model.radiation_mode, model)
10291029
update_lw_fluxes!(model.radiation_mode, model)
10301030
update_sw_fluxes!(model.radiation_mode, model)
@@ -1262,4 +1262,5 @@ function update_net_fluxes!(::AllSkyRadiationWithClearSkyDiagnostics, model)
12621262
model.face_flux .= model.face_lw_flux .+ model.face_sw_flux
12631263
end
12641264

1265+
include("update_inputs.jl")
12651266
end # end module

0 commit comments

Comments
 (0)