Time stepping
Omega supports choice of multiple time stepping schemes. The time stepping
module provides implementations of different time stepping schemes and general
infrastructure for managing time steppers. To achieve modularity, each time
stepper is implemented as a separate class. To ensure common interface and
enable sharing of common code and data, every time stepper inherits from the
TimeStepper
base class.
Time stepper type
An enumeration listing all implemented schemes is provided. It needs to be extended every time a new time stepper is added. It is used to identify a time stepper at run time.
enum class TimeStepperType { ForwardBackward, RungeKutta4, RungeKutta2 };
TimeStepper base class
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.
Do step method
The doStep
method is the main method of every time stepper class. It exists
in the base class as a pure virtual method, meaning it defines an interface but
has no implementation. Its signature is
void TimeStepper::doStep(OceanState *State, TimeInstant &SimTime) const;
It is meant to advance State
by one time step, from Time
to Time + TimeStep
. Classes implementing concrete time stepping schemes need to provide
implementations of this method. As part of the time step, this routine advances
the Clock associated with the time stepper and returns the current simulation
time. For the default time stepper, this is advances the primary model clock.
Time stepper management methods
Initialization
Two static methods:
TimeStepper::init1();
TimeStepper::init2();
initialize the default time stepper in two phases. The first phase must be called early in the initialization process. It creates and time stepper instance, fills it with various time quantities (StartTime, EndTime, TimeStep) and creates a Clock (the Model Clock for the simulation) and an EndAlarm to ring when this portion of the simulation should stop. The second phase is called after the default tendency, auxiliary state, horizontal mesh, and halo objects have been initialized. It attaches pointers to these objects for later use during the time stop phase. A pointer to the default time stepper can be retrieved at any time using:
TimeStepper* DefTimeStepper = TimeStepper::getDefault();
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
TimeStepper* NewTimeStepper = TimeStepper::create(Name, Type, StartTime,
EndTime, TimeStep, 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
by calling the static get
method:
TimeStepper* NewTimeStepper = TimeStepper::get(Name);
Changing the time step
The time step is set on creation, but if the time step must change, the function
Stepper->changeTimeStep(TimeStep);
can be used where TimeStep
is an instance of TimeInterval
class.
Getters
Given a pointer to a TimeStepper
you can obtain various class members.
Pointers to the associated Clock and EndAlarm can also be retrieved.
TimeStepperType Type = Stepper->getType();
int NTimeLevels = Stepper->getNTimeLevels();
std::string Name = Stepper->getName();
TimeInterval TimeStep = Stepper->getTimeStep();
TimeInstant StartTime = Stepper->getStartTime();
TimeInstant StopTime = Stepper->getStopTime();
Clock *ModelClock = Stepper->getClock();
Alarm *EndAlarm = Stepper->getEndAlarm();
Removal of time steppers
To erase a specific named time stepper use erase
TimeStepper::erase(Name);
To clear all instances do:
TimeStepper::clear();
Utility methods
In addition to the above management methods, the base class provides common
functions that are useful in implementing different time steppers. Given two
pointers to OceanState
objects State1
and State2
, two integers
representing two time levels TimeLevel1
and TimeLevel2
, and coefficient
Coeff
of type TimeInterval
calling
updateStateByTend(State1, TimeLevel1, State2, TimeLevel2, Coeff);
conceptually performs the following update
State1(TimeLevel1) = State2(TimeLevel2) + Coeff * Tend
element-wise for every state variable. To perform this update only for
layer thickness do
updateThicknessByTend(State1, TimeLevel1, *State2, TimeLevel2, Coeff);
and only for normal velocity do
updateVelocityByTend(State1, TimeLevel1, State2, TimeLevel2, Coeff);
Similarly for tracers, the method for updating tracers is
updateTracersByTend(NextTracers, CurTracers, State1, TimeLevel1, State2, TimeLevel2, Coeff);
Additionally, for the RK4 method, there are methods for initializing, accumulating, and finalizing the tracer integration for a given time step
weightTracers(NextTracers, CurTracers, CurState, TimeLevel1);
accumulateTracersUpdate(AccumTracer, Coeff);
finalizeTracersUpdate(NextTracers, State, TimeLevel);
Implemented time steppers
The following time steppers are currently implemented
Class name |
Enum value |
Scheme |
---|---|---|
ForwardBackwardStepper |
TimeStepperType::ForwardBackward |
forward-backward |
RungeKutta2Stepper |
TimeStepperType::RungeKutta2 |
second-order two-stage midpoint Runge Kutta method |
RungeKutta4Stepper |
TimeStepperType::RungeKutta4 |
classic fourth-order four-stage Runge Kutta method |