Components
Currently, there are two components, ocean
, which encompasses all the tasks
for MPAS-Ocean and Omega, and seaice
, which implements tasks for MPAS-Seaice.
From a developer’s perspective, a component is a package within polaris that has four major pieces:
A class that descends from the
polaris.Component
base class. The class is defined in__init__.py
and its__init__()
method calls thepolaris.Component.add_tasks()
method (or helper functions that, in turn, call this method) to add tasks to the component.A
tasks
package, which contains packages for individual tasks and their steps, possibly within packages that help to sort them into broader categories.An
<component>.cfg
config file containing any default config options that are universal to all tasks of the component.Additional “framework” packages and modules shared broadly between tasks.
The component’s framework is a mix of shared code and other files (config files, YAML files for model config options, etc.) that is expected to be used only by modules and packages within the component, not by other components or the main polaris Framework.
Constructor
The constructor (__init__()
method) for a child class of
polaris.Component
simply calls the parent class’ version
of the constructor with super().__init__()
, passing the name of the
component. Then, it calls helper functions to add tasks to the component, as
in this example from polaris.ocean.Ocean
:
from polaris import Component
from polaris.ocean.tasks.baroclinic_channel import add_baroclinic_channel_tasks
from polaris.ocean.tasks.cosine_bell import add_cosine_bell_tasks
from polaris.ocean.tasks.inertial_gravity_wave import (
add_inertial_gravity_wave_tasks,
)
from polaris.ocean.tasks.manufactured_solution import (
add_manufactured_solution_tasks,
)
from polaris.ocean.tasks.single_column import add_single_column_tasks
class Ocean(Component):
"""
The collection of all test case for the MPAS-Ocean core
"""
def __init__(self):
"""
Construct the collection of MPAS-Ocean test cases
"""
super().__init__(name='ocean')
# please keep these in alphabetical order
add_baroclinic_channel_tasks(component=self)
add_cosine_bell_tasks(component=self)
add_inertial_gravity_wave_tasks(component=self)
add_manufactured_solution_tasks(component=self)
add_single_column_tasks(component=self)
The object self
is always passed as the component
argument to the helper
function so it can, in turn, be used both to add the task to the component and
to identify which component the task belongs to in its constructor.
An example of a helper function that adds tasks for baroclinic channel test cases is:
from polaris.ocean.resolution import resolution_to_subdir
from polaris.ocean.tasks.baroclinic_channel.decomp import Decomp
from polaris.ocean.tasks.baroclinic_channel.default import Default
from polaris.ocean.tasks.baroclinic_channel.init import Init
from polaris.ocean.tasks.baroclinic_channel.restart import Restart
from polaris.ocean.tasks.baroclinic_channel.rpe import Rpe
from polaris.ocean.tasks.baroclinic_channel.threads import Threads
def add_baroclinic_channel_tasks(component):
"""
Add tasks for different baroclinic channel tests to the ocean component
component : polaris.ocean.Ocean
the ocean component that the tasks will be added to
"""
for resolution in [10., 4., 1.]:
resdir = resolution_to_subdir(resolution)
resdir = f'planar/baroclinic_channel/{resdir}'
init = Init(component=component, resolution=resolution, indir=resdir)
component.add_task(
Default(component=component, resolution=resolution,
indir=resdir, init=init))
if resolution == 10.:
component.add_task(
Decomp(component=component, resolution=resolution,
indir=resdir, init=init))
component.add_task(
Restart(component=component, resolution=resolution,
indir=resdir, init=init))
component.add_task(
Threads(component=component, resolution=resolution,
indir=resdir, init=init))
component.add_task(
Rpe(component=component, resolution=resolution,
indir=resdir, init=init))
Config file
The config file for the component should, at the very least, define the
default value for the component_path
path in the [paths]
section. This
path should point to the path within the appropriate E3SM submodule where the
standalone component can be built. This is the path to the directory where the
E3SM component’s executable will be built, not to the executable itself.
Typically, the config file will also define the paths to the component executable and the default namelist and streams files for “forward mode” (and, for MPAS-Ocean, “init mode”):
# This config file has default config options for the landice core
# The paths section points polaris to external paths
[paths]
# the relative or absolute path to the root of a branch where MALI has been
# built
component_path = e3sm_submodules/MALI-Dev/components/mpas-albany-landice
# The namelists section defines paths to example_compact namelists that will be used
# to generate specific namelists. By default, these point to the forward and
# init namelists in the default_inputs directory after a successful build of
# the landice model. Change these in a custom config file if you need a different
# example_compact.
[namelists]
forward = ${paths:component_path}/default_inputs/namelist.landice
# The streams section defines paths to example_compact streams files that will be used
# to generate specific streams files. By default, these point to the forward and
# init streams files in the default_inputs directory after a successful build of
# the landice model. Change these in a custom config file if you need a different
# example_compact.
[streams]
forward = ${paths:component_path}/default_inputs/streams.landice
# The executables section defines paths to required executables. These
# executables are provided for use by specific tasks. Most tools that
# polaris needs should be in the conda environment, so this is only the path
# to the MALI executable by default.
[executables]
component = ${paths:component_path}/landice_model