{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b2d35af7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:56.958024Z",
     "iopub.status.busy": "2026-10-02T14:41:56.957751Z",
     "iopub.status.idle": "2026-10-02T14:41:56.962784Z",
     "shell.execute_reply": "2026-10-02T14:41:56.962243Z"
    },
    "papermill": {
     "duration": 0.008652,
     "end_time": "2026-10-02T14:41:56.963687+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:56.955035+00:00",
     "status": "completed"
    },
    "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",
   "id": "5adfd66c",
   "metadata": {
    "papermill": {
     "duration": 0.001705,
     "end_time": "2026-10-02T14:41:56.967524+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:56.965819+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# pyOptSparseDriver\n",
    "\n",
    "pyOptSparseDriver wraps the optimizer package pyOptSparse, which provides a common interface for many gradient-based optimizers, some of which are included in the package (e.g., SLSQP and NSGA2), and some of which are commercial products that must be obtained from their respective authors (e.g., SNOPT). The pyOptSparse package is based on pyOpt, but adds support for sparse specification of constraint Jacobians. Most of the sparsity features are only applicable when using the SNOPT optimizer.\n",
    "\n",
    "In addition to the optimizers included with pyOptSparse, you can use the Uno optimizer by installing the optional `unopy` package:\n",
    "\n",
    "```bash\n",
    "pip install unopy\n",
    "```\n",
    "\n",
    "```{note}\n",
    "The pyOptSparse package does not come included with the OpenMDAO installation. It is a separate optional package that can be obtained from [mdolab](https://github.com/mdolab/pyoptsparse).\n",
    "```\n",
    "\n",
    "In this simple example, we use the SLSQP optimizer to minimize the objective of a Sellar MDA model."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee31e875",
   "metadata": {
    "papermill": {
     "duration": 0.002096,
     "end_time": "2026-10-02T14:41:56.971358+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:56.969262+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "We will use a SellarMDA class to encapsulate the Sellar model with it's design variables, objective and constraints:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4813795b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:57.271929Z",
     "iopub.status.busy": "2026-10-02T14:41:57.271668Z",
     "iopub.status.idle": "2026-10-02T14:42:00.010853Z",
     "shell.execute_reply": "2026-10-02T14:42:00.010058Z"
    },
    "papermill": {
     "duration": 2.743328,
     "end_time": "2026-10-02T14:42:00.011873+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:57.268545+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "application/papermill.record/text/html": "<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #F00 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #04D } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #00F; font-weight: bold } /* Name.Class */\n.output_html .no { color: #800 } /* Name.Constant */\n.output_html .nd { color: #A2F } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #00F } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #BBB } /* Text.Whitespace */\n.output_html .mb { color: #666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666 } /* Literal.Number.Float */\n.output_html .mh { color: #666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #00F } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SellarDis1withDerivatives</span><span class=\"p\">(</span><span class=\"n\">SellarDis1</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Component containing Discipline 1 -- derivatives version.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setup_partials</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Analytic Derivs</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">declare_partials</span><span class=\"p\">(</span><span class=\"n\">of</span><span class=\"o\">=</span><span class=\"s1\">&#39;*&#39;</span><span class=\"p\">,</span> <span class=\"n\">wrt</span><span class=\"o\">=</span><span class=\"s1\">&#39;*&#39;</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">compute_partials</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">inputs</span><span class=\"p\">,</span> <span class=\"n\">partials</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Jacobian for Sellar discipline 1.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">partials</span><span class=\"p\">[</span><span class=\"s1\">&#39;y1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;y2&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"o\">-</span><span class=\"mf\">0.2</span>\n        <span class=\"n\">partials</span><span class=\"p\">[</span><span class=\"s1\">&#39;y1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;z&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">array</span><span class=\"p\">([[</span><span class=\"mf\">2.0</span> <span class=\"o\">*</span> <span class=\"n\">inputs</span><span class=\"p\">[</span><span class=\"s1\">&#39;z&#39;</span><span class=\"p\">][</span><span class=\"mi\">0</span><span class=\"p\">],</span> <span class=\"mf\">1.0</span><span class=\"p\">]])</span>\n        <span class=\"n\">partials</span><span class=\"p\">[</span><span class=\"s1\">&#39;y1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;x&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mf\">1.0</span>\n</pre></div>\n",
      "application/papermill.record/text/latex": "\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n\\PY{k}{class}\\PY{+w}{ }\\PY{n+nc}{SellarDis1withDerivatives}\\PY{p}{(}\\PY{n}{SellarDis1}\\PY{p}{)}\\PY{p}{:}\n\\PY{+w}{    }\\PY{l+s+sd}{\\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\\PY{l+s+sd}{    Component containing Discipline 1 \\PYZhy{}\\PYZhy{} derivatives version.}\n\\PY{l+s+sd}{    \\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\n    \\PY{k}{def}\\PY{+w}{ }\\PY{n+nf}{setup\\PYZus{}partials}\\PY{p}{(}\\PY{n+nb+bp}{self}\\PY{p}{)}\\PY{p}{:}\n        \\PY{c+c1}{\\PYZsh{} Analytic Derivs}\n        \\PY{n+nb+bp}{self}\\PY{o}{.}\\PY{n}{declare\\PYZus{}partials}\\PY{p}{(}\\PY{n}{of}\\PY{o}{=}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{*}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{n}{wrt}\\PY{o}{=}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{*}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{)}\n\n    \\PY{k}{def}\\PY{+w}{ }\\PY{n+nf}{compute\\PYZus{}partials}\\PY{p}{(}\\PY{n+nb+bp}{self}\\PY{p}{,} \\PY{n}{inputs}\\PY{p}{,} \\PY{n}{partials}\\PY{p}{)}\\PY{p}{:}\n\\PY{+w}{        }\\PY{l+s+sd}{\\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\\PY{l+s+sd}{        Jacobian for Sellar discipline 1.}\n\\PY{l+s+sd}{        \\PYZdq{}\\PYZdq{}\\PYZdq{}}\n        \\PY{n}{partials}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y1}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y2}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]} \\PY{o}{=} \\PY{o}{\\PYZhy{}}\\PY{l+m+mf}{0.2}\n        \\PY{n}{partials}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y1}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{z}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]} \\PY{o}{=} \\PY{n}{np}\\PY{o}{.}\\PY{n}{array}\\PY{p}{(}\\PY{p}{[}\\PY{p}{[}\\PY{l+m+mf}{2.0} \\PY{o}{*} \\PY{n}{inputs}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{z}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]}\\PY{p}{[}\\PY{l+m+mi}{0}\\PY{p}{]}\\PY{p}{,} \\PY{l+m+mf}{1.0}\\PY{p}{]}\\PY{p}{]}\\PY{p}{)}\n        \\PY{n}{partials}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y1}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{x}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]} \\PY{o}{=} \\PY{l+m+mf}{1.0}\n\\end{Verbatim}\n",
      "application/papermill.record/text/plain": "class SellarDis1withDerivatives(SellarDis1):\n    \"\"\"\n    Component containing Discipline 1 -- derivatives version.\n    \"\"\"\n\n    def setup_partials(self):\n        # Analytic Derivs\n        self.declare_partials(of='*', wrt='*')\n\n    def compute_partials(self, inputs, partials):\n        \"\"\"\n        Jacobian for Sellar discipline 1.\n        \"\"\"\n        partials['y1', 'y2'] = -0.2\n        partials['y1', 'z'] = np.array([[2.0 * inputs['z'][0], 1.0]])\n        partials['y1', 'x'] = 1.0"
     },
     "metadata": {
      "scrapbook": {
       "mime_prefix": "application/papermill.record/",
       "name": "code_pos_sellar_d1"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import get_code\n",
    "from myst_nb import glue\n",
    "glue(\"code_pos_sellar_d1\", get_code(\"openmdao.test_suite.components.sellar.SellarDis1withDerivatives\"), display=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "23114207",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:00.018006Z",
     "iopub.status.busy": "2026-10-02T14:42:00.017731Z",
     "iopub.status.idle": "2026-10-02T14:42:00.027978Z",
     "shell.execute_reply": "2026-10-02T14:42:00.027138Z"
    },
    "papermill": {
     "duration": 0.014108,
     "end_time": "2026-10-02T14:42:00.028600+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:00.014492+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "application/papermill.record/text/html": "<style>pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.output_html .hll { background-color: #ffffcc }\n.output_html { background: #f8f8f8; }\n.output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n.output_html .err { border: 1px solid #F00 } /* Error */\n.output_html .k { color: #008000; font-weight: bold } /* Keyword */\n.output_html .o { color: #666 } /* Operator */\n.output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n.output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n.output_html .cp { color: #9C6500 } /* Comment.Preproc */\n.output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n.output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n.output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n.output_html .gd { color: #A00000 } /* Generic.Deleted */\n.output_html .ge { font-style: italic } /* Generic.Emph */\n.output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.output_html .gr { color: #E40000 } /* Generic.Error */\n.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.output_html .gi { color: #008400 } /* Generic.Inserted */\n.output_html .go { color: #717171 } /* Generic.Output */\n.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.output_html .gs { font-weight: bold } /* Generic.Strong */\n.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.output_html .gt { color: #04D } /* Generic.Traceback */\n.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.output_html .kp { color: #008000 } /* Keyword.Pseudo */\n.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.output_html .kt { color: #B00040 } /* Keyword.Type */\n.output_html .m { color: #666 } /* Literal.Number */\n.output_html .s { color: #BA2121 } /* Literal.String */\n.output_html .na { color: #687822 } /* Name.Attribute */\n.output_html .nb { color: #008000 } /* Name.Builtin */\n.output_html .nc { color: #00F; font-weight: bold } /* Name.Class */\n.output_html .no { color: #800 } /* Name.Constant */\n.output_html .nd { color: #A2F } /* Name.Decorator */\n.output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n.output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n.output_html .nf { color: #00F } /* Name.Function */\n.output_html .nl { color: #767600 } /* Name.Label */\n.output_html .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.output_html .nv { color: #19177C } /* Name.Variable */\n.output_html .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n.output_html .w { color: #BBB } /* Text.Whitespace */\n.output_html .mb { color: #666 } /* Literal.Number.Bin */\n.output_html .mf { color: #666 } /* Literal.Number.Float */\n.output_html .mh { color: #666 } /* Literal.Number.Hex */\n.output_html .mi { color: #666 } /* Literal.Number.Integer */\n.output_html .mo { color: #666 } /* Literal.Number.Oct */\n.output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n.output_html .sc { color: #BA2121 } /* Literal.String.Char */\n.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n.output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n.output_html .sx { color: #008000 } /* Literal.String.Other */\n.output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n.output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n.output_html .ss { color: #19177C } /* Literal.String.Symbol */\n.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.output_html .fm { color: #00F } /* Name.Function.Magic */\n.output_html .vc { color: #19177C } /* Name.Variable.Class */\n.output_html .vg { color: #19177C } /* Name.Variable.Global */\n.output_html .vi { color: #19177C } /* Name.Variable.Instance */\n.output_html .vm { color: #19177C } /* Name.Variable.Magic */\n.output_html .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SellarDis2withDerivatives</span><span class=\"p\">(</span><span class=\"n\">SellarDis2</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Component containing Discipline 2 -- derivatives version.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setup_partials</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Analytic Derivs</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">declare_partials</span><span class=\"p\">(</span><span class=\"n\">of</span><span class=\"o\">=</span><span class=\"s1\">&#39;*&#39;</span><span class=\"p\">,</span> <span class=\"n\">wrt</span><span class=\"o\">=</span><span class=\"s1\">&#39;*&#39;</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">compute_partials</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">inputs</span><span class=\"p\">,</span> <span class=\"n\">J</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Jacobian for Sellar discipline 2.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">y1</span> <span class=\"o\">=</span> <span class=\"n\">inputs</span><span class=\"p\">[</span><span class=\"s1\">&#39;y1&#39;</span><span class=\"p\">]</span>\n        <span class=\"k\">if</span> <span class=\"n\">y1</span><span class=\"o\">.</span><span class=\"n\">real</span> <span class=\"o\">&lt;</span> <span class=\"mf\">0.0</span><span class=\"p\">:</span>\n            <span class=\"n\">y1</span> <span class=\"o\">*=</span> <span class=\"o\">-</span><span class=\"mi\">1</span>\n        <span class=\"k\">if</span> <span class=\"n\">y1</span><span class=\"o\">.</span><span class=\"n\">real</span> <span class=\"o\">&lt;</span> <span class=\"mf\">1e-8</span><span class=\"p\">:</span>\n            <span class=\"n\">y1</span> <span class=\"o\">=</span> <span class=\"mf\">1e-8</span>\n\n        <span class=\"n\">J</span><span class=\"p\">[</span><span class=\"s1\">&#39;y2&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;y1&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mf\">.5</span><span class=\"o\">*</span><span class=\"n\">y1</span><span class=\"o\">**-</span><span class=\"mf\">.5</span>\n        <span class=\"n\">J</span><span class=\"p\">[</span><span class=\"s1\">&#39;y2&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;z&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">array</span><span class=\"p\">([[</span><span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">]])</span>\n</pre></div>\n",
      "application/papermill.record/text/latex": "\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n\\PY{k}{class}\\PY{+w}{ }\\PY{n+nc}{SellarDis2withDerivatives}\\PY{p}{(}\\PY{n}{SellarDis2}\\PY{p}{)}\\PY{p}{:}\n\\PY{+w}{    }\\PY{l+s+sd}{\\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\\PY{l+s+sd}{    Component containing Discipline 2 \\PYZhy{}\\PYZhy{} derivatives version.}\n\\PY{l+s+sd}{    \\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\n    \\PY{k}{def}\\PY{+w}{ }\\PY{n+nf}{setup\\PYZus{}partials}\\PY{p}{(}\\PY{n+nb+bp}{self}\\PY{p}{)}\\PY{p}{:}\n        \\PY{c+c1}{\\PYZsh{} Analytic Derivs}\n        \\PY{n+nb+bp}{self}\\PY{o}{.}\\PY{n}{declare\\PYZus{}partials}\\PY{p}{(}\\PY{n}{of}\\PY{o}{=}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{*}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{n}{wrt}\\PY{o}{=}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{*}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{)}\n\n    \\PY{k}{def}\\PY{+w}{ }\\PY{n+nf}{compute\\PYZus{}partials}\\PY{p}{(}\\PY{n+nb+bp}{self}\\PY{p}{,} \\PY{n}{inputs}\\PY{p}{,} \\PY{n}{J}\\PY{p}{)}\\PY{p}{:}\n\\PY{+w}{        }\\PY{l+s+sd}{\\PYZdq{}\\PYZdq{}\\PYZdq{}}\n\\PY{l+s+sd}{        Jacobian for Sellar discipline 2.}\n\\PY{l+s+sd}{        \\PYZdq{}\\PYZdq{}\\PYZdq{}}\n        \\PY{n}{y1} \\PY{o}{=} \\PY{n}{inputs}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y1}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]}\n        \\PY{k}{if} \\PY{n}{y1}\\PY{o}{.}\\PY{n}{real} \\PY{o}{\\PYZlt{}} \\PY{l+m+mf}{0.0}\\PY{p}{:}\n            \\PY{n}{y1} \\PY{o}{*}\\PY{o}{=} \\PY{o}{\\PYZhy{}}\\PY{l+m+mi}{1}\n        \\PY{k}{if} \\PY{n}{y1}\\PY{o}{.}\\PY{n}{real} \\PY{o}{\\PYZlt{}} \\PY{l+m+mf}{1e\\PYZhy{}8}\\PY{p}{:}\n            \\PY{n}{y1} \\PY{o}{=} \\PY{l+m+mf}{1e\\PYZhy{}8}\n\n        \\PY{n}{J}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y2}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y1}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]} \\PY{o}{=} \\PY{l+m+mf}{.5}\\PY{o}{*}\\PY{n}{y1}\\PY{o}{*}\\PY{o}{*}\\PY{o}{\\PYZhy{}}\\PY{l+m+mf}{.5}\n        \\PY{n}{J}\\PY{p}{[}\\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{y2}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{,} \\PY{l+s+s1}{\\PYZsq{}}\\PY{l+s+s1}{z}\\PY{l+s+s1}{\\PYZsq{}}\\PY{p}{]} \\PY{o}{=} \\PY{n}{np}\\PY{o}{.}\\PY{n}{array}\\PY{p}{(}\\PY{p}{[}\\PY{p}{[}\\PY{l+m+mf}{1.0}\\PY{p}{,} \\PY{l+m+mf}{1.0}\\PY{p}{]}\\PY{p}{]}\\PY{p}{)}\n\\end{Verbatim}\n",
      "application/papermill.record/text/plain": "class SellarDis2withDerivatives(SellarDis2):\n    \"\"\"\n    Component containing Discipline 2 -- derivatives version.\n    \"\"\"\n\n    def setup_partials(self):\n        # Analytic Derivs\n        self.declare_partials(of='*', wrt='*')\n\n    def compute_partials(self, inputs, J):\n        \"\"\"\n        Jacobian for Sellar discipline 2.\n        \"\"\"\n        y1 = inputs['y1']\n        if y1.real < 0.0:\n            y1 *= -1\n        if y1.real < 1e-8:\n            y1 = 1e-8\n\n        J['y2', 'y1'] = .5*y1**-.5\n        J['y2', 'z'] = np.array([[1.0, 1.0]])"
     },
     "metadata": {
      "scrapbook": {
       "mime_prefix": "application/papermill.record/",
       "name": "code_pos_sellar_d2"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import get_code\n",
    "from myst_nb import glue\n",
    "glue(\"code_pos_sellar_d2\", get_code(\"openmdao.test_suite.components.sellar.SellarDis2withDerivatives\"), display=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48194da6",
   "metadata": {
    "papermill": {
     "duration": 0.001868,
     "end_time": "2026-10-02T14:42:00.032778+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:00.030910+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    ":::{dropdown} `SellarDis1withDerivatives` class definition \n",
    "\n",
    "{glue:}`code_pos_sellar_d1`\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecaa3271",
   "metadata": {
    "papermill": {
     "duration": 0.001883,
     "end_time": "2026-10-02T14:42:00.036949+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:00.035066+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    ":::{dropdown} `SellarDis2withDerivatives` class definition \n",
    "\n",
    "{glue:}`code_pos_sellar_d2`\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "fe697ae4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:00.041857Z",
     "iopub.status.busy": "2026-10-02T14:42:00.041628Z",
     "iopub.status.idle": "2026-10-02T14:42:00.047819Z",
     "shell.execute_reply": "2026-10-02T14:42:00.046996Z"
    },
    "papermill": {
     "duration": 0.009881,
     "end_time": "2026-10-02T14:42:00.048541+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:00.038660+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "import openmdao.api as om\n",
    "\n",
    "from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives\n",
    "  \n",
    "class SellarMDA(om.Group):\n",
    "    \"\"\"\n",
    "    Group containing the Sellar MDA model.\n",
    "    \"\"\"\n",
    "\n",
    "    def setup(self):\n",
    "        # add the two disciplines in an 'mda' subgroup\n",
    "        self.mda = mda = self.add_subsystem('mda', om.Group(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "        mda.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "        mda.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])\n",
    "\n",
    "        # add components to calculate objectives and constraints\n",
    "        self.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',\n",
    "                                                  z=np.array([0.0, 0.0]), x=0.0, y1=0.0, y2=0.0),\n",
    "                           promotes=['obj', 'x', 'z', 'y1', 'y2'])\n",
    "\n",
    "        self.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])\n",
    "        self.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])\n",
    "\n",
    "        # set default values for the inputs\n",
    "        self.set_input_defaults('x', 1.0)\n",
    "        self.set_input_defaults('z', np.array([5.0, 2.0]))\n",
    "        \n",
    "        # add design vars, objective and constraints\n",
    "        self.add_design_var('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0]))\n",
    "        self.add_design_var('x', lower=0.0, upper=10.0)\n",
    "        self.add_objective('obj')\n",
    "        self.add_constraint('con1', upper=0.0)\n",
    "        self.add_constraint('con2', upper=0.0)\n",
    "\n",
    "    def configure(self):\n",
    "        # set the solvers for the model and cycle groups\n",
    "        self.nonlinear_solver = om.NonlinearBlockGS()\n",
    "        self.linear_solver = om.ScipyKrylov()\n",
    "        self.mda.nonlinear_solver = om.NonlinearBlockGS()\n",
    "        self.mda.linear_solver = om.ScipyKrylov()\n",
    "\n",
    "        # default to non-verbose\n",
    "        self.set_solver_print(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c9bd7e3e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:00.054255Z",
     "iopub.status.busy": "2026-10-02T14:42:00.054058Z",
     "iopub.status.idle": "2026-10-02T14:42:01.414429Z",
     "shell.execute_reply": "2026-10-02T14:42:01.413463Z"
    },
    "papermill": {
     "duration": 1.364201,
     "end_time": "2026-10-02T14:42:01.414991+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:00.050790+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952121.286918] [runnervm8df0l:6943 :0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x558a8c2bf620 failed to create UD QP TX wr:256 sge:6 inl:64 resp:0 RX wr:4096 sge:1 resp:0 failed: Operation not supported\n",
      "[1790952121.287200] [runnervm8df0l:6943 :0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Optimization Problem -- Optimization using pyOpt_sparse\n",
      "================================================================================\n",
      "    Objective Function: _objfunc\n",
      "\n",
      "    Solution: \n",
      "--------------------------------------------------------------------------------\n",
      "    Total Time:                    0.0841\n",
      "       User Objective Time :       0.0082\n",
      "       User Sensitivity Time :     0.0443\n",
      "       Interface Time :            0.0035\n",
      "       Opt Solver Time:            0.0280\n",
      "    Calls to Objective Function :       6\n",
      "    Calls to Sens Function :            6\n",
      "\n",
      "\n",
      "   Objectives\n",
      "      Index  Name            Value\n",
      "          0  obj     3.183394E+00\n",
      "\n",
      "   Variables (c - continuous, i - integer, d - discrete)\n",
      "      Index  Name   Type      Lower Bound            Value      Upper Bound     Status\n",
      "          0  z_0      c    -1.000000E+01     1.977639E+00     1.000000E+01           \n",
      "          1  z_1      c     0.000000E+00     0.000000E+00     1.000000E+01          l\n",
      "          2  x_0      c     0.000000E+00     7.459756E-16     1.000000E+01          l\n",
      "\n",
      "   Constraints (i - inequality, e - equality)\n",
      "      Index  Name Type          Lower           Value           Upper    Status  Lagrange Multiplier (N/A)\n",
      "          0  con1    i  -1.000000E+20   -8.567680E-11    0.000000E+00         u    9.00000E+100\n",
      "          1  con2    i  -1.000000E+20   -2.024472E+01    0.000000E+00              9.00000E+100\n",
      "\n",
      "\n",
      "   Exit Status\n",
      "      Inform  Description\n",
      "           0  Optimization terminated successfully.\n",
      "--------------------------------------------------------------------------------\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[runnervm8df0l:06943] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Problem: problem\n",
       "Driver:  pyOptSparseDriver\n",
       "  success     : True\n",
       "  iterations  : 7\n",
       "  runtime     : 8.7978E-02 s\n",
       "  model_evals : 7\n",
       "  model_time  : 6.0230E-03 s\n",
       "  deriv_evals : 6\n",
       "  deriv_time  : 4.4209E-02 s\n",
       "  exit_status : SUCCESS"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem(model=SellarMDA())\n",
    "prob.setup(check=False, mode='rev')\n",
    "\n",
    "prob.driver = om.pyOptSparseDriver(optimizer='SLSQP')\n",
    "\n",
    "prob.run_driver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "82e719e8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.420717Z",
     "iopub.status.busy": "2026-10-02T14:42:01.420251Z",
     "iopub.status.idle": "2026-10-02T14:42:01.424152Z",
     "shell.execute_reply": "2026-10-02T14:42:01.423220Z"
    },
    "papermill": {
     "duration": 0.007648,
     "end_time": "2026-10-02T14:42:01.424751+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.417103+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.977638883487249\n"
     ]
    }
   ],
   "source": [
    "print(prob.get_val('z', indices=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "abb4abf1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.430097Z",
     "iopub.status.busy": "2026-10-02T14:42:01.429942Z",
     "iopub.status.idle": "2026-10-02T14:42:01.434565Z",
     "shell.execute_reply": "2026-10-02T14:42:01.433581Z"
    },
    "papermill": {
     "duration": 0.008073,
     "end_time": "2026-10-02T14:42:01.435126+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.427053+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.9661957548997498e-05)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "assert_near_equal(prob.get_val('z', indices=0), 1.9776, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e03b3ac",
   "metadata": {
    "papermill": {
     "duration": 0.002315,
     "end_time": "2026-10-02T14:42:01.462002+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.459687+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## pyOptSparseDriver Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d519dbda",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.467068Z",
     "iopub.status.busy": "2026-10-02T14:42:01.466906Z",
     "iopub.status.idle": "2026-10-02T14:42:01.471074Z",
     "shell.execute_reply": "2026-10-02T14:42:01.470603Z"
    },
    "papermill": {
     "duration": 0.007787,
     "end_time": "2026-10-02T14:42:01.471943+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.464156+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<!DOCTYPE html>\n",
       "<html lang=\"en\">\n",
       "<head>\n",
       "    <style>\n",
       "        h2 {\n",
       "            text-align: center;\n",
       "        }\n",
       "    </style>\n",
       "</head>\n",
       "<body>\n",
       "    <h2></h2>\n",
       "        <table style=\"border: 1px solid #999; border-collapse: collapse;\">\n",
       "        <tr><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Option</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Default</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Acceptable Values</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Acceptable Types</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Description</th></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">debug_print</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;desvars&#x27;, &#x27;nl_cons&#x27;, &#x27;ln_cons&#x27;, &#x27;objs&#x27;, &#x27;totals&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;list&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">List of what type of Driver variables to print at each iteration.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">gradient_method</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">openmdao</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;openmdao&#x27;, &#x27;snopt_fd&#x27;, &#x27;pyopt_fd&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Finite difference implementation to use</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">hist_file</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">File location for saving pyopt_sparse optimization history. Default is None for no output.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">hotstart_file</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">File location of a pyopt_sparse optimization history to use to hot start the optimization. Default is None.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">invalid_desvar_behavior</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">warn</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;warn&#x27;, &#x27;raise&#x27;, &#x27;ignore&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Behavior of driver if the initial value of a design variable exceeds its bounds. The default value may beset using the `OPENMDAO_INVALID_DESVAR_BEHAVIOR` environment variable to one of the valid options.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">optimizer</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">SLSQP</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;PSQP&#x27;, &#x27;CONMIN&#x27;, &#x27;SNOPT&#x27;, &#x27;NSGA2&#x27;, &#x27;SLSQP&#x27;, &#x27;IPOPT&#x27;, &#x27;Uno&#x27;, &#x27;NLPQLP&#x27;, &#x27;ALPSO&#x27;, &#x27;ParOpt&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Name of optimizers to use</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">output_dir</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">DEFAULT_REPORTS_DIR</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;, &#x27;_ReprClass&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Directory location of pyopt_sparse output files.Default is {prob_name}_out/reports.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">print_opt_prob</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">False</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[True, False]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;bool&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Print the opt problem summary before running the optimization</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">print_results</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">True</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;bool&#x27;, &#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Print pyOpt results if True</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">singular_jac_behavior</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">warn</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;error&#x27;, &#x27;warn&#x27;, &#x27;ignore&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Defines behavior of a zero row/col check after first call tocompute_totals:error - raise an error.warn - raise a warning.ignore - don&#x27;t perform check.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">singular_jac_tol</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">1e-16</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Tolerance for zero row/column check.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">title</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Optimization using pyOpt_sparse</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Title of this optimization run</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">user_terminate_signal</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">OS signal that triggers a clean user-termination. Only SNOPT supports this option.</td></tr>\n",
       "    </table>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "om.show_options_table(\"openmdao.drivers.pyoptsparse_driver.pyOptSparseDriver\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adf7053f",
   "metadata": {
    "papermill": {
     "duration": 0.00199,
     "end_time": "2026-10-02T14:42:01.476044+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.474054+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## pyOptSparseDriver Constructor\n",
    "\n",
    "The call signature for the *pyOptSparseDriver* constructor is:\n",
    "\n",
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.drivers.pyoptsparse_driver.pyOptSparseDriver.__init__\n",
    "       :noindex:\n",
    "```    \n",
    "\n",
    "## Using pyOptSparseDriver\n",
    "\n",
    "pyOptSparseDriver has a small number of unified options that can be specified as keyword arguments when it is instantiated or by using the “options” dictionary. We have already shown how to set the `optimizer` option. Next we see how the `print_results` option can be used to turn on or off the echoing of the results when the optimization finishes. The default is True, but here, we turn it off."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a29b9df2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.490562Z",
     "iopub.status.busy": "2026-10-02T14:42:01.490384Z",
     "iopub.status.idle": "2026-10-02T14:42:01.532469Z",
     "shell.execute_reply": "2026-10-02T14:42:01.531851Z"
    },
    "papermill": {
     "duration": 0.046109,
     "end_time": "2026-10-02T14:42:01.533141+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.487032+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Problem: problem2\n",
       "Driver:  pyOptSparseDriver\n",
       "  success     : True\n",
       "  iterations  : 7\n",
       "  runtime     : 2.9099E-02 s\n",
       "  model_evals : 7\n",
       "  model_time  : 4.8104E-03 s\n",
       "  deriv_evals : 6\n",
       "  deriv_time  : 1.6299E-02 s\n",
       "  exit_status : SUCCESS"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem(model=SellarMDA())\n",
    "prob.setup(check=False, mode='rev')\n",
    "\n",
    "prob.driver = om.pyOptSparseDriver(optimizer='SLSQP')\n",
    "\n",
    "prob.driver.options['print_results'] = False\n",
    "\n",
    "prob.run_driver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "24937323",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.539410Z",
     "iopub.status.busy": "2026-10-02T14:42:01.539228Z",
     "iopub.status.idle": "2026-10-02T14:42:01.542722Z",
     "shell.execute_reply": "2026-10-02T14:42:01.541869Z"
    },
    "papermill": {
     "duration": 0.007419,
     "end_time": "2026-10-02T14:42:01.543327+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.535908+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.977638883487249\n"
     ]
    }
   ],
   "source": [
    "print(prob.get_val('z', indices=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "20f60dd6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.548398Z",
     "iopub.status.busy": "2026-10-02T14:42:01.548208Z",
     "iopub.status.idle": "2026-10-02T14:42:01.552431Z",
     "shell.execute_reply": "2026-10-02T14:42:01.551391Z"
    },
    "papermill": {
     "duration": 0.007778,
     "end_time": "2026-10-02T14:42:01.552972+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.545194+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.9661957548997498e-05)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(prob.get_val('z', indices=0), 1.9776, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4baec3d3",
   "metadata": {
    "papermill": {
     "duration": 0.002071,
     "end_time": "2026-10-02T14:42:01.557181+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.555110+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Every optimizer also has its own specialized settings that allow you to fine-tune the algorithm that it uses. You can access these within the `opt_setting` dictionary. These options are different for each optimizer, so to find out what they are, you need to read your optimizer's documentation. We present a few common ones here.\n",
    "\n",
    "\n",
    "## SLSQP-Specific Settings\n",
    "\n",
    "Here, we set a convergence tolerance for SLSQP:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2ef450ff",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.562681Z",
     "iopub.status.busy": "2026-10-02T14:42:01.562521Z",
     "iopub.status.idle": "2026-10-02T14:42:01.811748Z",
     "shell.execute_reply": "2026-10-02T14:42:01.811280Z"
    },
    "papermill": {
     "duration": 0.253707,
     "end_time": "2026-10-02T14:42:01.813053+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.559346+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Optimization Problem -- Optimization using pyOpt_sparse\n",
      "================================================================================\n",
      "    Objective Function: _objfunc\n",
      "\n",
      "    Solution: \n",
      "--------------------------------------------------------------------------------\n",
      "    Total Time:                    0.0300\n",
      "       User Objective Time :       0.0074\n",
      "       User Sensitivity Time :     0.0183\n",
      "       Interface Time :            0.0032\n",
      "       Opt Solver Time:            0.0010\n",
      "    Calls to Objective Function :       6\n",
      "    Calls to Sens Function :            6\n",
      "\n",
      "\n",
      "   Objectives\n",
      "      Index  Name            Value\n",
      "          0  obj     3.183394E+00\n",
      "\n",
      "   Variables (c - continuous, i - integer, d - discrete)\n",
      "      Index  Name   Type      Lower Bound            Value      Upper Bound     Status\n",
      "          0  z_0      c    -1.000000E+01     1.977639E+00     1.000000E+01           \n",
      "          1  z_1      c     0.000000E+00     0.000000E+00     1.000000E+01          l\n",
      "          2  x_0      c     0.000000E+00     7.459756E-16     1.000000E+01          l\n",
      "\n",
      "   Constraints (i - inequality, e - equality)\n",
      "      Index  Name Type          Lower           Value           Upper    Status  Lagrange Multiplier (N/A)\n",
      "          0  con1    i  -1.000000E+20   -8.567680E-11    0.000000E+00         u    9.00000E+100\n",
      "          1  con2    i  -1.000000E+20   -2.024472E+01    0.000000E+00              9.00000E+100\n",
      "\n",
      "\n",
      "   Exit Status\n",
      "      Inform  Description\n",
      "           0  Optimization terminated successfully.\n",
      "--------------------------------------------------------------------------------\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Problem: problem3\n",
       "Driver:  pyOptSparseDriver\n",
       "  success     : True\n",
       "  iterations  : 7\n",
       "  runtime     : 3.3994E-02 s\n",
       "  model_evals : 7\n",
       "  model_time  : 5.8417E-03 s\n",
       "  deriv_evals : 6\n",
       "  deriv_time  : 1.8199E-02 s\n",
       "  exit_status : SUCCESS"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem(model=SellarMDA())\n",
    "prob.setup(check=False, mode='rev')\n",
    "\n",
    "prob.driver = om.pyOptSparseDriver(optimizer='SLSQP')\n",
    "\n",
    "prob.driver.opt_settings['ACC'] = 1e-9\n",
    "\n",
    "prob.setup(check=False, mode='rev')\n",
    "prob.run_driver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c602470b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.819869Z",
     "iopub.status.busy": "2026-10-02T14:42:01.819680Z",
     "iopub.status.idle": "2026-10-02T14:42:01.822778Z",
     "shell.execute_reply": "2026-10-02T14:42:01.822305Z"
    },
    "papermill": {
     "duration": 0.007329,
     "end_time": "2026-10-02T14:42:01.823224+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.815895+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.977638883487249\n"
     ]
    }
   ],
   "source": [
    "print(prob.get_val('z', indices=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "7946979f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.828948Z",
     "iopub.status.busy": "2026-10-02T14:42:01.828798Z",
     "iopub.status.idle": "2026-10-02T14:42:01.832473Z",
     "shell.execute_reply": "2026-10-02T14:42:01.831658Z"
    },
    "papermill": {
     "duration": 0.007463,
     "end_time": "2026-10-02T14:42:01.832998+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.825535+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.9661957548997498e-05)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(prob.get_val('z', indices=0), 1.9776, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8160fe0f",
   "metadata": {
    "papermill": {
     "duration": 0.002361,
     "end_time": "2026-10-02T14:42:01.837552+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.835191+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Similarly, we can set an iteration limit. Here, we set it to just a few iterations, and don't quite reach the optimum.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "56880d54",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.843590Z",
     "iopub.status.busy": "2026-10-02T14:42:01.843431Z",
     "iopub.status.idle": "2026-10-02T14:42:01.876123Z",
     "shell.execute_reply": "2026-10-02T14:42:01.875524Z"
    },
    "papermill": {
     "duration": 0.036298,
     "end_time": "2026-10-02T14:42:01.876496+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.840198+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "Optimization Problem -- Optimization using pyOpt_sparse\n",
      "================================================================================\n",
      "    Objective Function: _objfunc\n",
      "\n",
      "    Solution: \n",
      "--------------------------------------------------------------------------------\n",
      "    Total Time:                    0.0196\n",
      "       User Objective Time :       0.0049\n",
      "       User Sensitivity Time :     0.0120\n",
      "       Interface Time :            0.0020\n",
      "       Opt Solver Time:            0.0006\n",
      "    Calls to Objective Function :       4\n",
      "    Calls to Sens Function :            4\n",
      "\n",
      "\n",
      "   Objectives\n",
      "      Index  Name            Value\n",
      "          0  obj     3.203561E+00\n",
      "\n",
      "   Variables (c - continuous, i - integer, d - discrete)\n",
      "      Index  Name   Type      Lower Bound            Value      Upper Bound     Status\n",
      "          0  z_0      c    -1.000000E+01     1.983377E+00     1.000000E+01           \n",
      "          1  z_1      c     0.000000E+00     0.000000E+00     1.000000E+01          l\n",
      "          2  x_0      c     0.000000E+00     0.000000E+00     1.000000E+01          l\n",
      "\n",
      "   Constraints (i - inequality, e - equality)\n",
      "      Index  Name Type          Lower           Value           Upper    Status  Lagrange Multiplier (N/A)\n",
      "          0  con1    i  -1.000000E+20   -2.043382E-02    0.000000E+00              9.00000E+100\n",
      "          1  con2    i  -1.000000E+20   -2.023325E+01    0.000000E+00              9.00000E+100\n",
      "\n",
      "\n",
      "   Exit Status\n",
      "      Inform  Description\n",
      "           9  Iteration limit exceeded\n",
      "--------------------------------------------------------------------------------\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Problem: problem4\n",
       "Driver:  pyOptSparseDriver\n",
       "  success     : False\n",
       "  iterations  : 5\n",
       "  runtime     : 2.3626E-02 s\n",
       "  model_evals : 5\n",
       "  model_time  : 3.8890E-03 s\n",
       "  deriv_evals : 4\n",
       "  deriv_time  : 1.1973E-02 s\n",
       "  exit_status : FAIL"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "\n",
    "prob = om.Problem(model=SellarMDA())\n",
    "prob.setup(check=False, mode='rev')\n",
    "\n",
    "prob.driver = om.pyOptSparseDriver(optimizer='SLSQP')\n",
    "\n",
    "prob.driver.opt_settings['MAXIT'] = 3\n",
    "\n",
    "prob.run_driver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "55e1afbb",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.881978Z",
     "iopub.status.busy": "2026-10-02T14:42:01.881832Z",
     "iopub.status.idle": "2026-10-02T14:42:01.884771Z",
     "shell.execute_reply": "2026-10-02T14:42:01.883781Z"
    },
    "papermill": {
     "duration": 0.006224,
     "end_time": "2026-10-02T14:42:01.885226+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.879002+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.9833770833077229\n"
     ]
    }
   ],
   "source": [
    "print(prob.get_val('z', indices=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "bbf07600",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:01.891690Z",
     "iopub.status.busy": "2026-10-02T14:42:01.891526Z",
     "iopub.status.idle": "2026-10-02T14:42:01.894554Z",
     "shell.execute_reply": "2026-10-02T14:42:01.894067Z"
    },
    "papermill": {
     "duration": 0.006936,
     "end_time": "2026-10-02T14:42:01.894958+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.888022+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.6677227027361418e-09)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(prob.get_val('z', indices=0), 1.98337708, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d93b8f0",
   "metadata": {
    "papermill": {
     "duration": 0.003101,
     "end_time": "2026-10-02T14:42:01.901075+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.897974+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## SNOPT-Specific Settings\n",
    "\n",
    "SNOPT has many customizable settings. Here we show two common ones.\n",
    "\n",
    "Setting the convergence tolerance:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5d4bed3",
   "metadata": {
    "papermill": {
     "duration": 0.002619,
     "end_time": "2026-10-02T14:42:01.973724+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.971105+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Setting a limit on the number of major iterations. Here, we set it to just a few iterations, and don't quite reach the optimum."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "771b731b",
   "metadata": {
    "papermill": {
     "duration": 0.002764,
     "end_time": "2026-10-02T14:42:01.979306+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.976542+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "If you have pyoptsparse 1.1 or greater, then you can send a signal such as SIGUSR1 to a running SNOPT optimization to tell it to terminate cleanly. This is useful if an optimization has gotten close enough to an optimum.  How to do this is dependent on your operating system in all cases, on your mpi implementation if you are running mpi, and on your queuing software if you are on a supercomputing cluster. Here is a simple example for unix and mpi.\n",
    "\n",
    "``` bash\n",
    "    ktmoore1$ ps -ef |grep sig\n",
    "      502 17955   951   0  4:05PM ttys000    0:00.02 mpirun -n 2 python sig_demo.py\n",
    "      502 17956 17955   0  4:05PM ttys000    0:00.03 python sig_demo.py\n",
    "      502 17957 17955   0  4:05PM ttys000    0:00.03 python sig_demo.py\n",
    "      502 17959 17312   0  4:05PM ttys001    0:00.00 grep sig\n",
    "\n",
    "    ktmoore1$ kill -SIGUSR1 17955\n",
    "```\n",
    "\n",
    "You can enable this feature by setting the \"user_terminate_signal\" option and giving it a signal (imported from the\n",
    "signal library in Python).  By default, user_terminate_signal is None, which disables the feature.\n",
    "Here, we set the signal to SIGUSR1:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac919d29",
   "metadata": {
    "papermill": {
     "duration": 0.002756,
     "end_time": "2026-10-02T14:42:01.984932+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:01.982176+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "You can learn more about the available options in the [SNOPT_Manual](http://www.sbsi-sol-optimize.com/manuals/SNOPT%20Manual.pdf)."
   ]
  }
 ],
 "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.13.14"
  },
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 6.666147,
   "end_time": "2026-10-02T14:42:02.806559+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/building_blocks/drivers/pyoptsparse_driver.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/pyoptsparse_driver.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:41:56.140412+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}