{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "active-ipynb",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    from openmdao.utils.notebook_utils import notebook_mode\n",
    "except ImportError:\n",
    "    !python -m pip install openmdao[notebooks]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LinearRunOnce\n",
    "\n",
    "The simplest linear solver in OpenMDAO is LinearRunOnce, which sequentially calls `apply_linear`\n",
    "and `solve_linear` once on each subsystem. It is directly analogous to applying a single pass of the\n",
    "chain rule to the whole system without any iteration at the top level. This linear solver can only be\n",
    "used in systems where the following conditions are satisfied:\n",
    "\n",
    "1. System does not contain a cycle, though subsystems may.\n",
    "2. System does not contain any implicit states, though subsystems may.\n",
    "\n",
    "However, subsystems can contain cycles or implicit states, provided that they are using the appropriate\n",
    "solver such as [ScipyKrylov](../../../_srcdocs/packages/solvers.linear/scipy_iter_solver).\n",
    "\n",
    "Here is an example of using LinearRunOnce to calculate the derivatives across a simple model with\n",
    "the `Paraboloid` component."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "from openmdao.utils.notebook_utils import get_code\n",
    "from myst_nb import glue\n",
    "glue(\"code_src28\", get_code(\"openmdao.test_suite.components.paraboloid.Paraboloid\"), display=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::{Admonition} `Paraboloid` class definition \n",
    ":class: dropdown\n",
    "\n",
    "{glue:}`code_src28`\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "\n",
    "prob = om.Problem()\n",
    "model = prob.model\n",
    "\n",
    "model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy'])\n",
    "\n",
    "model.linear_solver = om.LinearRunOnce()\n",
    "\n",
    "prob.setup(check=False, mode='fwd')\n",
    "\n",
    "prob.set_val('x', 0.0)\n",
    "prob.set_val('y', 0.0)\n",
    "\n",
    "prob.run_model()\n",
    "\n",
    "of = ['f_xy']\n",
    "wrt = ['x', 'y']\n",
    "derivs = prob.compute_totals(of=of, wrt=wrt, return_format='dict')\n",
    "\n",
    "print(derivs['f_xy']['x'], [[-6.0]])\n",
    "print(derivs['f_xy']['y'], [[8.0]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "\n",
    "assert_near_equal(derivs['f_xy']['x'], [[-6.0]], 1e-6)\n",
    "assert_near_equal(derivs['f_xy']['y'], [[8.0]], 1e-6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LinearRunOnce Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "om.show_options_table(\"openmdao.solvers.linear.linear_runonce.LinearRunOnce\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LinearRunOnce Constructor\n",
    "\n",
    "The call signature for the `LinearRunOnce` constructor is:\n",
    "\n",
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.solvers.linear.linear_runonce.LinearRunOnce.__init__\n",
    "        :noindex:\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.1"
  },
  "orphan": true
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
