Skip to content

Latest commit

 

History

History
407 lines (346 loc) · 24.6 KB

File metadata and controls

407 lines (346 loc) · 24.6 KB

Interfacer

This module contains functions that define the interface for coupling component models, as well as stub objects that contain prescribed fields. Here we explain each type of component model, and the functions that must be implemented to use a component model with ClimaCoupler.jl

Coupled simulation

A CoupledSimulation stores info for ESM run and contains each of the component model simulations. We currently require that each CoupledSimulation contains one atmos_sim, and at least one surface simulation (land_sim, ocean_sim, and/or ice_sim). If a simulation surface type is not needed for a given run, it may be omitted.

Component simulations

Individual component model simulations fall under ComponentModelSimulation, which together combine to make the CoupledSimulation. We have two types of ComponentModelSimulations: AtmosModelSimulation and SurfaceModelSimulation. The two have different requirements, which are detailed below. SurfaceModelSimulation is further divided into SeaIceModelSimulation, LandModelSimulation, and OceanModelSimulation, representing the 3 currently-supported options for surface models.

ComponentModelSimulation - required functions

A component model simulation should be implemented as a struct that is a concrete subtype of a ComponentModelSimulation. This struct should contain all of the information needed to run that simulation.

Each ComponentModelSimulation must extend the following functions to be able to use our coupler. For some existing models, these are defined within ClimaCoupler.jl in that model’s file in experiments/ClimaEarth/components/, but it is preferable for these to be defined in a model’s own repository. Note that the dispatch ::ComponentModelSimulation in the function definitions given below should be replaced with the particular component model extending these functions.

  • constructor: construct and return an instance of the ComponentModelSimulation, and perform all initialization. This function should return a simulation that is ready to be stepped in the coupled simulation. The interface for this function varies across component models.

  • step!(::ComponentModelSimulation, t): 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.

ComponentModelSimulation - optional functions

  • Checkpointer.get_model_prog_state(::ComponentModelSimulation): A function that returns the state vector of the simulation at its current state. This is used for checkpointing the simulation.

  • Checkpointer.get_model_cache(::ComponentModelSimulation): A function that returns the cache of the simulation at its current state. This is used for checkpointing the simulation.

  • Checkpointer.restore_cache(::ComponentModelSimulation, new_cache): A function that updates the cache of the simulation with the provided new_cache. This is used for restarting the simulation.

  • get_field(::ComponentModelSimulation, ::Val{property}): Default get_field functions are provided for energy and water fields, described in the table below. These quantities are used to track conservation, and the defaults return nothing. To check conservation throughout a simulation, these functions must be extended for all models being run.

Coupler name Description Units Default value
energy vertically integrated energy per surface area J m⁻² nothing
water vertically integrated water per surface area kg m⁻² nothing
  • add_coupler_fields!(coupler_field_names, ::ComponentModelSimulation): A set of default coupler exchange fields is initialized for each coupled simulation, but depending on the component models being run, additional coupler fields may be required. For example, the integrated land model requires the concentration of atmospheric CO2 for photosynthesis calculations, but the slab ocean does not. add_coupler_fields! is extended for any component model simulation that requires coupler fields in addition to the defaults, allowing us to allocate space for and exchange the extra fields only when necessary. All coupler fields are defined on the boundary space.
    • Any additional fields specified here will likely also require an update_field! method defined for this component model, so the coupler can update the component. They may also require a new method of import_atmos_fields! or combine_surfaces! to update the coupler fields from the component model that computes the field.

The default coupler exchange fields are the following, defined in default_coupler_fields() in the Interfacer module:

Coupler name Description Units
T_atmos atmosphere temperature at the bottom layer K
q_atmos atmosphere humidity at the bottom layer kg kg⁻¹
ρ_atmos atmosphere air density at the bottom layer kg m⁻³
z_int height of the first internal atmosphere level (center) m
z_sfc height of the bottom atmosphere layer (face) m
F_lh latent heat flux W m⁻²
F_sh sensible heat flux W m⁻²
F_turb_moisture turbulent moisture flux kg m⁻² s⁻¹
F_turb_ρτxz turbulent momentum flux in the zonal direction kg m⁻¹ s⁻²
F_turb_ρτyz turbulent momentum flux in the meridional direction kg m⁻¹ s⁻²
F_radiative net radiative flux at the surface W m⁻²
emissivity surface emissivity -
T_sfc surface temperature, averaged across components K
P_liq liquid precipitation kg m⁻² s⁻¹
P_snow snow precipitation kg m⁻² s⁻¹
scalar_temp1 a surface scalar field used for intermediate calculations -
scalar_temp2 a surface scalar field used for intermediate calculations -
scalar_temp3 a surface scalar field used for intermediate calculations -
scalar_temp4 a surface scalar field used for intermediate calculations -

!!! note "What should be stored in the coupler exchange fields?" In general, the coupler fields should contain exchange fields for fluxes, including turbulent fluxes, radiative fluxes, and precipitation. They also hold any quantities that a component model requires from another component. For example, the atmosphere needs surface temperature and emissivity from the surface models to compute radiation, so the coupler allocates space to exchange them. The coupler exchange fields may also hold quantities from components that are used to compute turbulent fluxes. As a general rule, we tend to store such quantities that come from the atmosphere model, but access them when needed for surface models. This is because we compute fluxes indvidually for the interface between each surface and the atmosphere model. As a result, the atmosphere quantities are used for each of these calculations, so storing them in the coupler fields allows us to avoid regridding them to the coupler space multiple times per coupling timestep.

  • update_sim!(::ComponentModelSimulation, csf): A function to update each of the fields of the component model simulation that are updated by the coupler. ClimaCoupler.jl provides defaults of this function for both AtmosModelSimulation and SurfaceModelSimulation that update each of the fields expected by the coupler. This function will need to be extended for any model that requires additional fields (specified via add_coupler_fields!).

  • set_cache!(sim::ComponentModelSimulation): A function to perform any initialization of the component model caches that isn't done during the model simulation initialization, and that must be done after the initial exchange. This is necessary, for example, when component models have cache interdependencies that must be handled in a specific order. Cache variables that are computed as part of the tendencies do not need to be set here.

AtmosModelSimulation - required functions

In addition to the functions required for a general ComponentModelSimulation, an AtmosModelSimulation requires the following functions to retrieve and update its fields.

  • get_field(::AtmosModelSimulation. ::Val{property}): This getter function returns the value of the field property for the simulation in its current state. For an AtmosModelSimulation, it must be extended for the following properties:
Coupler name Description Units
air_density air density at the bottom cell centers of the atmosphere kg m⁻³
air_pressure air pressure at the bottom cell centers of the atmosphere Pa
air_temperature air temperature at the bottom cell centers of the atmosphere K
height_int height at the bottom cell center of the atmosphere space m
height_sfc height at the bottom face of the atmosphere space m
liquid_precipitation liquid precipitation at the surface kg m⁻² s⁻¹
radiative_energy_flux_sfc net radiative flux at the surface W m⁻²
radiative_energy_flux_toa net radiative flux at the top of the atmosphere W m⁻²
snow_precipitation snow precipitation at the surface kg m⁻² s⁻¹
specific_humidity specific humidity at the bottom cell centers of the atmosphere kg kg⁻¹
turbulent_energy_flux aerodynamic turbulent surface fluxes of energy (sensible and latent heat) W m⁻²
turbulent_moisture_flux aerodynamic turbulent surface fluxes of energy (evaporation) kg m⁻² s⁻¹
u_int zonal wind velocity vector at the first internal model level m s⁻¹
v_int meridional wind velocity vector at the first internal model level m s⁻¹
  • update_field!(::AtmosModelSimulation. ::Val{property}, field): A function to update the value of property in the component model simulation, using the values in field. This update should be done in place. If this function isn't extended for a property, that property will remain constant throughout the simulation and a warning will be raised. This function is expected to be extended for the following properties, and may also be extended for any additional properties needed by a component model.
Coupler name Description Units
emissivity surface emissivity
surface_direct_albedo bulk direct surface albedo over the whole surface space
surface_diffuse_albedo bulk diffuse surface albedo over the whole surface space
surface_temperature temperature over the combined surface space K
turbulent_fluxes turbulent fluxes W m⁻²

ClimaAtmos should also add the following coupler fields for Monin-Obukhov similarity theory:

Coupler name Description Units
ustar friction velocity m s⁻¹
L_MO Obukhov length m
buoyancy_flux flux of buoyancy m⁻²s⁻³

AtmosModelSimulation - required functions to run with the ClimaLandSimulation

Coupling with the integrated ClimaLandSimulation requires the following functions, in addition to the functions required for coupling with a general SurfaceModelSimulation.

  • get_field(::AtmosModelSimulation. ::Val{property}): This getter function must be extended for the following properties:
Coupler name Description Units
co2 global mean co2 ppm
diffuse_fraction fraction of downwards shortwave flux that is direct
LW_d downwards longwave flux W m⁻²
SW_d downwards shortwave flux W m⁻²

!!! note co2, diffuse_fraction, LW_d and SW_d will not be present in a ClimaAtmosSimulation if the model is setup with no radiation. Because of this, a ClimaAtmosSimulation must have radiation enabled if running with the full ClimaLand model.

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 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
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_temperature surface temperature K

!!! note area_fraction is expected to be defined on the boundary space of the simulation, while all other fields will likely be on the simulation's own space.

  • 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 isn't extended for a property, that property will remain constant throughout the simulation and a warning will be raised. This function is expected to be extended for the following properties, and may also be extended for any additional properties needed by a component model.
Coupler name Description Units
area_fraction fraction of the simulation grid surface area this model covers
liquid_precipitation liquid precipitation at the surface kg m⁻² s⁻¹
radiative_energy_flux_sfc OR LW_d, SW_d net radiative flux at the surface OR downward longwave, shortwave radiation W m⁻²
snow_precipitation snow precipitation at the surface kg m⁻² s⁻¹
turbulent_energy_flux aerodynamic turbulent surface fluxes of energy (sensible and latent heat) W m⁻²
turbulent_moisture_flux aerodynamic turbulent surface fluxes of energy (evaporation) kg m⁻² s⁻¹

!!! note update_field!(::SurfaceModelSimulation, ::Val{:area_fraction}, field) is not required to be extended for land models, since they're assumed to have a constant area fraction.

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
  • 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 and moisture turbulent fluxes stored in fields which are calculated by the coupler.

Prescribed surface conditions - SurfaceStub

  • 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. This model is intended to be used for testing or as a simple stand-in model. The above adapter functions are already predefined for AbstractSurfaceStub, which is extended by SurfaceStub in the surface_stub.jl file, with 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{:roughness_buoyancy}) = sim.cache.z0b
get_field(sim::AbstractSurfaceStub, ::Val{:roughness_momentum}) = sim.cache.z0m
get_field(sim::AbstractSurfaceStub, ::Val{:surface_direct_albedo}) = sim.cache.α_direct
get_field(sim::AbstractSurfaceStub, ::Val{:surface_diffuse_albedo}) = sim.cache.α_diffuse
get_field(sim::AbstractSurfaceStub, ::Val{:surface_temperature}) = sim.cache.T_sfc

and with the corresponding update_field! functions

function update_field!(sim::AbstractSurfaceStub, ::Val{:area_fraction}, field::ClimaCore.Fields.Field)
    sim.cache.area_fraction .= field # `area_fraction` is on the boundary space, so it doesn't need remapping
end
function update_field!(sim::AbstractSurfaceStub, ::Val{:surface_temperature}, field::ClimaCore.Fields.Field)
    Interfacer.remap!(sim.cache.T_sfc, field)
end
function update_field!(sim::AbstractSurfaceStub, ::Val{:surface_direct_albedo}, field::CC.Fields.Field)
    Interfacer.remap!(sim.cache.α_direct, field)
end
function update_field!(sim::AbstractSurfaceStub, ::Val{:surface_diffuse_albedo}, field::CC.Fields.Field)
    Interfacer.remap!(sim.cache.α_diffuse, field)
end

Remapping interface

For component models that don't use ClimaCore Fields, some additional functions must be extended to enable remapping between the component model's grid and the boundary space of the coupled simulation. These are described below.

To regrid from a component model's grid to the boundary space, we can typically use ClimaCore's Remapping module. Users may want to create a remapping object containing both the ClimaCore.Remapping.Remapper object and scratch space to reduce allocations during the remapping. This has been done for the OceananigansSimulation in experiments/ClimaEarth/components/ocean/oceananigans.jl. This direction simply requires supplying a matrix of ClimaCore.Geometry.LatLongPoint objects containing latitude/longitude pairs at each point of the source grid.

remap(field, target_space, remapper)

Remap the given field onto the target_space. If the field is already on the target space or a compatible one, it is returned unchanged.

For ClimaCore Fields, this function is implemented by default and does not require a remapper object. Component models that use non-ClimaCore fields (such as Oceananigans) must extend this function to provide a method that handles remapping from their native field type to a ClimaCore Field on the target space.

!!! note "Performance" The remap method allocates a new field and is not efficient for performance-critical code. For better performance, use the in-place option remap! instead.

Signature:

  • field: The source field to be remapped
  • target_space: The target space (typically the boundary space) onto which the field should be remapped
  • remapper: An optional remapper object returned by get_remapper_to_cc(sim). For ClimaCore Fields, this can be nothing.

Returns: A new field remapped onto the target space

remap!(target_field, source, remapper)

Remap the given source field onto the target_field in place. This is the preferred method for remapping when performance is important, as it avoids allocating a new field.

For ClimaCore Fields, this function is implemented by default. Component models that use non-ClimaCore fields must extend this function to provide a method that handles remapping from their native field type into the provided target_field.

Signature:

  • target_field: The destination field (must be a ClimaCore Field) where remapped data will be stored
  • source: The source field to be remapped (can be a ClimaCore Field or a non-ClimaCore field type)
  • remapper: An optional remapper object returned by get_remapper_to_cc(sim). For ClimaCore Fields, this can be nothing.

Returns: nothing (updates target_field in place)

get_remapper_to_cc(sim::ComponentModelSimulation)

Return the remapper object used to remap quantities from this component model's grid onto the boundary space.

By default, this function returns nothing, which is intended for use with components that use the default remapping functions (i.e. components using ClimaCore Fields). Components that require an alternative remapper (such as the XESMF regridder for Oceananigans) should extend this function to return their remapper object. If this function is extended, the component model will also need to extend remap and remap! to use the remapper object.

Signature:

  • sim: The component model simulation

Returns: A remapper object (or nothing for ClimaCore-based models)

Example: For an Oceananigans simulation, this returns a NamedTuple containing an XESMF regridder object with an initialized weight matrix, as well as scratch space to be used during remapping.

Interfacer API

    ClimaCoupler.Interfacer.CoupledSimulation
    ClimaCoupler.Interfacer.AtmosModelSimulation
    ClimaCoupler.Interfacer.SurfaceModelSimulation
    ClimaCoupler.Interfacer.ComponentModelSimulation
    ClimaCoupler.Interfacer.AbstractSurfaceStub
    ClimaCoupler.Interfacer.SurfaceStub
    ClimaCoupler.Interfacer.get_field
    ClimaCoupler.Interfacer.update_field!
    ClimaCoupler.Interfacer.AbstractSlabplanetSimulationMode
    ClimaCoupler.Interfacer.AMIPMode
    ClimaCoupler.Interfacer.SubseasonalMode
    ClimaCoupler.Interfacer.SlabplanetMode
    ClimaCoupler.Interfacer.SlabplanetAquaMode
    ClimaCoupler.Interfacer.SlabplanetTerraMode
    ClimaCoupler.Interfacer.set_cache!
    ClimaCoupler.Interfacer.remap
    ClimaCoupler.Interfacer.remap!
    ClimaCoupler.Interfacer.boundary_space

Interfacer Internal Functions and Types

    ClimaCoupler.Interfacer.AbstractSimulation
    ClimaCoupler.Interfacer.AbstractSimulationMode