@@ -21,6 +21,18 @@ struct ClimaAtmosSimulation{P, Y, D, I} <: Interfacer.AtmosModelSimulation
21
21
end
22
22
Interfacer. name (:: ClimaAtmosSimulation ) = " ClimaAtmosSimulation"
23
23
24
+ hasradiation = function (integrator)
25
+ return ! isnothing (integrator. p. atmos. radiation_mode)
26
+ end
27
+
28
+ hasmoisture = function (integrator)
29
+ return ! (integrator. p. atmos. moisture_model isa CA. DryModel)
30
+ end
31
+
32
+ zero_scalar_half (integrator) = zeros (axes (CC. Fields. level (integrator. p. scratch. ᶠtemp_scalar, CC. Utilities. half)))
33
+ zero_scalar_one (integrator) = zeros (axes (CC. Fields. level (integrator. p. scratch. ᶜtemp_scalar, 1 )))
34
+ zero_scalar_center (integrator) = zeros (axes (integrator. p. scratch. ᶜtemp_scalar))
35
+
24
36
function atmos_init (:: Type{FT} , atmos_config_dict:: Dict ) where {FT}
25
37
# By passing `parsed_args` to `AtmosConfig`, `parsed_args` overwrites the default atmos config
26
38
atmos_config_dict[" surface_albedo" ] = " CouplerAlbedo"
@@ -35,27 +47,30 @@ function atmos_init(::Type{FT}, atmos_config_dict::Dict) where {FT}
35
47
@warn (" Running with ρe_int in coupled mode is not tested yet." , maxlog = 1 )
36
48
end
37
49
38
- # define shorter references for long variable Interfacer.names to increase readability
50
+ # define shorter references for long variable Interfacer.names to increase readability, and set to zero
39
51
ρ_flux_h_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_h_tot
40
- ρ_flux_q_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot
41
- ᶠradiation_flux = integrator. p. radiation. ᶠradiation_flux
42
52
ρ_flux_uₕ = integrator. p. precomputed. sfc_conditions. ρ_flux_uₕ
43
- col_integrated_rain = integrator. p. precipitation. col_integrated_rain
44
- col_integrated_snow = integrator. p. precipitation. col_integrated_snow
45
- ᶜS_ρq_tot = integrator. p. precipitation. ᶜS_ρq_tot
46
- ᶜ3d_rain = integrator. p. precipitation. ᶜ3d_rain
47
- ᶜ3d_snow = integrator. p. precipitation. ᶜ3d_snow
48
-
49
- # set initial fluxes to zero
50
53
@. ρ_flux_h_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
51
- @. ρ_flux_q_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
52
- @. ᶠradiation_flux = CC. Geometry. WVector (FT (0 ))
53
54
ρ_flux_uₕ. components .= Ref (StaticArrays. SMatrix {1, 2} ([FT (0 ), FT (0 )]))
54
- col_integrated_rain .= FT (0 )
55
- col_integrated_snow .= FT (0 )
56
- ᶜS_ρq_tot .= FT (0 )
57
- ᶜ3d_rain .= FT (0 )
58
- ᶜ3d_snow .= FT (0 )
55
+
56
+ if hasmoisture (integrator)
57
+ ρ_flux_q_tot = integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot
58
+ col_integrated_rain = integrator. p. precipitation. col_integrated_rain
59
+ col_integrated_snow = integrator. p. precipitation. col_integrated_snow
60
+ ᶜS_ρq_tot = integrator. p. precipitation. ᶜS_ρq_tot
61
+ ᶜ3d_rain = integrator. p. precipitation. ᶜ3d_rain
62
+ ᶜ3d_snow = integrator. p. precipitation. ᶜ3d_snow
63
+ @. ρ_flux_q_tot = CC. Geometry. Covariant3Vector (FT (0.0 ))
64
+ col_integrated_rain .= FT (0 )
65
+ col_integrated_snow .= FT (0 )
66
+ ᶜS_ρq_tot .= FT (0 )
67
+ ᶜ3d_rain .= FT (0 )
68
+ ᶜ3d_snow .= FT (0 )
69
+ end
70
+ if hasradiation (integrator)
71
+ ᶠradiation_flux = integrator. p. radiation. ᶠradiation_flux
72
+ @. ᶠradiation_flux = CC. Geometry. WVector (FT (0 ))
73
+ end
59
74
60
75
sim = ClimaAtmosSimulation (integrator. p. params, Y, spaces, integrator)
61
76
@@ -82,7 +97,7 @@ upward and downward longwave and shortwave radiation.
82
97
function Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:radiative_energy_flux_toa} )
83
98
FT = eltype (atmos_sim. integrator. u)
84
99
85
- if atmos_sim. integrator. p . radiation . radiation_model != nothing
100
+ if hasradiation ( atmos_sim. integrator)
86
101
face_space = axes (atmos_sim. integrator. u. f)
87
102
nz_faces = length (CC. Spaces. vertical_topology (face_space). mesh. faces)
88
103
@@ -100,48 +115,68 @@ function Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:radiative_
100
115
101
116
return @. - (LWd_TOA + SWd_TOA - LWu_TOA - SWu_TOA)
102
117
else
103
- return FT ( 0 )
118
+ return zero_scalar_half (atmos_sim . integrator )
104
119
end
105
120
end
106
121
107
122
function Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:energy} )
108
- thermo_params = get_thermo_params (atmos_sim)
123
+ integrator = atmos_sim. integrator
124
+ p = integrator. p
109
125
110
- ᶜS_ρq_tot = atmos_sim. integrator. p. precipitation. ᶜS_ρq_tot
111
- ᶜts = atmos_sim. integrator. p. precomputed. ᶜts
112
- ᶜΦ = atmos_sim. integrator. p. core. ᶜΦ
113
126
114
127
# return total energy and (if Microphysics0Moment) the energy lost due to precipitation removal
115
- if atmos_sim . integrator . p. atmos. precip_model isa CA. Microphysics0Moment
116
- ᶜS_ρq_tot = atmos_sim . integrator . p . precipitation . ᶜS_ρq_tot
117
- ᶜts = atmos_sim . integrator . p . precomputed . ᶜts
118
- ᶜΦ = atmos_sim . integrator . p . core . ᶜΦ
119
- return atmos_sim . integrator . u . c . ρe_tot .-
120
- ᶜS_ρq_tot .* CA . e_tot_0M_precipitation_sources_helper .( Ref (thermo_params), ᶜts, ᶜΦ) .*
121
- atmos_sim . integrator. dt
128
+ if p. atmos. precip_model isa CA. Microphysics0Moment
129
+ ᶜts = p . precomputed . ᶜts
130
+ ᶜΦ = p . core . ᶜΦ
131
+ ᶜS_ρq_tot = p . precipitation . ᶜS_ρq_tot
132
+ thermo_params = get_thermo_params (atmos_sim)
133
+ return integrator . u . c . ρe_tot .-
134
+ ᶜS_ρq_tot .* CA . e_tot_0M_precipitation_sources_helper .( Ref (thermo_params), ᶜts, ᶜΦ) .* integrator. dt
122
135
else
123
- return atmos_sim . integrator. u. c. ρe_tot
136
+ return integrator. u. c. ρe_tot
124
137
end
125
138
end
126
139
140
+ # helpers for get_field extensions
141
+
142
+ col_integrated_rain (:: CA.DryModel , integrator) = zero_scalar_half (integrator)
143
+ col_integrated_rain (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
144
+ integrator. p. precipitation. col_integrated_rain
145
+
146
+ col_integrated_snow (:: CA.DryModel , integrator) = zero_scalar_half (integrator)
147
+ col_integrated_snow (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
148
+ integrator. p. precipitation. col_integrated_snow
149
+
150
+ surface_radiation_flux (:: Nothing , integrator) = zero_scalar_half (integrator)
151
+ surface_radiation_flux (:: CA.RRTMGPI.AbstractRRTMGPMode , integrator) =
152
+ CC. Fields. level (integrator. p. radiation. ᶠradiation_flux, CC. Utilities. half)
153
+
154
+ moisture_flux (:: CA.DryModel , integrator) = zero_scalar_half (integrator)
155
+ moisture_flux (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) =
156
+ integrator. p. precomputed. sfc_conditions. ρ_flux_q_tot
157
+
158
+ ρq_tot (:: CA.DryModel , integrator) = zero_scalar_center (integrator)
159
+ ρq_tot (:: Union{CA.EquilMoistModel, CA.NonEquilMoistModel} , integrator) = integrator. u. c. ρq_tot
160
+
127
161
# extensions required by the Interfacer
128
162
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:air_density} ) =
129
163
TD. air_density .(thermo_params, sim. integrator. p. precomputed. ᶜts)
130
164
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:air_temperature} ) =
131
165
TD. air_temperature .(thermo_params, sim. integrator. p. precomputed. ᶜts)
132
166
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:liquid_precipitation} ) =
133
- sim. integrator. p. precipitation . col_integrated_rain
167
+ col_integrated_rain ( sim. integrator. p. atmos . moisture_model, sim . integrator)
134
168
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:radiative_energy_flux_sfc} ) =
135
- CC . Fields . level (sim. integrator. p. radiation . ᶠradiation_flux, CC . Utilities . half )
169
+ surface_radiation_flux (sim. integrator. p. atmos . radiation_mode, sim . integrator )
136
170
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:snow_precipitation} ) =
137
- sim. integrator. p. precipitation . col_integrated_snow
171
+ col_integrated_snow ( sim. integrator. p. atmos . moisture_model, sim . integrator)
138
172
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:turbulent_energy_flux} ) =
139
173
CC. Geometry. WVector .(sim. integrator. p. precomputed. sfc_conditions. ρ_flux_h_tot)
140
174
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:turbulent_moisture_flux} ) =
141
- CC. Geometry. WVector .(sim. integrator. p. precomputed . sfc_conditions . ρ_flux_q_tot )
175
+ CC. Geometry. WVector .(moisture_flux ( sim. integrator. p. atmos . moisture_model, sim . integrator) )
142
176
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:thermo_state_int} ) =
143
177
CC. Spaces. level (sim. integrator. p. precomputed. ᶜts, 1 )
144
- Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:water} ) = atmos_sim. integrator. u. c. ρq_tot
178
+ Interfacer. get_field (atmos_sim:: ClimaAtmosSimulation , :: Val{:water} ) =
179
+ ρq_tot (atmos_sim. integrator. p. atmos. moisture_model, atmos_sim. integrator)
145
180
146
181
# extensions required by FluxCalculator (partitioned fluxes)
147
182
Interfacer. get_field (sim:: ClimaAtmosSimulation , :: Val{:height_int} ) =
@@ -162,10 +197,6 @@ function Interfacer.update_field!(atmos_sim::ClimaAtmosSimulation, ::Val{:co2},
162
197
end
163
198
end
164
199
# extensions required by the Interfacer
165
- function Interfacer. update_field! (sim:: ClimaAtmosSimulation , :: Val{:surface_temperature} , csf)
166
- sim. integrator. p. radiation. radiation_model. surface_temperature .= CA. RRTMGPI. field2array (csf. T_S)
167
- end
168
-
169
200
function Interfacer. update_field! (sim:: ClimaAtmosSimulation , :: Val{:surface_direct_albedo} , field)
170
201
sim. integrator. p. radiation. radiation_model. direct_sw_surface_albedo .=
171
202
reshape (CA. RRTMGPI. field2array (field), 1 , length (parent (field)))
@@ -180,7 +211,7 @@ function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:turbulent_fl
180
211
(; F_turb_energy, F_turb_moisture, F_turb_ρτxz, F_turb_ρτyz) = fields
181
212
182
213
Y = sim. integrator. u
183
- surface_local_geometry = CC. Fields. level (CC. Fields. local_geometry_field (Y. f), CC. Fields . half)
214
+ surface_local_geometry = CC. Fields. level (CC. Fields. local_geometry_field (Y. f), CC. Utilities . half)
184
215
surface_normal = @. CA. C3 (CA. unit_basis_vector_data (CA. C3, surface_local_geometry))
185
216
186
217
# get template objects for the contravariant components of the momentum fluxes (required by Atmos boundary conditions)
@@ -208,9 +239,10 @@ Interfacer.step!(sim::ClimaAtmosSimulation, t) = Interfacer.step!(sim.integrator
208
239
Interfacer. reinit! (sim:: ClimaAtmosSimulation ) = Interfacer. reinit! (sim. integrator)
209
240
210
241
function FieldExchanger. update_sim! (atmos_sim:: ClimaAtmosSimulation , csf, turbulent_fluxes)
211
- Interfacer. update_field! (atmos_sim, Val (:surface_direct_albedo ), csf. surface_direct_albedo)
212
- Interfacer. update_field! (atmos_sim, Val (:surface_diffuse_albedo ), csf. surface_diffuse_albedo)
213
- Interfacer. update_field! (atmos_sim, Val (:surface_temperature ), csf)
242
+ if hasradiation (atmos_sim. integrator)
243
+ Interfacer. update_field! (atmos_sim, Val (:surface_direct_albedo ), csf. surface_direct_albedo)
244
+ Interfacer. update_field! (atmos_sim, Val (:surface_diffuse_albedo ), csf. surface_diffuse_albedo)
245
+ end
214
246
215
247
if turbulent_fluxes isa FluxCalculator. PartitionedStateFluxes
216
248
Interfacer. update_field! (atmos_sim, Val (:turbulent_fluxes ), csf)
@@ -235,12 +267,12 @@ FluxCalculator.get_surface_params(sim::ClimaAtmosSimulation) = CAP.surface_fluxe
235
267
# ## ClimaAtmos.jl model-specific functions (not explicitly required by ClimaCoupler.jl)
236
268
# ##
237
269
"""
238
- get_atmos_config (coupler_dict::Dict)
270
+ get_atmos_config_dict (coupler_dict::Dict)
239
271
240
- Returns the specified atmospheric configuration (`atmos_config_dict `) overwitten by arguments
241
- in the coupler dictionary (`config_dict`).
272
+ Returns the specified atmospheric configuration (`atmos_config `) overwitten by arguments
273
+ in the coupler dictionary (`config_dict`). The returned dictionary will then be passed to CA.AtmosConfig().
242
274
"""
243
- function get_atmos_config (coupler_dict)
275
+ function get_atmos_config_dict (coupler_dict)
244
276
atmos_config_file = coupler_dict[" atmos_config_file" ]
245
277
# override default or specified configs with coupler arguments, and set the correct atmos config_file
246
278
if isnothing (atmos_config_file)
@@ -295,8 +327,12 @@ Sets up `surface_setup` as a `CC.Fields.Field` of `SurfaceState`s.
295
327
"""
296
328
function coupler_surface_setup (
297
329
:: CoupledMoninObukhov ,
298
- p;
299
- csf_sfc = (; T = nothing , z0m = nothing , z0b = nothing , beta = nothing , q_vap = nothing ),
330
+ p,
331
+ T = nothing ,
332
+ z0m = nothing ,
333
+ z0b = nothing ,
334
+ beta = nothing ,
335
+ q_vap = nothing ,
300
336
)
301
337
302
338
surface_state (z0m, z0b, T, beta, q_vap) = CA. SurfaceConditions. SurfaceState (;
@@ -305,7 +341,7 @@ function coupler_surface_setup(
305
341
beta,
306
342
q_vap,
307
343
)
308
- surface_state_field = @. surface_state (csf_sfc . z0m, csf_sfc . z0b, csf_sfc . T, csf_sfc . beta, csf_sfc . q_vap)
344
+ surface_state_field = @. surface_state (z0m, z0b, T, beta, q_vap)
309
345
return surface_state_field
310
346
end
311
347
@@ -315,23 +351,18 @@ end
315
351
Returns a new `p` with the updated surface conditions.
316
352
"""
317
353
function get_new_cache (atmos_sim:: ClimaAtmosSimulation , csf)
318
- csf_sfc = (; T = csf. T_S, z0m = csf. z0m_S, z0b = csf. z0b_S, beta = csf. beta, q_vap = csf. q_sfc)
319
- modified_atmos_cache (atmos_sim, csf_sfc)
320
- end
321
-
322
- """
323
- modified_atmos_cache(atmos_sim, csf_sfc)
324
-
325
- Returns a new `p` with the updated surface conditions.
326
- """
327
- function modified_atmos_cache (atmos_sim, csf_sfc)
354
+ if hasmoisture (atmos_sim. integrator)
355
+ csf_sfc = (csf. T_S, csf. z0m_S, csf. z0b_S, csf. beta, csf. q_sfc)
356
+ else
357
+ csf_sfc = (csf. T_S, csf. z0m_S, csf. z0b_S, csf. beta)
358
+ end
328
359
329
360
p = atmos_sim. integrator. p
330
361
331
- coupler_sfc_setup = coupler_surface_setup (CoupledMoninObukhov (), p; csf_sfc = csf_sfc )
362
+ coupler_sfc_setup = coupler_surface_setup (CoupledMoninObukhov (), p, csf_sfc... )
332
363
333
364
p_names = propertynames (p)
334
- p_values = map (x -> x == :sfc_setup ? coupler_sfc_setup : getproperty (p, x), p_names) # TODO : use merge here
365
+ p_values = map (x -> x == :sfc_setup ? coupler_sfc_setup : getproperty (p, x), p_names)
335
366
336
367
(; zip (p_names, p_values)... )
337
368
end
0 commit comments