# Variables#

An Optimal Control problem in Dymos consists of the following variable types.

## Time#

Optimal control problems in Dymos assume a system that is evolving in time. State variables typically obey some ordinary differential equation that provides the derivative of the states w.r.t. time.

Users can specify various options relating to time with the set_time_options method of Phase.

In Dymos, the phase time is controlled by two inputs:

• t_initial - The initial time of the phase

• t_duration - The duration of the phase

The bounds, scaling, and units of these variables may be set using set_time_options. In addition, the user can specify that the initial time or duration of a phase is to be connected to some external output by specifying input_initial = True or input_duration = True. In the case of fixed initial time or duration, or input initial time or duration, the optimization-related options have no effect and a warning will be raised if they are used.

The variables t_initial and t_duration are converted to time values at the nodes within the phase. Dymos computes the following time values, which can be used inside the ODE:

• time - The canonical time. At the start of the phase time = t_initial, and time = t_initial + t_duration at the end of the phase.

• time_phase - The elapsed time since the beginning of the phase. time_phase = time - t_initial

• t_initial - The initial time of the current phase (this value is the same at all nodes within the phase).

• t_duration - The phase time duration of the current phase (this value is the same at all nodes within the phase).

### Renaming the integration variable#

In some casees the integration in a phase might take place over some non-time variable. For instance, in the race car example, thee dynamics are integrated over the track length s. In such cases it might be preferable to rename the time variable to make the outputs somewhat more understandable. This can be achieved by using the name parameter to set_time_options, for instance:

phase.set_time_options(name='s', ...)


When doing so, the timeseries will replace time with the given name s and time_phase with s_phase. If one wishes to use the renamed integration variablee (or the phase-relative version), it can be used in the add_objective and add_boundary_constraint and add_path_constraint methods on Phase. For instance:

phase.set_time_options(name='W', ...)
.
.
.


### Recovering time for the timeseries outputs#

When creating timeseries plots in dymos, it expects the phase_name.timeseries.time to be present. In a multi-phase trajectory where some phases use a different variable of integratoin, it may be helpful to to add an expression for time to the timeseries manually.

For instance, the race car example integrates the expression dt_ds to accumulate the elapsed time of the phase as a state named t. This can be manulally added to the timeseries outputs

phase.add_timeseries_output('t', output_name='time')


Similarly, we can form linkage constraints that would link two phases where time might be the integration variable in one phase and a state variable in a subsequent phase.

### Options for Time Variables#

om.show_options_table("dymos.phase.options.TimeOptionsDictionary")

OptionDefaultAcceptable ValuesAcceptable TypesDescription
duration_bounds(None, None)N/A['Iterable']Tuple of (lower, upper) bounds for the duration of the integration variable across the phase.
duration_refN/AN/A['Number']Unit-reference value for the duration of the integration variable across the phase.
duration_ref0N/AN/A['Number']Zero-reference value for the duration of the integration variable across the phase.
duration_scalerN/AN/A['Number']Scalar for the duration of the integration variable across the phase.
duration_val1.0N/A['Number']Value of the duration of the integration variable across the phase.
fix_durationFalse[True, False]['bool']If True, the phase duration is not a design variable.
fix_initialFalse[True, False]['bool']If True, the initial value of time is not a design variable.
initial_bounds(None, None)N/A['Iterable']Tuple of (lower, upper) bounds for the integration variable at the start of the phase.
initial_refN/AN/A['Number']Unit-reference value for the initial value of the integration variable.
initial_ref0N/AN/A['Number']Zero-reference value for the initial value of the integration variable.
initial_scalerN/AN/A['Number']Scalar for the initial value of the integration variable.
initial_val0.0N/A['Number']Value of the integration variable at the start of the phase.
input_durationFalse[True, False]['bool']If True, the phase duration (t_duration) is expected to be connected to an external output source.
input_initialFalse[True, False]['bool']If True, the initial value of time (t_initial) is expected to be connected to an external output source.
nametimeN/A['str']Name of the integraiton variable in the phase.
t_duration_balance_options{}N/AN/Aoptions dictionary for the duration residual
t_duration_targets[]N/AN/Atargets in the ODE to which the total duration of the phase is connected
t_initial_targets[]N/AN/Atargets in the ODE to which the initial time of the phase is connected
targetsunspecifiedN/AN/Atargets in the ODE to which the integration variable is connected
time_phase_targetsunspecifiedN/AN/Atargets in the ODE to which the elapsed duration of the phase is connected
unitssN/A['str']Units for the integration variable

## States#

States are variables that define the current condition of the system. For instance, in trajectory optimization they are typically coordinates that define the position and velocity of the vehicle. They can also be things like component bulk temperatures or battery state-of-charge. In most dynamic systems, states obey some ordinary differential equation. As such, these are defined in an ODE object.

At the phase level, we assume that states evolve continuously such that they can be modeled as a series of one or more polynomials. The phase duration is broken into one or more segments on which each state (and each dynamic control) is modeled as a polynomial. The order of the polynomial is specified using the transcription_order method. In Dymos, the minimum state transcription order is 3.

Users can specify bounds and scaling of the state variables with the phase method add_state. The units and shape arguments are not required, as dymos will pull that information from the rate_source when possible. You may still add units if you would like the driver or the timeseries to see a different unit than what is defined in the rate source. There are two exceptions:

• If the rate_source references a control that has no targets, shape is required.

• If the rate_source is another state, that state needs to be declared first. If the relationship is circular, shape is required.

Settings on a previously-added state variable may be changed using the set_state_options method. The following options are valid:

### Options for State Variables#

om.show_options_table("dymos.phase.options.StateOptionsDictionary")

OptionDefaultAcceptable ValuesAcceptable TypesDescriptionDeprecation
adderN/AN/A['Iterable', 'Number']Adder of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
connected_initialFalse[True, False]['bool']Whether an input is created to pass in the initial state. This may be set by a trajectory that links phases.State option 'connected_initial' is deprecated. Please use 'input_initial' instead.
continuityTrueN/A['bool', 'dict']Enforce continuity of state values at segment boundaries. This option is invalid if opt=False.N/A
continuity_refN/AN/A['Number']Reference unit value for continuity at segment boundaries instead of scaler.This option is invalid if opt=False.N/A
continuity_scalerN/AN/A['Number']Scaler for continuity at segment boundaries. This option is invalid if opt=False.N/A
defect_refN/AN/A['Iterable', 'Number']Unit-reference value of the state defects at the collocation nodes. This option is invalid if opt=False. If provided, this option overrides defect_scaler. If defect_scaler and defect_ref are both None but the state scaler or ref are provided, use those values as the defect scaler or ref.N/A
defect_scalerN/AN/A['Iterable', 'Number']Scaler of the state variable defects at the collocation nodes. If defect_scaler and defect_ref are both None but the state scaler or ref are provided, use those values as the defect scaler or ref. This option is invalid if opt=False.N/A
descN/A['str']description of the state variableN/A
final_boundsN/AN/A['Iterable']Bounds on the value of the state at the end of the phase. This option is invalid if opt=False.N/A
fix_finalFalseN/A['bool', 'Iterable']If True, the final value of this state is fixed and not a design variable. If the state variable has a non-scalar shape, this may be an iterable of bool for each index. This option is invalid if opt=False.N/A
fix_initialFalseN/A['bool', 'Iterable']If True, the initial value of this state is fixed and not a design variable. If the state variable has a non-scalar shape, this may be an iterable of bool for each index. This option is invalid if opt=False.N/A
initial_boundsN/AN/A['Iterable']Bounds on the value of the state at the start of the phase. This option is invalid if opt=False.N/A
input_finalFalse[True, False]['bool']Whether the final value of the state is expected to be connected to an exterior value.N/A
input_initialFalse[True, False]['bool']Whether the initial value of the state is expected to be connected to an exterior value.N/A
lowerN/AN/A['Iterable', 'Number']Lower bound of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
name**Required**N/A['str']name of ODE state variableN/A
optTrue[True, False]['bool']If true, the values of this state are a design variable for the optimizer. Otherwise it exists as an unconnected input.N/A
rate_sourceN/AN/A['str']ODE-path or phase variable providing the derivative of the state variableN/A
refN/AN/A['Iterable', 'Number']Unit-reference value of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
ref0N/AN/A['Iterable', 'Number']Zero-reference value of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
scalerN/AN/A['Iterable', 'Number']Scaler of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
shapeN/AN/A['Iterable']shape of the state variable, as determined by introspectionN/A
solve_segmentsN/A[False, 'forward', 'backward']N/AIf 'forward', collocation defects within eachsegment are solved with a Newton solver by fixing the initial value in thephase (if using compressed transcription) or segment (if not using compressed transcription). This provides a forward shooting (or multiple shooting)method. If 'backward', the final value in the phase or segment is fixedand a solver finds the other ones to mimic reverse propagation. If None, (the default) use the value of solve_segments in the transcription. Set to False to explicitly disable the use of a solver to converge the statetime history.N/A
sourceN/AN/A['str']RHS-path or phase variable providing value of the state variable, for Analytic transcription only!N/A
targetsunspecifiedN/AN/ATargets in the ODE to which the state is connectedN/A
unitsunspecifiedN/AN/Aunits in which the state variable is definedN/A
upperN/AN/A['Iterable', 'Number']Upper bound of the state variable at the discretization nodes. This option is invalid if opt=False.N/A
val1.0N/A['Iterable', 'Number']Default value of the state variable at the discretization nodesN/A

The Radau Pseudospectral and Gauss Lobatto phase types in Dymos use differential defects to approximate the evolution of the state variables with respect to time. In addition to scaling the state values, scaling the defect constraints correctly is important to good performance of the collocation algorithms. This is accomplished with the defect_scaler or defect_ref options. As the name implies, defect_scaler is multiplied by the defect value to provide the defect constraint value to the optimizer. Alternatively, the user can specify defect_ref. If provided, defect_ref overrides defect_scaler and is the value of the defect seen as 1 by the optimizer.

If the ODE is explicitly depending on a state’s value (for example, the brachistochrone ODE is a function of the bead’s speed), then the user specifies those inputs in the ODE to which the state is to be connected using the targets option. It can take the following values:

• (default) If left unspecified, targets assumes a special dymos.utils.misc._unspecified value. In this case, dymos will attempt to connect to an input of the same name at the top of the ODE (either promoted there, or there because the ODE is a single component).

• None The state is explicitly not connected to any inputs in the ODE.

• str or sequence of str The state values are connected to inputs of the given name or names in the ODE. These targets are specified by their path relative to the top level of the ODE.

To simplify state specifications, using the first option (not specifying targets) and promoting targets of the state to inputs of the same name at the top-level of the ODE.

## Controls#

Typically, an ODE will have inputs that impact its values but, unlike states, don’t define the system itself. Such inputs include things like throttle level, elevator deflection angle, or spring constants. In Dymos, dynamic inputs are referred to as controls, while static inputs are called parameters.

Dynamic controls are values which we might expect to vary continuously throughout a trajectory, like an elevator deflection angle for instance. The value of these controls are often determined by an optimizer.

Note

The order of a dynamic control polynomial in a segment is one less than the state
transcription order (i.e. a dynamic control in a phase with transcription_order=3 will
be represented by a second-order polynomial.


### Options for Control Variables#

om.show_options_table("dymos.phase.options.ControlOptionsDictionary")

OptionDefaultAcceptable ValuesAcceptable TypesDescription
adderN/AN/A['Iterable', 'Number']The adder of the control variable at the nodes. This option is invalid if opt=False.
continuityTrueN/A['bool', 'dict']Enforce continuity of control values at segment boundaries. This option is invalid if opt=False.
continuity_refN/AN/A['Number']Reference unit value for continuity at segment boundaries instead of scaler.This option is invalid if opt=False.
continuity_scalerN/AN/A['Number']Scaler for continuity at segment boundaries. This option is invalid if opt=False.
control_typefullN/A['str']The type of control variable. Options are full or polynomial.
descN/A['str']The description of the control variable.
fix_finalFalse[True, False]['bool']If True, the final value of this control is fixed and not a design variable. This option is invalid if opt=False.
fix_initialFalse[True, False]['bool']If True, the initial value of this control is fixed and not a design variable. This option is invalid if opt=False.
lowerN/AN/A['Iterable', 'Number']The lower bound of the control variable at the nodes. This option is invalid if opt=False.
name**Required**N/A['str']The name of ODE system parameter to be controlled.
optTrue[True, False]['bool']If True, the control value will be a design variable for the optimization problem. If False, allow the control to be connected externally.
orderN/AN/A['int']A integer that provides the interpolation order when the control is to assume a single polynomial basis across the entire phase, or None to use the default control behavior.
rate2_continuityFalseN/A['bool', 'dict']Enforce continuity of control second derivatives at segment boundaries. This option is invalid if opt=False.
rate2_continuity_refN/AN/A['Number']Reference unit value for rate2 continuity at segment boundaries instead of scaler.This option is invalid if opt=False.
rate2_continuity_scalerN/AN/A['Number']Scaler of the rate2 continuity constraint at segment boundaries. This option is invalid if opt=False.
rate2_targetsunspecifiedN/AN/AThe targets in the ODE to which the control 2nd derivative is connected
rate_continuityTrueN/A['bool', 'dict']Enforce continuity of control first derivatives in dimensionless time at segment boundaries. This option is invalid if opt=False.
rate_continuity_refN/AN/A['Number']Reference unit value for rate continuity at segment boundaries instead of scaler.This option is invalid if opt=False.
rate_continuity_scalerN/AN/A['Number']Scaler of the rate continuity constraint at segment boundaries. This option is invalid if opt=False.
rate_targetsunspecifiedN/AN/AThe targets in the ODE to which the control rate is connected
refN/AN/A['Iterable', 'Number']The unit-reference value of the control variable at the nodes. This option is invalid if opt=False.
ref0N/AN/A['Iterable', 'Number']The zero-reference value of the control variable at the nodes. This option is invalid if opt=False.
scalerN/AN/A['Iterable', 'Number']The scaler of the control variable at the nodes. This option is invalid if opt=False.
shapeN/AN/A['Iterable']The shape of the control variable at each point in time.
targetsunspecifiedN/AN/ATargets in the ODE to which the state is connected
unitsunspecifiedN/AN/AThe units in which the control variable is defined.
upperN/AN/A['Iterable', 'Number']The upper bound of the control variable at the nodes. This option is invalid if opt=False.
val[0.]N/A['Iterable', 'ndarray', 'Number']The default value of the control variable at the control discretization nodes.

Control values are connected to the ODE using the targets argument. The values of this argument obey the same rules as those for states.

The control first and second derivatives w.r.t. time may also be connected to the ODE. First derivatives of controls in Dymos assume the name <control_name>_rate. Second derivatives of controls in Dymos assume the name <control_name>_rate2. Control rates are automatically connected if a top-level input of the ODE is named <control_name>_rate or <control_name>_rate2. These variables are available in the timeseries output as timeseries.control_rates.<control_name>_rate and timeseries.control_rates.<control_name>_rate2, respectively.

### Polynomial Controls#

Sometimes it can be easier to optimize a problem by reducing the freedom in the controls. For instance, one might want the control to be linearly or quadratically varying throughout a phase, rather than having a different value specified at each node. In Dymos, this role is filled by the PolynomialControl. Polynomial controls are specified at some limited number of points throughout a phase, and then have their values interpolated to each node in each segment. Controls added with control_type='polynomial' are added as polynomial controls.

## Parameters#

Some inputs impact the system but have one set value throughout the trajectory. We refer to these non-time-varying inputs as parameters, since they typically involve parameters which define a system. Parameters could include things like the wingspan of a vehicle or the mass of a heatsink. In Dymos, parameters can be optimized (by providing argument opt = True). If not optimized they can be targets for connections from outside of the Phase or Trajectory.

### Options for Parameters#

om.show_options_table("dymos.phase.options.ParameterOptionsDictionary")

OptionDefaultAcceptable ValuesAcceptable TypesDescriptionDeprecation
adderN/AN/A['Iterable', 'Number']The adder of the parameter. This option is invalid if opt=False.N/A
descN/A['str']The description of the parameter.N/A
dynamicunspecified[True, False, unspecified]N/ATrue if this parameter can be used as a dynamic control, else False.If _unspecified, attempt to determine through introspection.Option dynamic has been replaced by option 'static_target' and will be removed in Dymos 2.0.0. Note that 'static_target' has the opposite meaning of option 'dynamic', so parameters with option 'dynamic' set to False should now use 'static_target' set to True.
include_timeseriesN/A[True, False]['bool']True if the static parameters should be included in output timeseries, else False.If None (default) set the value based on Phase.timeseries_options["include_parameters"]N/A
lowerN/AN/A['Iterable', 'Number']The lower bound of the parameter. This option is invalid if opt=False.N/A
name**Required**N/A['str']The name of ODE system parameter to be set via parameter.N/A
optTrue[True, False]['bool']If True, the control value will be a design variable for the optimization problem. If False, allow the control to be connected externally.N/A
refN/AN/A['Iterable', 'Number']The unit-reference value of the parameter. This option is invalid if opt=False.N/A
ref0N/AN/A['Iterable', 'Number']The zero-reference value of the parameter. This option is invalid if opt=False.N/A
scalerN/AN/A['Iterable', 'Number']The scaler of the parameter. This option is invalid if opt=False.N/A
shapeunspecifiedN/AN/AThe shape of the parameter.N/A
static_targetunspecifiedN/AN/ATrue if the target of this parameter does NOT have a unique value at each node in the ODE.If _unspecified, attempt to determine through introspection.Use option static_targets to specify whether all targets are static (static_targets=True), none are static (static_targets=False), static_targets are determined via introspection (static_targets=_unspecified), or give an explicit sequence of the static targets.
static_targetsunspecifiedN/AN/AIf a boolean, specifies whether all targets are static (True), or no targets are static (False). Otherwise, provide a list of the static targets within the ODE. If left unspecified, static targets will be determined by finding inptus tagged with 'dymos.static_target'.N/A
targetsunspecifiedN/AN/ATargets in the ODE to which the state is connectedN/A
unitsunspecifiedN/AN/AThe units in which the parameter is defined.N/A
upperN/AN/A['Iterable', 'Number']The upper bound of the parameter. This option is invalid if opt=False.N/A
val0.0N/A['Iterable', 'ndarray', 'Number']The default value of the parameter in the phase.N/A

Parameters can have their values determined by the optimizer, or they can be passed in from an external source.

Parameters obey the same connection rules as other variables, if targets is left unspecified.

Parameters are available in the timeseries output as timeseries.parameters.<parameter_name>. Since parameters are constant throughout a trajectory, some users may want to prevent them from inclusion in the timeseries. This can be done by specifying include_timeseries = False in the parameter options.