Driver and Component Layer
1 Overview
OMEGA can be used as either a standalone ocean model or as the ocean component of E3SM. In either case, OMEGA requires a top-level driver and interface layer. Here we describe the requirements and design of both the standalone driver (main) and the component interface for coupled simulation.
2 Requirements
2.1 Requirement: Component interfaces
When running as part of a larger coupled model, OMEGA must supply initialize, run and finalize methods. These routines must export all variables needed by the parent model while also importing all fields needed by OMEGA. In most cases, there will also need to be a thin wrapper to translate data types between the parent model and internal OMEGA data types.
2.2 Requirement: Standalone driver
When OMEGA is used as a standalone model, it must supply a driver or main routine. For consistency with coupled simulations, this driver must mimic a parent coupled model, calling the same init, run and finalize methods and supplying any needed data (eg surface forcing data).
2.3 Requirement: Encapsulation and persistent model state
Communication with the parent model or standalone driver must be through the component interfaces as method arguments. All other aspects of the OMEGA model and model state that need to be retained across component calls or subsequent run intervals must be stored internally within OMEGA as static variables.
2.4 Requirement: Managing environments
Initializing and exiting environments like MPI and Kokkos must take place at the driver level (standalone driver or coupled model driver) as these environments are shared by other components. The finalize method described below must clean up all of Omega memory and data types so that these environments can be exited cleanly.
2.5 Requirement: Run method
The run method must advance the model one specified time interval based on a set of inputs (the import state) and must return a set of outputs (the export state) at the end of the time interval. In a coupled simulation, this interval will be the coupling interval. In standalone simulations, this interval is typically the fastest forcing data interval.
2.6 Requirement: Finalize method
The finalize method must provide a graceful exit, checkpointing as needed and cleaning up all memory. It must not, however, exit the MPI or other shared environments (eg Kokkos) per requirement 2.4
2.7 Requirement: Init method
An initialization method must initialize all model state, mesh and other information needed by the model itself or the parent coupled system. Variables needed by the parent model will be returned as arguments while all other parts of the model state will be retained in static variables for later retrieval by the run method as described in Req 2.3. The model state on initialization must correspond to the initial time for the simulation integration.
3 Algorithmic Formulation
No algorithms are introduced.
4 Design
The design is essentially determined by the requirements above. We define an init, run and finalize method. There will actually be two layers of these functions. One will be the internal Omega inteface used by the Omega standalone driver. A second layer will be needed for translating between internal Omega data types and E3SM (or other parent model) data types and ensuring the model is synchronized correctly with the parent.
Within the directory structure of OMEGA, the src/driver
directory will contain two subdirectories called standalone
and E3SM. The standalone subdirectory will contain the
standalone driver (obviously) and the E3SM directory will
contain the wrapper interfaces that translate between the
E3SM components and data types and the Omega methods and data
types. The CMake build system will determine which directory
will be used in the build. The actual OcnInit, OcnRun, OcnFinalize
routines described below will reside in the src/ocean
directory.
4.1 Data types and parameters
4.1.1 Parameters
There are currently no additional parameters needed for this level. Configuration is generally determined by other modules.
4.1.2 Class/structs/data types
For standalone simulation, data types are determined by other modules (eg state and mesh). No new data types are needed here.
E3SM data types are in flux (from MCT to MOAB). We will add the coupled model data types here in the future.
4.2 Methods
4.2.1 Init
The Init method (OcnInit) will call individual initialization
routines for every module in Omega. On input, it requires the
MPI communicator to use as the master ocean communicator
(MPI_COMM_WORLD
for standalone, a coupler-partitioned
communicator for coupled simulations). On output, it will
return mesh information, the current model state and the
time instant associated with that state.
The precise interface awaits the design of various other modules, but will look something like:
int OMEGA::OcnInit(
MPIComm Comm, ///< [in] ocean MPI communicator
OMEGA::TimeInstant &StartTime, ///< [out] sim start time
OMEGA::TimeInterval &RunInterval, ///< [out] interval for run method
OMEGA::State &CurrState, ///< [out] current model state
other args as needed
);
The routine will return the initial state, the start time and the run interval computed based on input options. An integer return value will be non-zero if errors are encountered and zero if successful. It is also possible that a multi-stage initialization may be needed, especially in coupled mode and would require additional OcnInit interfaces. This will be determined during integration with E3SM later.
4.2.2 Run
The run method will advance the model one time interval, typically the coupling time or the fastest forcing interval. The interface will look like:
int OMEGA::OcnRun(
OMEGA::TimeInstant &CurrTime, ///< [inout] current sim time
OMEGA::TimeInterval &RunInterval, ///< [in] interval to advance model
OMEGA::Alarm &EndAlarm, ///< [out] alarm to end simulation
OMEGA::State &CurrState, ///< [inout] current model state
other args as needed (eg forcing)
)
The model state, current time and the time interval will be input. Other variables will be needed as well, like the surface forcing fields, and will be added as needed. On return, the time instant will contain the end time of the interval and the end alarm will be ringing if the end of the simulation has been reached. The CurrState will be the ocean state at the end of the run interval. An integer error code will be zero if successful and non-zero if an error was encountered. This interface will be modified as needed to include other fields.
4.2.3 Finalize
The finalize method will write a checkpoint/restart file (if not already written by driver or run method on the final timestep) and then clean up all arrays and classes by calling the relevant routines for all Omega modules. The interface is similar to the Init interface:
int OMEGA::OcnFinalize(
OMEGA::TimeInstant &CurrTime, ///< [in] current sim time
OMEGA::State &CurrState, ///< [in] current model state
other args as needed for restart
);
An integer return value will be zero if successful and non-zero if an error is encountered either writing a restart or deallocating memory.
4.2.4 Standalone driver (main)
With the interfaces above, the standalone driver should look something like the code below (details subject to change during implementation).
int main(int argc, char **argv) {
MPI_Init(); // initialize MPI
Kokkos::init(); // initialize Kokkos
{
OMEGA::State CurrState;
OMEGA::TimeInstant CurrTime;
OMEGA::TimeInterval RunInterval;
OMEGA::Alarm EndAlarm;
int Err = OcnInit(MPI_COMM_WORLD, CurrTime, RunInterval, CurrState,
EndAlarm, etc);
if (Err != 0) LOG_ERROR("Error initializing OMEGA");
while (Err == 0 && !(EndAlarm.isRinging()) ) {
// call routines for forcing and other inputs
// call run method
Err = OMEGA::OcnRun(CurrTime, RunInterval, EndAlarm,
CurrState, etc);
if (Err != 0) LOG_ERROR("Error advancing Omega one interval");
// Other tasks if needed (eg IO could occur here or within run
// method
}
int Err2 = OMEGA::OcnFinalize(CurrTime, CurrState, etc);
if (Err2 != 0) LOG_ERROR("Error finalizing Omega");
int ErrAll = abs(Err) + abs(Err2);
if (ErrAll == 0){
LOG_INFO("OMEGA successfully completed");
} else {
LOG_ERROR("OMEGA terminating due to error");
}
}
Kokkos::finalize(); // Exit Kokkos
MPI::Finalize(); // Exit MPI
return ErrAll;
}
4.2.5 Coupler-component interfaces
To be added later
5 Verification and Testing
5.1 Test forward model
A forward model smoke test is included as part of the CTest unit test suite. This test runs the standalone model in a minimal configuration and only tests for successful completion. Other forward model system testing (eg in Polaris) will be inherently testing the driver layers.
tests requirements 2.2-2.7
5.2 Coupled model testing
Once Omega is integrated into E3SM, various E3SM system tests will be run regularly and will test all coupled interfaces. We will add an Omega developer test suite to include these tests.
tests requirement 2.1