TL;DR — Check out the proposed POEM_015 for details on how we think we can get rid of the need to manually specify an IndepVarComp in your models.
The IndepVarComp has been a part of OpenMDAO since the start of the version 1 era. In V2.0 its API changed a little bit, but it stayed mostly the same. Its job is to provide the variables the very start of any analysis. We will call these the “model inputs”. Despite providing something that is conceptually an input, the way it works in OpenMDAO is that these variables are the outputs of the IndepVarComp.
No doubt, many users have found this confusing at first though most seem to quickly accept it as wart on the API. A number have asked me why IndepVarComp outputs needed exist at all. It is admittedly confusing, since these model inputs end up being defined by calls to the add_output()
method on the IndepVarComp component.
So why can’t you just work directly with the input variables? There is a mathematical reason anchored in the MAUD formulation that OpenMDAO is based on. There is also a practical reason. There is an ambiguity when multiple inputs are promoted to the same name at the group level, but each input has different units. If that promoted variable happens to be a model input, then the IndepVarComp output is used to resolve that ambiguity.
We’ve always thought it would be nice to get rid of the need for the IndepVarComp, but saw no way around it. As of OpenMDAO V2.10, a new addition to the API (which is specified in great detail in POEM_003) has provided us a a way forward. So now we’re proposing POEM_015 to accomplish this. POEM_0015 would let you go from this:
PRE POEM_015
import openmdao.api as om
class AGroup(om.Group):
def intialize(self):
self.options.declare('owns_dvs', default=True)
def setup(self):
if self.options['owns_dvs']:
dvs = self.add_subsystem('dvs', IndepVarComp(), promotes=['*'])
dvs.add_output('X', value=10, units='furlongs/fortnight')
**do other stuff**
.
.
.
if __name__ == "__main__":
# To use G0 stand alond
p = om.Problem()
p.model.add_subsystem('G0', AGroup(owns_dvs=True))
p.model.add_design_var('G0.X', lower=-1, upper=1)
# To use G0 with some other component
p = om.Problem()
dvs = p.model.add_subsystem('dvs', IndepVarComp(), promotes=['*'])
dvs.add_output('speed', -4, units='furlongs/fortnight')
p.model.connect('speed', 'some_comp.speed')
p.model.add_subsystem('some_comp',
om.ExecComp('X=speed+3', units='furlongs/fortnight'))
p.model.add_subsystem('G0', AGroup(owns_dvs=False))
p.model.connect('some_comp.X', 'G0.X')
p.model.add_design_var('speed', lower=-4, upper=-2)
POST POEM_015
import openmdao.api as om
class AGroup(om.Group):
def setup(self):
self.add_input('X', units='furlongs/fortnight')
**do stuff**
.
.
.
if __name__ == "__main__":
# To use G0 stand alond
p = om.Problem()
p.model.add_subsystem('G0', AGroup())
p.model.add_design_var('G0.X', lower=-1, upper=1)
# To use G0 with some other component
p = om.Problem()
p.model.add_subsystem('some_comp',
om.ExecComp('X=speed+3', units='furlongs/fortnight'))
p.model.add_subsystem('G0', AGroup())
p.model.connect('some_comp.X', 'G0.X')
p.model.add_design_var('some_comp.speed', lower=-4, upper=-2)
Notice the lack of any IndepVarComp instances and the new add_input()
method on group… looks better right? We think so!
Minor Backwards Incompatibility
There are some very mild backwards incompatible changes in POEM_015, and we’ve specifically called them out as well as proposed an release plan that would provide you with some deprecation warnings as a means of facilitating the upgrade.
So is this going to happen?
The leadership team (Rob, Eric, and Justin) think it’s a good idea… so it’s probably going to happen. We’ve pinged several users who’ve all expressed strong support. But we’re expressly asking for your opinions (positive or negative). Feel free to post comments or just thumbs up/down on the PR for the poem. We’ll keep an open mind, and if anyone raises any issues we’ll try to address them in the POEM before accepting it.