Driver
The Omega Driver runs Omega either as a standalone model or as the ocean
component of E3SM (currently via the MCT coupler). In both modes execution
is divided into init, run, and finalize phases, but the coupled driver
splits init into two phases and calls run once per coupling interval
instead of once for the whole simulation. All entry points below are
declared in OceanDriver.h.
Standalone driver
ocnInit reads omega.yml, calls initOmegaModules to initialize every
Omega module (including the default TimeStepper, which owns the model
Clock and EndAlarm), reads the InitialState or RestartRead IOStream,
and updates halo/host arrays for the resulting state:
int ocnInit(MPI_Comm Comm);
ocnRun advances the model, calling the default TimeStepper’s doStep
once per ocean time step, until the EndAlarm attached to the model
Clock rings:
int ocnRun(TimeInstant &CurrTime);
ocnFinalize cleans up all Omega objects; CurrTime is passed in case a
final restart needs to be written:
int ocnFinalize(const TimeInstant &CurrTime);
The standalone main (src/drivers/standalone/OceanDriver.cpp) wraps
these three calls with MPI_Init/Kokkos::initialize and their shutdown
counterparts.
Coupled driver
The coupled driver (src/drivers/coupled/) runs Omega as the ocn
component of an MCT-based E3SM system. ocn_comp_mct.F90 is the MCT cap,
exposing ocn_init_mct/ocn_run_mct/ocn_final_mct to the coupler. It
calls bind(c) interfaces declared in omega_f2cxx_interface.F90 and
implemented in omega_cxx2f_interface.cpp, which call the C++ entry
points below.
Init
Init is split into two phases because the coupler needs Omega’s
decomposition (NCellsOwned) before it can size and allocate the MCT
attribute vectors (x2o/o2x) that SfcCoupling attaches to:
int ocnInit1(MPI_Comm Comm, const int OcnId, const std::string &ConfigFile,
const std::string &LogFile, const StartType StartType,
const TimeInitParams &TimeParams,
const CouplingInitParams &CouplingParams);
int ocnInit2(const Real *CplToOcnData, Real *OcnToCplData);
ocnInit1 initializes every Omega module, using the coupled overload of
initOmegaModules(Comm, TimeParams, CouplingParams), which also calls
SfcCoupling::init. It then reads the InitialState or RestartRead
IOStream based on StartType:
enum class StartType { StartUp, Continue, Branch };
converted from the coupler’s integer start-type code by
safeIntToStartType. On restart/branch, the simulation time is taken from
the restart file rather than the coupler (which only knows the case start
time). On a cold start, ocnInit1 advances the model Clock to the first
coupling-interval boundary so it is in sync with the coupler’s clock.
ocnInit2 runs once the coupler has allocated x2o/o2x: it attaches
them to SfcCoupling (SfcCoupling::attachData), does the initial
export/import exchange with the coupler, and updates halo/host arrays.
Run
The coupled overload of ocnRun advances the model one coupling interval,
rather than to the end of the simulation: it imports coupler fields into
Forcing at the start of the interval, steps until SfcCoupling’s
CouplingAlarm rings (updating SfcCoupling’s export accumulators every
ocean time step), and exports the accumulated fields back to the coupler.
WriteRestart is set by the coupler (from its own restart alarm) to force
a restart write at the end of the interval:
int ocnRun(TimeInstant &CurrTime, bool WriteRestart);
Finalize
ocnFinalize is shared with the standalone driver; it additionally clears
all SfcCoupling instances.
Field name/index mapping
omega_cpl_indices.F90 builds the import (x2o) and export (o2x) field
name and coupler-column-index arrays from a dummy MCT attribute vector,
before Omega (and its HorzMesh) exists. omega_ocn_init1 passes these
arrays through to omega_cxx2f_interface.cpp’s buildFieldIndexMap, which
builds the std::map<std::string, int> (ImportIdx/ExportIdx) required
by CouplingInitParams; see Surface Coupling
for how those maps are used.
Mesh/decomposition queries
Before the coupler-owned buffers exist, the Fortran bridge needs Omega’s
decomposition to build its MCT gsMap and domain. These bridge-only
queries expose that information and have no dependency on SfcCoupling:
int omega_get_ncells_local();
int omega_get_ncells_global();
void omega_get_index_to_cell_id(int *CellID);
void omega_get_lonlat_cell(double *LonCell, double *LatCell);
void omega_get_area_cell(double *AreaCell);