Skip to content

Commit

Permalink
Merge pull request #718 from CliMA/js/stub
Browse files Browse the repository at this point in the history
move SurfaceStub to its own file
  • Loading branch information
juliasloan25 authored Apr 5, 2024
2 parents 90bb1b0 + 54b6508 commit 1a00ea9
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 122 deletions.
10 changes: 0 additions & 10 deletions docs/src/fieldexchanger.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ The component models are updated by broadcasting the coupler fields, via the `up

If an `update_field!` function is not defined for a particular component model, it will be ignored.

Each component model is also required to define its own `step!` and `reinit!` functions, otherwise this will be ignored.

## FieldExchanger API

```@docs
Expand All @@ -25,11 +23,3 @@ Each component model is also required to define its own `step!` and `reinit!` fu
ClimaCoupler.FieldExchanger.reinit_model_sims!
ClimaCoupler.FieldExchanger.step_model_sims!
```


## FieldExchanger Internal Functions

```@docs
ClimaCoupler.FieldExchanger.step!
ClimaCoupler.FieldExchanger.reinit!
```
3 changes: 2 additions & 1 deletion docs/src/interfacer.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ module docs for more information.
- `SurfaceStub` is a `SurfaceModelSimulation`, but it only contains
required data in `<surface_stub>.cache`, e.g., for the calculation
of surface fluxes through a prescribed surface state. The above
adapter functions are already predefined for `SurfaceStub`, with
adapter functions are already predefined for `SurfaceStub`
in the `surface_stub.jl` file, with
the cache variables specified as:
```
get_field(sim::SurfaceStub, ::Val{:air_density}) = sim.cache.ρ_sfc
Expand Down
4 changes: 2 additions & 2 deletions experiments/AMIP/components/atmosphere/climaatmos.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import ClimaCoupler.FluxCalculator:
extrapolate_ρ_to_sfc,
get_surface_params,
water_albedo_from_atmosphere!
import ClimaCoupler.Interfacer: get_field, update_field!, name
import ClimaCoupler.Interfacer: get_field, update_field!, name, step!, reinit!
import ClimaCoupler.Checkpointer: get_model_prog_state
import ClimaCoupler.FieldExchanger: update_sim!, step!, reinit!
import ClimaCoupler.FieldExchanger: update_sim!
import ClimaCoupler.Utilities: swap_space!

include("climaatmos_extra_diags.jl")
Expand Down
3 changes: 1 addition & 2 deletions experiments/AMIP/components/land/climaland_bucket.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ using ClimaLand:
CoupledAtmosphere
import ClimaLand.Parameters as LP

import ClimaCoupler.Interfacer: LandModelSimulation, get_field, update_field!, name
import ClimaCoupler.FieldExchanger: step!, reinit!
import ClimaCoupler.Interfacer: LandModelSimulation, get_field, update_field!, name, step!, reinit!
import ClimaCoupler.FluxCalculator: update_turbulent_fluxes_point!, surface_thermo_state

###
Expand Down
3 changes: 1 addition & 2 deletions experiments/AMIP/components/ocean/eisenman_seaice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import ClimaTimeSteppers as CTS
import ClimaCoupler: FluxCalculator
import ClimaCoupler.FluxCalculator:
update_turbulent_fluxes_point!, differentiate_turbulent_fluxes!, surface_thermo_state
import ClimaCoupler.Interfacer: get_field, update_field!
import ClimaCoupler.FieldExchanger: step!, reinit!
import ClimaCoupler.Interfacer: get_field, update_field!, step!, reinit!

###
### Functions required by ClimaCoupler.jl for a SurfaceModelSimulation
Expand Down
3 changes: 1 addition & 2 deletions experiments/AMIP/components/ocean/prescr_seaice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ using ClimaCore
import ClimaTimeSteppers as CTS
import Thermodynamics as TD

import ClimaCoupler.Interfacer: SeaIceModelSimulation, get_field, update_field!, name
import ClimaCoupler.FieldExchanger: step!, reinit!
import ClimaCoupler.Interfacer: SeaIceModelSimulation, get_field, update_field!, name, step!, reinit!
import ClimaCoupler.FluxCalculator: update_turbulent_fluxes_point!
using ClimaCoupler: Regridder
import ClimaCoupler.Utilities: swap_space!
Expand Down
3 changes: 1 addition & 2 deletions experiments/AMIP/components/ocean/slab_ocean.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import SciMLBase: ODEProblem, init

using ClimaCore
import ClimaTimeSteppers as CTS
import ClimaCoupler.Interfacer: OceanModelSimulation, get_field, update_field!, name
import ClimaCoupler.FieldExchanger: step!, reinit!
import ClimaCoupler.Interfacer: OceanModelSimulation, get_field, update_field!, name, step!, reinit!
import ClimaCoupler.FluxCalculator: update_turbulent_fluxes_point!
import ClimaCoupler.Utilities: swap_space!
import ClimaCoupler.BCReader: float_type_bcf
Expand Down
2 changes: 1 addition & 1 deletion experiments/AMIP/coupler_driver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ using ClimaCoupler.FluxCalculator:
MoninObukhovScheme,
partitioned_turbulent_fluxes!,
water_albedo_from_atmosphere!
using ClimaCoupler.Interfacer: CoupledSimulation, SurfaceStub, get_field, update_field!
using ClimaCoupler.Interfacer: CoupledSimulation, SurfaceStub, get_field, update_field!, step!
using ClimaCoupler.Regridder
using ClimaCoupler.Regridder: update_surface_fractions!, combine_surfaces!, binary_mask
using ClimaCoupler.TimeManager:
Expand Down
24 changes: 1 addition & 23 deletions src/FieldExchanger.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ atmospheric and surface component models.
"""
module FieldExchanger

import SciMLBase: step!, reinit!
export import_atmos_fields!,
import_combined_surface_fields!, update_sim!, update_model_sims!, reinit_model_sims!, step_model_sims!

using ClimaCoupler: Interfacer, FluxCalculator, Regridder, Utilities
import ClimaCoupler.Interfacer: step!, reinit!

"""
import_atmos_fields!(csf, model_sims, boundary_space, turbulent_fluxes)
Expand Down Expand Up @@ -148,14 +148,6 @@ function update_sim!(sim::Interfacer.SurfaceModelSimulation, csf, turbulent_flux
Interfacer.update_field!(sim, Val(:snow_precipitation), csf.P_snow)
end

"""
update_sim!(::SurfaceStub, csf, area_fraction)
The stub surface simulation only updates the air density (needed for the turbulent flux calculation).
"""
function update_sim!(sim::Interfacer.SurfaceStub, csf, area_fraction)
Interfacer.update_field!(sim, Val(:air_density), csf.ρ_sfc)
end
"""
update_model_sims!(model_sims, csf, turbulent_fluxes)
Expand Down Expand Up @@ -192,13 +184,6 @@ function reinit_model_sims!(model_sims)
end
end

"""
reinit!(cs::SurfaceStub)
The stub surface simulation is not updated by this function. Extends `SciMLBase.reinit!`.
"""
reinit!(::Interfacer.SurfaceStub) = nothing

"""
step_model_sims!(model_sims, t)
Expand All @@ -214,11 +199,4 @@ function step_model_sims!(model_sims, t)
end
end

"""
step!(::SurfaceStub, t)
The stub surface simulation is not updated by this function. Extends `SciMLBase.step!`.
"""
step!(::Interfacer.SurfaceStub, _) = nothing

end # module
2 changes: 0 additions & 2 deletions src/FluxCalculator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,6 @@ function update_turbulent_fluxes_point!(
)
end

update_turbulent_fluxes_point!(sim::Interfacer.SurfaceStub, fields::NamedTuple, colidx::Fields.ColumnIndex) = nothing

"""
differentiate_turbulent_fluxes!(sim::Interfacer.SurfaceModelSimulation, args)
Expand Down
90 changes: 32 additions & 58 deletions src/Interfacer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ This modules contains abstract types, interface templates and model stubs for co
"""
module Interfacer
import Thermodynamics as TD
import SciMLBase: step!, reinit!

using ClimaCore: Fields
export CoupledSimulation,
float_type,
ComponentModelSimulation,
AtmosModelSimulation,
SurfaceModelSimulation,
SurfaceStub,
SeaIceModelSimulation,
LandModelSimulation,
OceanModelSimulation,
name,
get_field,
update_field!
update_field!,
SurfaceStub,
step!,
reinit!


"""
Expand Down Expand Up @@ -163,41 +166,6 @@ 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))


"""
SurfaceStub
On object containing simulation-like info, used as a stub or for prescribed data.
"""
struct SurfaceStub{I} <: SurfaceModelSimulation
cache::I
end

"""
stub_init(cache)
Initialization function for SurfaceStub simulation type.
"""
stub_init(cache) = SurfaceStub(cache)

"""
get_field(::SurfaceStub, ::Val)
A getter function, that should not allocate. If undefined, it returns a descriptive error.
"""
get_field(sim::SurfaceStub, ::Val{:air_density}) = sim.cache.ρ_sfc
get_field(sim::SurfaceStub, ::Val{:area_fraction}) = sim.cache.area_fraction
get_field(sim::SurfaceStub, ::Val{:beta}) = sim.cache.beta
get_field(sim::SurfaceStub, ::Val{:energy}) = nothing
get_field(sim::SurfaceStub, ::Val{:roughness_buoyancy}) = sim.cache.z0b
get_field(sim::SurfaceStub, ::Val{:roughness_momentum}) = sim.cache.z0m
get_field(sim::SurfaceStub, ::Val{:surface_direct_albedo}) = sim.cache.α_direct
get_field(sim::SurfaceStub, ::Val{:surface_diffuse_albedo}) = sim.cache.α_diffuse
get_field(sim::SurfaceStub, ::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::SurfaceStub, ::Val{:surface_temperature}) = sim.cache.T_sfc
get_field(sim::SurfaceStub, ::Val{:water}) = nothing

"""
get_field(::ComponentModelSimulation, ::Val, colidx::Fields.ColumnIndex)
Expand Down Expand Up @@ -257,32 +225,38 @@ update_field_warning(sim, val::Val{X}) where {X} =
@warn("`update_field!` is not extended for the `$X` field of " * name(sim) * ": skipping update.", maxlog = 1)

"""
update_field!(sim::SurfaceStub, ::Val{:area_fraction}, field::Fields.Field)
name(::ComponentModelSimulation)
Updates the specified value in the cache of `SurfaceStub`.
Returns simulation name, if defined, or `Unnamed` if not.
"""
function update_field!(sim::SurfaceStub, ::Val{:area_fraction}, field::Fields.Field)
sim.cache.area_fraction .= field
end
function update_field!(sim::SurfaceStub, ::Val{:surface_temperature}, field::Fields.Field)
sim.cache.T_sfc .= field
end
function update_field!(sim::SurfaceStub, ::Val{:air_density}, field)
parent(sim.cache.ρ_sfc) .= parent(field)
end
function update_field!(sim::SurfaceStub, ::Val{:surface_direct_albedo}, field::Fields.Field)
sim.cache.α_direct .= field
end
function update_field!(sim::SurfaceStub, ::Val{:surface_diffuse_albedo}, field::Fields.Field)
sim.cache.α_diffuse .= field
end
name(::ComponentModelSimulation) = "Unnamed"

"""
name(::ComponentModelSimulation)
step!(sim::ComponentModelSimulation, t)
Returns simulation name, if defined, or `Unnamed` if not.
A function to update the simulation in-place with values calculate for time `t`.
For the models we currently have implemented, this is a simple wrapper around
the `step!` function implemented in SciMLBase.jl.
This must be extended for all component models - otherwise this default
function will be called and an error will be raised.
"""
name(::ComponentModelSimulation) = "Unnamed"
name(::SurfaceStub) = "SurfaceStub"
step!(sim::ComponentModelSimulation, t) = error("undefined step! for " * name(sim))

"""
reinit!(sim::ComponentModelSimulation)
A function to restart a simulation after solving of the simulation has been
paused or interrupted. Like `step!`, this is currently a simple wrapper
around the `reinit!` function of SciMLBase.jl.
This must be extended for all component models - otherwise this default
function will be called and an error will be raised.
"""
reinit!(sim::ComponentModelSimulation) = error("undefined reinit! for " * name(sim))


# Include file containing the surface stub simulation type.
include("surface_stub.jl")

end # module
94 changes: 94 additions & 0 deletions src/surface_stub.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
SurfaceStub
On object containing simulation-like info, used as a stub or for prescribed data.
"""
struct SurfaceStub{I} <: SurfaceModelSimulation
cache::I
end

"""
stub_init(cache)
Initialization function for SurfaceStub simulation type.
"""
stub_init(cache) = SurfaceStub(cache)

## Extensions of Interfacer.jl functions

"""
get_field(::SurfaceStub, ::Val)
A getter function, that should not allocate. If undefined, it returns a descriptive error.
"""
get_field(sim::SurfaceStub, ::Val{:air_density}) = sim.cache.ρ_sfc
get_field(sim::SurfaceStub, ::Val{:area_fraction}) = sim.cache.area_fraction
get_field(sim::SurfaceStub, ::Val{:beta}) = sim.cache.beta
get_field(sim::SurfaceStub, ::Val{:energy}) = nothing
get_field(sim::SurfaceStub, ::Val{:roughness_buoyancy}) = sim.cache.z0b
get_field(sim::SurfaceStub, ::Val{:roughness_momentum}) = sim.cache.z0m
get_field(sim::SurfaceStub, ::Val{:surface_direct_albedo}) = sim.cache.α_direct
get_field(sim::SurfaceStub, ::Val{:surface_diffuse_albedo}) = sim.cache.α_diffuse
get_field(sim::SurfaceStub, ::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::SurfaceStub, ::Val{:surface_temperature}) = sim.cache.T_sfc
get_field(sim::SurfaceStub, ::Val{:water}) = nothing

"""
update_field!(sim::SurfaceStub, ::Val{:area_fraction}, field::Fields.Field)
Updates the specified value in the cache of `SurfaceStub`.
"""
function update_field!(sim::SurfaceStub, ::Val{:area_fraction}, field::Fields.Field)
sim.cache.area_fraction .= field
end
function update_field!(sim::SurfaceStub, ::Val{:surface_temperature}, field::Fields.Field)
sim.cache.T_sfc .= field
end
function update_field!(sim::SurfaceStub, ::Val{:air_density}, field)
parent(sim.cache.ρ_sfc) .= parent(field)
end
function update_field!(sim::SurfaceStub, ::Val{:surface_direct_albedo}, field::Fields.Field)
sim.cache.α_direct .= field
end
function update_field!(sim::SurfaceStub, ::Val{:surface_diffuse_albedo}, field::Fields.Field)
sim.cache.α_diffuse .= field
end

"""
name(::ComponentModelSimulation)
Returns simulation name, if defined, or `Unnamed` if not.
"""
name(::SurfaceStub) = "SurfaceStub"


## Extensions of FieldExchanger.jl functions

"""
update_sim!(::SurfaceStub, csf, area_fraction)
The stub surface simulation only updates the air density (needed for the turbulent flux calculation).
"""
function update_sim!(sim::SurfaceStub, csf, area_fraction)
update_field!(sim, Val(:air_density), csf.ρ_sfc)
end

"""
reinit!(cs::SurfaceStub)
The stub surface simulation is not updated by this function. Extends `SciMLBase.reinit!`.
"""
reinit!(::SurfaceStub) = nothing

"""
step!(::SurfaceStub, t)
The stub surface simulation is not updated by this function. Extends `SciMLBase.step!`.
"""
step!(::SurfaceStub, _) = nothing


## Extensions of FluxCalculator.jl functions

update_turbulent_fluxes_point!(sim::SurfaceStub, fields::NamedTuple, colidx::Fields.ColumnIndex) = nothing
2 changes: 1 addition & 1 deletion test/component_model_tests/eisenman_seaice_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using ClimaCore: Fields, Spaces

import ClimaCoupler
import ClimaCoupler.TestHelper
import ClimaCoupler.Interfacer: SeaIceModelSimulation
import ClimaCoupler.Interfacer: SeaIceModelSimulation, step!
import ClimaCoupler: Regridder

import ClimaParams as CP
Expand Down
Loading

0 comments on commit 1a00ea9

Please sign in to comment.