Declaring Variables

Calling add_input and add_output

Every component in an OpenMDAO model is an instance of IndepVarComp, ExplicitComponent, ImplicitComponent, or a subclass of one of these classes. Regardless of the type, each component has input variables and output variables that it must declare.

In explicit and implicit components, the user must call add_input and add_output to declare variables in the setup method. An example is given below.

class TestExplCompSimple(ExplicitComponent):

    def setup(self):
        self.add_input('length', val=1., desc='length of rectangle')
        self.add_input('width', val=1., desc='width of rectangle')
        self.add_output('area', val=1., desc='area of rectangle')

        self.declare_partials('*', '*')

    def compute(self, inputs, outputs):
        outputs['area'] = inputs['length'] * inputs['width']

Note

Variable names have few restrictions, but the following characters are not allowed in a variable name: ‘.’, ‘*’, ‘?’, ‘!’, ‘[‘, ‘]’.

Method Signatures

Component.add_input(self, name, val=1.0, shape=None, src_indices=None, flat_src_indices=None, units=None, desc='', tags=None)[source]

Add an input variable to the component.

Parameters
namestr

name of the variable in this component’s namespace.

valfloat or list or tuple or ndarray or Iterable

The initial value of the variable being added in user-defined units. Default is 1.0.

shapeint or tuple or list or None

Shape of this variable, only required if src_indices not provided and val is not an array. Default is None.

src_indicesint or list of ints or tuple of ints or int ndarray or Iterable or None

The global indices of the source variable to transfer data from. A value of None implies this input depends on all entries of source. Default is None. The shapes of the target and src_indices must match, and form of the entries within is determined by the value of ‘flat_src_indices’.

flat_src_indicesbool

If True, each entry of src_indices is assumed to be an index into the flattened source. Otherwise each entry must be a tuple or list of size equal to the number of dimensions of the source.

unitsstr or None

Units in which this input variable will be provided to the component during execution. Default is None, which means it is unitless.

descstr

description of the variable

tagsstr or list of strs

User defined tags that can be used to filter what gets listed when calling list_inputs and list_outputs.

Returns
dict

metadata for added variable

Component.add_output(self, name, val=1.0, shape=None, units=None, res_units=None, desc='', lower=None, upper=None, ref=1.0, ref0=0.0, res_ref=1.0, tags=None)[source]

Add an output variable to the component.

Parameters
namestr

name of the variable in this component’s namespace.

valfloat or list or tuple or ndarray

The initial value of the variable being added in user-defined units. Default is 1.0.

shapeint or tuple or list or None

Shape of this variable, only required if val is not an array. Default is None.

unitsstr or None

Units in which the output variables will be provided to the component during execution. Default is None, which means it has no units.

res_unitsstr or None

Units in which the residuals of this output will be given to the user when requested. Default is None, which means it has no units.

descstr

description of the variable.

lowerfloat or list or tuple or ndarray or Iterable or None

lower bound(s) in user-defined units. It can be (1) a float, (2) an array_like consistent with the shape arg (if given), or (3) an array_like matching the shape of val, if val is array_like. A value of None means this output has no lower bound. Default is None.

upperfloat or list or tuple or ndarray or or Iterable None

upper bound(s) in user-defined units. It can be (1) a float, (2) an array_like consistent with the shape arg (if given), or (3) an array_like matching the shape of val, if val is array_like. A value of None means this output has no upper bound. Default is None.

reffloat or ndarray

Scaling parameter. The value in the user-defined units of this output variable when the scaled value is 1. Default is 1.

ref0float or ndarray

Scaling parameter. The value in the user-defined units of this output variable when the scaled value is 0. Default is 0.

res_reffloat or ndarray

Scaling parameter. The value in the user-defined res_units of this output’s residual when the scaled value is 1. Default is 1.

tagsstr or list of strs or set of strs

User defined tags that can be used to filter what gets listed when calling list_inputs and list_outputs.

Returns
dict

metadata for added variable

Usage

  1. Declaring with only the default value.

class CompAddWithDefault(om.ExplicitComponent):
    """Component for tests for declaring only default value."""

    def setup(self):
        self.add_input('x_a')
        self.add_input('x_b', val=3.)
        self.add_input('x_c', val=(3., 3.))
        self.add_input('x_d', val=[3., 3.])
        self.add_input('x_e', val=3. * np.ones((2, 2)))
        self.add_output('y_a')
        self.add_output('y_b', val=6.)
        self.add_output('y_c', val=(6., 6., 6.))
        self.add_output('y_d', val=[6., 6., 6.])
        self.add_output('y_e', val=6. * np.ones((3, 2)))
"""Test declaring only default value."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddWithDefault

p = om.Problem(model=CompAddWithDefault())
p.setup()

print(p['x_a'])
[1.]
print(p['x_b'])
[3.]
print(p['x_c'])
[3. 3.]
print(p['x_d'])
[3. 3.]
print(p['x_e'])
[[3. 3.]
 [3. 3.]]
print(p['y_a'])
[1.]
print(p['y_b'])
[6.]
print(p['y_c'])
[6. 6. 6.]
print(p['y_d'])
[6. 6. 6.]
print(p['y_e'])
[[6. 6.]
 [6. 6.]
 [6. 6.]]
  1. Declaring with only the shape argument.

class CompAddWithShape(om.ExplicitComponent):
    """Component for tests for declaring only shape."""

    def setup(self):
        self.add_input('x_a', shape=2)
        self.add_input('x_b', shape=(2, 2))
        self.add_input('x_c', shape=[2, 2])
        self.add_output('y_a', shape=3)
        self.add_output('y_b', shape=(3, 3))
        self.add_output('y_c', shape=[3, 3])
"""Test declaring only shape."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddWithShape

p = om.Problem(model=CompAddWithShape())
p.setup()

print(p['x_a'])
[1. 1.]
print(p['x_b'])
[[1. 1.]
 [1. 1.]]
print(p['x_c'])
[[1. 1.]
 [1. 1.]]
print(p['y_a'])
[1. 1. 1.]
print(p['y_b'])
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
print(p['y_c'])
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
  1. Declaring with only the indices argument.

class CompAddWithIndices(om.ExplicitComponent):
    """Component for tests for declaring only indices."""

    def setup(self):
        self.add_input('x_a', src_indices=0)
        self.add_input('x_b', src_indices=(0, 1))
        self.add_input('x_c', src_indices=[0, 1])
        self.add_input('x_d', src_indices=np.arange(6))
        self.add_input('x_e', src_indices=np.arange(6).reshape((3, 2)), shape=(3,2))
        self.add_output('y')
"""Test declaring only indices."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddWithIndices

p = om.Problem(model=CompAddWithIndices())
p.setup()

print(p['x_a'])
[1.]
print(p['x_b'])
[1. 1.]
print(p['x_c'])
[1. 1.]
print(p['x_d'])
[1. 1. 1. 1. 1. 1.]
print(p['x_e'])
[[1. 1.]
 [1. 1.]
 [1. 1.]]
  1. Declaring an array variable with a scalar default value.

class CompAddArrayWithScalar(om.ExplicitComponent):
    """Component for tests for declaring a scalar val with an array variable."""

    def setup(self):
        self.add_input('x_a', val=2.0, shape=(6))
        self.add_input('x_b', val=2.0, shape=(3, 2))
        self.add_input('x_c', val=2.0, src_indices=np.arange(6))
        self.add_input('x_d', val=2.0, src_indices=np.arange(6).reshape((3,2)), shape=(3,2))
        self.add_output('y_a', val=3.0, shape=(6))
        self.add_output('y_b', val=3.0, shape=(3, 2))
"""Test declaring a scalar val with an array variable."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddArrayWithScalar

p = om.Problem(model=CompAddArrayWithScalar())
p.setup()

print(p['x_a'])
[2. 2. 2. 2. 2. 2.]
print(p['x_b'])
[[2. 2.]
 [2. 2.]
 [2. 2.]]
print(p['x_c'])
[2. 2. 2. 2. 2. 2.]
print(p['x_d'])
[[2. 2.]
 [2. 2.]
 [2. 2.]]
print(p['y_a'])
[3. 3. 3. 3. 3. 3.]
print(p['y_b'])
[[3. 3.]
 [3. 3.]
 [3. 3.]]
  1. Declaring with an array val and indices (their shapes must match).

class CompAddWithArrayIndices(om.ExplicitComponent):
    """Component for tests for declaring with array val and array indices."""

    def setup(self):
        self.add_input('x_a', val=2.0 * np.ones(6), src_indices=np.arange(6))
        self.add_input('x_b', val=2.0 * np.ones((3, 2)), src_indices=np.arange(6).reshape((3, 2)))
        self.add_output('y')
"""Test declaring with array val and array indices."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddWithArrayIndices

p = om.Problem(model=CompAddWithArrayIndices())
p.setup()

print(p['x_a'])
[2. 2. 2. 2. 2. 2.]
print(p['x_b'])
[[2. 2.]
 [2. 2.]
 [2. 2.]]
  1. Declaring an output with bounds, using upper and/or lower arguments.

class CompAddWithBounds(om.ExplicitComponent):
    """Component for tests for declaring bounds."""

    def setup(self):
        self.add_input('x')
        self.add_output('y_a', val=2.0, lower=0.)
        self.add_output('y_b', val=2.0, lower=0., upper=10.)
        self.add_output('y_c', val=2.0 * np.ones(6),  lower=np.zeros(6), upper=10.)
        self.add_output('y_d', val=2.0 * np.ones(6), lower=0., upper=[12, 10, 10, 10, 10, 12])
        self.add_output('y_e', val=2.0 * np.ones((3, 2)), lower=np.zeros((3, 2)))
"""Test declaring bounds."""
import openmdao.api as om
from openmdao.core.tests.test_add_var import CompAddWithBounds

p = om.Problem(model=CompAddWithBounds())
p.setup()

print(p['y_a'])
[2.]
print(p['y_b'])
[2.]
print(p['y_c'])
[2. 2. 2. 2. 2. 2.]
print(p['y_d'])
[2. 2. 2. 2. 2. 2.]
print(p['y_e'])
[[2. 2.]
 [2. 2.]
 [2. 2.]]
  1. Adding tags to input and output variables. These tags can then be used to filter what gets displayed from the

    System.list_inputs and System.list_outputs methods.

from openmdao.api import Problem, ExplicitComponent

class RectangleCompWithTags(ExplicitComponent):
    """
    A simple Explicit Component that also has input and output with tags.
    """

    def setup(self):
        self.add_input('length', val=1., tags=["tag1", "tag2"])
        self.add_input('width', val=1., tags=["tag2"])
        self.add_output('area', val=1., tags="tag1")

        self.declare_partials('*', '*')

    def compute(self, inputs, outputs):
        outputs['area'] = inputs['length'] * inputs['width']

prob = Problem(RectangleCompWithTags())
prob.setup(check=False)
prob.run_model()

# Inputs no tags
inputs = prob.model.list_inputs(values=False, out_stream=None)
print(sorted(inputs))
[('length', {}), ('width', {})]
# Inputs with tags
inputs = prob.model.list_inputs(values=False, out_stream=None, tags="tag1")
print(sorted(inputs))
[('length', {})]
# Inputs with multiple tags
inputs = prob.model.list_inputs(values=False, out_stream=None, tags=["tag1", "tag2"])
print(sorted(inputs))
[('length', {}), ('width', {})]
# Inputs with tag that does not match
inputs = prob.model.list_inputs(values=False, out_stream=None, tags="tag3")
print(sorted(inputs))
[]
# Outputs no tags
outputs = prob.model.list_outputs(values=False, out_stream=None)
print(sorted(outputs))
[('area', {})]
# Outputs with tags
outputs = prob.model.list_outputs(values=False, out_stream=None, tags="tag1")
print(sorted(outputs))
[('area', {})]
# Outputs with multiple tags
outputs = prob.model.list_outputs(values=False, out_stream=None, tags=["tag1", "tag3"])
print(sorted(outputs))
[('area', {})]
# Outputs with tag that does not match
outputs = prob.model.list_outputs(values=False, out_stream=None, tags="tag3")
print(sorted(outputs))
[]