Skip to content
Open
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
30 changes: 22 additions & 8 deletions components/omega/doc/devGuide/TimeStepping.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ enum class TimeStepperType { ForwardBackward, RungeKutta4, RungeKutta2 };
The `TimeStepper` class is a base class for all Omega time steppers. It stores
as members common data needed by every time stepper. These include a name and
time stepping method as well as some time tracking variables, including
StartTime, StopTime, TimeStep, a Clock and an EndAlarm. Its `doStep` method
defines the interface that every time stepper needs to implement. In addition to this
method, it provides a number of other methods that can divided into two groups.
The first group is for general time stepper management. The second group is
utility functions that provide common functionality that can be re-used in
implementation of different time steppers.
a Clock, TimeStep, StartTime, StopTime (optional) and an EndAlarm (optional).
The StopTime and EndAlarm are optional, because in coupled E3SM simulations the
components do not know the StopTime and therefore no EndAlarm can be created.
Its `doStep` method defines the interface that every time stepper needs to
implement. In addition to this method, it provides a number of other methods
that can divided into two groups. The first group is for general time stepper
management. The second group is utility functions that provide common
functionality that can be re-used in implementation of different time steppers.

### Do step method
The `doStep` method is the main method of every time stepper class. It exists
Expand Down Expand Up @@ -62,14 +64,26 @@ retrieved at any time using:
TimeStepper* DefTimeStepper = TimeStepper::getDefault();
```

In standalone simulations, `TimeStepper::init1();` will read the StartTime from
the configuration file. For coupled simulations the StartTime is provided by
coupler, overriding the value defined in the configuration file.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
coupler, overriding the value defined in the configuration file.
the coupler, overriding the value defined in the configuration file.

In this case, the first phase of time stepper initialization would look like:
```c++
// coupled simulations have a start time but no stop time
TimeInitParams TimeParams{StartTime, std::nullopt};

// initialize TimeStepper with coupler provided start time
TimeStepper::init1(TimeParams);
```

#### Creation of non-default time steppers

A non-default time stepper can be created from a string `Name`, time stepper
type `Type`, `TimeStep`, `StartTime`, `EndTime`, tendencies `Tend`,
auxiliary state `AuxState`, horizontal mesh `Mesh`, and halo layer `MyHalo`
```c++
TimeStepper* NewTimeStepper = TimeStepper::create(Name, Type, StartTime,
EndTime, TimeStep, Tend, AuxState, Mesh, MyHalo);
TimeStepper* NewTimeStepper = TimeStepper::create(Name, Type, TimeStep,
StartTime, EndTime, Tend, AuxState, Mesh, MyHalo);
```
For convenience, this returns a pointer to the newly created time stepper.
Given its name, a pointer to a named time stepper can be obtained at any time
Expand Down
4 changes: 4 additions & 0 deletions components/omega/src/ocn/OceanDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "Config.h"
#include "TimeMgr.h"
#include "TimeStepper.h"

#include "mpi.h"

Expand All @@ -34,6 +35,9 @@ int ocnFinalize(const TimeInstant &CurrTime);
/// Initialize Omega modules needed to run ocean model
int initOmegaModules(MPI_Comm Comm);

/// Initialize Omega modules with coupler-provided time parameters
int initOmegaModules(MPI_Comm Comm, const TimeInitParams &TParams);

} // end namespace OMEGA

//===----------------------------------------------------------------------===//
Expand Down
119 changes: 68 additions & 51 deletions components/omega/src/ocn/OceanInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,59 +102,9 @@ int ocnInit(MPI_Comm Comm ///< [in] ocean MPI communicator
if (Err != 0)
ABORT_ERROR("ocnInit: Error initializing Omega modules");

return Err;

} // end ocnInit

// Call init routines for remaining Omega modules
int initOmegaModules(MPI_Comm Comm) {

// error and return codes
int Err = 0;

// Initialize the default time stepper (phase 1) that includes the
// calendar, model clock and start/stop times and alarms
TimeStepper::init1();
TimeStepper *DefStepper = TimeStepper::getDefault();
Clock *ModelClock = DefStepper->getClock();

// Initialize IOStreams - this does not yet validate the contents
// of each file, only creates streams from Config
IOStream::init(ModelClock);

IO::init(Comm);
Field::init(ModelClock);
Decomp::init();

Err = Halo::init();
if (Err != 0) {
ABORT_ERROR("ocnInit: Error initializing default halo");
}

HorzMesh::init();
VertCoord::init();
Tracers::init();
VertAdv::init();
AuxiliaryState::init();
Eos::init();
PressureGrad::init();
Tendencies::init();

// Validate SurfaceTracerRestoring configuration
Tendencies *DefTend = Tendencies::getDefault();
if (DefTend->SurfaceTracerRestoring.Enabled &&
DefTend->SurfaceTracerRestoring.NTracersToRestore == 0) {
ABORT_ERROR("OceanInit: SurfaceTracerRestoring is enabled but "
"TracersToRestore is empty");
}

TimeStepper::init2();

Err = OceanState::init();
if (Err != 0) {
ABORT_ERROR("ocnInit: Error initializing default state");
}

// Now that all fields have been defined, validate all the streams
// contents
bool StreamsValid = IOStream::validateAll();
Expand Down Expand Up @@ -212,7 +162,74 @@ int initOmegaModules(MPI_Comm Comm) {

return Err;

} // end initOmegaModules
} // end ocnInit

// Call init routines for remaining Omega modules
// Internal helper — all module init after TimeStepper::init1 is called.
// Called by both initOmegaModules overloads.
static int initOmegaModulesImpl(MPI_Comm Comm) {

// error and return codes
int Err = 0;

TimeStepper *DefStepper = TimeStepper::getDefault();
Clock *ModelClock = DefStepper->getClock();

// Initialize IOStreams - this does not yet validate the contents
// of each file, only creates streams from Config
IOStream::init(ModelClock);

IO::init(Comm);
Field::init(ModelClock);
Decomp::init();

Err = Halo::init();
if (Err != 0) {
ABORT_ERROR("ocnInit: Error initializing default halo");
}

HorzMesh::init();
VertCoord::init();
Tracers::init();
VertAdv::init();
AuxiliaryState::init();
Eos::init();
PressureGrad::init();
Tendencies::init();

// Validate SurfaceTracerRestoring configuration
Tendencies *DefTend = Tendencies::getDefault();
if (DefTend->SurfaceTracerRestoring.Enabled &&
DefTend->SurfaceTracerRestoring.NTracersToRestore == 0) {
ABORT_ERROR("OceanInit: SurfaceTracerRestoring is enabled but "
"TracersToRestore is empty");
}

TimeStepper::init2();

Err = OceanState::init();
if (Err != 0) {
ABORT_ERROR("ocnInit: Error initializing default state");
}

return Err;

} // end initOmegaModulesImpl

int initOmegaModules(MPI_Comm Comm) {
// Initialize the default time stepper (phase 1) that includes the
// calendar, model clock and start/stop times and alarms with all options
// read from the config file
TimeStepper::init1();
return initOmegaModulesImpl(Comm);
}

int initOmegaModules(MPI_Comm Comm, const TimeInitParams &TParams) {
// Initialize time stepper (phase 1) using coupler provided time parameters
// Calendar should have already been initalized
TimeStepper::init1(TParams);
return initOmegaModulesImpl(Comm);
}

} // end namespace OMEGA
//===----------------------------------------------------------------------===//
3 changes: 3 additions & 0 deletions components/omega/src/ocn/OceanRun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ int ocnRun(TimeInstant &CurrTime ///< [inout] current sim time
OceanState *DefOceanState = OceanState::getDefault();
TimeStepper *DefTimeStepper = TimeStepper::getDefault();

// EndAlarm must be set before calling ocnRun
OMEGA_REQUIRE(DefTimeStepper->hasEndAlarm(), "ocnRun: no EndAlarm");

// get simulation time and other time info
Clock *OmegaClock = DefTimeStepper->getClock();
Alarm *EndAlarm = DefTimeStepper->getEndAlarm();
Expand Down
10 changes: 5 additions & 5 deletions components/omega/src/timeStepping/ForwardBackwardStepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ namespace OMEGA {
// Mostly passes relevant info to the base constructor.
ForwardBackwardStepper::ForwardBackwardStepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
)
: TimeStepper(InName, TimeStepperType::ForwardBackward, 2, InStartTime,
InStopTime, InTimeStep) {}
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime)
: TimeStepper(InName, TimeStepperType::ForwardBackward, 2, InTimeStep,
InStartTime, InStopTime) {}

//------------------------------------------------------------------------------
// Advance the state by one step of the forward-backward scheme
Expand Down
6 changes: 3 additions & 3 deletions components/omega/src/timeStepping/ForwardBackwardStepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class ForwardBackwardStepper : public TimeStepper {
/// fills with some time information. Data pointers are added later.
ForwardBackwardStepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
);
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime = std::nullopt);

/// Advance the state by one step of the forward-backward scheme
void doStep(OceanState *State, ///< [inout] model state
Expand Down
10 changes: 5 additions & 5 deletions components/omega/src/timeStepping/RungeKutta2Stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ namespace OMEGA {
// Mostly just passes info to the base constructor.
RungeKutta2Stepper::RungeKutta2Stepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
)
: TimeStepper(InName, TimeStepperType::RungeKutta2, 2, InStartTime,
InStopTime, InTimeStep) {}
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime)
: TimeStepper(InName, TimeStepperType::RungeKutta2, 2, InTimeStep,
InStartTime, InStopTime) {}

//------------------------------------------------------------------------------
// Advance the state by one step of the midpoint Runge Kutta scheme
Expand Down
6 changes: 3 additions & 3 deletions components/omega/src/timeStepping/RungeKutta2Stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ class RungeKutta2Stepper : public TimeStepper {
/// fills with some time information. Data pointers are added later.
RungeKutta2Stepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
);
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime = std::nullopt);

/// Advance the state by one step of the midpoint Runge Kutta scheme
void doStep(OceanState *State, ///< [inout] model state
Expand Down
10 changes: 5 additions & 5 deletions components/omega/src/timeStepping/RungeKutta4Stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ namespace OMEGA {
// Uses the base constructor and adds some coefficients.
RungeKutta4Stepper::RungeKutta4Stepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
)
: TimeStepper(InName, TimeStepperType::RungeKutta4, 2, InStartTime,
InStopTime, InTimeStep) {
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime)
: TimeStepper(InName, TimeStepperType::RungeKutta4, 2, InTimeStep,
InStartTime, InStopTime) {

RKA[0] = 0;
RKA[1] = 1. / 2;
Expand Down
6 changes: 3 additions & 3 deletions components/omega/src/timeStepping/RungeKutta4Stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class RungeKutta4Stepper : public TimeStepper {
/// fills with some time information. Data pointers are added later.
RungeKutta4Stepper(
const std::string &InName, ///< [in] name of time stepper
const TimeInterval &InTimeStep, ///< [in] time step
const TimeInstant &InStartTime, ///< [in] start time for time stepping
const TimeInstant &InStopTime, ///< [in] stop time for time stepping
const TimeInterval &InTimeStep ///< [in] time step
);
///< [in] stop time for time stepping, missing in coupled mode
std::optional<TimeInstant> InStopTime = std::nullopt);

/// Advance the state by one step of the fourth-order Runge Kutta scheme
void doStep(OceanState *State, ///< [inout] model state
Expand Down
Loading
Loading