OpenMDAO2 restrictions on group connections and input/output variables is throwing a wrench into my desire to write clean, modular software
from openmdao.api import Group, ExplicitComponent, IndepVarComp, Problem
class A(ExplicitComponent):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('Az', val=0.0)
def compute(self, inputs, outputs):
outputs['Az'] = inputs['x'] + inputs['y']
class B(ExplicitComponent):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('Bz', val=0.0)
def compute(self, inputs, outputs):
outputs['Bz'] = 2*inputs['x'] - inputs['y']
class AB(Group):
def setup(self):
self.add_subsystem('A', A(), promotes=['*'])
self.add_subsystem('B', B(), promotes=['*'])
indeps = IndepVarComp()
indeps.add_output('x', 0.0)
indeps.add_output('y', 0.0)
self.add_subsystem('indeps', indeps, promotes=['*'])
class C(ExplicitComponent):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('Cz', val=0.0)
def compute(self, inputs, outputs):
outputs['Cz'] = 3*inputs['x'] - 2*inputs['y']
class D(ExplicitComponent):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('Dz', val=0.0)
def compute(self, inputs, outputs):
outputs['Dz'] = 4*inputs['x'] - 2.5*inputs['y']
class CD(Group):
def setup(self):
self.add_subsystem('C', C(), promotes=['*'])
self.add_subsystem('D', D(), promotes=['*'])
indeps = IndepVarComp()
indeps.add_output('x', 0.0)
indeps.add_output('y', 0.0)
self.add_subsystem('indeps', indeps, promotes=['*'])
Sometimes I would like to work with Group AB only (run scenarios, optimize, etc.) and sometimes I would like to work with Group CD only. I can do that with,
prob = Problem()
prob.model = AB()
prob.setup()
prob['x'] = 10.0
prob['y'] = 20.0
prob.run_model()
print(prob['Az'],prob['Bz'])
However, sometimes I would like to work with Group ABCD:
class ABCD(Group):
def setup(self):
self.add_subsystem('AB', AB())
self.add_subsystem('CD', CD())
indeps = IndepVarComp()
indeps.add_output('xx', 0.0)
indeps.add_output('yy', 0.0)
self.add_subsystem('indeps', indeps, promotes=['*'])
self.connect('xx', ['AB.x', 'CD.x'])
self.connect('yy', ['AB.y', 'CD.y'])
In that case, there is no combination of variable promotion, connections, or usage of IndepVarComps that doesn't give me an error of "inputs with multiple connections".
In OpenMDAO 1.x I was able to get around that by removing the IndepVarComps from the lower level groups (AB, CD) and only using them at the highest level group (see answer). However, OpenMDAO 2.x throws an error that two inputs are connected without an output. For example:
class AB(Group):
def setup(self):
self.add_subsystem('A', A(), promotes=['*'])
self.add_subsystem('B', B(), promotes=['*'])
Now I am stuck with maintaining multiple copies of the same code, one copy for AB and another for ABCD, or just manually connecting my modules in pure python and moving away from OpenMDAO. Am I missing something? Any help or guidance would be welcome.