{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9ebd7a88",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:42.480110Z",
     "iopub.status.busy": "2026-10-02T14:42:42.479888Z",
     "iopub.status.idle": "2026-10-02T14:42:42.484418Z",
     "shell.execute_reply": "2026-10-02T14:42:42.483580Z"
    },
    "papermill": {
     "duration": 0.007551,
     "end_time": "2026-10-02T14:42:42.484972+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:42.477421+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": "ac7442d5",
   "metadata": {
    "papermill": {
     "duration": 0.001044,
     "end_time": "2026-10-02T14:42:42.487385+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:42.486341+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# Modifying Solver Options\n",
    "\n",
    "In OpenMDAO, implicit outputs can have bounds and scaling attached to them. These are defined when `add_output` is called on an implicit component.\n",
    "\n",
    "In complex models, this means that a user may need to tweak bounds and scaling in multiple files. The bounds and scaling of a variable may be dependent upon the application of the model. These bounds may need to be adjusted in a file that is generally outside of the expertise of the user.\n",
    "\n",
    "OpenMDAO provides a method `System.set_output_solver_options` that allows users to set bounds throughout their model from a single script or notebook."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76a3b6c0",
   "metadata": {
    "papermill": {
     "duration": 0.001045,
     "end_time": "2026-10-02T14:42:42.489581+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:42.488536+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.core.system.System.set_output_solver_options\n",
    "        :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdfb9410",
   "metadata": {
    "papermill": {
     "duration": 0.00103,
     "end_time": "2026-10-02T14:42:42.491736+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:42.490706+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Example of Setting Solver Output Options\n",
    "\n",
    "Here is an example of how to make use of the `System.set_output_solver_options` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "aff8bf0a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:42.494789Z",
     "iopub.status.busy": "2026-10-02T14:42:42.494619Z",
     "iopub.status.idle": "2026-10-02T14:42:43.975480Z",
     "shell.execute_reply": "2026-10-02T14:42:43.974793Z"
    },
    "papermill": {
     "duration": 1.483177,
     "end_time": "2026-10-02T14:42:43.976059+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:42.492882+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Implicit component in which bounds and scaling are set on outputs\n",
    "import openmdao.api as om\n",
    "\n",
    "class ScalingExample3(om.ImplicitComponent):\n",
    "\n",
    "    def setup(self):\n",
    "        self.add_input('x1', val=100.0)\n",
    "        self.add_input('x2', val=5000.0)\n",
    "        self.add_output('y1', val=200., ref=1e2, res_ref=1e5, ref0=1.0, lower=2., upper=3)\n",
    "        self.add_output('y2', val=6000., ref=1e3, res_ref=1e-5)\n",
    "\n",
    "    def apply_nonlinear(self, inputs, outputs, residuals):\n",
    "        x1 = inputs['x1']\n",
    "        x2 = inputs['x2']\n",
    "        y1 = outputs['y1']\n",
    "        y2 = outputs['y2']\n",
    "\n",
    "        residuals['y1'] = 1e5 * (x1 - y1) / y1\n",
    "        residuals['y2'] = 1e-5 * (x2 - y2) / y2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e304e311",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:43.979029Z",
     "iopub.status.busy": "2026-10-02T14:42:43.978642Z",
     "iopub.status.idle": "2026-10-02T14:42:45.183302Z",
     "shell.execute_reply": "2026-10-02T14:42:45.182248Z"
    },
    "papermill": {
     "duration": 1.206743,
     "end_time": "2026-10-02T14:42:45.183860+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:43.977117+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952165.171467] [runnervm8df0l:7258 :0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x56105f3b9c90 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",
      "[1790952165.171772] [runnervm8df0l:7258 :0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[runnervm8df0l:07258] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    }
   ],
   "source": [
    "# Script that makes use of this implicit component\n",
    "prob = om.Problem()\n",
    "\n",
    "# ScalingExample3 sets values for ref, res_ref, ref0, lower, and upper\n",
    "comp = prob.model.add_subsystem('comp', ScalingExample3())\n",
    "\n",
    "prob.setup()\n",
    "prob.run_model() # Run model with the bounds and scaling set in the component"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f4704694",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:45.187159Z",
     "iopub.status.busy": "2026-10-02T14:42:45.186971Z",
     "iopub.status.idle": "2026-10-02T14:42:45.191741Z",
     "shell.execute_reply": "2026-10-02T14:42:45.190366Z"
    },
    "papermill": {
     "duration": 0.007425,
     "end_time": "2026-10-02T14:42:45.192615+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:45.185190+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "with prob.model._scaled_context_all():\n",
    "    assert_near_equal(prob.get_val('comp.y1'), 2.0, 1e-2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1ee98810",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:45.195213Z",
     "iopub.status.busy": "2026-10-02T14:42:45.195081Z",
     "iopub.status.idle": "2026-10-02T14:42:45.199961Z",
     "shell.execute_reply": "2026-10-02T14:42:45.199146Z"
    },
    "papermill": {
     "duration": 0.006627,
     "end_time": "2026-10-02T14:42:45.200358+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:45.193731+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Now override a value from this cell (could also be from a separate script) and re-run the model\n",
    "prob.model.set_output_solver_options(name='comp.y1',ref=1e3)\n",
    "prob.setup()\n",
    "prob.run_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ca1e45d3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:42:45.202816Z",
     "iopub.status.busy": "2026-10-02T14:42:45.202665Z",
     "iopub.status.idle": "2026-10-02T14:42:45.205277Z",
     "shell.execute_reply": "2026-10-02T14:42:45.204374Z"
    },
    "papermill": {
     "duration": 0.004428,
     "end_time": "2026-10-02T14:42:45.205718+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:42:45.201290+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "with prob.model._scaled_context_all():\n",
    "    assert_near_equal(prob.get_val('comp.y1'), 0.2, 1e-2)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.14"
  },
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 3.922289,
   "end_time": "2026-10-02T14:42:45.722000+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/building_blocks/solvers/modify_solver_options.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/solvers/modify_solver_options.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:42:41.799711+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}