Search code examples
openmdao

Creation of a 'partial objective' in OpenMDAO


I am creating a program that optimizes a set of coupled subcomponents to minimize for their total mass. Currently each component is a group that has a promoted output for it's mass and then another group group exists at the top level that takes each of these masses as inputs, computes the sum, and then this sum is used as the objective for the optimizer.

This program is designed to be operated by a user where the type and number of subcomponents is set at runtime. This proves problematic for my statically declared mass summing group that would need to change it's inputs depending on what components are added at runtime.

I was therefor wondering if is there a way to declare a 'partial objective' where each of these partial pieces would be summed together for the final objective processed by the ScipyOptimize Driver? The 'partial objectives', design variable and constraints could simply be added in each subsystem, and the subsystem is added to the model, they would ready to go to fit into the larger optimization.

Another way could be some sort of summer behavior in a group where the inputs to be summed were exclusively created via glob pattern. Something along the lines of

self.add_subsystem('sum', Summer(inputs='mass:*'))

Is there any way to achieve either of these types of functionality in OpenMDAO 3.1.1?


Solution

  • We're planning changes that will make more model introspection at the time of setup/configure possible. Until those changes are implemented, then the typical way of achieving this is similar to what you've implemented. Without introspection, you need to give Summer the names of the inputs it should expect (not wildcard-based).

    You can give your systems which compute mass some attribute, for instance 'mass_output_name'.

    Then, you could iterate through all such systems:

    mass_output_systems = [sys_a, sys_b, sys_c]
    mass_names = [sys.mass_output_name for sys in mass_output_systems]
    

    And then feed these to your summing subsystem:

    self.add_subsystem('sum', Summer(inputs=mass_names))