Skip to content

Commit a62d04e

Browse files
authored
Tr/add get_fields and update_fields to ClimaAtmosSimulation (#1205)
* Add more get_fields to ClimaAtmosSimulation Add diffuse_fraction, SW_d, LW_d, and cos of the zenith_angle to get_field on AtmosModelSimulation in Interfacer.jl. Add get_field methods for the above values in ClimaAtmosSimulation Remove safe_div and use anonymous func Only calculate on first level for diffuse_frac Add update_field for emissivity in AtmosModelSim Add emissivity to update_field in the Interfacer, and add a method definition for it in climaatmos.jl All 16 bands are set to the same values. Clamp diffuse_fraction to [0,1] Remove :co2 from atmos update_field :co2 is removed from the default AtmosModelSimulation update_field. The method definition is also removed for ClimaAtmosSimulation. Add atmos get_field for :co2 Add a default get_field for :co2 with AtmosModelSimulation, and a method definition for ClimaAtmosSimulation. Note that this returns a scalar. Add new fields to interfacer_tests Revert to returning zero when dividing by zero In get_field(::ClimaAtmosSimulation, ::Val{:diffuse_fraction} * Add air pressure, air temp, and humidity get_field Add them to the the generic get_field for AtmosModelSimulations and specific methods for ClimaAtmosSimulations * Update Interfacer.md with atmos get_field changes * Change `cos_zenith_angle` to `cos_zenith` It is refered to as `cos_zenith` by atmos and `cos\thetas` by land. This unifies it with one of the models. [skip ci] * Change humidity to specific_humidity for atmos * Remove not always required fields default get_field remove from interfacer tests
1 parent 04365bd commit a62d04e

File tree

5 files changed

+75
-12
lines changed

5 files changed

+75
-12
lines changed

docs/src/interfacer.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ following properties:
113113

114114
| Coupler name | Description | Units |
115115
|-------------------|-------------|-------|
116-
| `co2` | global mean co2 | ppm |
116+
| `emissivity` | surface emissivity | |
117117
| `surface_direct_albedo` | bulk direct surface albedo over the whole surface space | |
118118
| `surface_diffuse_albedo` | bulk diffuse surface albedo over the whole surface space | |
119119
| `surface_temperature` | temperature over the combined surface space | K |
@@ -123,6 +123,31 @@ following properties:
123123
A function to return the air density of the atmosphere simulation
124124
extrapolated to the surface, with units of [kg m^-3].
125125

126+
<!-- replace "full ClimaLand model" with name of coupler sim struct-->
127+
### AtmosModelSimulation - required functions to run with the full ClimaLand model
128+
129+
Coupling with full `ClimaLand` model requires the following functions, in addition
130+
to the functions required for coupling with a general `SurfaceModelSimulation`.
131+
132+
- `get_field(::AtmosModelSimulation. ::Val{property})`:
133+
This getter function must be extended
134+
for the following properties:
135+
136+
| Coupler name | Description | Units |
137+
|-------------------|-------------|-------|
138+
| `air_pressure` | air pressure at the bottom cell centers of the atmosphere | Pa |
139+
| `air_temperature` | air temperature at the bottom cell centers of the atmosphere | K |
140+
| `cos_zenith` | cosine of the zenith angle | |
141+
| `co2` | global mean co2 | ppm |
142+
| `diffuse_fraction` | fraction of downwards shortwave flux that is direct | |
143+
| `specific_humidity` | specific humidity at the bottom cell centers of the atmosphere| kg kg^-1 |
144+
| `LW_d` | downwards longwave flux | W m^-2 |
145+
| `SW_d` | downwards shortwave flux | W m^-2 |
146+
147+
Note that `air_temperature`, `air_pressure`, `cos_zenith`, `co2`, `diffuse_fraction`, `LW_d` and
148+
`SW_d` will not be present in a `ClimaAtmosSimulation` if the model is setup with no radiation.
149+
Because of this, a `ClimaAtmosSimulation` must have radiation if running with the full `ClimaLand` model.
150+
126151
### SurfaceModelSimulation - required functions
127152
Analogously to the `AtmosModelSimulation`, a `SurfaceModelSimulation`
128153
requires additional functions to those required for a general `ComponentModelSimulation`.

experiments/ClimaEarth/components/atmosphere/climaatmos.jl

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,54 @@ moisture_flux(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) =
171171
ρq_tot(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) = integrator.u.c.ρq_tot
172172

173173
# extensions required by the Interfacer
174+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:air_pressure}) =
175+
CC.Fields.level(sim.integrator.p.precomputed.ᶜp, 1)
176+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:air_temperature}) =
177+
TD.air_temperature.(
178+
sim.integrator.p.params.thermodynamics_params,
179+
CC.Fields.level(sim.integrator.p.precomputed.ᶜts, 1),
180+
)
181+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:cos_zenith}) = CC.Fields.array2field(
182+
sim.integrator.p.radiation.rrtmgp_model.cos_zenith,
183+
CC.Fields.level(axes(sim.integrator.u.c), 1),
184+
)
185+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:co2}) =
186+
sim.integrator.p.radiation.rrtmgp_model.volume_mixing_ratio_co2[]
187+
function Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:diffuse_fraction})
188+
radiation_model = sim.integrator.p.radiation.rrtmgp_model
189+
# only take the first level
190+
total_flux_dn = radiation_model.face_sw_flux_dn[1, :]
191+
lowest_face_space = CC.Spaces.level(axes(sim.integrator.u.f), CC.Utilities.half)
192+
if radiation_model.radiation_mode isa CA.RRTMGPInterface.GrayRadiation
193+
diffuse_fraction = zero(total_flux_dn)
194+
else
195+
direct_flux_dn = radiation_model.face_sw_direct_flux_dn[1, :]
196+
FT = eltype(total_flux_dn)
197+
diffuse_fraction =
198+
clamp.(
199+
((x, y) -> y > zero(y) ? x / y : zero(y)).(total_flux_dn .- direct_flux_dn, total_flux_dn),
200+
zero(FT),
201+
one(FT),
202+
)
203+
end
204+
return CC.Fields.array2field(diffuse_fraction, lowest_face_space)
205+
end
174206
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:liquid_precipitation}) =
175207
surface_rain_flux(sim.integrator.p.atmos.moisture_model, sim.integrator)
208+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:LW_d}) = CC.Fields.level(
209+
CC.Fields.array2field(sim.integrator.p.radiation.rrtmgp_model.face_lw_flux_dn, axes(sim.integrator.u.f)),
210+
CC.Utilities.half,
211+
)
212+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:specific_humidity}) =
213+
CC.Fields.level(sim.integrator.u.c.ρq_tot ./ sim.integrator.u.c.ρ, 1)
176214
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:radiative_energy_flux_sfc}) =
177215
surface_radiation_flux(sim.integrator.p.atmos.radiation_mode, sim.integrator)
178216
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:snow_precipitation}) =
179217
surface_snow_flux(sim.integrator.p.atmos.moisture_model, sim.integrator)
218+
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:SW_d}) = CC.Fields.level(
219+
CC.Fields.array2field(sim.integrator.p.radiation.rrtmgp_model.face_sw_flux_dn, axes(sim.integrator.u.f)),
220+
CC.Utilities.half,
221+
)
180222
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_energy_flux}) =
181223
CC.Geometry.WVector.(sim.integrator.p.precomputed.sfc_conditions.ρ_flux_h_tot)
182224
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_moisture_flux}) =
@@ -201,15 +243,12 @@ function Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:uv_int})
201243
return @. StaticArrays.SVector(uₕ_int.components.data.:1, uₕ_int.components.data.:2)
202244
end
203245

204-
function Interfacer.update_field!(atmos_sim::ClimaAtmosSimulation, ::Val{:co2}, field)
205-
if atmos_sim.integrator.p.atmos.radiation_mode isa CA.RRTMGPI.GrayRadiation
206-
@warn("Gray radiation model initialized, skipping CO2 update", maxlog = 1)
207-
return
208-
else
209-
atmos_sim.integrator.p.radiation.rrtmgp_model.volume_mixing_ratio_co2 .= Statistics.mean(parent(field))
210-
end
211-
end
212246
# extensions required by the Interfacer
247+
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:emissivity}, field)
248+
# sets all 16 bands (rows) to the same values
249+
sim.integrator.p.radiation.rrtmgp_model.surface_emissivity .=
250+
reshape(CC.Fields.field2array(field), 1, length(parent(field)))
251+
end
213252
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:surface_direct_albedo}, field)
214253
sim.integrator.p.radiation.rrtmgp_model.direct_sw_surface_albedo .=
215254
reshape(CC.Fields.field2array(field), 1, length(parent(field)))

src/Interfacer.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ If it isn't extended, the field won't be updated and a warning will be raised.
214214
update_field!(
215215
sim::AtmosModelSimulation,
216216
val::Union{
217-
Val{:co2},
217+
Val{:emissivity},
218218
Val{:surface_direct_albedo},
219219
Val{:surface_diffuse_albedo},
220220
Val{:surface_temperature},

test/field_exchanger_tests.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ end
9393
function Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:roughness_momentum}, field)
9494
parent(sim.cache.roughness_momentum) .= parent(field)
9595
end
96-
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:co2}, field) = nothing
9796
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:surface_temperature}, field) = nothing
9897
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:roughness_buoyancy}, field) = nothing
9998
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:beta}, field) = nothing

test/interfacer_tests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ end
209209
sim = DummySimulation4(space)
210210

211211
# Test that update_field! gives correct warnings for unextended fields
212-
for value in (:co2, :surface_direct_albedo, :surface_diffuse_albedo, :surface_temperature, :turbulent_fluxes)
212+
for value in (:emissivity, :surface_direct_albedo, :surface_diffuse_albedo, :surface_temperature, :turbulent_fluxes)
213213
val = Val(value)
214214
@test_logs (
215215
:warn,

0 commit comments

Comments
 (0)