Conversion Guide for the Auto-IVC (IndepVarComp) Feature#
As of the OpenMDAO 3.2 release, it is no longer necessary to add an IndepVarComp to your model to handle the assignment of unconnected inputs as design variables.
Declaring Design Variables#
This is what we used to do
import openmdao.api as om
prob = om.Problem()
indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))
prob.model.connect('indeps.x', 'paraboloid.x')
prob.model.connect('indeps.y', 'paraboloid.y')
# setup the optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('paraboloid.f')
prob.setup()
prob.run_driver()
This is how we handle IVCs now
prob = om.Problem()
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),
promotes_inputs=['x', 'y'])
# setup the optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('x', lower=-50, upper=50)
prob.model.add_design_var('y', lower=-50, upper=50)
prob.model.add_objective('paraboloid.f')
prob.setup()
prob['x'] = 3.0
prob['y'] = -4.0
prob.run_driver()
Declaring a Multi-Component Input as a Design Variable#
import openmdao.api as om
prob = om.Problem()
indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem('parab', Paraboloid())
# define the component whose output will be constrained
prob.model.add_subsystem('const', om.ExecComp('g = x + y'))
prob.model.connect('indeps.x', ['parab.x', 'const.x'])
prob.model.connect('indeps.y', ['parab.y', 'const.y'])
# setup the optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'COBYLA'
prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('parab.f_xy')
# to add the constraint to the model
prob.model.add_constraint('const.g', lower=0, upper=10.)
# prob.model.add_constraint('const.g', equals=0.)
prob.setup()
prob.run_driver()
prob = om.Problem()
prob.model.add_subsystem('parab', Paraboloid(),
promotes_inputs=['x', 'y'])
# define the component whose output will be constrained
prob.model.add_subsystem('const', om.ExecComp('g = x + y'),
promotes_inputs=['x', 'y'])
# Design variables 'x' and 'y' span components, so we need to provide a common initial
# value for them.
prob.model.set_input_defaults('x', 3.0)
prob.model.set_input_defaults('y', -4.0)
# setup the optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'COBYLA'
prob.model.add_design_var('x', lower=-50, upper=50)
prob.model.add_design_var('y', lower=-50, upper=50)
prob.model.add_objective('parab.f_xy')
# to add the constraint to the model
prob.model.add_constraint('const.g', lower=0, upper=10.)
prob.setup()
prob.run_driver()
Declaring a New Name for a Promoted Input#
prob = om.Problem()
indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())
indeps.add_output('width', 3.0)
indeps.add_output('length', -4.0)
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))
prob.model.connect('indeps.width', 'paraboloid.x')
prob.model.connect('indeps.length', 'paraboloid.y')
prob.setup()
prob = om.Problem()
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),
promotes_inputs=[('x', 'width'), ('y', 'length')])
# Could also set these after setup.
prob.model.set_input_defaults('width', 3.0)
prob.model.set_input_defaults('length', -4.0)
prob.setup()
Declare an Input Defined with Source Indices as a Design Variable#
class MyComp1(om.ExplicitComponent):
def setup(self):
self.add_input('x', np.ones(3))
self.add_output('y', 1.0)
def compute(self, inputs, outputs):
outputs['y'] = np.sum(inputs['x'])*2.0
class MyComp2(om.ExplicitComponent):
def setup(self):
self.add_input('x', np.ones(2))
self.add_output('y', 1.0)
def compute(self, inputs, outputs):
outputs['y'] = np.sum(inputs['x'])*4.0
p = om.Problem()
p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),
promotes_outputs=['x'])
p.model.add_subsystem('C1', MyComp1())
p.model.add_subsystem('C2', MyComp2())
# this input will connect to entries 0, 1, and 2 of its source
p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])
# this input will connect to entries 3 and 4 of its source
p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])
p.model.add_design_var('x')
p.setup()
p.run_model()
class MyComp1(om.ExplicitComponent):
def setup(self):
self.add_input('x', np.ones(3))
self.add_output('y', 1.0)
def compute(self, inputs, outputs):
outputs['y'] = np.sum(inputs['x'])*2.0
class MyComp2(om.ExplicitComponent):
def setup(self):
self.add_input('x', np.ones(2))
self.add_output('y', 1.0)
def compute(self, inputs, outputs):
outputs['y'] = np.sum(inputs['x'])*4.0
p = om.Problem()
# IndepVarComp is required to define the full size of the source vector.
p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),
promotes_outputs=['x'])
p.model.add_subsystem('C1', MyComp1())
p.model.add_subsystem('C2', MyComp2())
# this input will connect to entries 0, 1, and 2 of its source
p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])
# this input will connect to entries 3 and 4 of its source
p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])
p.model.add_design_var('x')
p.setup()
p.run_model()
Setting Default Units for an Input#
prob = om.Problem()
ivc = om.IndepVarComp()
ivc.add_output('x2', 100.0, units='degC')
prob.model.add_subsystem('T1', ivc,
promotes_outputs=['x2'])
# Input units in degF
prob.model.add_subsystem('tgtF', TgtCompF(),
promotes_inputs=['x2'])
# Input units in degC
prob.model.add_subsystem('tgtC', TgtCompC(),
promotes_inputs=['x2'])
# Input units in deg
prob.model.add_subsystem('tgtK', TgtCompK(),
promotes_inputs=['x2'])
prob.setup()
prob = om.Problem()
# Input units in degF
prob.model.add_subsystem('tgtF', TgtCompF(),
promotes_inputs=['x2'])
# Input units in degC
prob.model.add_subsystem('tgtC', TgtCompC(),
promotes_inputs=['x2'])
# Input units in degK
prob.model.add_subsystem('tgtK', TgtCompK(),
promotes_inputs=['x2'])
prob.model.set_input_defaults('x2', 100.0, units='degC')
prob.setup()
Creating a Distributed Component with Unconnected Inputs#
size = 4
prob = om.Problem()
prob.model.add_subsystem("C1", DistribNoncontiguousComp(arr_size=size),
promotes=['invec', 'outvec'])
prob.setup()
rank = prob.model.comm.rank
if rank == 0:
prob.set_val('invec', np.array([1.0, 3.0]))
else:
prob.set_val('invec', np.array([5.0, 7.0]))
prob.run_model()
size = 4
prob = om.Problem()
# An IndepVarComp is required on all unconnected distributed inputs.
ivc = om.IndepVarComp()
ivc.add_output('invec', np.ones(size), distributed=True)
prob.model.add_subsystem('P', ivc,
promotes_outputs=['invec'])
prob.model.add_subsystem("C1", DistribNoncontiguousComp(arr_size=size),
promotes=['invec', 'outvec'])
prob.setup()
prob.set_val('P.invec', np.array([1.0, 3.0, 5.0, 7.0]))
prob.run_model()
Setting and Getting Inputs#
prob = om.Problem()
indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))
prob.model.connect('indeps.x', 'paraboloid.x')
prob.model.connect('indeps.y', 'paraboloid.y')
prob.setup()
x = prob.get_val('indeps.x')
prob.set_val('indeps.y', 15.0)
prob = om.Problem()
prob.model.add_subsystem('paraboloid',
om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),
promotes_inputs=['x', 'y'])
prob.setup()
x = prob.get_val('x')
prob.set_val('y', 15.0)