Skip to content

Commit

Permalink
add default get_field methods
Browse files Browse the repository at this point in the history
  • Loading branch information
juliasloan25 committed Feb 27, 2025
1 parent b30a881 commit 45d4a99
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 16 deletions.
19 changes: 14 additions & 5 deletions docs/src/interfacer.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,22 @@ extrapolated to the surface, with units of [kg m^-3].
### SurfaceModelSimulation - required functions
Analogously to the `AtmosModelSimulation`, a `SurfaceModelSimulation`
requires additional functions to those required for a general `ComponentModelSimulation`.
- `get_field(::SurfaceModelSimulation. ::Val{property})`: This getter
- `get_field(::SurfaceModelSimulation, ::Val{property})`: This getter
function returns the value of the field property for the simulation at
the current time. For a `SurfaceModelSimulation`, it must be extended
for the following properties:

| Coupler name | Description | Units |
|-------------------|-------------|-------|
| `area_fraction` | fraction of the simulation grid surface area this model covers | |
| `beta` | factor that scales evaporation based on its estimated level of saturation | |
| `roughness_buoyancy` | aerodynamic roughness length for buoyancy | m |
| `roughness_momentum` | aerodynamic roughness length for momentum | m |
| `surface_direct albedo` | bulk direct surface albedo | |
| `surface_diffuse albedo` | bulk diffuse surface albedo | |
| `surface_humidity` | surface humidity | kg kg^-1 |
| `surface_temperature` | surface temperature | K |

- `update_field!(::SurfaceModelSimulation. ::Val{property}, field)`:
- `update_field!(::SurfaceModelSimulation, ::Val{property}, field)`:
A function to update the value of property in the component model
simulation, using the values in `field` passed from the coupler
This update should be done in place. If this function
Expand All @@ -157,6 +156,18 @@ following properties:
| `surface_diffuse_albedo` | bulk diffuse surface albedo; needed if calculated externally of the surface model (e.g. ocean albedo from the atmospheric state) | |

### SurfaceModelSimulation - optional functions
- `get_field(::SurfaceModelSimulation, ::Val{property})`:
For some quantities, default `get_field` functions are provided, which may be
overwritten or used as-is. These currently include the following:

| Coupler name | Description | Units | Default value |
|-------------------|-------------|-------|---------------|
| `beta` | factor that scales evaporation based on its estimated level of saturation | | 1 |
| `emissivity` | measure of how much energy a surface radiates | | 1 |
| `height_disp` | displacement height relative to the surface | m | 0 |
| `energy` | globally integrated energy | J | `nothing` |
| `water` | globally integrated water | kg | `nothing` |

- `update_turbulent_fluxes!(::ComponentModelSimulation, fields::NamedTuple)`:
This function updates the turbulent fluxes of the component model simulation
at this point in horizontal space. The values are updated using the energy
Expand All @@ -176,13 +187,11 @@ the cache variables specified as:
```
get_field(sim::AbstractSurfaceStub, ::Val{:area_fraction}) = sim.cache.area_fraction
get_field(sim::AbstractSurfaceStub, ::Val{:beta}) = sim.cache.beta
get_field(sim::AbstractSurfaceStub, ::Val{:energy}) = nothing
get_field(sim::AbstractSurfaceStub, ::Val{:roughness_buoyancy}) = sim.cache.z0b
get_field(sim::AbstractSurfaceStub, ::Val{:roughness_momentum}) = sim.cache.z0m
get_field(sim::AbstractSurfaceStub, ::Union{Val{:surface_direct_albedo}, Val{:surface_diffuse_albedo}}) = sim.cache.α
get_field(sim::AbstractSurfaceStub, ::Val{:surface_humidity}) = TD.q_vap_saturation_generic.(sim.cache.thermo_params, sim.cache.T_sfc, sim.cache.ρ_sfc, sim.cache.phase)
get_field(sim::AbstractSurfaceStub, ::Val{:surface_temperature}) = sim.cache.T_sfc
get_field(sim::AbstractSurfaceStub, ::Val{:water}) = nothing
```
and with the corresponding `update_field!` functions
```
Expand Down
2 changes: 0 additions & 2 deletions experiments/ClimaEarth/components/ocean/eisenman_seaice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ end

# extensions required by Interfacer
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:area_fraction}) = sim.integrator.p.area_fraction
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:beta}) = convert(eltype(sim.integrator.u), 1.0)
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:roughness_buoyancy}) =
@. sim.integrator.p.params.p_i.z0b * (sim.integrator.p.ice_area_fraction) +
sim.integrator.p.params.p_o.z0b .* (1 - sim.integrator.p.ice_area_fraction)
Expand All @@ -105,7 +104,6 @@ Interfacer.get_field(sim::EisenmanIceSimulation, ::Union{Val{:surface_direct_alb
sim.integrator.p.params.p_o.α .* (1 - sim.integrator.p.ice_area_fraction)
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:surface_humidity}) = sim.integrator.u.q_sfc
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:surface_temperature}) = sim.integrator.u.T_sfc
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:water}) = nothing

"""
Interfacer.get_field(sim::EisenmanIceSimulation, ::Val{:energy})
Expand Down
2 changes: 0 additions & 2 deletions experiments/ClimaEarth/components/ocean/prescr_seaice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,12 @@ end

# extensions required by Interfacer
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:area_fraction}) = sim.integrator.p.area_fraction
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:beta}) = convert(eltype(sim.integrator.u), 1.0)
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:roughness_buoyancy}) = sim.integrator.p.params.z0b
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:roughness_momentum}) = sim.integrator.p.params.z0m
Interfacer.get_field(sim::PrescribedIceSimulation, ::Union{Val{:surface_direct_albedo}, Val{:surface_diffuse_albedo}}) =
sim.integrator.p.params.α
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:surface_humidity}) = sim.integrator.p.q_sfc
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:surface_temperature}) = sim.integrator.u.T_sfc
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:water}) = nothing

"""
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:energy})
Expand Down
2 changes: 0 additions & 2 deletions experiments/ClimaEarth/components/ocean/slab_ocean.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,12 @@ end

# extensions required by Interfacer
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:area_fraction}) = sim.integrator.p.area_fraction
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:beta}) = convert(eltype(sim.integrator.u), 1.0)
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:roughness_buoyancy}) = sim.integrator.p.params.z0b
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:roughness_momentum}) = sim.integrator.p.params.z0m
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:surface_direct_albedo}) = sim.integrator.p.α_direct
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:surface_diffuse_albedo}) = sim.integrator.p.α_diffuse
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:surface_humidity}) = sim.integrator.p.q_sfc
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:surface_temperature}) = sim.integrator.u.T_sfc
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:water}) = nothing

"""
Interfacer.get_field(sim::SlabOceanSimulation, ::Val{:energy})
Expand Down
9 changes: 7 additions & 2 deletions src/Interfacer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ get_field(
Val{:turbulent_moisture_flux},
Val{:thermo_state_int},
Val{:uv_int},
Val{:water},
},
) = get_field_error(sim, val)

Expand All @@ -181,7 +180,6 @@ get_field(
sim::SurfaceModelSimulation,
val::Union{
Val{:area_fraction},
Val{:beta},
Val{:roughness_buoyancy},
Val{:roughness_momentum},
Val{:surface_direct_albedo},
Expand All @@ -200,6 +198,13 @@ get_field(sim::ComponentModelSimulation, val::Val) = get_field_error(sim, val)

get_field_error(sim, val::Val{X}) where {X} = error("undefined field `$X` for " * name(sim))

# Set default values for fields that are not defined in all component models
get_field(sim::ComponentModelSimulation, ::Val{:beta}) = convert(eltype(sim.integrator.u), 1.0)
get_field(sim::ComponentModelSimulation, ::Val{:emissivity}) = convert(eltype(sim.integrator.u), 1.0)
get_field(sim::ComponentModelSimulation, ::Val{:height_disp}) = convert(eltype(sim.integrator.u), 0.0)
get_field(::ComponentModelSimulation, ::Val{:energy}) = nothing
get_field(::ComponentModelSimulation, ::Val{:water}) = nothing

"""
update_field!(::AtmosModelSimulation, ::Val, _...)
Expand Down
1 change: 0 additions & 1 deletion src/surface_stub.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ get_field(sim::AbstractSurfaceStub, ::Val{:surface_diffuse_albedo}) = sim.cache.
get_field(sim::AbstractSurfaceStub, ::Val{:surface_humidity}) =
TD.q_vap_saturation_generic.(sim.cache.thermo_params, sim.cache.T_sfc, sim.cache.ρ_sfc, sim.cache.phase)
get_field(sim::AbstractSurfaceStub, ::Val{:surface_temperature}) = sim.cache.T_sfc
get_field(sim::AbstractSurfaceStub, ::Val{:water}) = nothing

"""
update_field!(sim::AbstractSurfaceStub, ::Val{:area_fraction}, field::CC.Fields.Field)
Expand Down
2 changes: 0 additions & 2 deletions test/interfacer_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ end
# Test that get_field gives correct warnings for unextended fields
for value in (
:area_fraction,
:beta,
:roughness_buoyancy,
:roughness_momentum,
:surface_direct_albedo,
Expand Down Expand Up @@ -167,7 +166,6 @@ end
:turbulent_moisture_flux,
:thermo_state_int,
:uv_int,
:water,
)
val = Val(value)
@test_throws ErrorException("undefined field `$value` for " * Interfacer.name(sim)) Interfacer.get_field(
Expand Down

0 comments on commit 45d4a99

Please sign in to comment.