Skip to content

Commit

Permalink
Add more get_fields to ClimaAtmosSimulation
Browse files Browse the repository at this point in the history
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}
  • Loading branch information
imreddyTeja committed Feb 28, 2025
1 parent 969653e commit df5d7b6
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 11 deletions.
46 changes: 38 additions & 8 deletions experiments/ClimaEarth/components/atmosphere/climaatmos.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,45 @@ moisture_flux(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) =
ρq_tot(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) = integrator.u.c.ρq_tot

# extensions required by the Interfacer
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:cos_zenith_angle}) = CC.Fields.array2field(
sim.integrator.p.radiation.rrtmgp_model.cos_zenith,
CC.Fields.level(axes(sim.integrator.u.c), 1),
)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:co2}) =
sim.integrator.p.radiation.rrtmgp_model.volume_mixing_ratio_co2[]
function Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:diffuse_fraction})
radiation_model = sim.integrator.p.radiation.rrtmgp_model
# only take the first level
total_flux_dn = radiation_model.face_sw_flux_dn[1, :]
lowest_face_space = CC.Spaces.level(axes(sim.integrator.u.f), CC.Utilities.half)
if radiation_model.radiation_mode isa CA.RRTMGPInterface.GrayRadiation
diffuse_fraction = zero(total_flux_dn)
else
direct_flux_dn = radiation_model.face_sw_direct_flux_dn[1, :]
FT = eltype(total_flux_dn)
diffuse_fraction =
clamp.(
((x, y) -> y > zero(y) ? x / y : zero(y)).(total_flux_dn .- direct_flux_dn, total_flux_dn),
zero(FT),
one(FT),
)
end
return CC.Fields.array2field(diffuse_fraction, lowest_face_space)
end
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:liquid_precipitation}) =
surface_rain_flux(sim.integrator.p.atmos.moisture_model, sim.integrator)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:LW_d}) = CC.Fields.level(
CC.Fields.array2field(sim.integrator.p.radiation.rrtmgp_model.face_lw_flux_dn, axes(sim.integrator.u.f)),
CC.Utilities.half,
)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:radiative_energy_flux_sfc}) =
surface_radiation_flux(sim.integrator.p.atmos.radiation_mode, sim.integrator)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:snow_precipitation}) =
surface_snow_flux(sim.integrator.p.atmos.moisture_model, sim.integrator)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:SW_d}) = CC.Fields.level(
CC.Fields.array2field(sim.integrator.p.radiation.rrtmgp_model.face_sw_flux_dn, axes(sim.integrator.u.f)),
CC.Utilities.half,
)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_energy_flux}) =
CC.Geometry.WVector.(sim.integrator.p.precomputed.sfc_conditions.ρ_flux_h_tot)
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_moisture_flux}) =
Expand All @@ -201,15 +234,12 @@ function Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:uv_int})
return @. StaticArrays.SVector(uₕ_int.components.data.:1, uₕ_int.components.data.:2)
end

function Interfacer.update_field!(atmos_sim::ClimaAtmosSimulation, ::Val{:co2}, field)
if atmos_sim.integrator.p.atmos.radiation_mode isa CA.RRTMGPI.GrayRadiation
@warn("Gray radiation model initialized, skipping CO2 update", maxlog = 1)
return
else
atmos_sim.integrator.p.radiation.rrtmgp_model.volume_mixing_ratio_co2 .= Statistics.mean(parent(field))
end
end
# extensions required by the Interfacer
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:emissivity}, field)
# sets all 16 bands (rows) to the same values
sim.integrator.p.radiation.rrtmgp_model.surface_emissivity .=
reshape(CC.Fields.field2array(field), 1, length(parent(field)))
end
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:surface_direct_albedo}, field)
sim.integrator.p.radiation.rrtmgp_model.direct_sw_surface_albedo .=
reshape(CC.Fields.field2array(field), 1, length(parent(field)))
Expand Down
7 changes: 6 additions & 1 deletion src/Interfacer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,17 @@ an atmosphere component model.
get_field(
sim::AtmosModelSimulation,
val::Union{
Val{:cos_zenith_angle},
Val{:co2},
Val{:diffuse_fraction},
Val{:height_int},
Val{:height_sfc},
Val{:liquid_precipitation},
Val{:LW_d},
Val{:radiative_energy_flux_sfc},
Val{:radiative_energy_flux_toa},
Val{:snow_precipitation},
Val{:SW_d},
Val{:turblent_energy_flux},
Val{:turbulent_moisture_flux},
Val{:thermo_state_int},
Expand Down Expand Up @@ -214,7 +219,7 @@ If it isn't extended, the field won't be updated and a warning will be raised.
update_field!(
sim::AtmosModelSimulation,
val::Union{
Val{:co2},
Val{:emissivity},
Val{:surface_direct_albedo},
Val{:surface_diffuse_albedo},
Val{:surface_temperature},
Expand Down
1 change: 0 additions & 1 deletion test/field_exchanger_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ end
function Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:roughness_momentum}, field)
parent(sim.cache.roughness_momentum) .= parent(field)
end
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:co2}, field) = nothing
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:surface_temperature}, field) = nothing
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:roughness_buoyancy}, field) = nothing
Interfacer.update_field!(sim::TestAtmosSimulation, ::Val{:beta}, field) = nothing
Expand Down
7 changes: 6 additions & 1 deletion test/interfacer_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,17 @@ end

# Test that get_field gives correct warnings for unextended fields
for value in (
:cos_zenith_angle,
:co2,
:diffuse_fraction,
:height_int,
:height_sfc,
:liquid_precipitation,
:LW_d,
:radiative_energy_flux_sfc,
:radiative_energy_flux_toa,
:snow_precipitation,
:SW_d,
:turbulent_energy_flux,
:turbulent_moisture_flux,
:thermo_state_int,
Expand Down Expand Up @@ -209,7 +214,7 @@ end
sim = DummySimulation4(space)

# Test that update_field! gives correct warnings for unextended fields
for value in (:co2, :surface_direct_albedo, :surface_diffuse_albedo, :surface_temperature, :turbulent_fluxes)
for value in (:emissivity, :surface_direct_albedo, :surface_diffuse_albedo, :surface_temperature, :turbulent_fluxes)
val = Val(value)
@test_logs (
:warn,
Expand Down

0 comments on commit df5d7b6

Please sign in to comment.