{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1ef6326e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:09.220029Z",
     "iopub.status.busy": "2026-10-02T14:48:09.219842Z",
     "iopub.status.idle": "2026-10-02T14:48:09.224155Z",
     "shell.execute_reply": "2026-10-02T14:48:09.223550Z"
    },
    "hide_input": true,
    "papermill": {
     "duration": 0.007496,
     "end_time": "2026-10-02T14:48:09.224593+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:09.217097+00:00",
     "status": "completed"
    },
    "tags": [
     "active-ipynb",
     "remove-input",
     "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": "4495a1eb",
   "metadata": {
    "papermill": {
     "duration": 0.001142,
     "end_time": "2026-10-02T14:48:09.227440+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:09.226298+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# AnalysisDriver\n",
    "\n",
    "AnalysisDriver serves to run a number of case _samples_ without optimization.\n",
    "The intent is to provide data about the response of a model's outputs when various inputs are changed.\n",
    "\n",
    "## AnalysisDriver Options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "846f6f30",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:09.230576Z",
     "iopub.status.busy": "2026-10-02T14:48:09.230427Z",
     "iopub.status.idle": "2026-10-02T14:48:10.345430Z",
     "shell.execute_reply": "2026-10-02T14:48:10.344620Z"
    },
    "papermill": {
     "duration": 1.117491,
     "end_time": "2026-10-02T14:48:10.346125+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:09.228634+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "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;\">batch_size</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">1000</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;\">Number of samples to distribute among the processors at a time when run_parallel is True. This should be limited when the memory required to store the batch size of samples grows too large.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><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: 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;\">procs_per_model</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;\">Number of processors to give each model under MPI.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">run_parallel</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;\">Set to True to execute samples in parallel.</td></tr>\n",
       "    </table>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "om.show_options_table(\"openmdao.drivers.analysis_driver.AnalysisDriver\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e6b0671",
   "metadata": {
    "papermill": {
     "duration": 0.001648,
     "end_time": "2026-10-02T14:48:10.349420+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:10.347772+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Specifying Samples for Execution\n",
    "\n",
    "Upon initialization, samples for AnalysisDriver can be provided in two ways.\n",
    "\n",
    "First, if a list or tuple is provided as the `samples` argument, it contains one or more dictionaries.\n",
    "Each dictionary in the sequence maps the keys (the promoted variable names to be set) to the associated metadata.\n",
    "Key `val` is required, while keys `units` and `indices` are optional.\n",
    "\n",
    "In the following example, nine samples of values for `x` and `y` are provided."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1f189a01",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:10.377130Z",
     "iopub.status.busy": "2026-10-02T14:48:10.376798Z",
     "iopub.status.idle": "2026-10-02T14:48:12.157730Z",
     "shell.execute_reply": "2026-10-02T14:48:12.156980Z"
    },
    "papermill": {
     "duration": 1.807413,
     "end_time": "2026-10-02T14:48:12.158234+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:10.350821+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952491.583061] [runnervm8df0l:11296:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x558274f21290 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",
      "[1790952491.583334] [runnervm8df0l:11296: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:11296] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Recorded 9 cases.\n",
      "  x          y         f_xy \n",
      " 0.000      0.000     22.000\n",
      " 0.500      0.000     19.250\n",
      " 1.000      0.000     17.000\n",
      " 0.000      0.500     26.250\n",
      " 0.500      0.500     23.750\n",
      " 1.000      0.500     21.750\n",
      " 0.000      1.000     31.000\n",
      " 0.500      1.000     28.750\n",
      " 1.000      1.000     27.000\n"
     ]
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('comp', Paraboloid(), promotes=['*'])\n",
    "\n",
    "samples_3x3 = [\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.5}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 1.}},\n",
    "]\n",
    "\n",
    "prob.driver = om.AnalysisDriver(samples=samples_3x3)\n",
    "prob.driver.add_recorder(om.SqliteRecorder('analysis_driver.sql'))\n",
    "\n",
    "prob.driver.add_response('f_xy', units=None, indices=[0])\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "prob.cleanup()\n",
    "\n",
    "cr = om.CaseReader(str(prob.get_outputs_dir() / \"analysis_driver.sql\"))\n",
    "cases = cr.get_cases(source='driver')\n",
    "\n",
    "print(f'Recorded {len(cases)} cases.')\n",
    "\n",
    "print(f'{\"x\":^6}     {\"y\":^6}     {\"f_xy\":^6}')\n",
    "for case in cases:\n",
    "    x = case.get_val('x')[0]\n",
    "    y = case.get_val('y')[0]\n",
    "    f_xy = case.get_val('f_xy')[0]\n",
    "    print(f'{x:6.3f}     {y:6.3f}     {f_xy:6.3f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90a1e74f",
   "metadata": {
    "papermill": {
     "duration": 0.012038,
     "end_time": "2026-10-02T14:48:12.172042+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:12.160004+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Specifying Responses for Derivative Recording\n",
    "\n",
    "Since AnalysisDriver does not rely upon the constraints and objectives defined within a model, if the recording\n",
    "of derivatives is requested when executing the AnalysisDriver, the user needs to specify those outputs (responses)\n",
    "whose derivatives are required.\n",
    "\n",
    "AnalysisDriver provides an `add_response` method used to indicate those outputs that should be\n",
    "recorded. When recording derivatives, derivatives will be recorded for all responses.\n",
    "\n",
    "```{eval-rst}\n",
    ".. automethod:: openmdao.drivers.analysis_driver.AnalysisDriver.add_response\n",
    "    :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "db0f943a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:12.175920Z",
     "iopub.status.busy": "2026-10-02T14:48:12.175764Z",
     "iopub.status.idle": "2026-10-02T14:48:12.586196Z",
     "shell.execute_reply": "2026-10-02T14:48:12.585585Z"
    },
    "papermill": {
     "duration": 0.413259,
     "end_time": "2026-10-02T14:48:12.586665+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:12.173406+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  x          y         f_xy      df/dx      df/dy \n",
      " 0.000      0.000     22.000     -6.0     8.0\n",
      " 0.500      0.000     19.250     -5.0     8.5\n",
      " 1.000      0.000     17.000     -4.0     9.0\n",
      " 0.000      0.500     26.250     -5.5     9.0\n",
      " 0.500      0.500     23.750     -4.5     9.5\n",
      " 1.000      0.500     21.750     -3.5     10.0\n",
      " 0.000      1.000     31.000     -5.0     10.0\n",
      " 0.500      1.000     28.750     -4.0     10.5\n",
      " 1.000      1.000     27.000     -3.0     11.0\n"
     ]
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('comp', Paraboloid(), promotes=['*'])\n",
    "\n",
    "samples_3x3 = [\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.5}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 1.}},\n",
    "]\n",
    "\n",
    "prob.driver = om.AnalysisDriver(samples=samples_3x3)\n",
    "prob.driver.add_recorder(om.SqliteRecorder('analysis_driver.sql'))\n",
    "prob.driver.recording_options['record_derivatives'] = True\n",
    "\n",
    "prob.driver.add_response('f_xy', units=None, indices=[0])\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "prob.cleanup()\n",
    "\n",
    "cr = om.CaseReader(str(prob.get_outputs_dir() / \"analysis_driver.sql\"))\n",
    "cases = cr.get_cases(source='driver')\n",
    "\n",
    "\n",
    "print(f'{\"x\":^6}     {\"y\":^6}     {\"f_xy\":^6}     {\"df/dx\":^6}     {\"df/dy\":^6}')\n",
    "for case in cases:\n",
    "    x = case.get_val('x')[0]\n",
    "    y = case.get_val('y')[0]\n",
    "    f_xy = case.get_val('f_xy')[0]\n",
    "    df_dx = case.derivatives['f_xy', 'x']\n",
    "    df_dy = case.derivatives['f_xy', 'y']\n",
    "    print(f'{x:6.3f}     {y:6.3f}     {f_xy:6.3f}     {df_dx[0][0]}     {df_dy[0][0]}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6de46ad9",
   "metadata": {
    "papermill": {
     "duration": 0.001388,
     "end_time": "2026-10-02T14:48:12.589892+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:12.588504+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "\n",
    "To quickly record multiple outputs without having an `add_response` call for each one, the user\n",
    "can use the `add_responses` method. This method can accept a sequence of strings, to quickly add\n",
    "outputs to be recorded. Alternatively, providing responses as a dictionary allows the units,\n",
    "indices, and other metadata to be added in a manner similar to samples.\n",
    "\n",
    "```{eval-rst}\n",
    ".. automethod:: openmdao.drivers.analysis_driver.AnalysisDriver.add_responses\n",
    "    :noindex:\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8567a539",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:12.593581Z",
     "iopub.status.busy": "2026-10-02T14:48:12.593348Z",
     "iopub.status.idle": "2026-10-02T14:48:13.052297Z",
     "shell.execute_reply": "2026-10-02T14:48:13.051239Z"
    },
    "papermill": {
     "duration": 0.461607,
     "end_time": "2026-10-02T14:48:13.052923+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:12.591316+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  x          y         f_xy        z   \n",
      " 0.000      0.000     22.000      0.000\n",
      " 0.500      0.250     21.438      0.750\n",
      " 1.000      0.125     18.141      1.125\n"
     ]
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('comp', Paraboloid(), promotes=['*'])\n",
    "prob.model.add_subsystem('execcomp', om.ExecComp('z = x + y'), promotes=['*'])\n",
    "prob.model.set_input_defaults('x', val=1.0)\n",
    "prob.model.set_input_defaults('y', val=1.0)\n",
    "\n",
    "samples = [\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.25}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.125}},\n",
    "]\n",
    "\n",
    "prob.driver = om.AnalysisDriver(samples=samples)\n",
    "prob.driver.add_recorder(om.SqliteRecorder('analysis_driver.sql'))\n",
    "\n",
    "prob.driver.add_responses(('f_xy', 'z'))\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "prob.cleanup()\n",
    "\n",
    "cr = om.CaseReader(str(prob.get_outputs_dir() / \"analysis_driver.sql\"))\n",
    "cases = cr.get_cases(source='driver')\n",
    "\n",
    "print(f'{\"x\":^6}     {\"y\":^6}     {\"f_xy\":^6}     {\"z\":^6}')\n",
    "for case in cases:\n",
    "    x = case.get_val('x')[0]\n",
    "    y = case.get_val('y')[0]\n",
    "    f_xy = case.get_val('f_xy')[0]\n",
    "    z = case.get_val('z')[0]\n",
    "    print(f'{x:6.3f}     {y:6.3f}     {f_xy:6.3f}     {z:6.3f}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bafcf593",
   "metadata": {
    "papermill": {
     "duration": 0.001366,
     "end_time": "2026-10-02T14:48:13.055994+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.054628+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "### How does AnalysisDriver compare to DOEDriver?\n",
    "\n",
    "AnalysisDriver is intended by be a generalization of DOEDriver that is more capable.\n",
    "\n",
    "DOEDriver was written for a more optimization-centric mindset.  By default, it would only perturb variables marked as design variables of the Problem.\n",
    "\n",
    "AnalysisDriver takes sample values for any input in the model, as well as implicit outputs.\n",
    "Setting the value of an explicit output in the model would have no effect, as the value would be overwritten\n",
    "upon the execution of the model.\n",
    "\n",
    "Unlike DOEDriver, it also allows units and indices to be specified for the variables in each sample.\n",
    "Essentially, any argument to `set_val` can be provided as part of the sample data.\n",
    "\n",
    "DOEDriver also realizes all of the design points to be analyized, while AnalysisDriver's generators do this in a lazy way, which could potentially save some memory when running large data sets.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47477ba0",
   "metadata": {
    "papermill": {
     "duration": 0.001989,
     "end_time": "2026-10-02T14:48:13.298745+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.296756+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Generating Cases\n",
    "\n",
    "Creating a sequence of more than a handful of sample cases can be daunting as the number of model inputs increases.\n",
    "In addition, exceedingly large numbers of cases for large models may begin to tax memory resources if they are all kept in memory.\n",
    "To alleviate these issues, samples for AnalysisDriver can be provided by a lazy pythonic generator descended from an AnalysisGenerator.\n",
    "\n",
    "There are currently three types of AnalysisGenerator included with OpenMDAO\n",
    "\n",
    "- ZipGenerator\n",
    "- ProductGenerator\n",
    "- CSVGenerator"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ca7eb93",
   "metadata": {
    "papermill": {
     "duration": 0.002086,
     "end_time": "2026-10-02T14:48:13.302839+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.300753+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## ZipGenerator \n",
    "\n",
    "ZipGenerator takes a dictionary that is similar to those given as a sample, except it provids all values to be assumed for each variable.\n",
    "It then uses python's `zip` function to create a sample for each value specified.\n",
    "\n",
    "For instance, the following ZipGenerator will generate three sample cases:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "60ab3468",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:13.307366Z",
     "iopub.status.busy": "2026-10-02T14:48:13.307169Z",
     "iopub.status.idle": "2026-10-02T14:48:13.310292Z",
     "shell.execute_reply": "2026-10-02T14:48:13.309744Z"
    },
    "papermill": {
     "duration": 0.006112,
     "end_time": "2026-10-02T14:48:13.310933+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.304821+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: {'x': {'val': 0.0, 'units': None, 'indices': None}, 'y': {'val': 4.0, 'units': None, 'indices': None}}\n",
      "1: {'x': {'val': 1.0, 'units': None, 'indices': None}, 'y': {'val': 5.0, 'units': None, 'indices': None}}\n",
      "2: {'x': {'val': 2.0, 'units': None, 'indices': None}, 'y': {'val': 6.0, 'units': None, 'indices': None}}\n"
     ]
    }
   ],
   "source": [
    "gen = om.ZipGenerator({'x': {'val': [0.0, 1.0, 2.0], 'units': None},\n",
    "                       'y': {'val': [4.0, 5.0, 6.0], 'units': None}})\n",
    "\n",
    "for i, sample in enumerate(gen):\n",
    "    print(f'{i}:', sample)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76fec51b",
   "metadata": {
    "papermill": {
     "duration": 0.001345,
     "end_time": "2026-10-02T14:48:13.313704+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.312359+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Note that the number of values given for each variable to be sampled must be the same.\n",
    "\n",
    "## ProductGenerator \n",
    "\n",
    "ProductGenerator, like ZipGenerator, takes a dictionary that provides values and optionally units and indices for\n",
    "each variable to be sampled.\n",
    "It uses Python's `itertools.product` to produce every possible combination of the values of sampled variables.\n",
    "\n",
    "For instance, the following example will generate 12 sample cases:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d2faafdf",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:13.317096Z",
     "iopub.status.busy": "2026-10-02T14:48:13.316953Z",
     "iopub.status.idle": "2026-10-02T14:48:13.319654Z",
     "shell.execute_reply": "2026-10-02T14:48:13.319117Z"
    },
    "papermill": {
     "duration": 0.005009,
     "end_time": "2026-10-02T14:48:13.320037+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.315028+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: {'x': {'val': 0.0, 'units': None, 'indices': None}, 'y': {'val': 4.0, 'units': None, 'indices': None}}\n",
      "1: {'x': {'val': 0.0, 'units': None, 'indices': None}, 'y': {'val': 5.0, 'units': None, 'indices': None}}\n",
      "2: {'x': {'val': 0.0, 'units': None, 'indices': None}, 'y': {'val': 6.0, 'units': None, 'indices': None}}\n",
      "3: {'x': {'val': 0.0, 'units': None, 'indices': None}, 'y': {'val': 7.0, 'units': None, 'indices': None}}\n",
      "4: {'x': {'val': 1.0, 'units': None, 'indices': None}, 'y': {'val': 4.0, 'units': None, 'indices': None}}\n",
      "5: {'x': {'val': 1.0, 'units': None, 'indices': None}, 'y': {'val': 5.0, 'units': None, 'indices': None}}\n",
      "6: {'x': {'val': 1.0, 'units': None, 'indices': None}, 'y': {'val': 6.0, 'units': None, 'indices': None}}\n",
      "7: {'x': {'val': 1.0, 'units': None, 'indices': None}, 'y': {'val': 7.0, 'units': None, 'indices': None}}\n",
      "8: {'x': {'val': 2.0, 'units': None, 'indices': None}, 'y': {'val': 4.0, 'units': None, 'indices': None}}\n",
      "9: {'x': {'val': 2.0, 'units': None, 'indices': None}, 'y': {'val': 5.0, 'units': None, 'indices': None}}\n",
      "10: {'x': {'val': 2.0, 'units': None, 'indices': None}, 'y': {'val': 6.0, 'units': None, 'indices': None}}\n",
      "11: {'x': {'val': 2.0, 'units': None, 'indices': None}, 'y': {'val': 7.0, 'units': None, 'indices': None}}\n"
     ]
    }
   ],
   "source": [
    "gen = om.ProductGenerator({'x': {'val': [0.0, 1.0, 2.0], 'units': None},\n",
    "                           'y': {'val': [4.0, 5.0, 6.0, 7.0], 'units': None}})\n",
    "\n",
    "for i, sample in enumerate(gen):\n",
    "    print(f'{i}:', sample)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "856a289b",
   "metadata": {
    "papermill": {
     "duration": 0.014755,
     "end_time": "2026-10-02T14:48:13.368547+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.353792+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "\n",
    "Unlike ZipGenerator, each variable can have a different number of sample values.\n",
    "\n",
    "## CSVGenerator\n",
    "\n",
    "CSVGenerator provides the ability to read cases from a comma-separated-values file.\n",
    "That is, this allows the user to create a table of cases to be run in a spreadsheet and then execute those cases via the AnalysisDriver.\n",
    "\n",
    "The first row of the CSV file should provide the promoted names of the variables to be sampled.\n",
    "The second row may optionally provide units for each variable to be sampled.\n",
    "The next row may optionally provide the indices to be set for each variable to be sampled.\n",
    "Following that, the remainder of rows provide values for each sampled variable.\n",
    "\n",
    "That is, the following csv file would provide the same nine cases as the ProductGenerator above.\n",
    "The second line contains the units of `x` and `y`.\n",
    "The third line provides the indices being set.\n",
    "These metadata values are unnecessary in this case but provided for illustration.\n",
    "\n",
    "```\n",
    "x, y\n",
    "None, None\n",
    "[0], [0]\n",
    "0.0, 4.0\n",
    "0.0, 5.0\n",
    "0.0, 6.0\n",
    "1.0, 4.0\n",
    "1.0, 5.0\n",
    "1.0, 6.0\n",
    "2.0, 4.0\n",
    "2.0, 5.0\n",
    "2.0, 6.0\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cf2f8ab",
   "metadata": {
    "papermill": {
     "duration": 0.048648,
     "end_time": "2026-10-02T14:48:13.418689+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.370041+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Running AnalysisDriver in Parallel\n",
    "\n",
    "To speed execution, AnalysisDriver can execute samples in parallel when multiple processors are available. This is done by setting the `run_parallel` option to True as shown in the following example and running your script using MPI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "98e6f704",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:13.446420Z",
     "iopub.status.busy": "2026-10-02T14:48:13.446246Z",
     "iopub.status.idle": "2026-10-02T14:48:13.450060Z",
     "shell.execute_reply": "2026-10-02T14:48:13.449603Z"
    },
    "papermill": {
     "duration": 0.007617,
     "end_time": "2026-10-02T14:48:13.450866+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.443249+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing mpi_script_0.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile mpi_script_0.py\n",
    "import openmdao.api as om\n",
    "from openmdao.test_suite.components.paraboloid import Paraboloid\n",
    "from openmdao.utils.mpi import MPI\n",
    "\n",
    "samples_3x3 = [\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 0.5}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 0.5}},\n",
    "\n",
    "    {'x': {'val': 0.}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': .5}, 'y': {'val': 1.}},\n",
    "    {'x': {'val': 1.}, 'y': {'val': 1.}},\n",
    "]\n",
    "\n",
    "rank = MPI.COMM_WORLD.rank\n",
    "\n",
    "prob = om.Problem()\n",
    "\n",
    "prob.model.add_subsystem('comp', Paraboloid(), promotes=['*'])\n",
    "\n",
    "prob.driver = om.AnalysisDriver(samples=samples_3x3, run_parallel=True)\n",
    "prob.driver.add_recorder(om.SqliteRecorder('analysis_driver.sql'))\n",
    "\n",
    "prob.driver.add_response('f_xy', units=None, indices=[0])\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "prob.cleanup()\n",
    "\n",
    "cr = om.CaseReader(str(prob.get_outputs_dir() / f'analysis_driver.sql_{rank}'))\n",
    "cases = cr.get_cases(source='driver')\n",
    "\n",
    "print(f'Recorded {len(cases)} cases on proc {rank}.')\n",
    "\n",
    "print(f'{\"x\":^6}     {\"y\":^6}     {\"f_xy\":^6}')\n",
    "for case in cases:\n",
    "    x = case.get_val('x')[0]\n",
    "    y = case.get_val('y')[0]\n",
    "    f_xy = case.get_val('f_xy')[0]\n",
    "    print(f'{x:6.3f}     {y:6.3f}     {f_xy:6.3f}')\n",
    "\n",
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "import numpy as np\n",
    "\n",
    "assert(len(cases) == 3 if rank == 0 else 2)\n",
    "# arrays in expected are [x, y, f_xy]\n",
    "if rank == 0:\n",
    "    expected = [[0.0, 0.0, 22.0], [0.5, 0.5, 23.75], [1.0, 1.0, 27.00]]\n",
    "elif rank == 1:\n",
    "    expected = [[0.5, 0.0, 19.25], [1.0, 0.5, 21.75]]\n",
    "elif rank == 2:\n",
    "    expected = [[1.0, 0.0, 17.00], [0.0, 1.0, 31.00]]\n",
    "else:\n",
    "    expected = [[0.0, 0.5, 26.25], [0.5, 1.0, 28.75]]\n",
    "\n",
    "for i, case in enumerate(cases):\n",
    "    x = case.get_val('x')[0]\n",
    "    y = case.get_val('y')[0]\n",
    "    f_xy = case.get_val('f_xy')[0]\n",
    "    assert_near_equal([x, y, f_xy], expected[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "1a608468",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:13.455018Z",
     "iopub.status.busy": "2026-10-02T14:48:13.454867Z",
     "iopub.status.idle": "2026-10-02T14:48:18.134115Z",
     "shell.execute_reply": "2026-10-02T14:48:18.133473Z"
    },
    "papermill": {
     "duration": 4.681761,
     "end_time": "2026-10-02T14:48:18.134537+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:13.452776+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div class=\"admonition note\"><p class=\"admonition-title\">Note</p><p>This feature requires MPI, and may not be able to be run on Colab or Binder.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<p>The following script is executed using <code>mpiexec -n 4 mpi_script_0.py</code>:</p><style>pre { line-height: 125%; }\n",
       "td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".highlight .hll { background-color: #ffffcc }\n",
       ".highlight { background: #f8f8f8; }\n",
       ".highlight .c { color: #3D7B7B; font-style: italic } /* Comment */\n",
       ".highlight .err { border: 1px solid #F00 } /* Error */\n",
       ".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".highlight .o { color: #666 } /* Operator */\n",
       ".highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n",
       ".highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n",
       ".highlight .cp { color: #9C6500 } /* Comment.Preproc */\n",
       ".highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n",
       ".highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n",
       ".highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n",
       ".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".highlight .ge { font-style: italic } /* Generic.Emph */\n",
       ".highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n",
       ".highlight .gr { color: #E40000 } /* Generic.Error */\n",
       ".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".highlight .gi { color: #008400 } /* Generic.Inserted */\n",
       ".highlight .go { color: #717171 } /* Generic.Output */\n",
       ".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
       ".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".highlight .gt { color: #04D } /* Generic.Traceback */\n",
       ".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
       ".highlight .m { color: #666 } /* Literal.Number */\n",
       ".highlight .s { color: #BA2121 } /* Literal.String */\n",
       ".highlight .na { color: #687822 } /* Name.Attribute */\n",
       ".highlight .nb { color: #008000 } /* Name.Builtin */\n",
       ".highlight .nc { color: #00F; font-weight: bold } /* Name.Class */\n",
       ".highlight .no { color: #800 } /* Name.Constant */\n",
       ".highlight .nd { color: #A2F } /* Name.Decorator */\n",
       ".highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */\n",
       ".highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n",
       ".highlight .nf { color: #00F } /* Name.Function */\n",
       ".highlight .nl { color: #767600 } /* Name.Label */\n",
       ".highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n",
       ".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".highlight .nv { color: #19177C } /* Name.Variable */\n",
       ".highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n",
       ".highlight .w { color: #BBB } /* Text.Whitespace */\n",
       ".highlight .mb { color: #666 } /* Literal.Number.Bin */\n",
       ".highlight .mf { color: #666 } /* Literal.Number.Float */\n",
       ".highlight .mh { color: #666 } /* Literal.Number.Hex */\n",
       ".highlight .mi { color: #666 } /* Literal.Number.Integer */\n",
       ".highlight .mo { color: #666 } /* Literal.Number.Oct */\n",
       ".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n",
       ".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n",
       ".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
       ".highlight .sr { color: #A45A77 } /* Literal.String.Regex */\n",
       ".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".highlight .fm { color: #00F } /* Name.Function.Magic */\n",
       ".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".highlight .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">openmdao.api</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"nn\">om</span>\n",
       "<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">openmdao.test_suite.components.paraboloid</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Paraboloid</span>\n",
       "<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">openmdao.utils.mpi</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">MPI</span>\n",
       "\n",
       "<span class=\"n\">samples_3x3</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">.5</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">}},</span>\n",
       "\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.5</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">.5</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.5</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.5</span><span class=\"p\">}},</span>\n",
       "\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">0.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">.5</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">}},</span>\n",
       "    <span class=\"p\">{</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">},</span> <span class=\"s1\">&#39;y&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"mf\">1.</span><span class=\"p\">}},</span>\n",
       "<span class=\"p\">]</span>\n",
       "\n",
       "<span class=\"n\">rank</span> <span class=\"o\">=</span> <span class=\"n\">MPI</span><span class=\"o\">.</span><span class=\"n\">COMM_WORLD</span><span class=\"o\">.</span><span class=\"n\">rank</span>\n",
       "\n",
       "<span class=\"n\">prob</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">Problem</span><span class=\"p\">()</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">model</span><span class=\"o\">.</span><span class=\"n\">add_subsystem</span><span class=\"p\">(</span><span class=\"s1\">&#39;comp&#39;</span><span class=\"p\">,</span> <span class=\"n\">Paraboloid</span><span class=\"p\">(),</span> <span class=\"n\">promotes</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;*&#39;</span><span class=\"p\">])</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">AnalysisDriver</span><span class=\"p\">(</span><span class=\"n\">samples</span><span class=\"o\">=</span><span class=\"n\">samples_3x3</span><span class=\"p\">,</span> <span class=\"n\">run_parallel</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">add_recorder</span><span class=\"p\">(</span><span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">SqliteRecorder</span><span class=\"p\">(</span><span class=\"s1\">&#39;analysis_driver.sql&#39;</span><span class=\"p\">))</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">add_response</span><span class=\"p\">(</span><span class=\"s1\">&#39;f_xy&#39;</span><span class=\"p\">,</span> <span class=\"n\">units</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">indices</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">])</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">setup</span><span class=\"p\">()</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">run_driver</span><span class=\"p\">()</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">cleanup</span><span class=\"p\">()</span>\n",
       "\n",
       "<span class=\"n\">cr</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">CaseReader</span><span class=\"p\">(</span><span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">get_outputs_dir</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"sa\">f</span><span class=\"s1\">&#39;analysis_driver.sql_</span><span class=\"si\">{</span><span class=\"n\">rank</span><span class=\"si\">}</span><span class=\"s1\">&#39;</span><span class=\"p\">))</span>\n",
       "<span class=\"n\">cases</span> <span class=\"o\">=</span> <span class=\"n\">cr</span><span class=\"o\">.</span><span class=\"n\">get_cases</span><span class=\"p\">(</span><span class=\"n\">source</span><span class=\"o\">=</span><span class=\"s1\">&#39;driver&#39;</span><span class=\"p\">)</span>\n",
       "\n",
       "<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"sa\">f</span><span class=\"s1\">&#39;Recorded </span><span class=\"si\">{</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">cases</span><span class=\"p\">)</span><span class=\"si\">}</span><span class=\"s1\"> cases on proc </span><span class=\"si\">{</span><span class=\"n\">rank</span><span class=\"si\">}</span><span class=\"s1\">.&#39;</span><span class=\"p\">)</span>\n",
       "\n",
       "<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"sa\">f</span><span class=\"s1\">&#39;</span><span class=\"si\">{</span><span class=\"s2\">&quot;x&quot;</span><span class=\"si\">:</span><span class=\"s1\">^6</span><span class=\"si\">}</span><span class=\"s1\">     </span><span class=\"si\">{</span><span class=\"s2\">&quot;y&quot;</span><span class=\"si\">:</span><span class=\"s1\">^6</span><span class=\"si\">}</span><span class=\"s1\">     </span><span class=\"si\">{</span><span class=\"s2\">&quot;f_xy&quot;</span><span class=\"si\">:</span><span class=\"s1\">^6</span><span class=\"si\">}</span><span class=\"s1\">&#39;</span><span class=\"p\">)</span>\n",
       "<span class=\"k\">for</span> <span class=\"n\">case</span> <span class=\"ow\">in</span> <span class=\"n\">cases</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;y&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">f_xy</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;f_xy&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"sa\">f</span><span class=\"s1\">&#39;</span><span class=\"si\">{</span><span class=\"n\">x</span><span class=\"si\">:</span><span class=\"s1\">6.3f</span><span class=\"si\">}</span><span class=\"s1\">     </span><span class=\"si\">{</span><span class=\"n\">y</span><span class=\"si\">:</span><span class=\"s1\">6.3f</span><span class=\"si\">}</span><span class=\"s1\">     </span><span class=\"si\">{</span><span class=\"n\">f_xy</span><span class=\"si\">:</span><span class=\"s1\">6.3f</span><span class=\"si\">}</span><span class=\"s1\">&#39;</span><span class=\"p\">)</span>\n",
       "\n",
       "<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">openmdao.utils.assert_utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">assert_near_equal</span>\n",
       "<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">numpy</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"nn\">np</span>\n",
       "\n",
       "<span class=\"k\">assert</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">cases</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"mi\">3</span> <span class=\"k\">if</span> <span class=\"n\">rank</span> <span class=\"o\">==</span> <span class=\"mi\">0</span> <span class=\"k\">else</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n",
       "<span class=\"c1\"># arrays in expected are [x, y, f_xy]</span>\n",
       "<span class=\"k\">if</span> <span class=\"n\">rank</span> <span class=\"o\">==</span> <span class=\"mi\">0</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">expected</span> <span class=\"o\">=</span> <span class=\"p\">[[</span><span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">22.0</span><span class=\"p\">],</span> <span class=\"p\">[</span><span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">23.75</span><span class=\"p\">],</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> <span class=\"mf\">27.00</span><span class=\"p\">]]</span>\n",
       "<span class=\"k\">elif</span> <span class=\"n\">rank</span> <span class=\"o\">==</span> <span class=\"mi\">1</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">expected</span> <span class=\"o\">=</span> <span class=\"p\">[[</span><span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">19.25</span><span class=\"p\">],</span> <span class=\"p\">[</span><span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">21.75</span><span class=\"p\">]]</span>\n",
       "<span class=\"k\">elif</span> <span class=\"n\">rank</span> <span class=\"o\">==</span> <span class=\"mi\">2</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">expected</span> <span class=\"o\">=</span> <span class=\"p\">[[</span><span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">17.00</span><span class=\"p\">],</span> <span class=\"p\">[</span><span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mf\">31.00</span><span class=\"p\">]]</span>\n",
       "<span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">expected</span> <span class=\"o\">=</span> <span class=\"p\">[[</span><span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">26.25</span><span class=\"p\">],</span> <span class=\"p\">[</span><span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mf\">28.75</span><span class=\"p\">]]</span>\n",
       "\n",
       "<span class=\"k\">for</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">case</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"n\">cases</span><span class=\"p\">):</span>\n",
       "    <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">y</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;y&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">f_xy</span> <span class=\"o\">=</span> <span class=\"n\">case</span><span class=\"o\">.</span><span class=\"n\">get_val</span><span class=\"p\">(</span><span class=\"s1\">&#39;f_xy&#39;</span><span class=\"p\">)[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">assert_near_equal</span><span class=\"p\">([</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">,</span> <span class=\"n\">f_xy</span><span class=\"p\">],</span> <span class=\"n\">expected</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span>\n",
       "</pre></div>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952495.211467] [runnervm8df0l:11322:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x557ca1b6a000 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",
      "[1790952495.211752] [runnervm8df0l:11322:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952495.213529] [runnervm8df0l:11323:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55d466f72b40 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",
      "[1790952495.213994] [runnervm8df0l:11323:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952495.236384] [runnervm8df0l:11320:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55be6090a820 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",
      "[1790952495.236801] [runnervm8df0l:11320:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952495.237008] [runnervm8df0l:11321:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55da95188b00 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",
      "[1790952495.237278] [runnervm8df0l:11321:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 1 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_0_out/analysis_driver.sql_1.\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 3 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_0_out/analysis_driver.sql_3.\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 2 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_0_out/analysis_driver.sql_2.\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 0 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_0_out/analysis_driver.sql_0.\n",
      "Note: Metadata is being recorded separately as /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_0_out/analysis_driver.sql_meta.\n",
      "Recorded 2 cases on proc 2.\n",
      "Recorded 2 cases on proc 1.\n",
      "  x          y         f_xy \n",
      " 0.500      0.000     19.250\n",
      " 1.000      0.500     21.750\n",
      "  x          y         f_xy \n",
      " 1.000      0.000     17.000\n",
      " 0.000      1.000     31.000\n",
      "Recorded 2 cases on proc 3.\n",
      "  x          y         f_xy \n",
      " 0.000      0.500     26.250\n",
      " 0.500      1.000     28.750\n",
      "Recorded 3 cases on proc 0.\n",
      "  x          y         f_xy \n",
      " 0.000      0.000     22.000\n",
      " 0.500      0.500     23.750\n",
      " 1.000      1.000     27.000\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import mpi_exec\n",
    "mpi_exec(4, 'mpi_script_0.py')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba89fbff",
   "metadata": {
    "papermill": {
     "duration": 0.011999,
     "end_time": "2026-10-02T14:48:18.148567+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:18.136568+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## Running MPI-enabled models in parallel with AnalysisDriver.\n",
    "\n",
    "If the model being executed supports parallelization, the user should also specify `procs_per_model` to dictate how many processor cores each model instance uses.\n",
    "\n",
    "The following example runs a model that can run two systems simultaneously `c1` and `c2` within a `ParallelGroup`.  In this case, each model can utilize two processors (`procs_per_model = 2`).\n",
    "\n",
    "When providing the number of processors via the `mpirun -n {num_procs} python myscript.py`, the total number of processors must be a multiple of `procs_per_model`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1e2317e9",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:18.241377Z",
     "iopub.status.busy": "2026-10-02T14:48:18.241188Z",
     "iopub.status.idle": "2026-10-02T14:48:18.244724Z",
     "shell.execute_reply": "2026-10-02T14:48:18.244256Z"
    },
    "papermill": {
     "duration": 0.007386,
     "end_time": "2026-10-02T14:48:18.245374+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:18.237988+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing mpi_script_1.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile mpi_script_1.py\n",
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "\n",
    "class FanInGrouped(om.Group):\n",
    "    \"\"\"\n",
    "    Topology where two components in a Group feed a single component\n",
    "    outside of that Group.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "\n",
    "        self.set_input_defaults('x1', 1.0)\n",
    "        self.set_input_defaults('x2', 1.0)\n",
    "\n",
    "        self.sub = self.add_subsystem('sub', om.ParallelGroup(),\n",
    "                                      promotes_inputs=['x1', 'x2'])\n",
    "\n",
    "        self.sub.add_subsystem('c1', om.ExecComp(['y=-2.0*x']),\n",
    "                               promotes_inputs=[('x', 'x1')])\n",
    "        self.sub.add_subsystem('c2', om.ExecComp(['y=5.0*x']),\n",
    "                               promotes_inputs=[('x', 'x2')])\n",
    "\n",
    "        self.add_subsystem('c3', om.ExecComp(['y=3.0*x1+7.0*x2']))\n",
    "\n",
    "        self.connect(\"sub.c1.y\", \"c3.x1\")\n",
    "        self.connect(\"sub.c2.y\", \"c3.x2\")\n",
    "\n",
    "prob = om.Problem(FanInGrouped())\n",
    "\n",
    "# Note the absense of adding design varaibles here, compared to DOEGenerator\n",
    "\n",
    "prob.driver = om.AnalysisDriver(om.ProductGenerator({'x1': {'val': np.linspace(0.0, 1.0, 10)},\n",
    "                                                     'x2': {'val': np.linspace(0.0, 1.0, 10)}}))\n",
    "\n",
    "prob.driver.add_recorder(om.SqliteRecorder(\"cases.sql\"))\n",
    "\n",
    "prob.driver.add_response('c3.y')\n",
    "\n",
    "# # the FanInGrouped model uses 2 processes, so we can run\n",
    "# # two instances of the model at a time, each using 2 of our 4 procs\n",
    "prob.driver.options['run_parallel'] = True\n",
    "prob.driver.options['procs_per_model'] = procs_per_model = 2\n",
    "\n",
    "prob.setup()\n",
    "prob.run_driver()\n",
    "prob.cleanup()\n",
    "\n",
    "# a separate case file will be written by rank 0 of each parallel model\n",
    "# (the top two global ranks)\n",
    "rank = prob.comm.rank\n",
    "\n",
    "num_models = prob.comm.size // procs_per_model\n",
    "\n",
    "if rank < num_models:\n",
    "    filename = f'cases.sql_{rank}'\n",
    "\n",
    "    cr = om.CaseReader(prob.get_outputs_dir() / filename)\n",
    "    cases = cr.list_cases('driver', out_stream=None)\n",
    "\n",
    "    values = []\n",
    "    for case in cases:\n",
    "        outputs = cr.get_case(case).outputs\n",
    "        values.append((outputs['x1'].item(), outputs['x2'].item(), outputs['c3.y'].item()))\n",
    "\n",
    "    print(\"\\n\"+\"\\n\".join([\"x1: %5.2f, x2: %5.2f, c3.y: %6.2f\" % (x1, x2, y) for x1, x2, y in values]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "17c6561a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:48:18.249658Z",
     "iopub.status.busy": "2026-10-02T14:48:18.249507Z",
     "iopub.status.idle": "2026-10-02T14:48:23.131815Z",
     "shell.execute_reply": "2026-10-02T14:48:23.131119Z"
    },
    "papermill": {
     "duration": 4.88505,
     "end_time": "2026-10-02T14:48:23.132326+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:48:18.247276+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div class=\"admonition note\"><p class=\"admonition-title\">Note</p><p>This feature requires MPI, and may not be able to be run on Colab or Binder.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<p>The following script is executed using <code>mpiexec -n 4 mpi_script_1.py</code>:</p><style>pre { line-height: 125%; }\n",
       "td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".highlight .hll { background-color: #ffffcc }\n",
       ".highlight { background: #f8f8f8; }\n",
       ".highlight .c { color: #3D7B7B; font-style: italic } /* Comment */\n",
       ".highlight .err { border: 1px solid #F00 } /* Error */\n",
       ".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".highlight .o { color: #666 } /* Operator */\n",
       ".highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n",
       ".highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n",
       ".highlight .cp { color: #9C6500 } /* Comment.Preproc */\n",
       ".highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n",
       ".highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n",
       ".highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n",
       ".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".highlight .ge { font-style: italic } /* Generic.Emph */\n",
       ".highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n",
       ".highlight .gr { color: #E40000 } /* Generic.Error */\n",
       ".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".highlight .gi { color: #008400 } /* Generic.Inserted */\n",
       ".highlight .go { color: #717171 } /* Generic.Output */\n",
       ".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
       ".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".highlight .gt { color: #04D } /* Generic.Traceback */\n",
       ".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
       ".highlight .m { color: #666 } /* Literal.Number */\n",
       ".highlight .s { color: #BA2121 } /* Literal.String */\n",
       ".highlight .na { color: #687822 } /* Name.Attribute */\n",
       ".highlight .nb { color: #008000 } /* Name.Builtin */\n",
       ".highlight .nc { color: #00F; font-weight: bold } /* Name.Class */\n",
       ".highlight .no { color: #800 } /* Name.Constant */\n",
       ".highlight .nd { color: #A2F } /* Name.Decorator */\n",
       ".highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */\n",
       ".highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n",
       ".highlight .nf { color: #00F } /* Name.Function */\n",
       ".highlight .nl { color: #767600 } /* Name.Label */\n",
       ".highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n",
       ".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".highlight .nv { color: #19177C } /* Name.Variable */\n",
       ".highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n",
       ".highlight .w { color: #BBB } /* Text.Whitespace */\n",
       ".highlight .mb { color: #666 } /* Literal.Number.Bin */\n",
       ".highlight .mf { color: #666 } /* Literal.Number.Float */\n",
       ".highlight .mh { color: #666 } /* Literal.Number.Hex */\n",
       ".highlight .mi { color: #666 } /* Literal.Number.Integer */\n",
       ".highlight .mo { color: #666 } /* Literal.Number.Oct */\n",
       ".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n",
       ".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n",
       ".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
       ".highlight .sr { color: #A45A77 } /* Literal.String.Regex */\n",
       ".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".highlight .fm { color: #00F } /* Name.Function.Magic */\n",
       ".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".highlight .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">numpy</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"nn\">np</span>\n",
       "<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">openmdao.api</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"nn\">om</span>\n",
       "\n",
       "<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">FanInGrouped</span><span class=\"p\">(</span><span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">Group</span><span class=\"p\">):</span>\n",
       "<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n",
       "<span class=\"sd\">    Topology where two components in a Group feed a single component</span>\n",
       "<span class=\"sd\">    outside of that Group.</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">()</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">set_input_defaults</span><span class=\"p\">(</span><span class=\"s1\">&#39;x1&#39;</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">set_input_defaults</span><span class=\"p\">(</span><span class=\"s1\">&#39;x2&#39;</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">)</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">sub</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">add_subsystem</span><span class=\"p\">(</span><span class=\"s1\">&#39;sub&#39;</span><span class=\"p\">,</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">ParallelGroup</span><span class=\"p\">(),</span>\n",
       "                                      <span class=\"n\">promotes_inputs</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;x1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;x2&#39;</span><span class=\"p\">])</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">sub</span><span class=\"o\">.</span><span class=\"n\">add_subsystem</span><span class=\"p\">(</span><span class=\"s1\">&#39;c1&#39;</span><span class=\"p\">,</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">ExecComp</span><span class=\"p\">([</span><span class=\"s1\">&#39;y=-2.0*x&#39;</span><span class=\"p\">]),</span>\n",
       "                               <span class=\"n\">promotes_inputs</span><span class=\"o\">=</span><span class=\"p\">[(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;x1&#39;</span><span class=\"p\">)])</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">sub</span><span class=\"o\">.</span><span class=\"n\">add_subsystem</span><span class=\"p\">(</span><span class=\"s1\">&#39;c2&#39;</span><span class=\"p\">,</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">ExecComp</span><span class=\"p\">([</span><span class=\"s1\">&#39;y=5.0*x&#39;</span><span class=\"p\">]),</span>\n",
       "                               <span class=\"n\">promotes_inputs</span><span class=\"o\">=</span><span class=\"p\">[(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;x2&#39;</span><span class=\"p\">)])</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">add_subsystem</span><span class=\"p\">(</span><span class=\"s1\">&#39;c3&#39;</span><span class=\"p\">,</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">ExecComp</span><span class=\"p\">([</span><span class=\"s1\">&#39;y=3.0*x1+7.0*x2&#39;</span><span class=\"p\">]))</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"s2\">&quot;sub.c1.y&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;c3.x1&quot;</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"s2\">&quot;sub.c2.y&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;c3.x2&quot;</span><span class=\"p\">)</span>\n",
       "\n",
       "<span class=\"n\">prob</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">Problem</span><span class=\"p\">(</span><span class=\"n\">FanInGrouped</span><span class=\"p\">())</span>\n",
       "\n",
       "<span class=\"c1\"># Note the absense of adding design varaibles here, compared to DOEGenerator</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">AnalysisDriver</span><span class=\"p\">(</span><span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">ProductGenerator</span><span class=\"p\">({</span><span class=\"s1\">&#39;x1&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">linspace</span><span class=\"p\">(</span><span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mi\">10</span><span class=\"p\">)},</span>\n",
       "                                                     <span class=\"s1\">&#39;x2&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">:</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">linspace</span><span class=\"p\">(</span><span class=\"mf\">0.0</span><span class=\"p\">,</span> <span class=\"mf\">1.0</span><span class=\"p\">,</span> <span class=\"mi\">10</span><span class=\"p\">)}}))</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">add_recorder</span><span class=\"p\">(</span><span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">SqliteRecorder</span><span class=\"p\">(</span><span class=\"s2\">&quot;cases.sql&quot;</span><span class=\"p\">))</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">add_response</span><span class=\"p\">(</span><span class=\"s1\">&#39;c3.y&#39;</span><span class=\"p\">)</span>\n",
       "\n",
       "<span class=\"c1\"># # the FanInGrouped model uses 2 processes, so we can run</span>\n",
       "<span class=\"c1\"># # two instances of the model at a time, each using 2 of our 4 procs</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">options</span><span class=\"p\">[</span><span class=\"s1\">&#39;run_parallel&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">options</span><span class=\"p\">[</span><span class=\"s1\">&#39;procs_per_model&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">procs_per_model</span> <span class=\"o\">=</span> <span class=\"mi\">2</span>\n",
       "\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">setup</span><span class=\"p\">()</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">run_driver</span><span class=\"p\">()</span>\n",
       "<span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">cleanup</span><span class=\"p\">()</span>\n",
       "\n",
       "<span class=\"c1\"># a separate case file will be written by rank 0 of each parallel model</span>\n",
       "<span class=\"c1\"># (the top two global ranks)</span>\n",
       "<span class=\"n\">rank</span> <span class=\"o\">=</span> <span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">comm</span><span class=\"o\">.</span><span class=\"n\">rank</span>\n",
       "\n",
       "<span class=\"n\">num_models</span> <span class=\"o\">=</span> <span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">comm</span><span class=\"o\">.</span><span class=\"n\">size</span> <span class=\"o\">//</span> <span class=\"n\">procs_per_model</span>\n",
       "\n",
       "<span class=\"k\">if</span> <span class=\"n\">rank</span> <span class=\"o\">&lt;</span> <span class=\"n\">num_models</span><span class=\"p\">:</span>\n",
       "    <span class=\"n\">filename</span> <span class=\"o\">=</span> <span class=\"sa\">f</span><span class=\"s1\">&#39;cases.sql_</span><span class=\"si\">{</span><span class=\"n\">rank</span><span class=\"si\">}</span><span class=\"s1\">&#39;</span>\n",
       "\n",
       "    <span class=\"n\">cr</span> <span class=\"o\">=</span> <span class=\"n\">om</span><span class=\"o\">.</span><span class=\"n\">CaseReader</span><span class=\"p\">(</span><span class=\"n\">prob</span><span class=\"o\">.</span><span class=\"n\">get_outputs_dir</span><span class=\"p\">()</span> <span class=\"o\">/</span> <span class=\"n\">filename</span><span class=\"p\">)</span>\n",
       "    <span class=\"n\">cases</span> <span class=\"o\">=</span> <span class=\"n\">cr</span><span class=\"o\">.</span><span class=\"n\">list_cases</span><span class=\"p\">(</span><span class=\"s1\">&#39;driver&#39;</span><span class=\"p\">,</span> <span class=\"n\">out_stream</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"n\">values</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">case</span> <span class=\"ow\">in</span> <span class=\"n\">cases</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">outputs</span> <span class=\"o\">=</span> <span class=\"n\">cr</span><span class=\"o\">.</span><span class=\"n\">get_case</span><span class=\"p\">(</span><span class=\"n\">case</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">outputs</span>\n",
       "        <span class=\"n\">values</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"n\">outputs</span><span class=\"p\">[</span><span class=\"s1\">&#39;x1&#39;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">item</span><span class=\"p\">(),</span> <span class=\"n\">outputs</span><span class=\"p\">[</span><span class=\"s1\">&#39;x2&#39;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">item</span><span class=\"p\">(),</span> <span class=\"n\">outputs</span><span class=\"p\">[</span><span class=\"s1\">&#39;c3.y&#39;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">item</span><span class=\"p\">()))</span>\n",
       "\n",
       "    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"o\">+</span><span class=\"s2\">&quot;</span><span class=\"se\">\\n</span><span class=\"s2\">&quot;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">([</span><span class=\"s2\">&quot;x1: </span><span class=\"si\">%5.2f</span><span class=\"s2\">, x2: </span><span class=\"si\">%5.2f</span><span class=\"s2\">, c3.y: </span><span class=\"si\">%6.2f</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">x1</span><span class=\"p\">,</span> <span class=\"n\">x2</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">x1</span><span class=\"p\">,</span> <span class=\"n\">x2</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">values</span><span class=\"p\">]))</span>\n",
       "</pre></div>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952499.977202] [runnervm8df0l:11345:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55aaf031a080 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",
      "[1790952499.977671] [runnervm8df0l:11346:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x561452f726b0 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",
      "[1790952499.977756] [runnervm8df0l:11343:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55f898825750 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",
      "[1790952499.977830] [runnervm8df0l:11344:0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x556668a432d0 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",
      "[1790952499.983759] [runnervm8df0l:11345:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952499.984003] [runnervm8df0l:11346:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952499.984106] [runnervm8df0l:11343:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[1790952499.984154] [runnervm8df0l:11344:0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 0 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_1_out/cases.sql_0.\n",
      "Note: Metadata is being recorded separately as /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_1_out/cases.sql_meta.\n",
      "Note: SqliteRecorder is running on multiple processors. Cases from rank 1 are being written to /home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/mpi_script_1_out/cases.sql_1.\n",
      "\n",
      "x1:  0.00, x2:  0.11, c3.y:   3.89\n",
      "x1:  0.00, x2:  0.33, c3.y:  11.67\n",
      "x1:  0.00, x2:  0.56, c3.y:  19.44\n",
      "x1:  0.00, x2:  0.78, c3.y:  27.22\n",
      "x1:  0.00, x2:  1.00, c3.y:  35.00\n",
      "x1:  0.11, x2:  0.11, c3.y:   3.22\n",
      "x1:  0.11, x2:  0.33, c3.y:  11.00\n",
      "x1:  0.11, x2:  0.56, c3.y:  18.78\n",
      "x1:  0.11, x2:  0.78, c3.y:  26.56\n",
      "x1:  0.11, x2:  1.00, c3.y:  34.33\n",
      "x1:  0.22, x2:  0.11, c3.y:   2.56\n",
      "x1:  0.22, x2:  0.33, c3.y:  10.33\n",
      "x1:  0.22, x2:  0.56, c3.y:  18.11\n",
      "x1:  0.22, x2:  0.78, c3.y:  25.89\n",
      "x1:  0.22, x2:  1.00, c3.y:  33.67\n",
      "x1:  0.33, x2:  0.11, c3.y:   1.89\n",
      "x1:  0.33, x2:  0.33, c3.y:   9.67\n",
      "x1:  0.33, x2:  0.56, c3.y:  17.44\n",
      "x1:  0.33, x2:  0.78, c3.y:  25.22\n",
      "x1:  0.33, x2:  1.00, c3.y:  33.00\n",
      "x1:  0.44, x2:  0.11, c3.y:   1.22\n",
      "x1:  0.44, x2:  0.33, c3.y:   9.00\n",
      "x1:  0.44, x2:  0.56, c3.y:  16.78\n",
      "x1:  0.44, x2:  0.78, c3.y:  24.56\n",
      "x1:  0.44, x2:  1.00, c3.y:  32.33\n",
      "x1:  0.56, x2:  0.11, c3.y:   0.56\n",
      "x1:  0.56, x2:  0.33, c3.y:   8.33\n",
      "x1:  0.56, x2:  0.56, c3.y:  16.11\n",
      "x1:  0.56, x2:  0.78, c3.y:  23.89\n",
      "x1:  0.56, x2:  1.00, c3.y:  31.67\n",
      "x1:  0.67, x2:  0.11, c3.y:  -0.11\n",
      "x1:  0.67, x2:  0.33, c3.y:   7.67\n",
      "x1:  0.67, x2:  0.56, c3.y:  15.44\n",
      "x1:  0.67, x2:  0.78, c3.y:  23.22\n",
      "x1:  0.67, x2:  1.00, c3.y:  31.00\n",
      "x1:  0.78, x2:  0.11, c3.y:  -0.78\n",
      "x1:  0.78, x2:  0.33, c3.y:   7.00\n",
      "x1:  0.78, x2:  0.56, c3.y:  14.78\n",
      "x1:  0.78, x2:  0.78, c3.y:  22.56\n",
      "x1:  0.78, x2:  1.00, c3.y:  30.33\n",
      "x1:  0.89, x2:  0.11, c3.y:  -1.44\n",
      "x1:  0.89, x2:  0.33, c3.y:   6.33\n",
      "x1:  0.89, x2:  0.56, c3.y:  14.11\n",
      "x1:  0.89, x2:  0.78, c3.y:  21.89\n",
      "x1:  0.89, x2:  1.00, c3.y:  29.67\n",
      "x1:  1.00, x2:  0.11, c3.y:  -2.11\n",
      "x1:  1.00, x2:  0.33, c3.y:   5.67\n",
      "x1:  1.00, x2:  0.56, c3.y:  13.44\n",
      "x1:  1.00, x2:  0.78, c3.y:  21.22\n",
      "x1:  1.00, x2:  1.00, c3.y:  29.00\n",
      "\n",
      "x1:  0.00, x2:  0.00, c3.y:   0.00\n",
      "x1:  0.00, x2:  0.22, c3.y:   7.78\n",
      "x1:  0.00, x2:  0.44, c3.y:  15.56\n",
      "x1:  0.00, x2:  0.67, c3.y:  23.33\n",
      "x1:  0.00, x2:  0.89, c3.y:  31.11\n",
      "x1:  0.11, x2:  0.00, c3.y:  -0.67\n",
      "x1:  0.11, x2:  0.22, c3.y:   7.11\n",
      "x1:  0.11, x2:  0.44, c3.y:  14.89\n",
      "x1:  0.11, x2:  0.67, c3.y:  22.67\n",
      "x1:  0.11, x2:  0.89, c3.y:  30.44\n",
      "x1:  0.22, x2:  0.00, c3.y:  -1.33\n",
      "x1:  0.22, x2:  0.22, c3.y:   6.44\n",
      "x1:  0.22, x2:  0.44, c3.y:  14.22\n",
      "x1:  0.22, x2:  0.67, c3.y:  22.00\n",
      "x1:  0.22, x2:  0.89, c3.y:  29.78\n",
      "x1:  0.33, x2:  0.00, c3.y:  -2.00\n",
      "x1:  0.33, x2:  0.22, c3.y:   5.78\n",
      "x1:  0.33, x2:  0.44, c3.y:  13.56\n",
      "x1:  0.33, x2:  0.67, c3.y:  21.33\n",
      "x1:  0.33, x2:  0.89, c3.y:  29.11\n",
      "x1:  0.44, x2:  0.00, c3.y:  -2.67\n",
      "x1:  0.44, x2:  0.22, c3.y:   5.11\n",
      "x1:  0.44, x2:  0.44, c3.y:  12.89\n",
      "x1:  0.44, x2:  0.67, c3.y:  20.67\n",
      "x1:  0.44, x2:  0.89, c3.y:  28.44\n",
      "x1:  0.56, x2:  0.00, c3.y:  -3.33\n",
      "x1:  0.56, x2:  0.22, c3.y:   4.44\n",
      "x1:  0.56, x2:  0.44, c3.y:  12.22\n",
      "x1:  0.56, x2:  0.67, c3.y:  20.00\n",
      "x1:  0.56, x2:  0.89, c3.y:  27.78\n",
      "x1:  0.67, x2:  0.00, c3.y:  -4.00\n",
      "x1:  0.67, x2:  0.22, c3.y:   3.78\n",
      "x1:  0.67, x2:  0.44, c3.y:  11.56\n",
      "x1:  0.67, x2:  0.67, c3.y:  19.33\n",
      "x1:  0.67, x2:  0.89, c3.y:  27.11\n",
      "x1:  0.78, x2:  0.00, c3.y:  -4.67\n",
      "x1:  0.78, x2:  0.22, c3.y:   3.11\n",
      "x1:  0.78, x2:  0.44, c3.y:  10.89\n",
      "x1:  0.78, x2:  0.67, c3.y:  18.67\n",
      "x1:  0.78, x2:  0.89, c3.y:  26.44\n",
      "x1:  0.89, x2:  0.00, c3.y:  -5.33\n",
      "x1:  0.89, x2:  0.22, c3.y:   2.44\n",
      "x1:  0.89, x2:  0.44, c3.y:  10.22\n",
      "x1:  0.89, x2:  0.67, c3.y:  18.00\n",
      "x1:  0.89, x2:  0.89, c3.y:  25.78\n",
      "x1:  1.00, x2:  0.00, c3.y:  -6.00\n",
      "x1:  1.00, x2:  0.22, c3.y:   1.78\n",
      "x1:  1.00, x2:  0.44, c3.y:   9.56\n",
      "x1:  1.00, x2:  0.67, c3.y:  17.33\n",
      "x1:  1.00, x2:  0.89, c3.y:  25.11\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from openmdao.utils.notebook_utils import mpi_exec\n",
    "mpi_exec(4, 'mpi_script_1.py')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py312",
   "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"
  },
  "mpi": true,
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 15.086281,
   "end_time": "2026-10-02T14:48:23.649316+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/building_blocks/drivers/analysis_driver.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/drivers/analysis_driver.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:48:08.563035+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}