Skip to content

Commit

Permalink
API Change: design_parameters and input_parameters have been combined…
Browse files Browse the repository at this point in the history
… into just parameters. (#365)

* First part works, but fixing openmdao bugs.

* small fix

* updates dymos for OpenMDAO list_inputs/list_outputs change #352

* revert back to Agg for plotting

* progress

* Still a few failures.

* fixed final bug in rework

* reverting some stuff in a test

* Move input creation to configure for GL too.

* re-trigger CI

* Bret review

* des param -> param

* continuing changes, including to trajectory

* more fixes to that

* input params removed from tests

* clean up tests

* A few more fixes.

* traj param copy fix

* lint

* A couple more fixes

* A couple more fixes

* bench

* remove debug

* last test augmented

* travis change

* doc cleanup

* more doc cleanup

* changed documentation references for the mkdocs system to only reference parameters

* docs cleanup

* review

* scaling change in the water rocket problem

Co-authored-by: Kenneth Moore <KenMooreZ1@gmail.com>
Co-authored-by: Rob Falck <rfalck@nasa.gov>
  • Loading branch information
3 people authored Aug 26, 2020
1 parent b8fb551 commit 0d49672
Show file tree
Hide file tree
Showing 86 changed files with 1,097 additions and 1,509 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ after_success:

deploy:
on:
condition: $UPLOAD_DOCS = 1
push:
branches:
- master
Expand Down
6 changes: 3 additions & 3 deletions benchmark/benchmark_brachistochrone.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, tran
phase.add_control('theta', continuity=True, rate_continuity=True,
units='deg', lower=0.01, upper=179.9, targets=['theta'])

phase.add_input_parameter('g', units='m/s**2', val=9.80665, targets=['g'])
phase.add_parameter('g', units='m/s**2', val=9.80665, targets=['g'])

phase.add_boundary_constraint('x', loc='final', equals=10)
phase.add_boundary_constraint('y', loc='final', equals=5)
Expand All @@ -65,7 +65,7 @@ def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, tran
p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input')
p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input')
p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input')
p['phase0.input_parameters:g'] = 9.80665
p['phase0.parameters:g'] = 9.80665

p.run_driver()

Expand All @@ -89,7 +89,7 @@ def run_asserts(self, p):
v0 = p.get_val('phase0.timeseries.states:v')[0]
vf = p.get_val('phase0.timeseries.states:v')[-1]

g = p.get_val('phase0.timeseries.input_parameters:g')[0]
g = p.get_val('phase0.timeseries.parameters:g')[0]

thetaf = p.get_val('phase0.timeseries.controls:theta')[-1]

Expand Down
2 changes: 1 addition & 1 deletion dymos/docs/examples/brachistochrone.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ in this case an :code:`ExplicitComponent`. The :code:`declare_time`, :code:`dec
:code:`declare_parameter` decorators are used to inform Dymos as to where the time, states, and
potential control variables should be connected to the system. These decorators are *optional* and
only provide defaults for these values. Otherwise they can be set via the Phase API (``set_time_options``,
``add_state``, ``add_control``, ``add_design_parameter``, ``add_input_parameter`` etc.
``add_state``, ``add_control``, ``add_parameter`` etc.
The :code:`rate_source` parameter of :code:`declare_state` dictates the output in the system
that provides the time-derivative of the corresponding state variable.

Expand Down
29 changes: 8 additions & 21 deletions dymos/docs/feature_reference/defining_odes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Defining ODEs

Optimal control problems contain ordinary differential equations (ODE) or
differential algebraic equations (DAE) that dictate the evolution of the state of the system.
Typically this evolution occurs in time, and the ODE represents equations of motion (EOM).
Typically this evolution occurs in time, and the ODE represents equations of motion (EOM).
The equations of motion can define a variety of systems, not just mechanical ones.
In other fields they are sometimes referred to as *process equations*.

Expand Down Expand Up @@ -90,30 +90,17 @@ Phase. The available options are as follows:
_ForDocs
control_options

Design Parameters
Parameters
^^^^^^^^^^^^^^^^^

Inputs to the ODE which can be design parameters are added via the `add_design_parameter` method of
Phase. The available options are as follows:

.. embed-options::
dymos.phase.options
_ForDocs
design_parameter_options

Input Parameters
^^^^^^^^^^^^^^^^

Inputs to the ODE which can be input parameters are added via the `add_input_parameter` method of
Phase.
They are similar to design parameters, but the phase cannot treat them as design
variables to the optimization problem.
The available options are as follows:
Inputs to the ODE which can be design parameters are added via the `add_parameter` method of
Phase. You can optionally choose whether the phase will see them as design parameters by
setting the "opt" argument to True. The available options are as follows:

.. embed-options::
dymos.phase.options
_ForDocs
input_parameter_options
parameter_options

Using decorators to associate time, control, and parameter options with the ODE system
--------------------------------------------------------------------------------------
Expand All @@ -124,7 +111,7 @@ For example, bounds on times, states, and controls will be problem-dependent.
Other options, such as the `rate_source` of state variables or the target of time, states, or controllable parameters are a function of the ODE itself.
Therefore it can sometimes be convenient to associate those properties with the ODE class itself.
To allow this, Dymos provides decorators for ODEs which assign *default* values of these properties at the ODE level.
These values can be overridden using the `set_time_options`, `add_state`, `add_control`, `add_design_parameter` or `add_input_parameter` methods on Phase.
These values can be overridden using the `set_time_options`, `add_state`, `add_control` or `add_parameter` methods on Phase.

.. note::

Expand Down Expand Up @@ -240,6 +227,6 @@ Non-Vector Inputs

Declaring inputs as vectors means that they have the potential to be used either as design parameters or as dynamic controls which can assume a different value at each node.
For some quantities, such as gravitational acceleration in the Brachistochrone example, we can assume that the value will never need to be dynamic.
To accommodate this, design and input parameters can be declared static with the argument `dynamic=False`.
To accommodate this, parameters can be declared static with the argument `dynamic=False`.
This prevents Dymos from "fanning out" the static value to the *n* nodes in the ODE system.
If a parameter is declared static in the `declare_parameter` decorator, it cannot be used as a dynamic control.
4 changes: 2 additions & 2 deletions dymos/docs/feature_reference/optimal_control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ In order to impact the behavior of such systems we need *controls*. Controls ma
to vary with time, such as the angle-of-attack of an aircraft during flight. We refer to these
as *dynamic* controls :math:`\left(\bar{u}\right)`. Other controllable parameters might be fixed
with time, such as the wingspan of an aircraft. We refer to these
as *design parameters* :math:`\left(\bar{d}\right)`, although in the literature they may also be
as *parameters* :math:`\left(\bar{d}\right)`, although in the literature they may also be
referred to as static controls. The endpoints in time, state values, control values, and
design parameter values define the independent variables for our optimization problem.
parameter values define the independent variables for our optimization problem.
In Dymos, we discretize these variables in time to convert a continuous-time optimal control
problem into a nonlinear programming (NLP) problem.

Expand Down
2 changes: 1 addition & 1 deletion dymos/docs/feature_reference/phases/constraints.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Path Constraints
The second class of constraints supported by Dymos are *path* constraints, so called because
they are imposed throughout the entire phase. Like bound constraints, path constraints can be
imposed on design variables using simple bounds. This is accomplished using the `lower` and `upper`
arguments to `add_state`, `add_control`, and `add_design_parameter`.
arguments to `add_state`, `add_control`, and `add_parameter`.
(Since time is monotonically increasing or decreasing the notion of a path constraint is
irrelevant for it).

Expand Down
4 changes: 2 additions & 2 deletions dymos/docs/feature_reference/phases/variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Other inputs are values which impact the system but have one set value throughou
We refer to these non-time-varying inputs as *design parameters*, since they typically involve
parameters which define a system. Design parameters include things like the wingspan of a vehicle
or the mass of a heatsink. A design parameter can be declared using the phase method
`add_design_parameter`.
`add_parameter`.

States are defined in the ODE. Controls and design parameters, on the other hand, are optionally
assigned to controllable parameters in the ODE. Therefore, the method name to add a control to
Expand All @@ -90,7 +90,7 @@ a phase is `add_control`. Valid options for controls and design parameters are a
.. embed-options::
dymos.phase.options
_ForDocs
design_parameter_options
parameter_options

Like states, *dynamic* controls are modeled as polynomials within each segment. When
transcribed to a nonlinear programming problem, a dynamic control is given a unique value at each
Expand Down
2 changes: 1 addition & 1 deletion dymos/docs/feature_reference/subclassing_phases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ to invoke `super(DerivedPhase, self).initialize()` at the beginning of your subc

If you want to override any options for time, states, controls, or parameters you can use the
`set_time_options`, `set_state_options`, `set_control_options`, `set_polynomial_control_options`,
`set_input_parameter_options`, or `set_design_parameter_options` to change any of the settings
or `set_parameter_options` to change any of the settings
whose defaults were set in the phase definition.


Expand Down
3 changes: 1 addition & 2 deletions dymos/docs/feature_reference/timeseries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ Path Description
``<phase path>.timeseries.polynomial_controls:<p>`` Value of polynomial control variable named u
``<phase path>.timeseries.polynomial_control_rates:<p>_rate`` Time derivative of polynomial control named u
``<phase path>.timeseries.polynomial_control_rates:<p>_rate2`` Second time derivative of polynomial control named u
``<phase path>.timeseries.design_parameters:<d>`` Value of design parameter named d
``<phase path>.timeseries.input_parameters:<s>`` Value of input parameter named s
``<phase path>.timeseries.parameters:<d>`` Value of parameter named d
============================================================== ====================================================

In addition to these default values, any output of the ODE can be added to the timeseries output
Expand Down
22 changes: 11 additions & 11 deletions dymos/docs/feature_reference/trajectories.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,34 @@ case is somewhat unusual in that the thrust acceleration is modeled as a state v
needs to be zero in the coast phase, but continuous between `burn1` and `burn2`, assuming no mass
was jettisoned during the coast and that the thrust magnitude doesn't change.

Trajectory Design Parameters and Input Parameters
-------------------------------------------------
Trajectory Parameters
---------------------
Often times, there are parameters which apply to the entirety of a trajectory that potentially
need to be optimized. If we implemented these as design parameters within each phase individually,
need to be optimized. If we implemented these as parameters within each phase individually,
we would need some constraints to ensure that they held the same value within each phase. To avoid
this complexity, Dymos Trajectory objects support their own Design Parameters and Input Parameters.
this complexity, Dymos Trajectory objects support their own Parameters.

Like their Phase-based counterparts, Trajectory design parameters produce an output which can be used
Like their Phase-based counterparts, Trajectory parameters produce an output which can be used
as a design variable to provide an optimal solution. Similarly, input parameters provide an input
at the trajectory level which may be connected to some output external to the trajectory.

When using Trajectory Design and Input parameters, their values are connected to each phase as an
Input Parameter within the Phase. Because ODEs in different phases may have different names
When using Trajectory parameters, their values are connected to each phase as an
parameter within the Phase. Because ODEs in different phases may have different names
for parameters (e.g. 'mass', 'm', 'm_total', etc) Dymos allows the user to specify the targeted
ODE parameters on a phase-by-phase basis using the `targets` and `target_params` option.
It can take on the following values.

* If `targets` is `None` the trajectory design or input parameter will be connected to the phase input parameter of the same name in each phase, if it exists (otherwise it is not connected to that phase).
* If `targets` is `None` the trajectory parameter will be connected to the phase parameter of the same name in each phase, if it exists (otherwise it is not connected to that phase).

* Otherwise targets should be specified as a dictionary. And the behavior depends on the value associated with each phase name:

* If the phase name is not in the given dictionary, attempt to connect to an existing input parameter of the same name in that phase.
* If the phase name is not in the given dictionary, attempt to connect to an existing parameter of the same name in that phase.

* If the associated value is None, explicitly omit a connection to that phase.

* If the associated value is a string, connect to an existing input parameter whose name is given by the string in that phase.
* If the associated value is a string, connect to an existing parameter whose name is given by the string in that phase.

* If the associated value is a Sequence, create an input parameter in that phase connected to the ODE targets given by the Sequence.
* If the associated value is a Sequence, create an parameter in that phase connected to the ODE targets given by the Sequence.

Explicit Simulation of Trajectories
-----------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ def test_steady_aircraft_for_docs(self):

phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False)

phase.add_input_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')
phase.add_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')

phase.add_input_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_input_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')
phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')

phase.add_path_constraint('propulsion.tau', lower=0.01, upper=2.0, shape=(1,))

p.model.connect('assumptions.S', 'traj.phase0.input_parameters:S')
p.model.connect('assumptions.mass_empty', 'traj.phase0.input_parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'traj.phase0.input_parameters:mass_payload')
p.model.connect('assumptions.S', 'traj.phase0.parameters:S')
p.model.connect('assumptions.mass_empty', 'traj.phase0.parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'traj.phase0.parameters:mass_payload')

phase.add_objective('range', loc='final', ref=-1.0e-4)

Expand Down
32 changes: 16 additions & 16 deletions dymos/examples/aircraft_steady_flight/test/test_aircraft_cruise.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,20 @@ def test_cruise_results_gl(self):

phase.add_control('climb_rate', targets=['gam_comp.climb_rate'], units='m/s', opt=False)

phase.add_input_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')
phase.add_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')

phase.add_input_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_input_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')
phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')

phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0, shape=(1,))

phase.add_timeseries_output('tas_comp.TAS', units='m/s')

p.model.connect('assumptions.S', 'phase0.input_parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload')
p.model.connect('assumptions.S', 'phase0.parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.parameters:mass_payload')

phase.add_objective('time', loc='final', ref=3600)

Expand Down Expand Up @@ -156,20 +156,20 @@ def test_cruise_results_radau(self):

phase.add_control('climb_rate', targets=['gam_comp.climb_rate'], units='m/s', opt=False)

phase.add_input_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')
phase.add_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')

phase.add_input_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_input_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')
phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')

phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0, shape=(1,))

phase.add_timeseries_output('tas_comp.TAS', units='m/s')

p.model.connect('assumptions.S', 'phase0.input_parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload')
p.model.connect('assumptions.S', 'phase0.parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.parameters:mass_payload')

phase.add_objective('time', loc='final', ref=3600)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,18 @@ def ex_aircraft_steady_flight(optimizer='SLSQP', solve_segments=False,

phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False)

phase.add_input_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')
phase.add_parameter('S',
targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
units='m**2')

phase.add_input_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_input_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')
phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg')
phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg')

phase.add_path_constraint('propulsion.tau', lower=0.01, upper=2.0, shape=(1,))

p.model.connect('assumptions.S', 'phase0.input_parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload')
p.model.connect('assumptions.S', 'phase0.parameters:S')
p.model.connect('assumptions.mass_empty', 'phase0.parameters:mass_empty')
p.model.connect('assumptions.mass_payload', 'phase0.parameters:mass_payload')

phase.add_objective('range', loc='final', ref=-1.0e-4)

Expand Down
Loading

0 comments on commit 0d49672

Please sign in to comment.