3.6. Performing State Propagation

Propagating the dynamics, using the settings discussed in previous wiki pages, is done by using a DynamicsSimulator object. We have several different derived classes of DynamicsSimulator for different types of propagation. The following are available or under development in Tudat:

As discussed below, the state may be propagated directly upon the creation of one of these objects, or at a later time (depending on the input that is used.)

Warning

It is important to ensure that the propagator settings are compatible with the dynamics simulator type selected. Otherwise it will result in an exception being thrown during run-time.

These are implemented in derived classes and are discussed below.

class DynamicsSimulator

Base class from which the classes below are derived.

class SingleArcDynamicsSimulator

This derived class simulates single arc dynamics and its constructor is:

SingleArcDynamicsSimulator< StateScalarType, TimeType >( bodyMap, integratorSettings, propagatorSettings );

where:

  • bodyMap

    NamedBodyMap the map containing al the objects of type Body used in the simulation.

  • integratorSettings

    IntegratorSettings contains the settings of the integrator used, as discussed in Integrator Settings.

  • propagatorSettings

    SingleArcPropagatorSettings contains the settings that defines how the orbit is propagated, as described in Propagator Settings: Basics.

  • StateScalarType

    Template argument used to set the precision of the state, double by default. For some application where a high precision is required this can be changed to e.g. long double (see Time and State Templates).

  • TimeType

    Template argument used to set the precision of the time, double by default. For some application where a high precision is required this can be changed to e.g. Time (see Time and State Templates).

By default, the equations of motion are integrated once the object is created. This can be changed by adding additional arguments to the cosntructors of the DynamicsSimulator, as shown below for the SingleArcDynamicsSimulator:

// Create simulation object and propagate dynamics.
SingleArcDynamicsSimulator< StateScalarType, TimeType >dynamicsSimulator(
   bodyMap, integratorSettings, propagatorSettings, areEquationsOfMotionToBeIntegrated,
   clearNumericalSolutions, setIntegratedResult, printNumberOfFunctionEvaluations );

where:

  • areEquationsOfMotionToBeIntegrated
    Boolean to denote whether equations of motion should be integrated immediately at the end of the contructor or not (default true).
  • clearNumericalSolutions
    Boolean to determine whether to clear the raw numerical solution member variables after propagation and resetting ephemerides (default false for SingleArcDynamicsSimulation, and true for MultiArcDynamicsSimulation and HybridArcDynamicsSimulation).
  • setIntegratedResult
    Boolean to determine whether to automatically use the integrated results to set ephemerides (default false for SingleArcDynamicsSimulation, and true for MultiArcDynamicsSimulation and HybridArcDynamicsSimulation).
  • printNumberOfFunctionEvaluations
    Boolean to toggle the printing of number of function evaluations at the end of propagation (default false).
class MultiArcDynamicsSimulator

This derived class allows the numerical propagation to be performed in an arc-wise manner. It is constructed using:

MultiArcDynamicsSimulator( bodyMap, integratorSettings, propagatorSettings, arcStartTimes,
                           areEquationsOfMotionToBeIntegrated, clearNumericalSolutions, setIntegratedResult );

where:

  • propagatorSettings

    MultiArcPropagatorSettings, contains the settings that defines how the orbit is propagated, as described in Propagator Settings: Basics. Note that the propagator settings may be identical, or different, per arc (depending on the contents of the settings object).

    • arcStartTimes

      std::vector< double > containing the times at which the separate arcs start. Note: there is no requirement for the arcs to be contiguous and/or overlapping.

The following, alternative, constructor allows you to specify different integrator settings per arc:

MultiArcDynamicsSimulator( bodyMap, integratorSettingsList, propagatorSettings, arcStartTimes,
                         areEquationsOfMotionToBeIntegrated, clearNumericalSolutions, setIntegratedResult );
  • integratorSettingsList

    std::vector is the list (same size as number of arcs) with the settings of the integrator used, per arc.

class HybridArcDynamicsSimulator
Allows some bodies to be propagated in a single arc, and some in a multi-arc fashion. This has the strict requirement that the single-arc bodies’ dynamics does not depend on the multi-arc bodies. For instance, the multi-arc bodies are typically spacecraft and the single-arc bodies solar system bodies. The vehicles do not exert an acceleration on the planets, but the planets exert accelerations on the spacecraft. When using hybrid-arc propagation, the single-arc bodies are first propagated, followed by the multi-arc bodies.
 HybridArcDynamicsSimulator( bodyMap, integratorSettings, propagatorSettings, arcStartTimes,
                            areEquationsOfMotionToBeIntegrated, clearNumericalSolutions, setIntegratedResult );

where:

3.6.1. Retrieving the Propagation History

Once the DynamicsSimulator object has been created and the equations of motion have been integrated, the propagation history of the selected bodies is stored within the DynamicsSimulator, unless the clearNumericalSolutions variable has been set to true. Note that this is the default for multi- and hybrid-arc propagation.

To make use of it, such history needs to be retrieved and saved to a file. The SingleDynamicsSimulator offers a few different options to extract results, based on what you have input in the simulation. All propagation history is stored as a std::map< double, Eigen::VectorXd > (assuming you are using standard TimeType and StateScalarType).

Note

All examples given below are valid for the single-arc propagation only. The corresponding functions of the multi- and hybird-arc models produce a std::vector< std::map< ..., ... > >, instead of the std::map< ..., ... > output used below.

First of all, you can access the history of the propagated states for each object you have simulated:

  • Extracting the state history in the conventional coordinates

    The conventional coordinates are those coordinates that are used to describe the acceleration model. For translational motion, these are the Cartesian coordinates, whereas for rotational motion, they are quaternions. To access and save these results you can use the function getEquationsOfMotionNumericalSolution of the DynamicsSimulator object, as shown below:

    // Write body propagation history in conventional coordinates to file.
    writeDataMapToTextFile( dynamicsSimulator.getEquationsOfMotionNumericalSolution( ),
                            "bodyPropagationHistory.dat",
                            outputPath );
    
  • Extracting the state history in the propagated coordinates

    The propagation coordinates are those coordinates that are used to describe the equations of motion and thus are the ones that are actually integrated. For translational motion, these can be Cartesian coordinates, Keplerian elements and one of the three unified state models, whereas for rotational motion, these can be quaternions, modified Rodrigues parameters or the exponential map. To access and save these results you can use the function getEquationsOfMotionNumericalSolutionRaw of the DynamicsSimulator object, as shown here:

    // Write body propagation history in propagation coordinates to file.
    writeDataMapToTextFile( dynamicsSimulator.getEquationsOfMotionNumericalSolutionRaw( ),
                            "bodyPropagationRawHistory.dat",
                            outputPath );
    

Tip

You can find more information about the difference between conventional and propagation coordinates in Propagator Settings: Conventional vs. Propagated Coordinates.

In case you have also decided to store some dependent variables, you can access and save their history by placing the following code after the DynamicsSimulator object creation:

// Write body dependent variable history to file.
writeDataMapToTextFile( dynamicsSimulator.getDependentVariableHistory( ),
                        "bodyDependentVariableHistory.dat",
                        outputPath );

Similarly to the getEquationsOfMotionNumericalSolution and getEquationsOfMotionNumericalSolutionRaw functions, the getDependentVariableHistory outputs a map, where the key is the time and the mapped value a vector of variable length. This length depends on a few things:

  • For extraction of numerical solutions: how many bodies are being propagated, how many propagators are used and the length of the conventional or propagation coordinates
  • For extraction of dependent variables: how many depenent variables are being saved and whether they are a scalar or a vector

Note

For the dependent variables, the simulation will automatically output the order and length of each dependent variable. This is true, however, only if you have not turned off this feature while adding the dependent variable settings to the propagator object.

Finally, the DynamicsSimulator object offers a couple more interesting member functions that can be used to access some internal variables. You can, for instance, use:

  • getCumulativeNumberOfFunctionEvaluations to access the history of the number of function evaluations over propagation; the key is the simulation time and the mapped value gives the cumulative number of function evaluations; this can be very useful when studying the performance of the propagation coordinates and/or of a variable step size integrator.
  • getCumulativeComputationTimeHistory to access the history of the computation time over propagation; the key is the simulation time and the mapped value gives the cumulative computation time.

The code snippets used at the beginning of this section can be also used to save the cumulative variables above. The result will be a .dat file in the folder specified by the outputPath string. You can make use of the tudat_applications::getOutputPath( ) function to get a folder name relative to the project folder.

Tip

In case you wanted to have more control on how the data is written to the text file (e.g., setting a different number of significant digits, adding a header to the file, etc.) you can check out the Wiki page on writeDataMapToTextFile at Input/Output.