From 1e0efc6239e84adfdb2fc0c4dbe30349c131c7e3 Mon Sep 17 00:00:00 2001 From: swryan Date: Mon, 21 Oct 2024 16:04:43 -0400 Subject: [PATCH 1/3] add set_input_defaults doc, tests, etc. --- openmdao/core/group.py | 10 + openmdao/core/tests/test_group.py | 103 ++++ .../running_your_models/main.ipynb | 3 +- .../running_your_models/set_get.ipynb | 9 +- .../set_input_defaults.ipynb | 475 ++++++++++++++++++ .../theory_manual/setup_stack.ipynb | 2 +- 6 files changed, 593 insertions(+), 9 deletions(-) create mode 100644 openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb diff --git a/openmdao/core/group.py b/openmdao/core/group.py index 549329da67..49f19eacf5 100644 --- a/openmdao/core/group.py +++ b/openmdao/core/group.py @@ -1974,6 +1974,16 @@ def _resolve_group_input_defaults(self, show_warnings=False): abs_in2prom_info[tgt][tree_level] = \ _PromotesInfo(src_shape=src_shape, prom=prom, promoted_from=self.pathname) + else: + # check for discrete targets + for tgt in prom2abs_in[prom]: + if tgt in self._discrete_inputs: + # for discretes we can only set the value (no units/indices) + {self._collect_error(f"{self.msginfo}: Cannot set '{key}={meta[key]}'" + f" for discrete variable '{tgt}'.") + for key in ('units', 'src_shape') if key in meta} + + self._discrete_inputs[tgt] = meta['val'] meta.update(fullmeta) diff --git a/openmdao/core/tests/test_group.py b/openmdao/core/tests/test_group.py index 51d043c696..9578099fd6 100644 --- a/openmdao/core/tests/test_group.py +++ b/openmdao/core/tests/test_group.py @@ -3161,6 +3161,109 @@ def test_conflicting_val(self): "promoted input 'x' with conflicting values for 'val'. Call .set_input_defaults('x', val=?), " "where is the model to remove the ambiguity.") + def test_set_input_defaults_discrete(self): + 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] + + # + # first check that we get errors when using invalid args to set defaults on a discrete + # + p = om.Problem() + model = p.model + + model.add_subsystem('square', SquarePlate(), promotes_inputs=['material']) + model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material']) + + # setting input defaults for units/src_shape is not valid for a discrete and will generate errors + model.set_input_defaults('material', 'steel', units='kg', src_shape=(1,)) + expect_errors = [ + f"Collected errors for problem '{p._get_inst_id()}':", + " : Cannot set 'units=kg' for discrete variable 'circle.material'.", + " : Cannot set 'src_shape=(1,)' for discrete variable 'circle.material'.", + " : Cannot set 'units=kg' for discrete variable 'square.material'.", + " : Cannot set 'src_shape=(1,)' for discrete variable 'square.material'.", + ] + + with self.assertRaises(Exception) as cm: + p.setup() + + err_msgs = cm.exception.args[0].split('\n') + for err_msg in expect_errors: + self.assertTrue(err_msg in err_msgs, + err_msg + ' not found in:\n' + cm.exception.args[0]) + + # + # now make sure that setting just the default value for a discrete works as expected + # + p = om.Problem() + model = p.model + + model.add_subsystem('square', SquarePlate(), promotes_inputs=['material']) + model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material']) + + model.set_input_defaults('material', 'steel') + + p.setup() + p.run_model() + + inputs = model.list_inputs(return_format='dict', out_stream=None) + self.assertEqual(inputs['square.material']['val'], 'steel') + self.assertEqual(inputs['circle.material']['val'], 'steel') + + assert_near_equal(p['square.weight'], 7.85) + assert_near_equal(p['circle.weight'], 24.66150233, 1e-6) + class MultComp(om.ExplicitComponent): """ diff --git a/openmdao/docs/openmdao_book/features/core_features/running_your_models/main.ipynb b/openmdao/docs/openmdao_book/features/core_features/running_your_models/main.ipynb index 53389a437a..34d9fcf899 100644 --- a/openmdao/docs/openmdao_book/features/core_features/running_your_models/main.ipynb +++ b/openmdao/docs/openmdao_book/features/core_features/running_your_models/main.ipynb @@ -7,6 +7,7 @@ "# Running Your Models\n", "\n", "- [Setting and Getting Component Variables](set_get.ipynb)\n", + "- [Using 'set_input_defaults'](set_input_defaults.ipynb)\n", "- [Setup Your Model](setup.ipynb)\n", "- [Run Your Model](run_model.ipynb)\n", "- [Run a Driver](run_driver.ipynb)" @@ -30,7 +31,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.6" }, "orphan": true }, diff --git a/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_get.ipynb b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_get.ipynb index a048cf5d38..b74a2c74b1 100644 --- a/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_get.ipynb +++ b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_get.ipynb @@ -641,14 +641,9 @@ "to the same name as an output, then again the framework will connect all of those inputs to an\n", "`_auto_ivc` output. If, however, there is any difference between the units or values of any of those inputs,\n", "then you must tell the framework what units and/or values to use when creating the corresponding\n", - "`_auto_ivc` output. You do this by calling the `set_input_defaults` function using the promoted\n", + "`_auto_ivc` output. You do this by calling the [set_input_defaults](./set_input_defaults.ipynb) function using the promoted\n", "input name on a Group that contains all of the promoted inputs.\n", "\n", - "```{eval-rst}\n", - " .. automethod:: openmdao.core.group.Group.set_input_defaults\n", - " :noindex:\n", - "```\n", - "\n", "Below is an example of what you'll see if you do *not* call `set_input_defaults` to disambiguate\n", "your units and/or values:" ] @@ -1088,7 +1083,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.12.6" }, "orphan": true }, diff --git a/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb new file mode 100644 index 0000000000..b1394dd89a --- /dev/null +++ b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb @@ -0,0 +1,475 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "active-ipynb", + "remove-output" + ] + }, + "outputs": [], + "source": [ + "try:\n", + " from openmdao.utils.notebook_utils import notebook_mode # noqa: F401\n", + "except ImportError:\n", + " !python -m pip install openmdao[notebooks]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The `set_input_defaults` function\n", + "\n", + "\n", + "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.\n", + "\n", + "```{eval-rst}\n", + " .. automethod:: openmdao.core.group.Group.set_input_defaults\n", + " :noindex:\n", + "```\n", + "\n", + "This function does not set the actual values of the inputs, only the metadata that will be used to populate the [AutoIVC](../../../other_useful_docs/auto_ivc_api_translation.ipynb) output connected to them. The metadata specified via `set_input_defaults` is applied during the model setup phase, when the AutoIVC connections are resolved.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example #1\n", + "\n", + "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:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import openmdao.api as om\n", + "\n", + "p1 = om.Problem()\n", + "model = p1.model\n", + "\n", + "# Note that units and value to use for the promoted variable 'x' are ambiguous due to having different defaults\n", + "model.add_subsystem('C1', om.ExecComp('y = 3.*x', x={'val': 3000., 'units': 'mm'}), promotes=['x'])\n", + "model.add_subsystem('C2', om.ExecComp('y = 4.*x', x={'val': 400., 'units': 'cm'}), promotes=['x'])\n", + "\n", + "try:\n", + " p1.setup() \n", + "except Exception as err:\n", + " print(str(err))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "remove-output", + "allow-assert" + ] + }, + "outputs": [], + "source": [ + "try:\n", + " p1.setup() \n", + "except Exception as err:\n", + " assert(str(err) == \"\\nCollected errors for problem 'problem':\\n : The following inputs, ['C1.x', 'C2.x'], promoted to 'x', are connected but their metadata entries ['units', 'val'] differ. Call .set_input_defaults('x', units=?, val=?), where is the model to remove the ambiguity.\")\n", + "else:\n", + " raise RuntimeError(\"Exception expected.\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ambiguity can be resolved by setting the desired default values for the promoted variable at the group level by calling `set_input_defaults`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "model.set_input_defaults('x', val=1., units='m')\n", + "\n", + "# Note that the we have specified the default metadata for the AutoIVC output that will supply values\n", + "# for the promoted 'x' (_auto_ivc.v0) but it has not been applied yet. It will be applied during setup.\n", + "\n", + "# Calling list_inputs at this point will show the default values from the component definitions\n", + "model.list_inputs(units=True)\n", + "model.list_outputs(units=True, list_autoivcs=True);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1.setup()\n", + "\n", + "# now the default value and units for the AutoIVC have been applied\n", + "model.list_inputs(units=True)\n", + "model.list_outputs(units=True, list_autoivcs=True);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1.run_model()\n", + "\n", + "model.list_inputs(units=True)\n", + "model.list_outputs(units=True, list_autoivcs=True);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "remove-output", + "allow-assert" + ] + }, + "outputs": [], + "source": [ + "from openmdao.utils.assert_utils import assert_near_equal\n", + "assert_near_equal(p1.get_val(\"C1.y\"), 3000.)\n", + "assert_near_equal(p1.get_val(\"C2.y\"), 400.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example #2\n", + "\n", + "For nested groups, `set_input_defaults` can be called in the sub-group's `configure` method:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import openmdao.api as om\n", + "\n", + "class MyGroup(om.Group):\n", + " def setup(self):\n", + " self.add_subsystem('C1', om.ExecComp('y = 3.*x', x={'val': 3000., 'units': 'mm'}), promotes=['x'])\n", + " self.add_subsystem('C2', om.ExecComp('y = 4.*x', x={'val': 400., 'units': 'cm'}), promotes=['x'])\n", + " \n", + " def configure(self):\n", + " self.set_input_defaults('x', val=1., units='m')\n", + " \n", + "p2 = om.Problem()\n", + "model = p2.model\n", + "\n", + "model.add_subsystem('G', MyGroup())\n", + "\n", + "p2.setup()\n", + "p2.run_model()\n", + "\n", + "model.list_inputs(units=True)\n", + "model.list_outputs(units=True, list_autoivcs=True);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "remove-output", + "allow-assert" + ] + }, + "outputs": [], + "source": [ + "from openmdao.utils.assert_utils import assert_near_equal\n", + "assert_near_equal(p2.get_val(\"G.C1.y\"), 3000.)\n", + "assert_near_equal(p2.get_val(\"G.C2.y\"), 400.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example #3\n", + "\n", + "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:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import openmdao.api as om\n", + "\n", + "class MyComp1(om.ExplicitComponent):\n", + " \"\"\" multiplies input array by 2. \"\"\"\n", + " def setup(self):\n", + " self.add_input('x', np.ones(3))\n", + " self.add_output('y', 1.0)\n", + "\n", + " def compute(self, inputs, outputs):\n", + " outputs['y'] = np.sum(inputs['x'])*2.0\n", + "\n", + "class MyComp2(om.ExplicitComponent):\n", + " \"\"\" multiplies input array by 4. \"\"\"\n", + " def setup(self):\n", + " self.add_input('x', np.ones(2))\n", + " self.add_output('y', 1.0)\n", + "\n", + " def compute(self, inputs, outputs):\n", + " outputs['y'] = np.sum(inputs['x'])*4.0\n", + "\n", + "class MyGroup(om.Group):\n", + " def setup(self):\n", + " self.add_subsystem('comp1', MyComp1())\n", + " self.add_subsystem('comp2', MyComp2())\n", + "\n", + " def configure(self):\n", + " # splits input via promotes using src_indices\n", + " self.promotes('comp1', inputs=['x'], src_indices=[0, 1, 2])\n", + " self.promotes('comp2', inputs=['x'], src_indices=[3, 4])\n", + "\n", + "p3 = om.Problem()\n", + "\n", + "# Note: src_shape is different that the shape of either target\n", + "p3.model.set_input_defaults('x', src_shape=(5,), val=1.)\n", + "\n", + "p3.model.add_subsystem('G1', MyGroup(), promotes_inputs=['x'])\n", + "\n", + "p3.setup()\n", + "\n", + "p3.get_val('x')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "remove-output", + "allow-assert" + ] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from openmdao.utils.assert_utils import assert_near_equal\n", + "assert_near_equal(p3.get_val('x'), np.ones((5,)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example #4\n", + "\n", + "The `set_input_defaults` function can be used to set default values for discrete variables as well.\n", + "\n", + "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:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import math\n", + "import openmdao.api as om\n", + "\n", + "density = {\n", + " 'steel': 7.85, # g/cm^3\n", + " 'aluminum': 2.7 # g/cm^3\n", + "}\n", + "\n", + "class SquarePlate(om.ExplicitComponent):\n", + " \"\"\"\n", + " Calculate the weight of a square plate.\n", + " material is a discrete input (default: steel)\n", + " \"\"\"\n", + " def setup(self):\n", + " self.add_discrete_input('material', 'steel')\n", + " \n", + " self.add_input('length', 1.0, units='cm')\n", + " self.add_input('width', 1.0, units='cm')\n", + " self.add_input('thickness', 1.0, units='cm')\n", + " \n", + " self.add_output('weight', 1.0, units='g')\n", + "\n", + " def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):\n", + " length = inputs['length']\n", + " width = inputs['width']\n", + " thickness = inputs['thickness']\n", + " material = discrete_inputs['material']\n", + " \n", + " outputs['weight'] = length * width * thickness * density[material]\n", + "\n", + "class CirclePlate(om.ExplicitComponent):\n", + " \"\"\"\n", + " Calculate the weight of a circular plate.\n", + " material is a discrete input (default: aluminum)\n", + " \"\"\"\n", + " def setup(self):\n", + " self.add_discrete_input('material', 'aluminum')\n", + " \n", + " self.add_input('radius', 1.0, units='cm')\n", + " self.add_input('thickness', 1.0, units='g')\n", + " \n", + " self.add_output('weight', 1.0, units='g')\n", + "\n", + " def compute(self, inputs, outputs, discrete_inputs, discrete_output):\n", + " radius = inputs['radius']\n", + " thickness = inputs['thickness']\n", + " material = discrete_inputs['material'] \n", + " \n", + " outputs['weight'] = math.pi * radius**2 * thickness * density[material]\n", + " \n", + "p4 = om.Problem()\n", + "model = p4.model\n", + "\n", + "model.add_subsystem('square', SquarePlate(), promotes_inputs=['material'])\n", + "model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material'])\n", + "\n", + "model.set_input_defaults('material', 'steel')\n", + "\n", + "p4.setup()\n", + "\n", + "p4.run_model()\n", + "\n", + "model.list_inputs(units=True)\n", + "model.list_outputs(units=True);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input", + "remove-output", + "allow-assert" + ] + }, + "outputs": [], + "source": [ + "from openmdao.utils.assert_utils import assert_near_equal\n", + "assert_near_equal(p4.get_val(\"square.weight\"), 7.85)\n", + "assert_near_equal(p4.get_val(\"circle.weight\"), 24.66150233, tolerance=1e-8)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p5 = om.Problem()\n", + "model = p5.model\n", + "\n", + "model.add_subsystem('square', SquarePlate(), promotes_inputs=['material'])\n", + "model.add_subsystem('circle', CirclePlate(), promotes_inputs=['material'])\n", + "\n", + "model.set_input_defaults('material', 'steel', units='g', src_shape=(1,))\n", + "\n", + "try:\n", + " p5.setup() \n", + "except Exception as err:\n", + " print(str(err))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## How the `set_input_defaults` function differs from the `set_val` function\n", + "\n", + "While both `set_input_defaults` and `set_val` deal with variable management in OpenMDAO, they have distinct purposes and are used in different contexts.\n", + "\n", + "- `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.\n", + "\n", + " - Used to resolve inconsistencies between Auto-IVC values.\n", + "\n", + " - 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.\n", + "\n", + "\n", + "- `set_val` is used at the problem level to set the actual value of a variable, including inputs, outputs, and independent variables. It can handle unit conversions and set values for specific indices in array variables.\n", + "\n", + " - Used at the run script level to set the value of an input variable.\n", + "\n", + " - Can be used to set the value of a variable in a different unit than its declared unit, and OpenMDAO will perform the conversion.\n", + "\n", + " - Can be used to set specific indices or index ranges of array variables.\n", + "\n", + "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.\n", + "\n", + "*Key Differences*\n", + "\n", + "- *Scope*: \n", + " `set_input_defaults` is used at the group level to define default metadata for promoted inputs, while `set_val` is used at the problem level to set specific values for variables.\n", + "\n", + "- *Purpose*: \n", + " `set_input_defaults` resolves ambiguities when multiple inputs are promoted to the same name, while `set_val` is used to assign values to variables.\n", + "\n", + "- *Timing*: \n", + " `set_input_defaults` is typically called during the model setup phase, while `set_val` can be called before or during a run of the model." + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + }, + "orphan": true + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/openmdao/docs/openmdao_book/theory_manual/setup_stack.ipynb b/openmdao/docs/openmdao_book/theory_manual/setup_stack.ipynb index 31192406bb..d6e0baf077 100644 --- a/openmdao/docs/openmdao_book/theory_manual/setup_stack.ipynb +++ b/openmdao/docs/openmdao_book/theory_manual/setup_stack.ipynb @@ -37,7 +37,7 @@ "line check](../other_useful_docs/om_command.ipynb). It is recommended that you do this after making any changes to the configuration\n", "of your model. The \"check\" argument to `setup` can be set to `True`, which will cause a default\n", "set of checks to run. It can also be set to 'all', which will run all available checks.\n", - "A value of `None` or `True` will result in no checks being run. Finally,\n", + "A value of `None` or `False` will result in no checks being run. Finally,\n", "it can be set to a specific list of checks to run as a list of strings. The checks that are available can be\n", "determined by running the following command:\n", "```\n", From 3e8222dce5a34dcd922ba70a38a929d4409396b2 Mon Sep 17 00:00:00 2001 From: swryan Date: Tue, 22 Oct 2024 10:17:32 -0400 Subject: [PATCH 2/3] conditional --- openmdao/core/group.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openmdao/core/group.py b/openmdao/core/group.py index 49f19eacf5..5717ba02f3 100644 --- a/openmdao/core/group.py +++ b/openmdao/core/group.py @@ -1978,12 +1978,13 @@ def _resolve_group_input_defaults(self, show_warnings=False): # check for discrete targets for tgt in prom2abs_in[prom]: if tgt in self._discrete_inputs: - # for discretes we can only set the value (no units/indices) - {self._collect_error(f"{self.msginfo}: Cannot set '{key}={meta[key]}'" - f" for discrete variable '{tgt}'.") - for key in ('units', 'src_shape') if key in meta} - - self._discrete_inputs[tgt] = meta['val'] + for key, val in meta.items(): + # for discretes we can only set the value (not units/src_shape) + if key == 'val': + self._discrete_inputs[tgt] = val + elif key in ('units', 'src_shape'): + self._collect_error(f"{self.msginfo}: Cannot set '{key}={val}'" + f" for discrete variable '{tgt}'.") meta.update(fullmeta) From 3b64e38482b1757ea3aa1158e0f84131b7e5a6af Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 31 Oct 2024 10:31:53 -0400 Subject: [PATCH 3/3] ken's feedback --- .../set_input_defaults.ipynb | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb index b1394dd89a..144b77c2fc 100644 --- a/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb +++ b/openmdao/docs/openmdao_book/features/core_features/running_your_models/set_input_defaults.ipynb @@ -105,9 +105,8 @@ "# Note that the we have specified the default metadata for the AutoIVC output that will supply values\n", "# for the promoted 'x' (_auto_ivc.v0) but it has not been applied yet. It will be applied during setup.\n", "\n", - "# Calling list_inputs at this point will show the default values from the component definitions\n", - "model.list_inputs(units=True)\n", - "model.list_outputs(units=True, list_autoivcs=True);" + "# Calling list_vars (or list_inputs/list_outputs) at this point will show the default values from the component definitions\n", + "model.list_vars(units=True, list_autoivcs=True);" ] }, { @@ -119,8 +118,7 @@ "p1.setup()\n", "\n", "# now the default value and units for the AutoIVC have been applied\n", - "model.list_inputs(units=True)\n", - "model.list_outputs(units=True, list_autoivcs=True);" + "model.list_vars(units=True, list_autoivcs=True);" ] }, { @@ -131,8 +129,7 @@ "source": [ "p1.run_model()\n", "\n", - "model.list_inputs(units=True)\n", - "model.list_outputs(units=True, list_autoivcs=True);" + "model.list_vars(units=True, list_autoivcs=True);" ] }, { @@ -185,8 +182,7 @@ "p2.setup()\n", "p2.run_model()\n", "\n", - "model.list_inputs(units=True)\n", - "model.list_outputs(units=True, list_autoivcs=True);" + "model.list_vars(units=True, list_autoivcs=True);" ] }, { @@ -362,8 +358,7 @@ "\n", "p4.run_model()\n", "\n", - "model.list_inputs(units=True)\n", - "model.list_outputs(units=True);" + "model.list_vars(units=True);" ] }, { @@ -426,7 +421,7 @@ " - 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.\n", "\n", "\n", - "- `set_val` is used at the problem level to set the actual value of a variable, including inputs, outputs, and independent variables. It can handle unit conversions and set values for specific indices in array variables.\n", + "- `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.\n", "\n", " - Used at the run script level to set the value of an input variable.\n", "\n", @@ -466,7 +461,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.12.6" }, "orphan": true },