Skip to content

Modular Simulation Loop (Virtual Functions)

Stephen Berry edited this page Feb 17, 2021 · 6 revisions

Ascent has a built in asc::Module class, which provides virtual function calls for building complex, modular simulations.

Modular simulations are easy to compose, connect and disconnect during a simulation.

Understanding the purpose of the virtual functions is critical to building a robust and efficient simulation engine.

Ascent does not provide a modular simulator class, but rather provides the structure to build custom simulation engines.

Module has the following virtual functions for building simulation loops:

  • link()
  • init()
  • operator()()
  • apply()
  • propagate(Propagator<double>& propagator, const double dt)
  • postprop()
  • postcalc()

By default these functions do nothing (except for propagate) and therefore not all must be implemented to build a working simulation engine.

Most new users will only have need of init, operator(), and postcalc. These are the most commonly implemented functions.

Link

The link function is meant to connect various modules together (link them). Often pointers are used, and valid pointers to other modules may be needed prior to initialization.

link should be called once per module

Init

The init function is meant for initialization code once the modules to be run are linked.

init should be called once per module

Function operator (operator())

The function operator is used for derivative accumulations. For example, computing and accumulating forces on a mass. For most systems the bulk of the computational code will exist within this function.

operator() will be called one or more times per numerical integration step. For example a Runge Kutta 4th order solver will call this four times.

Apply

The apply function is used to apply accumulated derivative computations (such as forces) prior to numerical integration (or propagation).

apply is called after operator() one or more times per numerical integration step.

Note: Some simply systems can apply within operator(), however generically handling multiple accumulating modules on another module requires the proper use of apply.

Propagate

Propagate typically doesn't need to be overridden by the user. It is used to actually update the underlying states (within the Module) with the result of the numerical integrator (within substeps).

propagate is called after apply one or more times per numerical integration step.

Postprop

postprop is used for calculations after state propagation. It is highly encouraged to limit calculations here to member states that are owned by the Module. Postprop allows for optimizations, where parameters computed from propagated values can be computed once and safely shared.

postprop is called after propagate one or more times per numerical integration step.

Postcalc

postcalc calls are outside of the numerical integrator and used for discrete calculations.

postcalc should be called after each full integration step.

What does the numerical integrator call?

A numerical integrator calls the following each substep:

operator()
apply
propagate
postprop

There can be multiple substeps per integration step.