Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move SurfaceStub to its own file #718

Merged
merged 1 commit into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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!
juliasloan25 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading