  # State and Configuration

A NumericalPropagatorDefinition holds collections of PropagationStateElements, AuxiliaryStateElements, and PropagationStateCorrectors, as well as a NumericalIntegrator. The propagation elements represent quantities, such as position, for which no trajectory is known and a set of differential equations can be defined to govern how the propagation element changes over time. The numerical integrator uses the differential equations defined on the propagation elements to advance from one time to the next. In the process, auxiliary values are computed either in the process of integrating the propagation elements or separate from them. However, unlike the propagation elements, the auxiliary elements do not have differential equations to integrate. Lastly, the correctors operate on the propagated elements after each integration step in order to update the values based on discrete criteria above and beyond the differential equations. Altogether, a NumericalPropagatorDefinition uses these collections and integrator in order to create a NumericalPropagator. Configuring Numerical Propagation

The following diagram illustrates the workflow involved in configuring several state elements together to define their relationships to each other. "CustomThrust" represents a model created by a user which can couple the differential equations between the mass and the position (forces). Geometry types such as Scalar, Vector, Point and Axes are used to define the abstract time-varying behavior of elements and dependencies within the state. For instance, the mass is represented by a Scalar which can be either a constant number, an abstract time-varying quantity, or a value representing the current value in the state during integration ("IntegrationMass"). This allows the system to remain agnostic as to whether a given dependency is a constant value, a predefined function of time and other quantities, or an active member of the state, respectively.

In the above example, a user is setting up a problem involving a gravity model and a custom thrust model. The gravity model requires a position ("TargetPoint") and data on the gravitational field to compute in order to produce a specific force. The custom thrust model also depends on the position as well as the current mass and defines a flow rate for the propellant (mass) in addition to being a force model. So, the user adds both force models to define the derivative of the state element for position and then adds the flow rate to define the derivative for the mass. Since the position also needs the mass to determine the acceleration as a result of Newton's Second Law, it gets coupled with the "IntegrationMass" from the state element representing the mass. This way, coupling complex relationships becomes a matter of connecting the geometries (and scalars) together prior to propagation.

This also allows a lot of places for users to customize behavior. If users wish to provide custom time-varying functions for drag coefficients, solar reflectivity coefficients, mass, pointing vectors, or any other elements which depend on geometry, so long as the configuration doesn't use the "integrated" geometry objects (e.g. "IntegrationPoint" or "IntegrationMass") outside of propagation everything will work properly in the propagator. In order to use "integrated" objects outside of propagation, users need to create new geometry objects which define the geometric values based on the time history of the state along with an appropriate interpolation scheme.

After creating a NumericalPropagator from a state, the abstract time-varying geometry is set in the propagator and any changes to the geometry will not impact the results of propagation. To change the results, a new propagator needs to be created after changing the configuration as necessary. If the only change needed is to respecify the initial conditions of the state or the initial epoch, the propagator can be reset to new initial conditions, using the same state and derivatives (force models).

The following example demonstrates this in code:

Java
```PropagationScalar mass = new PropagationScalar();
mass.setIdentification("MyVehicleMass"); // Needed to identify output after propagation
mass.setScalarDerivative(massFlowRate);
// To specify a second-order differential equation for mass,
// include a "FirstDerivative" in the Motion for the InitialState.
// Then, the "ScalarDerivative" represents the derivative of the
// mass flow rate.  As a result, both mass and mass flow
// will be integrated by the propagator.
mass.setInitialState(new Motion1<Double>(initialMass));

PropagationNewtonianPoint position = new PropagationNewtonianPoint();
position.setIdentification("MyVehiclePosition"); // Needed to identify output after propagation
position.setInitialPosition(initialPosition);
position.setInitialVelocity(initialVelocity);
position.setIntegrationFrame(earth.getInertialFrame());
position.setMass(mass.getIntegrationValue());

SphericalHarmonicGravity gravity = new SphericalHarmonicGravity();
gravity.setTargetPoint(position.getIntegrationPoint()); // Will represent the position during propagation
int degree = 41;
int order = 41;
boolean includeTwoBodyForce = true;
gravity.setGravityField(new SphericalHarmonicGravityField(gravityModel, degree, order, includeTwoBodyForce, SphericalHarmonicsTideType.NONE));

AtmosphericDragForce drag = new AtmosphericDragForce();
double solarFlux = 150.0;
double kp = 3.00;
ScalarDensityJacchiaRoberts density = new ScalarDensityJacchiaRoberts();
density.setSolarGeophysicalData(new ConstantSolarGeophysicalData(solarFlux, kp));
density.setTargetPoint(position.getIntegrationPoint()); // Will represent the position during propagation
density.setApparentSunPosition(); // More accurate, slightly slower performance
density.setUseApproximateAltitude(true); // Faster, better numerical precision, very slightly worse accuracy
drag.setDensity(density);
drag.setCoefficientOfDrag(Scalar.toScalar(2.2)); // This could be a time varying Scalar instead
drag.setReferenceArea(Scalar.toScalar(20.0));

AuxiliaryStateScalar densityOutput = new AuxiliaryStateScalar(density);
String densityID = "MyAtmosphericDensity";
densityOutput.setIdentification(densityID);

RungeKuttaFehlberg78Integrator integrator = new RungeKuttaFehlberg78Integrator();
integrator.setInitialStepSize(stepSize);

NumericalPropagatorDefinition state = new NumericalPropagatorDefinition();
state.setEpoch(epoch);
state.setIntegrator(integrator); Propagation and Auxiliary State Elements State Correctors