{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "active-ipynb",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "from ipyparallel import Client, error  # noqa: F401\n",
    "cluster=Client(profile=\"mpi\")\n",
    "view=cluster[:]\n",
    "view.block=True\n",
    "\n",
    "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": [
    "# Conversion Guide for the Auto-IVC (IndepVarComp) Feature\n",
    "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."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Declaring Design Variables\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "This is what we used to do\n",
    "```\n",
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.x', 'paraboloid.x')\n",
    "prob.model.connect('indeps.y', 'paraboloid.y')\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'SLSQP'\n",
    "\n",
    "prob.model.add_design_var('indeps.x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('indeps.y', lower=-50, upper=50)\n",
    "prob.model.add_objective('paraboloid.f')\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "```\n",
    "````\n",
    "````{tab-item} With Auto IVC\n",
    "This is how we handle IVCs now\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'SLSQP'\n",
    "\n",
    "prob.model.add_design_var('x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('y', lower=-50, upper=50)\n",
    "prob.model.add_objective('paraboloid.f')\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "prob['x'] = 3.0\n",
    "prob['y'] = -4.0\n",
    "\n",
    "prob.run_driver()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "# Old way\n",
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.x', 'paraboloid.x')\n",
    "prob.model.connect('indeps.y', 'paraboloid.y')\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'SLSQP'\n",
    "\n",
    "prob.model.add_design_var('indeps.x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('indeps.y', lower=-50, upper=50)\n",
    "prob.model.add_objective('paraboloid.f')\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "# New way\n",
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'SLSQP'\n",
    "\n",
    "prob.model.add_design_var('x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('y', lower=-50, upper=50)\n",
    "prob.model.add_objective('paraboloid.f')\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "prob['x'] = 3.0\n",
    "prob['y'] = -4.0\n",
    "\n",
    "prob.run_driver();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Declaring a Multi-Component Input as a Design Variable\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('parab', Paraboloid())\n",
    "\n",
    "# define the component whose output will be constrained\n",
    "prob.model.add_subsystem('const', om.ExecComp('g = x + y'))\n",
    "\n",
    "prob.model.connect('indeps.x', ['parab.x', 'const.x'])\n",
    "prob.model.connect('indeps.y', ['parab.y', 'const.y'])\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'COBYLA'\n",
    "\n",
    "prob.model.add_design_var('indeps.x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('indeps.y', lower=-50, upper=50)\n",
    "prob.model.add_objective('parab.f_xy')\n",
    "\n",
    "# to add the constraint to the model\n",
    "prob.model.add_constraint('const.g', lower=0, upper=10.)\n",
    "# prob.model.add_constraint('const.g', equals=0.)\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "prob.model.add_subsystem('parab', Paraboloid(),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# define the component whose output will be constrained\n",
    "prob.model.add_subsystem('const', om.ExecComp('g = x + y'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# Design variables 'x' and 'y' span components, so we need to provide a common initial\n",
    "# value for them.\n",
    "prob.model.set_input_defaults('x', 3.0)\n",
    "prob.model.set_input_defaults('y', -4.0)\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'COBYLA'\n",
    "\n",
    "prob.model.add_design_var('x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('y', lower=-50, upper=50)\n",
    "prob.model.add_objective('parab.f_xy')\n",
    "\n",
    "# to add the constraint to the model\n",
    "prob.model.add_constraint('const.g', lower=0, upper=10.)\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('parab', Paraboloid())\n",
    "\n",
    "# define the component whose output will be constrained\n",
    "prob.model.add_subsystem('const', om.ExecComp('g = x + y'))\n",
    "\n",
    "prob.model.connect('indeps.x', ['parab.x', 'const.x'])\n",
    "prob.model.connect('indeps.y', ['parab.y', 'const.y'])\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'COBYLA'\n",
    "\n",
    "prob.model.add_design_var('indeps.x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('indeps.y', lower=-50, upper=50)\n",
    "prob.model.add_objective('parab.f_xy')\n",
    "\n",
    "# to add the constraint to the model\n",
    "prob.model.add_constraint('const.g', lower=0, upper=10.)\n",
    "# prob.model.add_constraint('const.g', equals=0.)\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "prob.model.add_subsystem('parab', Paraboloid(),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# define the component whose output will be constrained\n",
    "prob.model.add_subsystem('const', om.ExecComp('g = x + y'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "# Design variables 'x' and 'y' span components, so we need to provide a common initial\n",
    "# value for them.\n",
    "prob.model.set_input_defaults('x', 3.0)\n",
    "prob.model.set_input_defaults('y', -4.0)\n",
    "\n",
    "# setup the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'COBYLA'\n",
    "\n",
    "prob.model.add_design_var('x', lower=-50, upper=50)\n",
    "prob.model.add_design_var('y', lower=-50, upper=50)\n",
    "prob.model.add_objective('parab.f_xy')\n",
    "\n",
    "# to add the constraint to the model\n",
    "prob.model.add_constraint('const.g', lower=0, upper=10.)\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Declaring a New Name for a Promoted Input\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('width', 3.0)\n",
    "indeps.add_output('length', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                       om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.width', 'paraboloid.x')\n",
    "prob.model.connect('indeps.length', 'paraboloid.y')\n",
    "\n",
    "prob.setup()\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=[('x', 'width'), ('y', 'length')])\n",
    "\n",
    "# Could also set these after setup.\n",
    "prob.model.set_input_defaults('width', 3.0)\n",
    "prob.model.set_input_defaults('length', -4.0)\n",
    "\n",
    "prob.setup()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('width', 3.0)\n",
    "indeps.add_output('length', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                       om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.width', 'paraboloid.x')\n",
    "prob.model.connect('indeps.length', 'paraboloid.y')\n",
    "\n",
    "prob.setup();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=[('x', 'width'), ('y', 'length')])\n",
    "\n",
    "# Could also set these after setup.\n",
    "prob.model.set_input_defaults('width', 3.0)\n",
    "prob.model.set_input_defaults('length', -4.0)\n",
    "\n",
    "prob.setup();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Declare an Input Defined with Source Indices as a Design Variable\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "class MyComp1(om.ExplicitComponent):\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",
    "    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",
    "p = om.Problem()\n",
    "\n",
    "p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),\n",
    "                      promotes_outputs=['x'])\n",
    "p.model.add_subsystem('C1', MyComp1())\n",
    "p.model.add_subsystem('C2', MyComp2())\n",
    "\n",
    "# this input will connect to entries 0, 1, and 2 of its source\n",
    "p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])\n",
    "\n",
    "# this input will connect to entries 3 and 4 of its source\n",
    "p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])\n",
    "\n",
    "p.model.add_design_var('x')\n",
    "p.setup()\n",
    "p.run_model()\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "class MyComp1(om.ExplicitComponent):\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",
    "    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",
    "p = om.Problem()\n",
    "\n",
    "# IndepVarComp is required to define the full size of the source vector.\n",
    "p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),\n",
    "                      promotes_outputs=['x'])\n",
    "p.model.add_subsystem('C1', MyComp1())\n",
    "p.model.add_subsystem('C2', MyComp2())\n",
    "\n",
    "# this input will connect to entries 0, 1, and 2 of its source\n",
    "p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])\n",
    "\n",
    "# this input will connect to entries 3 and 4 of its source\n",
    "p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])\n",
    "\n",
    "p.model.add_design_var('x')\n",
    "p.setup()\n",
    "p.run_model()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "\n",
    "\n",
    "class MyComp1(om.ExplicitComponent):\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",
    "    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",
    "p = om.Problem()\n",
    "\n",
    "p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),\n",
    "                      promotes_outputs=['x'])\n",
    "p.model.add_subsystem('C1', MyComp1())\n",
    "p.model.add_subsystem('C2', MyComp2())\n",
    "\n",
    "# this input will connect to entries 0, 1, and 2 of its source\n",
    "p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])\n",
    "\n",
    "# this input will connect to entries 3 and 4 of its source\n",
    "p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])\n",
    "\n",
    "p.model.add_design_var('x')\n",
    "p.setup()\n",
    "p.run_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "\n",
    "class MyComp1(om.ExplicitComponent):\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",
    "    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",
    "p = om.Problem()\n",
    "\n",
    "# IndepVarComp is required to define the full size of the source vector.\n",
    "p.model.add_subsystem('indep', om.IndepVarComp('x', np.ones(5)),\n",
    "                      promotes_outputs=['x'])\n",
    "p.model.add_subsystem('C1', MyComp1())\n",
    "p.model.add_subsystem('C2', MyComp2())\n",
    "\n",
    "# this input will connect to entries 0, 1, and 2 of its source\n",
    "p.model.promotes('C1', inputs=['x'], src_indices=[0, 1, 2])\n",
    "\n",
    "# this input will connect to entries 3 and 4 of its source\n",
    "p.model.promotes('C2', inputs=['x'], src_indices=[3, 4])\n",
    "\n",
    "p.model.add_design_var('x')\n",
    "p.setup()\n",
    "p.run_model()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setting Default Units for an Input\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "ivc = om.IndepVarComp()\n",
    "ivc.add_output('x2', 100.0, units='degC')\n",
    "prob.model.add_subsystem('T1', ivc,\n",
    "                       promotes_outputs=['x2'])\n",
    "\n",
    "# Input units in degF\n",
    "prob.model.add_subsystem('tgtF', TgtCompF(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degC\n",
    "prob.model.add_subsystem('tgtC', TgtCompC(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in deg\n",
    "prob.model.add_subsystem('tgtK', TgtCompK(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "prob.setup()\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "# Input units in degF\n",
    "prob.model.add_subsystem('tgtF', TgtCompF(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degC\n",
    "prob.model.add_subsystem('tgtC', TgtCompC(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degK\n",
    "prob.model.add_subsystem('tgtK', TgtCompK(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "prob.model.set_input_defaults('x2', 100.0, units='degC')\n",
    "\n",
    "prob.setup()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.unit_conv import TgtCompC, TgtCompF, TgtCompK\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "ivc = om.IndepVarComp()\n",
    "ivc.add_output('x2', 100.0, units='degC')\n",
    "prob.model.add_subsystem('T1', ivc,\n",
    "                       promotes_outputs=['x2'])\n",
    "\n",
    "# Input units in degF\n",
    "prob.model.add_subsystem('tgtF', TgtCompF(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degC\n",
    "prob.model.add_subsystem('tgtC', TgtCompC(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in deg\n",
    "prob.model.add_subsystem('tgtK', TgtCompK(),\n",
    "                       promotes_inputs=['x2'])\n",
    "\n",
    "prob.setup();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "# Input units in degF\n",
    "prob.model.add_subsystem('tgtF', TgtCompF(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degC\n",
    "prob.model.add_subsystem('tgtC', TgtCompC(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "# Input units in degK\n",
    "prob.model.add_subsystem('tgtK', TgtCompK(),\n",
    "                         promotes_inputs=['x2'])\n",
    "\n",
    "prob.model.set_input_defaults('x2', 100.0, units='degC')\n",
    "\n",
    "prob.setup();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating a Distributed Component with Unconnected Inputs\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "size = 4\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem(\"C1\", DistribNoncontiguousComp(arr_size=size),\n",
    "                       promotes=['invec', 'outvec'])\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "rank = prob.model.comm.rank\n",
    "if rank == 0:\n",
    "    prob.set_val('invec', np.array([1.0, 3.0]))\n",
    "else:\n",
    "    prob.set_val('invec', np.array([5.0, 7.0]))\n",
    "\n",
    "prob.run_model()\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "size = 4\n",
    "dist_size = 2\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "# An IndepVarComp is required on all unconnected distributed inputs.\n",
    "ivc = om.IndepVarComp()\n",
    "ivc.add_output('invec', np.ones(dist_size), distributed=True)\n",
    "prob.model.add_subsystem('P', ivc,\n",
    "                         promotes_outputs=['invec'])\n",
    "\n",
    "prob.model.add_subsystem(\"C1\", DistribNoncontiguousComp(arr_size=size),\n",
    "                         promotes=['invec', 'outvec'])\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "prob.set_val('P.invec', np.array([1.0, 3.0, 5.0, 7.0]))\n",
    "\n",
    "prob.run_model()\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "%%px\n",
    "\n",
    "import openmdao.api as om\n",
    "\n",
    "from openmdao.utils.array_utils import take_nth\n",
    "\n",
    "class DistribNoncontiguousComp(om.ExplicitComponent):\n",
    "    \"\"\"Uses 4 procs and takes non-contiguous input var slices and has output\n",
    "    var slices as well\n",
    "    \"\"\"\n",
    "\n",
    "    def initialize(self):\n",
    "        self.options.declare('arr_size', types=int, default=11,\n",
    "                             desc=\"Size of input and output vectors.\")\n",
    "\n",
    "    def compute(self, inputs, outputs):\n",
    "        outputs['outvec'] = inputs['invec']*2.0\n",
    "\n",
    "    def setup(self):\n",
    "        arr_size = self.options['arr_size']\n",
    "\n",
    "        self.add_input('invec', np.ones(arr_size, float), distributed=True)\n",
    "        self.add_output('outvec', np.ones(arr_size, float), distributed=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "%%px\n",
    "\n",
    "size = 4\n",
    "\n",
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "from openmdao.utils.array_utils import take_nth\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "comm = prob.comm\n",
    "rank = comm.rank\n",
    "idxs = list(take_nth(rank, comm.size, range(size)))\n",
    "\n",
    "# An IndepVarComp is required on all unconnected distributed inputs.\n",
    "ivc = om.IndepVarComp()\n",
    "ivc.add_output('invec', np.ones(len(idxs)), distributed=True)\n",
    "\n",
    "prob.model.add_subsystem('P', ivc, promotes_outputs=['invec'])\n",
    "prob.model.add_subsystem(\"C1\", DistribNoncontiguousComp(arr_size=len(idxs)),\n",
    "                         promotes_outputs=['outvec'])\n",
    "\n",
    "prob.model.promotes('C1', inputs=['invec'], src_indices=idxs)\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "val_array = np.array([1.0, 3.0, 5.0, 7.0])\n",
    "\n",
    "rank = prob.model.comm.rank\n",
    "prob.set_val('invec', val_array[idxs])\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "assert_near_equal(prob.get_val('C1.outvec', get_remote=True), np.array([2.0, 6.0, 10.0, 14.0]))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setting and Getting Inputs\n",
    "\n",
    "\n",
    "`````{tab-set}\n",
    "````{tab-item} Pre Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.x', 'paraboloid.x')\n",
    "prob.model.connect('indeps.y', 'paraboloid.y')\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "x = prob.get_val('indeps.x')\n",
    "prob.set_val('indeps.y', 15.0)\n",
    "```\n",
    "````\n",
    "\n",
    "````{tab-item} With Auto IVC\n",
    "```\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "x = prob.get_val('x')\n",
    "prob.set_val('y', 15.0)\n",
    "```\n",
    "````\n",
    "`````\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "indeps = prob.model.add_subsystem('indeps', om.IndepVarComp())\n",
    "indeps.add_output('x', 3.0)\n",
    "indeps.add_output('y', -4.0)\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))\n",
    "\n",
    "prob.model.connect('indeps.x', 'paraboloid.x')\n",
    "prob.model.connect('indeps.y', 'paraboloid.y')\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "x = prob.get_val('indeps.x')\n",
    "prob.set_val('indeps.y', 15.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('paraboloid',\n",
    "                         om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),\n",
    "                         promotes_inputs=['x', 'y'])\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "x = prob.get_val('x')\n",
    "prob.set_val('y', 15.0)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "dev311",
   "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.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
