# 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', ...)
.
.
.
phase.add_objective('W', loc='final')
```

### 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")
```

Option | Default | Acceptable Values | Acceptable Types | Description |
---|---|---|---|---|

duration_adder | N/A | N/A | ['Number'] | Adder for the duration of the integration variable across the phase. |

duration_bounds | (None, None) | N/A | ['Iterable'] | Tuple of (lower, upper) bounds for the duration of the integration variable across the phase. |

duration_ref | N/A | N/A | ['Number'] | Unit-reference value for the duration of the integration variable across the phase. |

duration_ref0 | N/A | N/A | ['Number'] | Zero-reference value for the duration of the integration variable across the phase. |

duration_scaler | N/A | N/A | ['Number'] | Scalar for the duration of the integration variable across the phase. |

duration_val | 1.0 | N/A | ['Number'] | Value of the duration of the integration variable across the phase. |

fix_duration | False | [True, False] | ['bool'] | If True, the phase duration is not a design variable. |

fix_initial | False | [True, False] | ['bool'] | If True, the initial value of time is not a design variable. |

initial_adder | N/A | N/A | ['Number'] | Adder for the initial value of the integration variable. |

initial_bounds | (None, None) | N/A | ['Iterable'] | Tuple of (lower, upper) bounds for the integration variable at the start of the phase. |

initial_ref | N/A | N/A | ['Number'] | Unit-reference value for the initial value of the integration variable. |

initial_ref0 | N/A | N/A | ['Number'] | Zero-reference value for the initial value of the integration variable. |

initial_scaler | N/A | N/A | ['Number'] | Scalar for the initial value of the integration variable. |

initial_val | 0.0 | N/A | ['Number'] | Value of the integration variable at the start of the phase. |

input_duration | False | [True, False] | ['bool'] | If True, the phase duration (t_duration) is expected to be connected to an external output source. |

input_initial | False | [True, False] | ['bool'] | If True, the initial value of time (t_initial) is expected to be connected to an external output source. |

name | time | N/A | ['str'] | Name of the integraiton variable in the phase. |

t_duration_balance_options | {} | N/A | N/A | options dictionary for the duration residual |

t_duration_targets | [] | N/A | N/A | targets in the ODE to which the total duration of the phase is connected |

t_initial_targets | [] | N/A | N/A | targets in the ODE to which the initial time of the phase is connected |

targets | unspecified | N/A | N/A | targets in the ODE to which the integration variable is connected |

time_phase_targets | unspecified | N/A | N/A | targets in the ODE to which the elapsed duration of the phase is connected |

units | s | N/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")
```

Option | Default | Acceptable Values | Acceptable Types | Description | Deprecation |
---|---|---|---|---|---|

adder | N/A | N/A | ['Iterable', 'Number'] | Adder of the state variable at the discretization nodes. This option is invalid if opt=False. | N/A |

connected_initial | False | [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. |

continuity | True | N/A | ['bool', 'dict'] | Enforce continuity of state values at segment boundaries. This option is invalid if opt=False. | N/A |

continuity_ref | N/A | N/A | ['Number'] | Reference unit value for continuity at segment boundaries instead of scaler.This option is invalid if opt=False. | N/A |

continuity_scaler | N/A | N/A | ['Number'] | Scaler for continuity at segment boundaries. This option is invalid if opt=False. | N/A |

defect_ref | N/A | N/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_scaler | N/A | N/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 |

desc | N/A | ['str'] | description of the state variable | N/A | |

final_bounds | N/A | N/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_final | False | N/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_initial | False | N/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_bounds | N/A | N/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_final | False | [True, False] | ['bool'] | Whether the final value of the state is expected to be connected to an exterior value. | N/A |

input_initial | False | [True, False] | ['bool'] | Whether the initial value of the state is expected to be connected to an exterior value. | N/A |

lower | N/A | N/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 variable | N/A |

opt | True | [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_source | N/A | N/A | ['str'] | ODE-path or phase variable providing the derivative of the state variable | N/A |

ref | N/A | N/A | ['Iterable', 'Number'] | Unit-reference value of the state variable at the discretization nodes. This option is invalid if opt=False. | N/A |

ref0 | N/A | N/A | ['Iterable', 'Number'] | Zero-reference value of the state variable at the discretization nodes. This option is invalid if opt=False. | N/A |

scaler | N/A | N/A | ['Iterable', 'Number'] | Scaler of the state variable at the discretization nodes. This option is invalid if opt=False. | N/A |

shape | N/A | N/A | ['Iterable'] | shape of the state variable, as determined by introspection | N/A |

solve_segments | N/A | [False, 'forward', 'backward'] | N/A | If '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 |

source | N/A | N/A | ['str'] | RHS-path or phase variable providing value of the state variable, for Analytic transcription only! | N/A |

targets | unspecified | N/A | N/A | Targets in the ODE to which the state is connected | N/A |

units | unspecified | N/A | N/A | units in which the state variable is defined | N/A |

upper | N/A | N/A | ['Iterable', 'Number'] | Upper bound of the state variable at the discretization nodes. This option is invalid if opt=False. | N/A |

val | 1.0 | N/A | ['Iterable', 'Number'] | Default value of the state variable at the discretization nodes | N/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")
```

Option | Default | Acceptable Values | Acceptable Types | Description |
---|---|---|---|---|

adder | N/A | N/A | ['Iterable', 'Number'] | The adder of the control variable at the nodes. This option is invalid if opt=False. |

continuity | True | N/A | ['bool', 'dict'] | Enforce continuity of control values at segment boundaries. This option is invalid if opt=False. |

continuity_ref | N/A | N/A | ['Number'] | Reference unit value for continuity at segment boundaries instead of scaler.This option is invalid if opt=False. |

continuity_scaler | N/A | N/A | ['Number'] | Scaler for continuity at segment boundaries. This option is invalid if opt=False. |

control_type | full | N/A | ['str'] | The type of control variable. Options are `full` or `polynomial`. |

desc | N/A | ['str'] | The description of the control variable. | |

fix_final | False | [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_initial | False | [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. |

lower | N/A | N/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. |

opt | True | [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. |

order | N/A | N/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_continuity | False | N/A | ['bool', 'dict'] | Enforce continuity of control second derivatives at segment boundaries. This option is invalid if opt=False. |

rate2_continuity_ref | N/A | N/A | ['Number'] | Reference unit value for rate2 continuity at segment boundaries instead of scaler.This option is invalid if opt=False. |

rate2_continuity_scaler | N/A | N/A | ['Number'] | Scaler of the rate2 continuity constraint at segment boundaries. This option is invalid if opt=False. |

rate2_targets | unspecified | N/A | N/A | The targets in the ODE to which the control 2nd derivative is connected |

rate_continuity | True | N/A | ['bool', 'dict'] | Enforce continuity of control first derivatives in dimensionless time at segment boundaries. This option is invalid if opt=False. |

rate_continuity_ref | N/A | N/A | ['Number'] | Reference unit value for rate continuity at segment boundaries instead of scaler.This option is invalid if opt=False. |

rate_continuity_scaler | N/A | N/A | ['Number'] | Scaler of the rate continuity constraint at segment boundaries. This option is invalid if opt=False. |

rate_targets | unspecified | N/A | N/A | The targets in the ODE to which the control rate is connected |

ref | N/A | N/A | ['Iterable', 'Number'] | The unit-reference value of the control variable at the nodes. This option is invalid if opt=False. |

ref0 | N/A | N/A | ['Iterable', 'Number'] | The zero-reference value of the control variable at the nodes. This option is invalid if opt=False. |

scaler | N/A | N/A | ['Iterable', 'Number'] | The scaler of the control variable at the nodes. This option is invalid if opt=False. |

shape | N/A | N/A | ['Iterable'] | The shape of the control variable at each point in time. |

targets | unspecified | N/A | N/A | Targets in the ODE to which the state is connected |

units | unspecified | N/A | N/A | The units in which the control variable is defined. |

upper | N/A | N/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")
```

Option | Default | Acceptable Values | Acceptable Types | Description | Deprecation |
---|---|---|---|---|---|

adder | N/A | N/A | ['Iterable', 'Number'] | The adder of the parameter. This option is invalid if opt=False. | N/A |

desc | N/A | ['str'] | The description of the parameter. | N/A | |

dynamic | unspecified | [True, False, unspecified] | N/A | True 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_timeseries | N/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 |

lower | N/A | N/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 |

opt | True | [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 |

ref | N/A | N/A | ['Iterable', 'Number'] | The unit-reference value of the parameter. This option is invalid if opt=False. | N/A |

ref0 | N/A | N/A | ['Iterable', 'Number'] | The zero-reference value of the parameter. This option is invalid if opt=False. | N/A |

scaler | N/A | N/A | ['Iterable', 'Number'] | The scaler of the parameter. This option is invalid if opt=False. | N/A |

shape | unspecified | N/A | N/A | The shape of the parameter. | N/A |

static_target | unspecified | N/A | N/A | True 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_targets | unspecified | N/A | N/A | If 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 |

targets | unspecified | N/A | N/A | Targets in the ODE to which the state is connected | N/A |

units | unspecified | N/A | N/A | The units in which the parameter is defined. | N/A |

upper | N/A | N/A | ['Iterable', 'Number'] | The upper bound of the parameter. This option is invalid if opt=False. | N/A |

val | 0.0 | N/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.