{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1e5201ce",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:35.484215Z",
     "iopub.status.busy": "2026-10-02T14:42:35.484007Z",
     "iopub.status.idle": "2026-10-02T14:42:35.489135Z",
     "shell.execute_reply": "2026-10-02T14:42:35.488212Z"
    },
    "papermill": {
     "duration": 0.00818,
     "end_time": "2026-10-02T14:42:35.489647+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:35.481467+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": "53b55de8",
   "metadata": {
    "papermill": {
     "duration": 0.071634,
     "end_time": "2026-10-02T14:42:35.562866+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:35.491232+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# LinearBlockJac\n",
    "\n",
    "LinearBlockJac uses the block Jacobi method to solve the linear system. The method is similar to that used by the\n",
    "[LinearBlockGS](../../../_srcdocs/packages/solvers.linear/linear_block_gs) solver, except that it propagates the derivatives from outputs to inputs only once per iteration. When to choose this solver over the other ones is an advanced topic.\n",
    "\n",
    "LinearBlockJac is a block solver, so you can specify different linear solvers in the subsystems and they\n",
    "will be utilized to solve the subsystem linear problem.\n",
    "\n",
    "Here, we calculate the total derivatives across the Sellar system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "609d0708",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:35.566405Z",
     "iopub.status.busy": "2026-10-02T14:42:35.566214Z",
     "iopub.status.idle": "2026-10-02T14:42:37.937175Z",
     "shell.execute_reply": "2026-10-02T14:42:37.936474Z"
    },
    "papermill": {
     "duration": 2.373905,
     "end_time": "2026-10-02T14:42:37.938156+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:35.564251+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_src26"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import get_code\n",
    "from myst_nb import glue\n",
    "glue(\"code_src26\", get_code(\"openmdao.test_suite.components.sellar.SellarDis1withDerivatives\"), display=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c47a1fbd",
   "metadata": {
    "papermill": {
     "duration": 0.001909,
     "end_time": "2026-10-02T14:42:37.943790+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:37.941881+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    ":::{dropdown} `SellarDis1withDerivatives` class definition \n",
    "\n",
    "{glue:}`code_src26`\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "9b7c07eb",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:38.019468Z",
     "iopub.status.busy": "2026-10-02T14:42:38.019216Z",
     "iopub.status.idle": "2026-10-02T14:42:38.027679Z",
     "shell.execute_reply": "2026-10-02T14:42:38.027189Z"
    },
    "papermill": {
     "duration": 0.077516,
     "end_time": "2026-10-02T14:42:38.028129+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:37.950613+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_src27"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import get_code\n",
    "from myst_nb import glue\n",
    "glue(\"code_src27\", get_code(\"openmdao.test_suite.components.sellar.SellarDis2withDerivatives\"), display=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5aa68b2",
   "metadata": {
    "papermill": {
     "duration": 0.001865,
     "end_time": "2026-10-02T14:42:38.031998+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:38.030133+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    ":::{dropdown} `SellarDis2withDerivatives` class definition \n",
    "\n",
    "{glue:}`code_src27`\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "33b4c20f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:38.037161Z",
     "iopub.status.busy": "2026-10-02T14:42:38.036988Z",
     "iopub.status.idle": "2026-10-02T14:42:39.322970Z",
     "shell.execute_reply": "2026-10-02T14:42:39.322236Z"
    },
    "papermill": {
     "duration": 1.289246,
     "end_time": "2026-10-02T14:42:39.323491+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:38.034245+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952159.274981] [runnervm8df0l:7190 :0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55c7e5c9ad30 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",
      "[1790952159.275265] [runnervm8df0l:7190 :0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "NL: NLBGS Converged in 8 iterations\n",
      "LN: LNBJSolver 'LN: LNBJ' on system '' failed to converge in 10 iterations.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[runnervm8df0l:07190] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "\n",
    "from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives\n",
    "\n",
    "prob = om.Problem()\n",
    "model = prob.model\n",
    "\n",
    "model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])\n",
    "\n",
    "model.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),\n",
    "                    promotes=['obj', 'x', 'z', 'y1', 'y2'])\n",
    "\n",
    "model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])\n",
    "model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])\n",
    "\n",
    "model.nonlinear_solver = om.NonlinearBlockGS()\n",
    "model.linear_solver = om.LinearBlockJac()\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "prob.set_val('x', 1.)\n",
    "prob.set_val('z', np.array([5.0, 2.0]))\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "wrt = ['z']\n",
    "of = ['obj']\n",
    "\n",
    "J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "49112868",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.342373Z",
     "iopub.status.busy": "2026-10-02T14:42:39.342113Z",
     "iopub.status.idle": "2026-10-02T14:42:39.345030Z",
     "shell.execute_reply": "2026-10-02T14:42:39.344208Z"
    },
    "papermill": {
     "duration": 0.018037,
     "end_time": "2026-10-02T14:42:39.345510+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.327473+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.610009089277705\n",
      "1.7844852158189335\n"
     ]
    }
   ],
   "source": [
    "print(J['obj', 'z'][0][0])\n",
    "print(J['obj', 'z'][0][1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e403f1f6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.455903Z",
     "iopub.status.busy": "2026-10-02T14:42:39.455605Z",
     "iopub.status.idle": "2026-10-02T14:42:39.460729Z",
     "shell.execute_reply": "2026-10-02T14:42:39.459930Z"
    },
    "papermill": {
     "duration": 0.008425,
     "end_time": "2026-10-02T14:42:39.461387+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.452962+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(6.95892892798351e-08)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "\n",
    "assert_near_equal(J['obj', 'z'][0][0], 9.61001056, .00001)\n",
    "assert_near_equal(J['obj', 'z'][0][1], 1.78448534, .00001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7bc553c5",
   "metadata": {
    "papermill": {
     "duration": 0.074088,
     "end_time": "2026-10-02T14:42:39.537674+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.463586+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## LinearBlockJac Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "75df2e29",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.606058Z",
     "iopub.status.busy": "2026-10-02T14:42:39.605778Z",
     "iopub.status.idle": "2026-10-02T14:42:39.610760Z",
     "shell.execute_reply": "2026-10-02T14:42:39.610041Z"
    },
    "papermill": {
     "duration": 0.009359,
     "end_time": "2026-10-02T14:42:39.611483+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.602124+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;\">assemble_jac</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;\">Activates use of assembled jacobian by this solver.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">atol</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">1e-10</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;\">absolute error tolerance</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">err_on_non_converge</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;\">When True, AnalysisError will be raised if we don&#x27;t converge.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">iprint</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">1</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;int&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">whether to print output</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">maxiter</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">10</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;int&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">maximum number of iterations</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">rtol</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">1e-10</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;\">relative error tolerance</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.solvers.linear.linear_block_jac.LinearBlockJac\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c8b2d8e",
   "metadata": {
    "papermill": {
     "duration": 0.002289,
     "end_time": "2026-10-02T14:42:39.616228+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.613939+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## LinearBlockJac Constructor\n",
    "\n",
    "The call signature for the `LinearBlockJac` constructor is:\n",
    "\n",
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.solvers.linear.linear_block_jac.LinearBlockJac.__init__\n",
    "        :noindex:\n",
    "```\n",
    "\n",
    "## LinearBlockJac Option Examples\n",
    "\n",
    "**maxiter**\n",
    "\n",
    "  This lets you specify the maximum number of Gauss-Seidel iterations to apply. In this example, we\n",
    "  cut it back from the default, ten, down to five, so that it terminates a few iterations earlier and doesn't  reach the specified absolute or relative tolerance. Note that due to the delayed transfer of\n",
    "  information, this takes more iterations to converge than the LinearBlockGS solver."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8877a2c4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.679163Z",
     "iopub.status.busy": "2026-10-02T14:42:39.678935Z",
     "iopub.status.idle": "2026-10-02T14:42:39.696281Z",
     "shell.execute_reply": "2026-10-02T14:42:39.695715Z"
    },
    "papermill": {
     "duration": 0.021667,
     "end_time": "2026-10-02T14:42:39.696991+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.675324+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NL: NLBGS Converged in 8 iterations\n",
      "LN: LNBJSolver 'LN: LNBJ' on system '' failed to converge in 5 iterations.\n"
     ]
    }
   ],
   "source": [
    "from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives\n",
    "\n",
    "prob = om.Problem()\n",
    "model = prob.model\n",
    "\n",
    "model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])\n",
    "\n",
    "model.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),\n",
    "                    promotes=['obj', 'x', 'z', 'y1', 'y2'])\n",
    "\n",
    "model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])\n",
    "model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])\n",
    "\n",
    "model.nonlinear_solver = om.NonlinearBlockGS()\n",
    "\n",
    "model.linear_solver = om.LinearBlockJac()\n",
    "model.linear_solver.options['maxiter'] = 5\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "prob.set_val('x', 1.)\n",
    "prob.set_val('z', np.array([5.0, 2.0]))\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "wrt = ['z']\n",
    "of = ['obj']\n",
    "\n",
    "J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a7388859",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.701652Z",
     "iopub.status.busy": "2026-10-02T14:42:39.701493Z",
     "iopub.status.idle": "2026-10-02T14:42:39.704272Z",
     "shell.execute_reply": "2026-10-02T14:42:39.703732Z"
    },
    "papermill": {
     "duration": 0.005796,
     "end_time": "2026-10-02T14:42:39.704974+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.699178+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.602301066797569\n",
      "1.7802249941460035\n"
     ]
    }
   ],
   "source": [
    "print(J['obj', 'z'][0][0])\n",
    "print(J['obj', 'z'][0][1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6e149e57",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.709072Z",
     "iopub.status.busy": "2026-10-02T14:42:39.708932Z",
     "iopub.status.idle": "2026-10-02T14:42:39.712508Z",
     "shell.execute_reply": "2026-10-02T14:42:39.711725Z"
    },
    "papermill": {
     "duration": 0.00653,
     "end_time": "2026-10-02T14:42:39.713220+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.706690+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(6.3609916569239266e-09)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(J['obj', 'z'][0][0], 9.60230118004, .00001)\n",
    "assert_near_equal(J['obj', 'z'][0][1], 1.78022500547, .00001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c8a50ac",
   "metadata": {
    "papermill": {
     "duration": 0.001667,
     "end_time": "2026-10-02T14:42:39.716651+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.714984+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "**atol**\n",
    "\n",
    "  Here, we set the absolute tolerance to a looser value that will trigger an earlier termination. After\n",
    "  each iteration, the norm of the linear residuals is calculated by calling `apply_linear`. If this norm value is lower than the absolute tolerance `atol`, the iteration will terminate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "41ee05d6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.856063Z",
     "iopub.status.busy": "2026-10-02T14:42:39.855825Z",
     "iopub.status.idle": "2026-10-02T14:42:39.868120Z",
     "shell.execute_reply": "2026-10-02T14:42:39.867179Z"
    },
    "papermill": {
     "duration": 0.055345,
     "end_time": "2026-10-02T14:42:39.868635+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.813290+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NL: NLBGS Converged in 8 iterations\n",
      "LN: LNBJ Converged in 7 iterations\n"
     ]
    }
   ],
   "source": [
    "from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives\n",
    "\n",
    "prob = om.Problem()\n",
    "model = prob.model\n",
    "\n",
    "model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])\n",
    "\n",
    "model.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),\n",
    "                    promotes=['obj', 'x', 'z', 'y1', 'y2'])\n",
    "\n",
    "model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])\n",
    "model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])\n",
    "\n",
    "model.nonlinear_solver = om.NonlinearBlockGS()\n",
    "\n",
    "model.linear_solver = om.LinearBlockJac()\n",
    "model.linear_solver.options['atol'] = 1.0e-3\n",
    "\n",
    "prob.setup(mode='rev')\n",
    "\n",
    "prob.set_val('x', 1.)\n",
    "prob.set_val('z', np.array([5.0, 2.0]))\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "wrt = ['z']\n",
    "of = ['obj']\n",
    "\n",
    "J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f0d5a95d",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.887987Z",
     "iopub.status.busy": "2026-10-02T14:42:39.887772Z",
     "iopub.status.idle": "2026-10-02T14:42:39.890982Z",
     "shell.execute_reply": "2026-10-02T14:42:39.890229Z"
    },
    "papermill": {
     "duration": 0.020903,
     "end_time": "2026-10-02T14:42:39.891506+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.870603+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.610162963993043\n",
      "1.784569557267524\n"
     ]
    }
   ],
   "source": [
    "print(J['obj', 'z'][0][0])\n",
    "print(J['obj', 'z'][0][1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "98bc2032",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.896319Z",
     "iopub.status.busy": "2026-10-02T14:42:39.896122Z",
     "iopub.status.idle": "2026-10-02T14:42:39.900137Z",
     "shell.execute_reply": "2026-10-02T14:42:39.899264Z"
    },
    "papermill": {
     "duration": 0.007183,
     "end_time": "2026-10-02T14:42:39.900658+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.893475+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.2749517033012263e-10)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(J['obj', 'z'][0][0], 9.61016296175, .00001)\n",
    "assert_near_equal(J['obj', 'z'][0][1], 1.78456955704, .00001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "312e12a6",
   "metadata": {
    "papermill": {
     "duration": 0.001754,
     "end_time": "2026-10-02T14:42:39.904210+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.902456+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "**rtol**\n",
    "\n",
    "  Here, we set the relative tolerance to a looser value that will trigger an earlier termination. After\n",
    "  each iteration, the norm of the linear residuals is calculated by calling `apply_linear`. If the ratio of the currently calculated norm to the initial residual norm is lower than the relative tolerance `rtol`, the iteration will terminate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "391850c1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:39.908637Z",
     "iopub.status.busy": "2026-10-02T14:42:39.908493Z",
     "iopub.status.idle": "2026-10-02T14:42:39.922448Z",
     "shell.execute_reply": "2026-10-02T14:42:39.921745Z"
    },
    "papermill": {
     "duration": 0.017099,
     "end_time": "2026-10-02T14:42:39.923118+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:39.906019+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NL: NLBGS Converged in 8 iterations\n",
      "LN: LNBJ Converged in 7 iterations\n"
     ]
    }
   ],
   "source": [
    "from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives\n",
    "\n",
    "prob = om.Problem()\n",
    "model = prob.model\n",
    "\n",
    "model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2'])\n",
    "model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])\n",
    "\n",
    "model.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),\n",
    "                    promotes=['obj', 'x', 'z', 'y1', 'y2'])\n",
    "\n",
    "model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])\n",
    "model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])\n",
    "\n",
    "model.nonlinear_solver = om.NonlinearBlockGS()\n",
    "\n",
    "model.linear_solver = om.LinearBlockJac()\n",
    "model.linear_solver.options['rtol'] = 1.0e-3\n",
    "\n",
    "prob.setup(mode='rev')\n",
    "\n",
    "prob.set_val('x', 1.)\n",
    "prob.set_val('z', np.array([5.0, 2.0]))\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "wrt = ['z']\n",
    "of = ['obj']\n",
    "\n",
    "J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "65b4a895",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:40.084261Z",
     "iopub.status.busy": "2026-10-02T14:42:40.083995Z",
     "iopub.status.idle": "2026-10-02T14:42:40.087212Z",
     "shell.execute_reply": "2026-10-02T14:42:40.086589Z"
    },
    "papermill": {
     "duration": 0.007998,
     "end_time": "2026-10-02T14:42:40.087950+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:40.079952+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.610162963993043\n",
      "1.784569557267524\n"
     ]
    }
   ],
   "source": [
    "print(J['obj', 'z'][0][0])\n",
    "print(J['obj', 'z'][0][1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "51e6e03e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:40.092470Z",
     "iopub.status.busy": "2026-10-02T14:42:40.092279Z",
     "iopub.status.idle": "2026-10-02T14:42:40.096393Z",
     "shell.execute_reply": "2026-10-02T14:42:40.095758Z"
    },
    "papermill": {
     "duration": 0.007106,
     "end_time": "2026-10-02T14:42:40.096905+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:40.089799+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.2749517033012263e-10)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(J['obj', 'z'][0][0], 9.61016296175, .00001)\n",
    "assert_near_equal(J['obj', 'z'][0][1], 1.78456955704, .00001)"
   ]
  }
 ],
 "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.13.14"
  },
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 5.974665,
   "end_time": "2026-10-02T14:42:40.815423+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/building_blocks/solvers/linear_block_jac.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/solvers/linear_block_jac.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:42:34.840758+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}