OpenMDAO / dymos

Open Source Optimization of Dynamic Multidisciplinary Systems
Apache License 2.0
208 stars 66 forks source link

Trajectory parameter no longer found after updating to Dymos 0.16.0 #493

Closed GuillaumeFiorello closed 3 years ago

GuillaumeFiorello commented 3 years ago

Summary of Issue

After updating to Dymos 0.16.0 and applying the changes of the release notes, OpenMDAO don’t seem to find the trajectory parameters during the simulation of the trajectory by Dymos (seems like it uses the wrong trajectory name).

Issue Type

Description

Hello, as part of my studies I’m using Dymos to simulate and optimize the trajectory of a 2D rocket launcher (my work is related to the one of Jorge Valderrama who openned an issue here before).

After a pause of several months, I am currently updating the code already written to be able to use the latest versions of OpenMDAO and Dymos using the release notes. I made the changes prescribed in the release notes for version 0.16.0. and while it works fine for some files, for some others, OpenMDAO do not seem to find the trajectory parameters. Indeed, when simulating a trajectory called « trajectory », I run into this :

• KeyError: '<model> <class Group>: Variable "traj.parameters:section" not found.'

instead of the simulation of the trajectory and the plots of the flight variables over the time of flight.

(I did add a parameter called section to the trajectory).

Example

From my repo :

https://github.com/supaero-aerospace-vehicle-design/LAST.git

The files of the « develop » branch are to be used with OpenMDAO 3.5 and Dymos 0.16.0.

Each of the source file of the program have an associated test script which can be run using the command :

• python Test_Driver.py File_Name

from the module folder. For example, to test the Phase_Generator function, go to

• your/repo/LAST/MODULES/TRAJECTORY_REWORK

and run the command

• python Test_Driver.py Phase_Generator

That being said, when I run this previous command, everything works fine (I got « Simulating trajectory trajectory » printed, since this is how the trajectory is named in the OpenMDAO hierachy), but when I test the Trajectory_Generator file using :

• python Test_Driver.py Trajectory_Generator

I got the following error message :

• KeyError: '<model> <class Group>: Variable "traj.parameters:section" not found.'

while the trajectory group is called « trajectory » in the OpenMDAO hierarchy. However, if I change this name to « traj », everything works fine.

I tried to modify the Phase_Generator_Test script to reproduce the behavior of the Trajectory_Generator function (which is adding parameters at the trajectory level and linking them whith there phase counterparts, when and where they exist) and i ran into the same error message.

The files of the « master » branch have been created using OpenMDAO 3.0 and Dymos 0.15.0. Using these packages, the commands :

• python Test_Driver.py Phase_Generator

and

• python Test_Driver.py Trajectory_Generator

should both work as intended.

In the folder Documentation can be found the manual of the program, named LAST_V3_0_0.pdf. Section 8 (p33 to 41) deal with the TRAJECTORY_REWORK module which is the one using Dymos, if you need more information.

Environment

Operating System: OS : Ubuntu 20.04.1 Python environment : Anaconda Python 3.8.5 Packages : • openmdao == 3.5.0 • dymos == 0.16.0 • matplotlib == 3.3.3 • numpy == 1.19.4 • scipy == 1.5.4

Do not hesitate to ask me for more information if I have been unclear. Thank you in advance for your help.

Guillaume Fiorello

robfalck commented 3 years ago

@GuillaumeFiorello is LAST a public repo? I don't seem to have access to your link above: https://github.com/supaero-aerospace-vehicle-design/LAST.git

GuillaumeFiorello commented 3 years ago

Whoops, totally forgot it was private sorry ^^"

Here are archives of the branches I talked in the post. I removed the folders and files that are irrelevant to my issue, so you shouldn't get lost.

https://drive.google.com/file/d/12QzvqoDiGn8OBUjPmADZm5XrC_Ho-k_J/view?usp=sharing https://drive.google.com/file/d/1CEoSnHQBRcKcZkCahnodJTUJ9ju4ZvHR/view?usp=sharing

robfalck commented 3 years ago

@GuillaumeFiorello Have you tried these with the latest version of master?

robfalck commented 3 years ago

I believe this is now working with the latest version of master. Please test to verify. I did slightly change the Trajectory_Generator script the following:

# -*- coding: utf-8 -*-
"""
Created on Fri Jul 25 2020

This file contains the definition of the trajectory_generator function,
which is used to build the OpenMDAO group representing a trajectory based
on its flight plan.

@author : g.fiorello
"""
#### Imports

from dymos import Trajectory

from .Phase_Generator import phase_generator

#### Function definition
"""
This function build the OpenMDAO group representing a trajectory based on
its flight plan.

Inputs:
-flight_plan: a list of phase_data instances describing the flight plan
followed by the rocket
-transcription: the optimal control transcription to use
-m_dry: dry mass of the rocket #kg

Outputs:
-trajectory: the group representing the trajectory (using Dymos)
"""
def trajectory_generator(flight_plan, transcription, m_dry):
    #Trajectory setup
    trajectory = Trajectory()
    phases_names = []
    input_parameters = []
    input_parameters_phases = []
    design_parameters = []
    design_parameters_phases = []

    #Phase-by-phase setup
    for phase_data in flight_plan:
        #Phase data retrieving
        phase_name = phase_data.name

        phase_input_parameters = phase_data.input_parameters
        for input_parameter in phase_input_parameters:
            already_known = False
            for index in range(len(input_parameters)):
                if input_parameters[index] == input_parameter:
                    input_parameters_phases[index].append(phase_name)
                    already_known = True
            if not already_known:
                input_parameters.append(input_parameter)
                input_parameters_phases.append([phase_name])

        phase_design_parameters = phase_data.design_parameters
        for design_parameter in phase_design_parameters:
            already_known = False
            for index in range(len(design_parameters)):
                if design_parameters[index] == design_parameter:
                    design_parameters_phases[index].append(phase_name)
                    already_known = True
            if not already_known:
                design_parameters.append(design_parameter)
                design_parameters_phases.append([phase_name])

        #Checking if this is the first phase
        takeoff = len(phases_names) == 0

        #Constructing the phase
        phases_names.append(phase_name)
        phase = phase_generator(transcription, phase_data, takeoff, m_dry)
        trajectory.add_phase(phase_name, phase)

    #Linking phases
    if len(phases_names) >= 2 :
        trajectory.link_phases(phases = phases_names, vars = ['*'])

    #Linking parameters common to multiple phases
    for index in range(len(input_parameters)):
        input_parameter = input_parameters[index]
        targets = {}
        for phase_name in input_parameters_phases[index]:
            targets[phase_name] = input_parameter.name
        trajectory.add_parameter(input_parameter.name, \
            units = input_parameter.units, \

            targets = targets)

    for index in range(len(design_parameters)):
        design_parameter = design_parameters[index]
        targets = {}
        for phase_name in design_parameters_phases[index]:
            targets[phase.name] = design_parameter.name
        trajectory.add_parameter(design_parameter.name, \
            units = design_parameter.units, \
            val = design_parameter.initial_guess, \
            targets = targets)

    return(trajectory)
GuillaumeFiorello commented 3 years ago

Tested your version on my side with latest version of master and it works as a charm, thank you!