{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "947654b4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:14.598054Z",
     "iopub.status.busy": "2026-10-02T14:41:14.597831Z",
     "iopub.status.idle": "2026-10-02T14:41:14.602466Z",
     "shell.execute_reply": "2026-10-02T14:41:14.601893Z"
    },
    "papermill": {
     "duration": 0.007814,
     "end_time": "2026-10-02T14:41:14.603332+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:14.595518+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "active-ipynb",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    from openmdao.utils.notebook_utils import notebook_mode  # noqa: F401\n",
    "except ImportError:\n",
    "    !python -m pip install openmdao[notebooks]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a67b7694",
   "metadata": {
    "papermill": {
     "duration": 0.001131,
     "end_time": "2026-10-02T14:41:14.605889+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:14.604758+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# DotProductComp\n",
    "\n",
    "`DotProductComp` performs a dot product between two compatible inputs.  It may be vectorized to provide the result at one or more points simultaneously.\n",
    "\n",
    "$$\n",
    "    c_i = \\bar{a}_i \\cdot \\bar{b}_i\n",
    "$$\n",
    "\n",
    "## DotProductComp Options\n",
    "\n",
    "The default `vec_size` is 1, providing the dot product of $a$ and $b$ at a single\n",
    "point.  The lengths of $a$ and $b$ are provided by option `length`.\n",
    "\n",
    "Other options for DotProductComp allow the user to rename the input variables $a$ and $b$ and the output $c$, as well as specifying their units."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4818c371",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:14.609354Z",
     "iopub.status.busy": "2026-10-02T14:41:14.609174Z",
     "iopub.status.idle": "2026-10-02T14:41:15.738053Z",
     "shell.execute_reply": "2026-10-02T14:41:15.737220Z"
    },
    "papermill": {
     "duration": 1.131397,
     "end_time": "2026-10-02T14:41:15.738573+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:14.607176+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<!DOCTYPE html>\n",
       "<html lang=\"en\">\n",
       "<head>\n",
       "    <style>\n",
       "        h2 {\n",
       "            text-align: center;\n",
       "        }\n",
       "    </style>\n",
       "</head>\n",
       "<body>\n",
       "    <h2></h2>\n",
       "        <table style=\"border: 1px solid #999; border-collapse: collapse;\">\n",
       "        <tr><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Option</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Default</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Acceptable Values</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Acceptable Types</th><th style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; background-color: #E9E9E9; text-align: left;\">Description</th></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">a_name</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">a</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The variable name for input vector a.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">a_units</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The units for vector a.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">always_opt</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;\">If True, force nonlinear operations on this component to be included in the optimization loop even if this component is not relevant to the design variables and responses.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">b_name</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">b</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The variable name for input vector b.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">b_units</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The units for vector b.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">c_name</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">c</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The variable name for output vector c.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">c_units</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">N/A</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[&#x27;str&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">The units for vector c.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">default_shape</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;tuple&#x27;]</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">Default shape for variables that do not set val to a non-scalar value or set shape, shape_by_conn, copy_shape, or compute_shape. Default is (1,).</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">derivs_method</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;jax&#x27;, &#x27;cs&#x27;, &#x27;fd&#x27;, None]</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;\">The method to use for computing derivatives</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">distributed</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;\">If True, set all variables in this component as distributed across multiple processes</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">length</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">3</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;\">The length of vectors a and b</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">run_root_only</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;\">If True, call compute, compute_partials, linearize, apply_linear, apply_nonlinear, solve_linear, solve_nonlinear, and compute_jacvec_product only on rank 0 and broadcast the results to the other ranks.</td></tr>\n",
       "       <tr style=\"background-color: ghostwhite;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">use_jit</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">True</td><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">[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;\">If True, attempt to use jit on compute_primal, assuming jax or some other AD package capable of jitting is active.</td></tr>\n",
       "       <tr style=\"background-color: #F3F3F3;\"><td style=\"border: 1px solid #999; border-collapse: collapse; padding: 5px; text-align: left;\">vec_size</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;\">The number of points at which the dot product is computed</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.components.dot_product_comp.DotProductComp\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31d5b3f7",
   "metadata": {
    "papermill": {
     "duration": 0.000859,
     "end_time": "2026-10-02T14:41:15.740630+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:15.739771+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## DotProductComp Constructor\n",
    "\n",
    "The call signature for the `DotProductComp` constructor is:\n",
    "\n",
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.components.dot_product_comp.DotProductComp.__init__\n",
    "        :noindex:\n",
    "```\n",
    "\n",
    "## DotProductComp Usage\n",
    "\n",
    "There are often situations when numerous products need to be computed, essentially in parallel.\n",
    "You can reduce the number of components required by having one `DotProductComp` perform multiple operations.\n",
    "This is also convenient when the different operations have common inputs.\n",
    "\n",
    "The ``add_product`` method is used to create additional products after instantiation.\n",
    "\n",
    "```{eval-rst}\n",
    "    .. automethod:: openmdao.components.dot_product_comp.DotProductComp.add_product\n",
    "       :noindex:\n",
    "```\n",
    "\n",
    "## DotProductComp Example\n",
    "\n",
    "In the following example DotProductComp is used to compute instantaneous power as the\n",
    "dot product of force and velocity at 100 points simultaneously.  Note the use of\n",
    "`a_name`, `b_name`, and `c_name` to assign names to the inputs and outputs.\n",
    "Units are assigned using `a_units`, `b_units`, and `c_units`.\n",
    "Note that no internal checks are performed to ensure that `c_units` are consistent\n",
    "with `a_units` and `b_units`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c1a3b078",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:15.743440Z",
     "iopub.status.busy": "2026-10-02T14:41:15.743055Z",
     "iopub.status.idle": "2026-10-02T14:41:16.986454Z",
     "shell.execute_reply": "2026-10-02T14:41:16.985735Z"
    },
    "papermill": {
     "duration": 1.245336,
     "end_time": "2026-10-02T14:41:16.986923+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:15.741587+00:00",
     "status": "completed"
    },
    "tags": [
     "allow-assert"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952076.974851] [runnervm8df0l:6401 :0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x55f3baabba40 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",
      "[1790952076.975115] [runnervm8df0l:6401 :0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "[0.00097596 0.00168304 0.00043161 0.00018362 0.00036013 0.00083429\n",
      " 0.00015871 0.00034926 0.00100133 0.00115079 0.00062111 0.00049656\n",
      " 0.00063133 0.00060394 0.0009077  0.00079927 0.00109658 0.00033565\n",
      " 0.00039861 0.00067336 0.00065559 0.00108073 0.00165062 0.00055527]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[runnervm8df0l:06401] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import openmdao.api as om\n",
    "\n",
    "n = 24\n",
    "\n",
    "p = om.Problem()\n",
    "\n",
    "dp_comp = om.DotProductComp(vec_size=n, length=3, a_name='F', b_name='v', c_name='P',\n",
    "                            a_units='N', b_units='m/s', c_units='W')\n",
    "\n",
    "p.model.add_subsystem(name='dot_prod_comp', subsys=dp_comp,\n",
    "                     promotes_inputs=[('F', 'force'), ('v', 'vel')])\n",
    "\n",
    "p.setup()\n",
    "\n",
    "p.set_val('force', np.random.rand(n, 3))\n",
    "p.set_val('vel', np.random.rand(n, 3))\n",
    "\n",
    "p.run_model()\n",
    "\n",
    "# Verify the results against numpy.dot in a for loop.\n",
    "expected = []\n",
    "for i in range(n):\n",
    "    a_i = p.get_val('force')[i, :]\n",
    "    b_i = p.get_val('vel')[i, :]\n",
    "    expected.append(np.dot(a_i, b_i))\n",
    "\n",
    "    actual_i = p.get_val('dot_prod_comp.P')[i]\n",
    "    rel_error = np.abs(expected[i] - actual_i)/actual_i\n",
    "    assert rel_error < 1e-9, f\"Relative error: {rel_error}\"\n",
    "\n",
    "print(p.get_val('dot_prod_comp.P', units='kW'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1a629bcd",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:16.990747Z",
     "iopub.status.busy": "2026-10-02T14:41:16.990563Z",
     "iopub.status.idle": "2026-10-02T14:41:16.995124Z",
     "shell.execute_reply": "2026-10-02T14:41:16.994486Z"
    },
    "papermill": {
     "duration": 0.007371,
     "end_time": "2026-10-02T14:41:16.995935+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:16.988564+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(6.920306347550852e-17)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from openmdao.utils.assert_utils import assert_near_equal\n",
    "\n",
    "assert_near_equal(p.get_val('dot_prod_comp.P', units='kW'), np.array(expected)/1000.)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6c2b68f",
   "metadata": {
    "papermill": {
     "duration": 0.001368,
     "end_time": "2026-10-02T14:41:16.998851+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:16.997483+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "## DotProductComp Example with Multiple Products\n",
    "\n",
    "When defining multiple products:\n",
    "\n",
    "- An input name in one call to `add_product` may not be an output name in another call, and vice-versa.\n",
    "- The units and shape of variables used across multiple products must be the same in each one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6dab0237",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:17.002192Z",
     "iopub.status.busy": "2026-10-02T14:41:17.002060Z",
     "iopub.status.idle": "2026-10-02T14:41:17.010712Z",
     "shell.execute_reply": "2026-10-02T14:41:17.009927Z"
    },
    "papermill": {
     "duration": 0.010883,
     "end_time": "2026-10-02T14:41:17.011125+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:17.000242+00:00",
     "status": "completed"
    },
    "tags": [
     "allow-assert"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.00143138 0.0009634  0.00101729 0.00112737 0.00097374 0.00040531\n",
      " 0.00065627 0.00082778 0.00026553 0.00041295 0.00017028 0.000543\n",
      " 0.00039183 0.00068912 0.00104271 0.00062888 0.00091903 0.00060143\n",
      " 0.0009909  0.0003096  0.0004878  0.00083574 0.00136847 0.00134076]\n"
     ]
    }
   ],
   "source": [
    "n = 24\n",
    "\n",
    "p = om.Problem()\n",
    "\n",
    "dp_comp = om.DotProductComp(vec_size=n, length=3,\n",
    "                            a_name='F', b_name='d', c_name='W',\n",
    "                            a_units='N', b_units='m', c_units='J')\n",
    "\n",
    "dp_comp.add_product(vec_size=n, length=3,\n",
    "                    a_name='F', b_name='v', c_name='P',\n",
    "                    a_units='N', b_units='m/s', c_units='W')\n",
    "\n",
    "p.model.add_subsystem(name='dot_prod_comp', subsys=dp_comp,\n",
    "                      promotes_inputs=[('F', 'force'), ('d', 'disp'), ('v', 'vel')])\n",
    "\n",
    "p.setup()\n",
    "\n",
    "p.set_val('force', np.random.rand(n, 3))\n",
    "p.set_val('disp', np.random.rand(n, 3))\n",
    "p.set_val('vel', np.random.rand(n, 3))\n",
    "\n",
    "p.run_model()\n",
    "\n",
    "# Verify the results against numpy.dot in a for loop.\n",
    "expected_P = []\n",
    "expected_W = []\n",
    "for i in range(n):\n",
    "    a_i = p.get_val('force')[i, :]\n",
    "\n",
    "    b_i = p.get_val('disp')[i, :]\n",
    "    expected_W.append(np.dot(a_i, b_i))\n",
    "\n",
    "    actual_i = p.get_val('dot_prod_comp.W')[i]\n",
    "    rel_error = np.abs(actual_i - expected_W[i])/actual_i\n",
    "    assert rel_error < 1e-9, f\"Relative error: {rel_error}\"\n",
    "\n",
    "    b_i = p.get_val('vel')[i, :]\n",
    "    expected_P.append(np.dot(a_i, b_i))\n",
    "\n",
    "    actual_i = p.get_val('dot_prod_comp.P')[i]\n",
    "    rel_error = np.abs(expected_P[i] - actual_i)/actual_i\n",
    "    assert rel_error < 1e-9, f\"Relative error: {rel_error}\"\n",
    "\n",
    "print(p.get_val('dot_prod_comp.W', units='kJ'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "616fdb06",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:17.094453Z",
     "iopub.status.busy": "2026-10-02T14:41:17.094243Z",
     "iopub.status.idle": "2026-10-02T14:41:17.097605Z",
     "shell.execute_reply": "2026-10-02T14:41:17.096872Z"
    },
    "papermill": {
     "duration": 0.085745,
     "end_time": "2026-10-02T14:41:17.098213+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:17.012468+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.13104156e-03 9.25121439e-04 6.23233390e-04 7.38227782e-04\n",
      " 7.52635168e-04 9.59667553e-04 6.37173121e-04 3.26654252e-04\n",
      " 1.02527423e-03 5.49291574e-04 3.75761884e-04 7.61772313e-05\n",
      " 6.27530654e-04 1.40115680e-03 3.96347040e-04 4.34220404e-04\n",
      " 2.34619561e-04 2.34374713e-04 1.22189509e-03 3.30189021e-04\n",
      " 6.64902487e-04 8.05518207e-04 9.39292030e-04 1.36047927e-03]\n"
     ]
    }
   ],
   "source": [
    "print(p.get_val('dot_prod_comp.P', units='kW'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "852b2e7f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:41:17.101829Z",
     "iopub.status.busy": "2026-10-02T14:41:17.101690Z",
     "iopub.status.idle": "2026-10-02T14:41:17.105055Z",
     "shell.execute_reply": "2026-10-02T14:41:17.104389Z"
    },
    "papermill": {
     "duration": 0.005891,
     "end_time": "2026-10-02T14:41:17.105612+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:41:17.099721+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(1.172333996090188e-16)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assert_near_equal(p.get_val('dot_prod_comp.W', units='kJ'), np.array(expected_W)/1000.)\n",
    "assert_near_equal(p.get_val('dot_prod_comp.P', units='kW'), np.array(expected_P)/1000.)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.14"
  },
  "orphan": true,
  "papermill": {
   "default_parameters": {},
   "duration": 3.812091,
   "end_time": "2026-10-02T14:41:17.622291+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/building_blocks/components/dot_product_comp.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/building_blocks/components/dot_product_comp.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:41:13.810200+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}