POEM ID: 003
Title: Allowing addition if I/O during Configure Author: anilyil (Anil Yildirim); justinsgray (Justin Gray); robfalck (Rob Falck) Competing POEMs: N/A
Related POEMs: N/A
Associated implementation PR: [https://github.com/OpenMDAO/OpenMDAO/pull/1140, ]
- Requesting decision
OpenMDAO components and groups utilize a
setup method to get themselves properly built up and ready for execution.
By the time a particular
setup method that component or group already has access to its comm object.
For groups, though they have their own comm, any children that they create during setup do not get their child-comms within that groups setup method.
This is because the
setup method recurses down the model tree, building it as it goes.
This works fine as all children in a group can be created using only information already known to that group, but do not require any information from their siblings in the hierarchy.
That is not to say that there can't be connections between children, but rather that no child needs information that any sibling would create in its
setup --- which has not yet been called while still inside the parent group's
In cases where one child needs information from a sibling's
setup call, then the current timing of the setup-stack is not sufficient.
One example of when this might occur is when dealing with a CFD solver that requires access to its comm to load its mesh and figure out the sizes of its state vector on each process.
Until the component has the comm, the I/O can't be created. Many things downstream of the CFD component might need to know the size of the state vector, or its distribution across the processors.
That kind of setup process can't be accommodated with the current top-down setup method in group.
So there needs to be a way for children of groups to do key setup tasks such as add I/O and issue connections, after the full hierarchy has been constructed and all groups/components all the way down have their comms.
What is needed is a method that can be defined on groups which gets called in a bottoms-up manner, after the full hierarchy has been built.
Groups already have a
configure method, which is called with precisely this timing, but as of V2.9.1 you could only make changes to solver setups and issue connections.
You could not make changes to the I/O configuration of components within the
This POEM proposes modifying OpenMDAO so that I/O can be created in the
configure method, to enable this use case.
Along with the change in functionality, several other smaller changes also need to be included.
Users must also be able to query children of a group for information about I/O status from within the
Proposed API Changes
- Group Promotes Method
The suggested signature of the Group
promotes method is
def promotes(subsys_name, any=None, inputs=None, outputs=None) Parameters ---------- subsystem_path : str The name of the child subsystem whose inputs/outputs are being promoted. any : Sequence of str or tuple A Sequence of variable names (or tuples) to be promoted, regardless of if they are inputs or outputs. This is equivalent to the items passed via the `promotes=` argument to add_subsystem. If given as a tuple, we use the "promote as" standard of ('real name', 'promoted name')*: inputs : Sequence of str or tuple A Sequence of input names (or tuples) to be promoted. Tuples are used for the "promote as" capability. outputs : Sequence of str or tuple A Sequence of output names (or tuples) to be promoted. Tuples are used for the "promote as" capability.
Promotes can only be used to promote directly from the children of the current group (one step, no more). Promoting things up a chain can be accomplished by multiple calls.
- Disable the use of
add_subsystemduring the configure portion of the setup stack.
Currently adding subsystems during the configure portion of the stack does not raise, but
it has undefined behavior that doesn't accomplish what the user expects.
Calling add_subsystem once configure has begun should explicitly raise an exception.
import numpy as np import openmdao.api as om class FlightDataComp(om.ExplicitComponent): """ Simulate data generated by an external source/code """ def setup(self): # number of points not known till after setup is called n = 3 self.add_input('scaler', 4) # The vector represents forces at n time points (rows) in 2 dimensional plane (cols) self.add_output(name='thrust', shape=(n, 2), units='kN') self.add_output(name='drag', shape=(n, 2), units='kN') self.add_output(name='lift', shape=(n, 2), units='kN') self.add_output(name='weight', shape=(n, 2), units='kN') def configure(self, inputs, outputs): outputs['thrust'][:, 0] = scaler*np.array([500, 600, 700]) outputs['drag'][:, 0] = scaler*np.array([400, 400, 400]) outputs['weight'][:, 1] = scaler*np.array([1000, 1001, 1002]) outputs['lift'][:, 1] = scaler*np.array([1000, 1000, 1000]) class ForceModel(om.Group): def setup(self): self.add_subsystem('flightdatacomp', FlightDataComp(), promotes_outputs=['thrust', 'drag', 'lift', 'weight']) self.add_subsystem('totalforcecomp', om.AddSubtractComp()) def configure(self): # Some models that require self-interrogation need to be able to add # I/O in components from the configure method of their containing groups. # In this case, we can only determine the 'vec_size' for totalforcecomp # after flightdatacomp has been setup. flight_data = dict(self.flightdatacomp.list_outputs(shape=True, out_stream=None)) data_shape = flight_data['thrust']['shape'] self.totalforcecomp.add_equation('total_force', input_names=['thrust', 'drag', 'lift', 'weight'], vec_size=data_shape, length=data_shape, scaling_factors=[1, -1, 1, -1], units='kN') p.model.connect('thrust', 'totalforcecomp.thrust') p.model.connect('drag', 'totalforcecomp.drag') p.model.connect('lift', 'totalforcecomp.lift') p.model.connect('weight', 'totalforcecomp.weight') p = om.Problem(model=ForceModel()) p.setup() p.run_model() print(p.get_val('totalforcecomp.total_force', units='kN'))
This proposal is originally made by the MDO Lab at University of Michigan. People who are actively involved in the proposal (in no particular order): Anil Yildirim, Joshua L. Anibal, Benjamin J. Brelje, Nicolas P. Bons, Charles A. Mader, Joaquim R.R.A. Martins
Contributions were also made by the OpenMDAO Dev team.