The set_input_defaults
function#
The set_input_defaults
function in OpenMDAO is used to specify metadata for inputs that are promoted to the same name within a Group. This is necessary when multiple inputs within a Group are promoted to the same name, but their units or initial values differ. If set_input_defaults
is not used in this scenario, OpenMDAO will raise an error during setup.
- Group.set_input_defaults(name, val=UNDEFINED, units=None, src_shape=None)[source]
Specify metadata to be assumed when multiple inputs are promoted to the same name.
- Parameters:
- namestr
Promoted input name.
- valobject
Value to assume for the promoted input.
- unitsstr or None
Units to assume for the promoted input.
- src_shapeint or tuple
Assumed shape of any connected source or higher level promoted input.
This function does not set the actual values of the inputs, only the metadata that will be used to populate the AutoIVC output connected to them. The metadata specified via set_input_defaults
is applied during the model setup phase, when the AutoIVC connections are resolved.
Example #1#
In this example, we have two components that promote the variable x
but use different units. This will result in an error during setup
if left unresolved:
import openmdao.api as om
p1 = om.Problem()
model = p1.model
# Note that units and value to use for the promoted variable 'x' are ambiguous due to having different defaults
model.add_subsystem('C1', om.ExecComp('y = 3.*x', x={'val': 3000., 'units': 'mm'}), promotes=['x'])
model.add_subsystem('C2', om.ExecComp('y = 4.*x', x={'val': 400., 'units': 'cm'}), promotes=['x'])
p1.setup()
try:
p1.final_setup()
except Exception as err:
print(str(err))
Collected errors for problem 'problem':
<model> <class Group>: The following inputs, ['C1.x', 'C2.x'], promoted to 'x', are connected but their metadata entries ['units', 'val'] differ. Call model.set_input_defaults('x', units=?, val=?) to remove the ambiguity.
The ambiguity can be resolved by setting the desired default values for the promoted variable at the group level by calling set_input_defaults
:
model.set_input_defaults('x', val=1., units='m')
# Note that the we have specified the default metadata for the AutoIVC output that will supply values
# for the promoted 'x' (_auto_ivc.v0) but it has not been applied yet. It will be applied during setup.
# Calling list_vars (or list_inputs/list_outputs) at this point will show the default values from the component definitions
model.list_vars(units=True, list_autoivcs=True);
5 Variables(s) in 'model'
varname val io units prom_name
--------- ------- ------ ----- ---------
_auto_ivc
v0 [3000.] output mm x
C1
x [3000.] input mm x
y [1.] output None C1.y
C2
x [400.] input cm x
y [1.] output None C2.y
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:4431: OpenMDAOWarning:Calling `list_vars` before `final_setup` will only display the default values of variables and will not show the result of any `set_val` calls.
p1.setup()
# now the default value and units for the AutoIVC have been applied
model.list_vars(units=True, list_autoivcs=True);
4 Variables(s) in 'model'
varname val io units prom_name
------- ------- ------ ----- ---------
C1
x [3000.] input mm x
y [1.] output None C1.y
C2
x [400.] input cm x
y [1.] output None C2.y
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:4431: OpenMDAOWarning:Calling `list_vars` before `final_setup` will only display the default values of variables and will not show the result of any `set_val` calls.
p1.run_model()
model.list_vars(units=True, list_autoivcs=True);
5 Variables(s) in 'model'
varname val io units prom_name
--------- ------- ------ ----- ---------
_auto_ivc
v0 [1.] output m x
C1
x [1000.] input mm x
y [3000.] output None C1.y
C2
x [100.] input cm x
y [400.] output None C2.y
Example #2#
For nested groups, set_input_defaults
can be called in the sub-group’s configure
method:
import openmdao.api as om
class MyGroup(om.Group):
def setup(self):
self.add_subsystem('C1', om.ExecComp('y = 3.*x', x={'val': 3000., 'units': 'mm'}), promotes=['x'])
self.add_subsystem('C2', om.ExecComp('y = 4.*x', x={'val': 400., 'units': 'cm'}), promotes=['x'])
def configure(self):
self.set_input_defaults('x', val=1., units='m')
p2 = om.Problem()
model = p2.model
model.add_subsystem('G', MyGroup())
p2.setup()
p2.run_model()
model.list_vars(units=True, list_autoivcs=True);
5 Variables(s) in 'model'
varname val io units prom_name
--------- ------- ------ ----- ---------
_auto_ivc
v0 [1.] output m G.x
G
C1
x [1000.] input mm G.x
y [3000.] output None G.C1.y
C2
x [100.] input cm G.x
y [400.] output None G.C2.y
Example #3#
The above examples demonstrate the use of set_input_defaults
to disambiguate default values and units. The following example shows how to use the src_shape
argument to specify the shape of an input that may be different then the promoted variables:
import numpy as np
import openmdao.api as om
class MyComp1(om.ExplicitComponent):
""" multiplies input array by 2. """
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):
""" multiplies input array by 4. """
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
class MyGroup(om.Group):
def setup(self):
self.add_subsystem('comp1', MyComp1())
self.add_subsystem('comp2', MyComp2())
def configure(self):
# splits input via promotes using src_indices
self.promotes('comp1', inputs=['x'], src_indices=[0, 1, 2])
self.promotes('comp2', inputs=['x'], src_indices=[3, 4])
p3 = om.Problem()
# Note: src_shape is different that the shape of either target
p3.model.set_input_defaults('x', src_shape=(5,), val=1.)
p3.model.add_subsystem('G1', MyGroup(), promotes_inputs=['x'])
p3.setup()
p3.final_setup()
p3.get_val('x')
array([1., 1., 1., 1., 1.])
Example #4#
The set_input_defaults
function can be used to set default values for discrete variables as well.
In the following example, the intent is to set the material for all objects by promoting it as a discrete variable from each component and setting it for the whole model:
import math
import openmdao.api as om
density = {
'steel': 7.85, # g/cm^3
'aluminum': 2.7 # g/cm^3
}
class SquarePlate(om.ExplicitComponent):
"""
Calculate the weight of a square plate.
material is a discrete input (default: steel)
"""
def setup(self):
self.add_discrete_input('material', 'steel')
self.add_input('length', 1.0, units='cm')
self.add_input('width', 1.0, units='cm')
self.add_input('thickness', 1.0, units='cm')
self.add_output('weight', 1.0, units='g')
def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
length = inputs['length']
width = inputs['width']
thickness = inputs['thickness']
material = discrete_inputs['material']
outputs['weight'] = length * width * thickness * density[material]
class CirclePlate(om.ExplicitComponent):
"""
Calculate the weight of a circular plate.
material is a discrete input (default: aluminum)
"""
def setup(self):
self.add_discrete_input('material', 'aluminum')
self.add_input('radius', 1.0, units='cm')
self.add_input('thickness', 1.0, units='g')
self.add_output('weight', 1.0, units='g')
def compute(self, inputs, outputs, discrete_inputs, discrete_output):
radius = inputs['radius']
thickness = inputs['thickness']
material = discrete_inputs['material']
outputs['weight'] = math.pi * radius**2 * thickness * density[material]
p4 = om.Problem()
model = p4.model
model.add_subsystem('square', SquarePlate(), promotes_inputs=['material'])
model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material'])
model.set_input_defaults('material', 'steel')
p4.setup()
p4.run_model()
model.list_vars(units=True);
9 Variables(s) in 'model'
varname val io units prom_name
----------- ------------- ------ ----- ----------------
square
length [1.] input cm square.length
width [1.] input cm square.width
thickness [1.] input cm square.thickness
weight [7.85] output g square.weight
material steel input n/a material
circle
radius [1.] input cm circle.radius
thickness [1.] input g circle.thickness
weight [24.66150233] output g circle.weight
material steel input n/a material
Note that setting units
or src_shape
is not valid for a discrete variable and will result in an error if either of those arguments are supplied:
p5 = om.Problem()
model = p5.model
model.add_subsystem('square', SquarePlate(), promotes_inputs=['material'])
model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material'])
model.set_input_defaults('material', 'steel', units='g', src_shape=(1,))
try:
p5.setup()
except Exception as err:
print(str(err))
How the set_input_defaults
function differs from the set_val
function#
While both set_input_defaults
and set_val
deal with variable management in OpenMDAO, they have distinct purposes and are used in different contexts.
set_input_defaults
is used at the group level to define default metadata (units and initial value) for promoted inputs, specifically to resolve ambiguity when multiple inputs are promoted to the same name. This is crucial for inputs connected to the automatically generated_auto_ivc
component.Used to resolve inconsistencies between Auto-IVC values.
Specifically used at the group level to specify metadata to be assumed when multiple inputs are promoted to the same name. This is required when the promoted inputs have differing units or values.
set_val
is used at the problem level to set the actual value of a variable, including inputs, outputs, and implicit state variables. It can handle unit conversions and set values for specific indices in array variables.Used at the run script level to set the value of an input variable.
Can be used to set the value of a variable in a different unit than its declared unit, and OpenMDAO will perform the conversion.
Can be used to set specific indices or index ranges of array variables.
In essence, set_input_defaults
helps OpenMDAO correctly determine the units and initial values of connected inputs during the setup phase, while set_val
is used to directly manipulate variable values before or during a run.
Key Differences
Scope:
set_input_defaults
is used at the group level to define default metadata for promoted inputs, whileset_val
is used at the problem level to set specific values for variables.Purpose:
set_input_defaults
resolves ambiguities when multiple inputs are promoted to the same name, whileset_val
is used to assign values to variables.Timing:
set_input_defaults
is typically called during the model setup phase, whileset_val
can be called before or during a run of the model.