@@ -21,6 +21,14 @@ struct ClimaAtmosSimulation{P, Y, D, I} <: Interfacer.AtmosModelSimulation
21
21
end
22
22
Interfacer. name (:: ClimaAtmosSimulation ) = " ClimaAtmosSimulation"
23
23
24
+ function hasradiation (integrator)
25
+ return ! isnothing (integrator. p. atmos. radiation_mode)
26
+ end
27
+
28
+ function hasmoisture (integrator)
29
+ return ! (integrator. p. atmos. moisture_model isa CA. DryModel)
30
+ end
31
+
24
32
function atmos_init (:: Type{FT} , atmos_config_dict:: Dict ) where {FT}
25
33
# By passing `parsed_args` to `AtmosConfig`, `parsed_args` overwrites the default atmos config
26
34
atmos_config = CA. AtmosConfig (atmos_config_dict)
@@ -34,27 +42,30 @@ function atmos_init(::Type{FT}, atmos_config_dict::Dict) where {FT}
34
42
@warn (" Running with ρe_int in coupled mode is not tested yet." , maxlog = 1 )
35
43
end
36
44
37
- # define shorter references for long variable Interfacer. names to increase readability
45
+ # define shorter references for long variable names to increase readability, and set to zero
38
46
ρ_flux_h_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_h_tot
39
- ρ_flux_q_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot
40
- ᶠradiation_flux = integrator. p. radiation. ᶠradiation_flux
41
47
ρ_flux_uₕ = integrator. p. precomputed. sfc_conditions. ρ_flux_uₕ
42
- col_integrated_rain = integrator. p. precipitation. col_integrated_rain
43
- col_integrated_snow = integrator. p. precipitation. col_integrated_snow
44
- ᶜS_ρq_tot = integrator. p. precipitation. ᶜS_ρq_tot
45
- ᶜ3d_rain = integrator. p. precipitation. ᶜ3d_rain
46
- ᶜ3d_snow = integrator. p. precipitation. ᶜ3d_snow
47
-
48
- # set initial fluxes to zero
49
48
@. ρ_flux_h_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
50
- @. ρ_flux_q_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
51
- @. ᶠradiation_flux = CC. Geometry. WVector (FT (0 ))
52
49
ρ_flux_uₕ. components .= Ref (StaticArrays. SMatrix {1, 2} ([FT (0 ), FT (0 )]))
53
- col_integrated_rain .= FT (0 )
54
- col_integrated_snow .= FT (0 )
55
- ᶜS_ρq_tot .= FT (0 )
56
- ᶜ3d_rain .= FT (0 )
57
- ᶜ3d_snow .= FT (0 )
50
+
51
+ if hasmoisture (integrator)
52
+ ρ_flux_q_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot
53
+ col_integrated_rain = integrator. p. precipitation. col_integrated_rain
54
+ col_integrated_snow = integrator. p. precipitation. col_integrated_snow
55
+ ᶜS_ρq_tot = integrator. p. precipitation. ᶜS_ρq_tot
56
+ ᶜ3d_rain = integrator. p. precipitation. ᶜ3d_rain
57
+ ᶜ3d_snow = integrator. p. precipitation. ᶜ3d_snow
58
+ @. ρ_flux_q_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
59
+ col_integrated_rain .= FT (0 )
60
+ col_integrated_snow .= FT (0 )
61
+ ᶜS_ρq_tot .= FT (0 )
62
+ ᶜ3d_rain .= FT (0 )
63
+ ᶜ3d_snow .= FT (0 )
64
+ end
65
+ if hasradiation (integrator)
66
+ ᶠradiation_flux = integrator. p. radiation. ᶠradiation_flux
67
+ @. ᶠradiation_flux = CC. Geometry. WVector (FT (0 ))
68
+ end
58
69
59
70
sim = ClimaAtmosSimulation (integrator. p. params, Y, spaces, integrator)
60
71
@@ -98,7 +109,7 @@ upward and downward longwave and shortwave radiation.
98
109
function Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:radiative_energy_flux_toa} )
99
110
FT = eltype (atmos_sim. integrator. u)
100
111
101
- if atmos_sim. integrator. p . radiation . radiation_model != nothing
112
+ if hasradiation ( atmos_sim. integrator)
102
113
face_space = axes (atmos_sim. integrator. u. f)
103
114
nz_faces = length (CC. Spaces. vertical_topology (face_space). mesh. faces)
104
115
@@ -116,49 +127,74 @@ function Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:radiative_
116
127
117
128
return @. - (LWd_TOA + SWd_TOA - LWu_TOA - SWu_TOA)
118
129
else
119
- return FT (0 )
130
+ return [ FT (0 )]
120
131
end
121
132
end
122
133
123
134
function Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:energy} )
124
- thermo_params = get_thermo_params (atmos_sim)
135
+ integrator = atmos_sim. integrator
136
+ p = integrator. p
125
137
126
- ᶜS_ρq_tot = atmos_sim. integrator. p. precipitation. ᶜS_ρq_tot
127
- ᶜts = atmos_sim. integrator. p. precomputed. ᶜts
128
- ᶜΦ = atmos_sim. integrator. p. core. ᶜΦ
129
138
130
139
# return total energy and (if Microphysics0Moment) the energy lost due to precipitation removal
131
- if atmos_sim . integrator . p. atmos. precip_model isa CA. Microphysics0Moment
132
- ᶜS_ρq_tot = atmos_sim . integrator . p . precipitation . ᶜS_ρq_tot
133
- ᶜts = atmos_sim . integrator . p . precomputed . ᶜts
134
- ᶜΦ = atmos_sim . integrator . p . core . ᶜΦ
135
- return atmos_sim . integrator . u . c . ρe_tot .-
136
- ᶜS_ρq_tot .* CA . e_tot_0M_precipitation_sources_helper .( Ref (thermo_params), ᶜts, ᶜΦ) .*
137
- atmos_sim . integrator. dt
140
+ if p. atmos. precip_model isa CA. Microphysics0Moment
141
+ ᶜts = p . precomputed . ᶜts
142
+ ᶜΦ = p . core . ᶜΦ
143
+ ᶜS_ρq_tot = p . precipitation . ᶜS_ρq_tot
144
+ thermo_params = get_thermo_params (atmos_sim)
145
+ return integrator . u . c . ρe_tot .-
146
+ ᶜS_ρq_tot .* CA . e_tot_0M_precipitation_sources_helper .( Ref (thermo_params), ᶜts, ᶜΦ) .* integrator. dt
138
147
else
139
- return atmos_sim . integrator. u. c. ρe_tot
148
+ return integrator. u. c. ρe_tot
140
149
end
141
150
end
142
151
152
+ # helpers for get_field extensions, dipatchable on different moisture model options and radiation modes
153
+
154
+ col_integrated_rain (:: CA.DryModel , integrator) = [eltype (integrator. u)(0 )]
155
+ col_integrated_rain (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
156
+ integrator. p. precipitation. col_integrated_rain
157
+
158
+ col_integrated_snow (:: CA.DryModel , integrator) = [eltype (integrator. u)(0 )]
159
+ col_integrated_snow (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
160
+ integrator. p. precipitation. col_integrated_snow
161
+
162
+ surface_radiation_flux (:: Nothing , integrator) = [eltype (integrator. u)(0 )]
163
+ surface_radiation_flux (:: CA.RRTMGPI.AbstractRRTMGPMode , integrator) =
164
+ CC. Fields. level (integrator. p. radiation. ᶠradiation_flux, CC. Utilities. half)
165
+
166
+ moisture_flux (:: CA.DryModel , integrator) = [eltype (integrator. u)(0 )]
167
+ moisture_flux (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
168
+ CC. Geometry. WVector .(integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot)
169
+
170
+ ρq_tot (:: CA.DryModel , integrator) = [eltype (integrator. u)(0 )]
171
+ ρq_tot (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) = integrator. u. c. ρq_tot
172
+
143
173
# extensions required by the Interfacer
144
174
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:air_density} ) =
145
175
TD. air_density .(thermo_params, sim. integrator. p. precomputed. ᶜts)
146
176
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:air_temperature} ) =
147
177
TD. air_temperature .(thermo_params, sim. integrator. p. precomputed. ᶜts)
148
178
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:liquid_precipitation} ) =
149
- sim. integrator. p. precipitation . col_integrated_rain
179
+ col_integrated_rain ( sim. integrator. p. atmos . moisture_model, sim . integrator)
150
180
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:radiative_energy_flux_sfc} ) =
151
- CC . Fields . level (sim. integrator. p. radiation . ᶠradiation_flux, CC . Utilities . half )
181
+ surface_radiation_flux (sim. integrator. p. atmos . radiation_mode, sim . integrator )
152
182
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:snow_precipitation} ) =
153
- sim. integrator. p. precipitation . col_integrated_snow
183
+ col_integrated_snow ( sim. integrator. p. atmos . moisture_model, sim . integrator)
154
184
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:turbulent_energy_flux} ) =
155
185
CC. Geometry. WVector .(sim. integrator. p. precomputed. sfc_conditions. ρ_flux_h_tot)
156
186
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:turbulent_moisture_flux} ) =
157
- CC . Geometry . WVector . (sim. integrator. p. precomputed . sfc_conditions . ρ_flux_q_tot )
187
+ moisture_flux (sim. integrator. p. atmos . moisture_model, sim . integrator )
158
188
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:thermo_state_int} ) =
159
189
CC. Spaces. level (sim. integrator. p. precomputed. ᶜts, 1 )
160
- Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:water} ) = atmos_sim. integrator. u. c. ρq_tot
161
-
190
+ Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:water} ) =
191
+ ρq_tot (atmos_sim. integrator. p. atmos. moisture_model, atmos_sim. integrator)
192
+ function Interfacer. update_field! (sim:: ClimaAtmosSimulation , :: Val{:surface_temperature} , csf)
193
+ # note that this field is also being updated internally by the surface thermo state in ClimaAtmos
194
+ # if turbulent fluxes are calculated, to ensure consistency. In case the turbulent fluxes are not
195
+ # calculated, we update the field here.
196
+ sim. integrator. p. radiation. radiation_model. surface_temperature .= CA. RRTMGPI. field2array (csf. T_S)
197
+ end
162
198
# extensions required by FluxCalculator (partitioned fluxes)
163
199
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:height_int} ) =
164
200
CC. Spaces. level (CC. Fields. coordinate_field (sim. integrator. u. c). z, 1 )
@@ -178,10 +214,6 @@ function Interfacer.update_field!(atmos_sim::ClimaAtmosSimulation, ::Val{:co2},
178
214
end
179
215
end
180
216
# extensions required by the Interfacer
181
- function Interfacer. update_field! (sim:: ClimaAtmosSimulation , :: Val{:surface_temperature} , csf)
182
- sim. integrator. p. radiation. radiation_model. surface_temperature .= CA. RRTMGPI. field2array (csf. T_S)
183
- end
184
-
185
217
function Interfacer. update_field! (sim:: ClimaAtmosSimulation , :: Val{:surface_direct_albedo} , field)
186
218
sim. integrator. p. radiation. radiation_model. direct_sw_surface_albedo .=
187
219
reshape (CA. RRTMGPI. field2array (field), 1 , length (parent (field)))
@@ -196,7 +228,7 @@ function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:turbulent_fl
196
228
(; F_turb_energy, F_turb_moisture, F_turb_ρτxz, F_turb_ρτyz) = fields
197
229
198
230
Y = sim. integrator. u
199
- surface_local_geometry = CC. Fields. level (CC. Fields. local_geometry_field (Y. f), CC. Fields . half)
231
+ surface_local_geometry = CC. Fields. level (CC. Fields. local_geometry_field (Y. f), CC. Utilities . half)
200
232
surface_normal = @. CA. C3 (CA. unit_basis_vector_data (CA. C3, surface_local_geometry))
201
233
202
234
# get template objects for the contravariant components of the momentum fluxes (required by Atmos boundary conditions)
@@ -229,11 +261,16 @@ function FieldExchanger.update_sim!(atmos_sim::ClimaAtmosSimulation, csf, turbul
229
261
p = atmos_sim. integrator. p
230
262
t = atmos_sim. integrator. t
231
263
232
- ! p. radiation. idealized_insolation && CA. set_insolation_variables! (u, p, t)
264
+ ! isempty (atmos_sim. integrator. p. radiation) &&
265
+ ! p. radiation. idealized_insolation &&
266
+ CA. set_insolation_variables! (u, p, t)
267
+
268
+ if hasradiation (atmos_sim. integrator)
269
+ Interfacer. update_field! (atmos_sim, Val (:surface_direct_albedo ), csf. surface_direct_albedo)
270
+ Interfacer. update_field! (atmos_sim, Val (:surface_diffuse_albedo ), csf. surface_diffuse_albedo)
271
+ end
233
272
234
- Interfacer. update_field! (atmos_sim, Val (:surface_direct_albedo ), csf. surface_direct_albedo)
235
- Interfacer. update_field! (atmos_sim, Val (:surface_diffuse_albedo ), csf. surface_diffuse_albedo)
236
- Interfacer. update_field! (atmos_sim, Val (:surface_temperature ), csf)
273
+ ! isempty (atmos_sim. integrator. p. radiation) && Interfacer. update_field! (atmos_sim, Val (:surface_temperature ), csf)
237
274
238
275
if turbulent_fluxes isa FluxCalculator. PartitionedStateFluxes
239
276
Interfacer. update_field! (atmos_sim, Val (:turbulent_fluxes ), csf)
@@ -258,12 +295,12 @@ FluxCalculator.get_surface_params(sim::ClimaAtmosSimulation) = CAP.surface_fluxe
258
295
# ## ClimaAtmos.jl model-specific functions (not explicitly required by ClimaCoupler.jl)
259
296
# ##
260
297
"""
261
- get_atmos_config (coupler_dict::Dict)
298
+ get_atmos_config_dict (coupler_dict::Dict)
262
299
263
- Returns the specified atmospheric configuration (`atmos_config_dict `) overwitten by arguments
264
- in the coupler dictionary (`config_dict`).
300
+ Returns the specified atmospheric configuration (`atmos_config `) overwitten by arguments
301
+ in the coupler dictionary (`config_dict`). The returned dictionary will then be passed to CA.AtmosConfig().
265
302
"""
266
- function get_atmos_config (coupler_dict)
303
+ function get_atmos_config_dict (coupler_dict)
267
304
atmos_config_file = coupler_dict[" atmos_config_file" ]
268
305
# override default or specified configs with coupler arguments, and set the correct atmos config_file
269
306
if isnothing (atmos_config_file)
@@ -318,8 +355,12 @@ Sets up `surface_setup` as a `CC.Fields.Field` of `SurfaceState`s.
318
355
"""
319
356
function coupler_surface_setup (
320
357
:: CoupledMoninObukhov ,
321
- p;
322
- csf_sfc = (; T = nothing , z0m = nothing , z0b = nothing , beta = nothing , q_vap = nothing ),
358
+ p,
359
+ T = nothing ,
360
+ z0m = nothing ,
361
+ z0b = nothing ,
362
+ beta = nothing ,
363
+ q_vap = nothing ,
323
364
)
324
365
325
366
surface_state (z0m, z0b, T, beta, q_vap) = CA. SurfaceConditions. SurfaceState (;
@@ -328,7 +369,7 @@ function coupler_surface_setup(
328
369
beta,
329
370
q_vap,
330
371
)
331
- surface_state_field = @. surface_state (csf_sfc . z0m, csf_sfc . z0b, csf_sfc . T, csf_sfc . beta, csf_sfc . q_vap)
372
+ surface_state_field = @. surface_state (z0m, z0b, T, beta, q_vap)
332
373
return surface_state_field
333
374
end
334
375
@@ -338,23 +379,18 @@ end
338
379
Returns a new `p` with the updated surface conditions.
339
380
"""
340
381
function get_new_cache (atmos_sim:: ClimaAtmosSimulation , csf)
341
- csf_sfc = (; T = csf. T_S, z0m = csf. z0m_S, z0b = csf. z0b_S, beta = csf. beta, q_vap = csf. q_sfc)
342
- modified_atmos_cache (atmos_sim, csf_sfc)
343
- end
344
-
345
- """
346
- modified_atmos_cache(atmos_sim, csf_sfc)
347
-
348
- Returns a new `p` with the updated surface conditions.
349
- """
350
- function modified_atmos_cache (atmos_sim, csf_sfc)
382
+ if hasmoisture (atmos_sim. integrator)
383
+ csf_sfc = (csf. T_S, csf. z0m_S, csf. z0b_S, csf. beta, csf. q_sfc)
384
+ else
385
+ csf_sfc = (csf. T_S, csf. z0m_S, csf. z0b_S, csf. beta)
386
+ end
351
387
352
388
p = atmos_sim. integrator. p
353
389
354
- coupler_sfc_setup = coupler_surface_setup (CoupledMoninObukhov (), p; csf_sfc = csf_sfc )
390
+ coupler_sfc_setup = coupler_surface_setup (CoupledMoninObukhov (), p, csf_sfc... )
355
391
356
392
p_names = propertynames (p)
357
- p_values = map (x -> x == :sfc_setup ? coupler_sfc_setup : getproperty (p, x), p_names) # TODO : use merge here
393
+ p_values = map (x -> x == :sfc_setup ? coupler_sfc_setup : getproperty (p, x), p_names)
358
394
359
395
(; zip (p_names, p_values)... )
360
396
end
0 commit comments