diff --git a/openmdao/core/indepvarcomp.py b/openmdao/core/indepvarcomp.py index f9f1b5d15a..2e3fcf9dc2 100644 --- a/openmdao/core/indepvarcomp.py +++ b/openmdao/core/indepvarcomp.py @@ -14,13 +14,17 @@ class IndepVarComp(ExplicitComponent): Parameters ---------- - name : str or None - Name of the variable. + name : str, list, tuple, or None + Name of the variable or list/tuple of variables. + If a string, defines a single variable with the specified name. + If a list or tuple, each element should be a tuple with the format (name, value) or + (name, value, kwargs) where `name` is a string, `value` can be any type compatible with val, + and `kwargs` is a dictionary of keyword arguments. If None, variables should be defined external to this class by calling add_output. val : float or ndarray - Value of the variable if a single variable is being defined. + Initial value of the variable if a single variable is being defined. **kwargs : dict - Keyword arguments. + Additional keyword arguments. """ def __init__(self, name=None, val=1.0, **kwargs): @@ -39,6 +43,33 @@ def __init__(self, name=None, val=1.0, **kwargs): if isinstance(name, str): super().add_output(name, val, **kwargs) + elif isinstance(name, (list, tuple)): + for tup in name: + if not isinstance(tup, tuple): + raise TypeError("Each entry in the list of tuples must be of type tuple.") + if len(tup) == 2: + if not isinstance(tup[0], str): + raise TypeError("The first element of the tuple must be a " + "string representing the variable name.") + if not isinstance(tup[1], (int, float, list, tuple, np.ndarray)): + raise TypeError("The second element of the tuple must be " + "the initial value of the variable.") + super().add_output(tup[0], tup[1], **kwargs) + elif len(tup) == 3: + if not isinstance(tup[0], str): + raise TypeError("The first element of the tuple must be a " + "string representing the variable name.") + if not isinstance(tup[1], (int, float, list, tuple, np.ndarray)): + raise TypeError("The second element of the tuple must be " + "the initial value of the variable.") + if not isinstance(tup[2], dict): + raise TypeError("The third element of the tuple must be a " + "dictionary of keyword arguments.") + super().add_output(tup[0], tup[1], **tup[2]) + else: + raise ValueError("Each entry in the list of tuples must be of the form " + "(name, value) or (name, value, keyword_dict).") + elif name is None: pass diff --git a/openmdao/core/tests/test_indep_var_comp.py b/openmdao/core/tests/test_indep_var_comp.py index d2e2feeba8..6ad494769a 100644 --- a/openmdao/core/tests/test_indep_var_comp.py +++ b/openmdao/core/tests/test_indep_var_comp.py @@ -105,6 +105,52 @@ def test_add_output(self): assert_near_equal(prob.get_val('indep_var_1'), 1.0) assert_near_equal(prob.get_val('indep_var_2'), 2.0) + def test_tuple_ivc(self): + """Define one independent variable using a tuple.""" + + ivcs = [ + ('indep_var', 1.0), + ('indep_var2', 2.0), + ] + + comp = om.IndepVarComp(ivcs) + + prob = om.Problem() + prob.model.add_subsystem('comp', comp, promotes=['*']) + prob.setup(check=False) + + assert_near_equal(prob.get_val('indep_var'), 1.0) + assert_near_equal(prob.get_val('indep_var2'), 2.0) + + def test_tuple_ivc_kwargs(self): + """Define one independent variable using a tuple with additional options.""" + + ivcs = [ + ('indep_var', 1.0, {'units': 'm'}), + ('indep_var2', 2.0, {'units': 'm'}), + ] + + comp = om.IndepVarComp(ivcs) + + prob = om.Problem() + prob.model.add_subsystem('comp', comp, promotes=['*']) + prob.setup(check=False) + + assert_near_equal(prob.get_val('indep_var', units='m'), 1.0) + assert_near_equal(prob.get_val('indep_var2', units='m'), 2.0) + + def test_tuple_error(self): + """Test to see if the objects in the list are actually tuples.""" + + ivcs = ['indep_var', 'indep_var2'] + + try: + om.IndepVarComp(ivcs) + except TypeError as err: + self.assertEqual(str(err), "Each entry in the list of tuples must be of type tuple.") + else: + self.fail('Exception expected.') + def test_promote_glob_no_inputs(self): p = om.Problem() p.model.add_subsystem('indep',