Aviary icon indicating copy to clipboard operation
Aviary copied to clipboard

Fancy post-mission bus variables

Open dingraha opened this issue 8 months ago • 5 comments

Summary

This PR adds a new method to SubsystemBuilderBase called get_mission_bus_variables. This method allows users to tell which mission output variables are needed in post-mission, and how to connect them from mission to post-mission. It is version of get_bus_variables but for mission variables: get_bus_variables is for connecting pre-mission variables to mission and post-mission, and get_mission_bus_variables is for connecting mission variables to post-mission.

To accomplish this, a new dymos timeseries is created for each phase called mission_bus_variables. Currently this timeseries is defined on a uniform time grid with the same number of segments as the corresponding phase. The get_mission_bus_variables method returns a nested dict that describes how the mission variables are connected to the post-mission:

def get_mission_bus_variables(self, aviary_data=None, phase_info=None):
        """
        Return a dict mapping phase names to a dict mapping mission variable names to (a list of) post-mission variable names.

        Mission variables local to a given external subsystem should be prefixed with that subsystem's name.
        For example, to connect a variable 'bar' that is an output of the external subsystem "foo"'s mission to the post-mission variable "cruise_foo", map "foo.bar" to "cruise_foo".

        Parameters
        ----------
        aviary_inputs : dict
            A dictionary containing the inputs to the subsystem.
        phase_info : dict
            The phase_info dict for all phases

        Example
        -------
        out = {}
        if phase_info:
            for phase_name, phase_data in phase_info.items():
                phase_d = {}
                if phase_data["do_the_thing"]:
                    phase_d[f"{self.name}.mission_variable_a"] = f"{phase_name}_post_mission_variable_a"
                    phase_d[f"{self.name}.mission_variable_b"] = [f"{phase_name}_post_mission_variable_b_name1", f"{phase_name}_post_mission_variable_b_name2"]
                    phase_d[f"{self.name}.mission_variable_c"] = [f"{phase_name}_post_mission_variable_c_name1"]
                    phase_d[Dynamic.Mission.VELOCITY] = [f"{phase_name}_post_mission_velocity_name1"]
                if phase_data["do_the_other_thing"]:
                    phase_d[f"{self.name}.mission_variable_d"] = f"{phase_name}_post_mission_variable_d"
                    phase_d[f"{self.name}.mission_variable_e"] = [f"{phase_name}_post_mission_variable_e_name1", f"{phase_name}_post_mission_variable_e_name2"]
                    phase_d[f"{self.name}.mission_variable_f"] = [f"{phase_name}_post_mission_variable_f_name1"]
                    phase_d[Dynamic.Atmosphere.KINEMATIC_VISCOSITY] = f"{phase_name}_post_mission_nu_name1"

                out[phase_name] = phase_d

        return out
        """
        return {}

The Aviary/aviary/subsystems/test/test_external_subsystem_bus.py file has been updated to test this new functionality. I haven't run any other tests, or updated the docs, or... Just want to get this on someone's radar for feedback, etc..

Related Issues

  • Resolves #

Backwards incompatibilities

~~Maybe! I had to change the interface for build_post_mission to accept a few more arguments to make this doable. I haven't thought about if it's backwards-compatible or not.~~

  • get_bus_variables has been renamed to get_pre_mission_bus_variables
  • An external subsystem's build_post_mission will now be called in the following manner:
def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths):

New Dependencies

None

dingraha avatar Apr 14 '25 21:04 dingraha

OK, I guess this PR is where I'd like it to be. Appreciate any feedback!

dingraha avatar Apr 16 '25 15:04 dingraha

You might get some formatting-based conflicts since we just switched the repo over to using ruff - if you run ruff over your code it should line it back up with main and the conflicts with main might resolve themselves https://github.com/astral-sh/ruff pip install ruff ruff format <filename.py>

jkirk5 avatar Apr 22 '25 20:04 jkirk5

@jkirk5 @Kenneth-T-Moore Do you have any idea what went wrong with the docs build? I only made one small change to one of the Jupyter notebooks (just renaming get_bus_variables to get_pre_mission_bus_variables). I tried to build them locally but I don't think I have everything set up (IPOPT, etc) to do that successfully.

dingraha avatar May 15 '25 13:05 dingraha

@jkirk5 @Kenneth-T-Moore Do you have any idea what went wrong with the docs build? I only made one small change to one of the Jupyter notebooks (just renaming get_bus_variables to get_pre_mission_bus_variables). I tried to build them locally but I don't think I have everything set up (IPOPT, etc) to do that successfully.

@dingraha I think you will just need to go to this file: https://github.com/OpenMDAO/Aviary/blob/85861c0ec5bb83f84ddeb0f29204742c16e1539a/aviary/docs/user_guide/subsystems.ipynb and replace get_bus_variables with get_pre_mission_bus_variables.

Kenneth-T-Moore avatar May 15 '25 14:05 Kenneth-T-Moore

@Kenneth-T-Moore Thanks, that did the trick! I did grep for get_bus_variables, but must have missed that one somehow.

dingraha avatar May 15 '25 15:05 dingraha