Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Transition from Example 1 to Example 2

Goal

The primary goal of Example 2: Use ModelEvaluator is to move the van der Pol problem definition into a Thyra::ModelEvaluator while preserving the same Thyra-based state representation and the same Forward Euler stepping logic used in Example 1: Utilize Thyra.

New concepts introduced are:

  • Thyra::ModelEvaluator
    • provides a standard Trilinos interface for evaluating the application model
  • Thyra::ModelEvaluatorBase::InArgs
    • supplies the model inputs such as time and state
  • Thyra::ModelEvaluatorBase::OutArgs
    • receives the model outputs such as the right-hand side
  • getNominalValues()
    • provides nominal initial conditions from the model
  • evalModel()
    • evaluates the model using the supplied input and output arguments

This is the first step in separating the problem physics from the time integration algorithm. Rather than evaluating the right-hand side directly in the application, the code now requests that evaluation through a common model interface. This is a key part of how Tempus steppers and integrators interact with application models.

What stays the same

  • The state is still stored in Thyra vectors.
  • The timestepper is still Forward Euler.
  • The application still controls the time loop directly.
  • The regression check follows the same pattern.

Selected code excerpts

The code excerpts below highlight the main changes needed to move from direct application-level right-hand-side evaluation to the use of a Thyra::ModelEvaluator.


Construct the model

Construct a ModelEvaluator. The application now creates an object that represents the problem model.

Before

int vectorLength = 2;
RCP<const Thyra::VectorSpaceBase<double> > xSpace =
Thyra::defaultSpmdVectorSpace<double>(vectorLength);

After

Teuchos::RCP<const Thyra::ModelEvaluator<double> >
model = Teuchos::rcp(new VanDerPol_ModelEvaluator_02<double>());
ModelEvaluator implementation for the example van der Pol Problem.

The application now delegates model-specific information to a dedicated model object.


Get initial conditions

Obtain nominal initial conditions from the model. The nominal solution and its time derivative are no longer assembled manually.

Before

RCP<Thyra::VectorBase<double> > x_n = Thyra::createMember(xSpace);
RCP<Thyra::VectorBase<double> > xDot_n = Thyra::createMember(xSpace);

After

RCP<Thyra::VectorBase<double> > x_n =
model->getNominalValues().get_x()->clone_v();
RCP<Thyra::VectorBase<double> > xDot_n =
model->getNominalValues().get_x_dot()->clone_v();

Evaluate the model

Evaluate the right-hand side through ModelEvaluator. The application fills InArgs and OutArgs and then requests the model evaluation.

Before

{
Thyra::ConstDetachedVectorView<double> x_n_view(*x_n);
Thyra::DetachedVectorView<double> xDot_n_view(*xDot_n);
xDot_n_view[0] = x_n_view[1];
xDot_n_view[1] =
((1.0-x_n_view[0]*x_n_view[0])*x_n_view[1]-x_n_view[0])/epsilon;
}

After

auto inArgs = model->createInArgs();
auto outArgs = model->createOutArgs();
inArgs.set_t(time);
inArgs.set_x(x_n);
inArgs.set_x_dot(Teuchos::null);
outArgs.set_f(xDot_n);
model->evalModel(inArgs, outArgs);

The right-hand side is now obtained through the model interface rather than being coded directly in the time loop.


How to compare the examples

A more detailed comparison can be made by diffing:

From the packages/tempus directory, a focused comparison of the main time-integration logic between these two examples can be generated locally in bash or zsh with:

git diff --no-index \
<(sed -n '60,130p' examples/01_Utilize_Thyra/01_Utilize_Thyra.cpp) \
<(sed -n '67,131p' examples/02_Use_ModelEvaluator/02_Use_ModelEvaluator.cpp)

This ignores leading header lines (for example, #include statements and Doxygen comments) and trailing regression-testing lines.

← Previous Example | Current Example | Next Example →