{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "tags": [
     "remove-input",
     "remove-output",
     "active-ipynb"
    ]
   },
   "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": [
    "# Modifying Design Variables, Constraints, and Objectives\n",
    "\n",
    "OpenMDAO provides 3 methods to let the user modify options for design variables, constraints, and objectives after they were set in their respective methods `add_design_var`, `add_constraint`, and `add_objective`. The methods are:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.core.system.System.set_design_var_options\n",
    "        :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.core.system.System.set_constraint_options\n",
    "        :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.core.system.System.set_objective_options\n",
    "        :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example of Modifying Design Variable, Constraint, and Objective Options\n",
    "\n",
    "Here is a simple examples of how these methods can be used for an optimizer example. Let's say a user runs an optimization, and then based on the result, they want to change the bounds of the constraint, and then re-optimize."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "# The initial optimization run\n",
    "\n",
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.sellar import SellarDerivatives\n",
    "\n",
    "prob = om.Problem(model=SellarDerivatives())\n",
    "model = prob.model\n",
    "model.nonlinear_solver = om.NonlinearBlockGS()\n",
    "\n",
    "prob.driver = om.ScipyOptimizeDriver()\n",
    "prob.driver.options['optimizer'] = 'SLSQP'\n",
    "prob.driver.options['tol'] = 1e-9\n",
    "\n",
    "model.add_design_var('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0]))\n",
    "model.add_design_var('x', lower=0.0, upper=10.0)\n",
    "model.add_objective('obj')\n",
    "model.add_constraint('con1', upper=0.0)\n",
    "model.add_constraint('con2', upper=0.0)\n",
    "\n",
    "prob.setup()\n",
    "prob.set_solver_print(level=0)\n",
    "prob.run_driver()\n",
    "print(f\"con1 = {prob.get_val('con1')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "assert_near_equal(prob.get_val('x'), 0.0, 1e-5)\n",
    "assert_near_equal(prob.get_val('y1'), 3.160000, 1e-2)\n",
    "assert_near_equal(prob.get_val('y2'), 3.755278, 1e-2)\n",
    "assert_near_equal(prob.get_val('z'), [1.977639, 0.000000], 1e-2)\n",
    "assert_near_equal(prob.get_val('obj'), 3.18339395, 1e-2)\n",
    "assert_near_equal(prob.get_val('con1'), 0.0, 1e-2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# modify the constraint and run again\n",
    "\n",
    "model.set_constraint_options(name='con1', upper=-1.0)\n",
    "prob.run_driver()\n",
    "print(f\"con1 = {prob.get_val('con1')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "assert_near_equal(prob.get_val('x'), 0.0, 1e-5)\n",
    "assert_near_equal(prob.get_val('y1'), 4.16, 1e-2)\n",
    "assert_near_equal(prob.get_val('y2'), 4.27921561, 1e-2)\n",
    "assert_near_equal(prob.get_val('z'), [2.23960781e+00, 0.000000], 1e-2)\n",
    "assert_near_equal(prob.get_val('obj'), 4.17385352, 1e-2)\n",
    "assert_near_equal(prob.get_val('con1'), -1.0, 1e-2)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "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.8.5"
  },
  "orphan": true
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
