Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trajectory linkage report based on the N2 diagram. #711

Closed
1 of 4 tasks
robfalck opened this issue Jan 19, 2022 · 3 comments · Fixed by #764
Closed
1 of 4 tasks

Add trajectory linkage report based on the N2 diagram. #711

robfalck opened this issue Jan 19, 2022 · 3 comments · Fixed by #764
Assignees

Comments

@robfalck
Copy link
Contributor

robfalck commented Jan 19, 2022

Issue Type

  • Bug
  • Enhancement
  • Docs
  • Miscellaneous

Description

The generality of Dymos makes it possible for the user to create ill-posed optimization problems.
With a report generation capability being developed for OpenMDAO, Dymos Trajectory objects should provide a report detailing how phases are linked together.

For the most part, phases are "linked" via constraint (e.g. two phases may be made continuous in time and state by forcing the difference between the final value of one and the initial value of another to be the same.

It is possible, while not as common, to link phases via connection. In this case, the report should give some visual indication of this.

Phases can branch. For instance, there may be a nominal trajectory whose performance is optimized such that an abort trajectory which branches off at some point is feasible. This makes describing phase continuity a challenge. Visualization via a networkx graph can lead to a lot of overlapping.

Since OpenMDAO's N2 tool was already developed for the purpose of displaying complex relationships between systems, we should leverage that capability. On the one hand, users will be familiar with the concept. However, we should try to make the tools visually different so new users don't confuse the two.

The following section is intended to give some expectations of what the N2 diagrams will look like for various example problems.

Example 1: Simple "one phase follows the previous one" in multi_phase_cannonball

Screen Shot 2022-01-19 at 2 54 53 PM

Phases occupy the left end where components would be in a standard N2 diagram. Phases do not nest, so we don't need to worry about any further subsystems here.

The next column breaks the linked variables into initial and final conditions.

Finally, the last of the columns on the left contains the variables. For the purposes of the example I've shown time and all states always, regardless of whether or not theyre involved in a linkage. Parameters and controls are then only shown if they are involved in a linkage. I think this is still up for debate. It would probably be good to show all paramters and controls always.

The main body of the diagram is very similar to the N2, in this case showing linkages from the final conditions of time and states of phase ascent to the initial time and state of phase descent.

I'm open to suggestions on how everything is laid out, but my current thoughts are:

  1. variables along the diagonal are black if they are free to be changed by the optimizer, yellow if they are fixed but not involved in a linkage, and red if they are fixed and also involved in a linkage. The rationale being that linking a variable fixed on one side is OK but warrants attention. Fixing a variable on both sides of a connection should actually raise an exception in Dymos.

  2. the linkages from the final values in phase ascent to the initial values in phase descent are green where there are no issues, and yellow for the one involving a fixed value on one end.

Example 2: A phase with cyclic constraints (racecar example)

In the racecar example, there is a single phase that links to itself. The variable time is actually the arclength along the center of the track, and the state variables describe the cars position/speed/acceleration at that location along the track. At the end of a single lap, the car's state is constrained such that it is in the same state relative to the start of the track. This theoretically allows the car to keep coming back to the same position on the track after completing a lap as quickly as possible.

Screen Shot 2022-01-19 at 2 55 05 PM

Example 3: Multiple phases, a branching trajectory, and linked final conditions.

This example finds the minimum runway length such that an aircraft which aborts a takeoff come to rest by the end of the field, while an aircraft that presses a single-engine out takeoff successfully clears an obstacle at the end of the runway.

There are multiple phases here that are linked in the standard way, but the trajectory branches at V1, with one branch completing the takeoff and the other rejecting it. Linkage constraints are used to ensure that the final range at the end of the two branches is the same, regardless of its value.

Screen Shot 2022-01-19 at 3 12 21 PM

Retrieving Linkage information:

Linkage data is stored in the _linkages attribute of Trajectory. The following code can be used to extract the properties of each linkage. _a refers to the "from" part of the linkage, and _b refers to the "to" part. In reality, since they're enforced as a constraint the order usually isn't completely relevant.

In the "is_fixed..." section below, this check currently doesn't exist for parameters because we can't guarantee that an unoptimized parameter isn't just connected to some incoming variable.

    for phase_pair, var_dict in traj._linkages.items():
        phase_name_a, phase_name_b = phase_pair

        phase_a = traj._get_subsystem(f'phases.{phase_name_a}')
        phase_b = traj._get_subsystem(f'phases.{phase_name_b}')

        for var_pair, options in var_dict.items():
            var_a, var_b = var_pair
            loc_a = options['loc_a']
            loc_b = options['loc_b']

            class_a = phase_a.classify_var(var_a)
            class_b = phase_b.classify_var(var_b)

            fixed_a = False
            fixed_b = False

            connected = options['connected']

            if class_a == 'time':
                fixed_a = phase_a.is_time_fixed(loc_a)
            elif class_a == 'state':
                fixed_a = phase_a.is_state_fixed(var_a, loc_a)
            elif class_a in {'input_control', 'indep_control'}:
                fixed_a = phase_a.is_control_fixed(var_a, loc_a)
            elif class_a in {'input_polynomial_control', 'indep_polynomial_control'}:
                fixed_a = phase_a.is_polynomial_control_fixed(var_a, loc_a)
            else:
                fixed_a = True

            if class_b == 'time':
                fixed_b = phase_b.is_time_fixed(loc_b)
            elif class_b == 'state':
                fixed_b = phase_b.is_state_fixed(var_b, loc_b)
            elif class_b in {'input_control', 'indep_control'}:
                fixed_b = phase_b.is_control_fixed(var_b, loc_b)
            elif class_b in {'input_polynomial_control', 'indep_polynomial_control'}:
                fixed_b = phase_b.is_polynomial_control_fixed(var_b, loc_b)
            else:
                fixed_b = True

Environment

N/A

@tadkollar
Copy link
Member

So I think I captured the linked-via-connection issue by labelling the cells with a "C", but I may have misunderstood. Updates are in my OM/DM branches (see below)

Some other items to consider:

  • Most of the standard N2 interactivity is still there, like zooming, collapsing, and filtering. Are all of those behaviors still desirable? If so, do they function in a way that makes sense?
  • Should the coloring of the linked variables be changed to be more colorblind friendly?

OM branch: https://github.com/tadkollar/OpenMDAO/tree/dmdiag
DM branch: https://github.com/tadkollar/dymos/tree/diag

@robfalck
Copy link
Contributor Author

robfalck commented Jun 1, 2022

I'll check these out shortly. I'll see if I can find a colorblindness simulator to run the HTML page through.

@robfalck
Copy link
Contributor Author

robfalck commented Jun 2, 2022

I think this is way more useful than the current ascii report that dymos generates.

  1. I think collapsing things down, at least inputs/outputs of each phase, provides a useful, more concise linkage report.
  2. The coloring looks good according to the colorblindly chrome plugin.
  3. We can enforce continuity in a variable between phases with either connections or constraints, so using the letter C there isn't a great idea. How about some sort of unicode arrow -> for connections?
  4. Is there any way to add a legend specific to this implementation of the N2 that explains to users what the colors mean?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants