{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bb8bfde7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:44:38.333335Z",
     "iopub.status.busy": "2026-10-02T14:44:38.333073Z",
     "iopub.status.idle": "2026-10-02T14:44:38.338580Z",
     "shell.execute_reply": "2026-10-02T14:44:38.337556Z"
    },
    "papermill": {
     "duration": 0.008648,
     "end_time": "2026-10-02T14:44:38.339297+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:44:38.330649+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": "b9cb7e94",
   "metadata": {
    "papermill": {
     "duration": 0.001248,
     "end_time": "2026-10-02T14:44:38.442895+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:44:38.441647+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "# Using CSDL Components\n",
    "\n",
    "## CSDL Background\n",
    "\n",
    "CSDL is domain-specific language embedded in Python designed for solving Multidisciplinary Design Analysis and Optimization (MDAO) problems. CSDL enables complete separation between specifying a mathematical model and implementing a numerical simulation of a physical system. Separation between specification and implementation enables engineers to operate at a high level of abstraction, without the need to implement low level algorithms, including derivative computation. It is an open source project created by the [Large-Scale Design Optimization (LSDO) Lab](https://lsdo.eng.ucsd.edu/) in the Department of Mechanical and Aerospace Engineering at the University of California San Diego. To learn more, visit the [CSDL Website](https://csdl-alpha.readthedocs.io/en/latest/).\n",
    "\n",
    "## Using CSDL in OpenMDAO\n",
    "\n",
    "CSDL models can be used directly in OpenMDAO models using the [csdl_om_connect](https://github.com/lsdolab/csdl_om_connect) package, also created by the LSDO Lab. This document explains how to do that by way of an example. In this example, we optimize the thickness (height) distribution of a cantilever beam.\n",
    "\n",
    "The example is based on two existing scripts. The first is a [pure OpenMDAO implementation](https://openmdao.org/newdocs/versions/latest/examples/beam_optimization_example.html) of the beam optimization problem. The second is the same problem solved using [only CSDL](https://modopt.readthedocs.io/en/latest/src/_temp/examples/ex_15_3cantilever_beam_csdl.html).\n",
    "\n",
    "The example below is a hybrid where CSDL is used to define the component, but OpenMDAO defines the problem, the driver, and does the optimization.\n",
    "\n",
    "The first step is to install the `csdl_om_connect` package, which will also install the `CSDL` package. The use of CSDL and csdl_om_connect is optional for OpenMDAO so if not already installed, the user needs to install it by \n",
    "issuing the following command at your operating system command prompt:\n",
    "```\n",
    "pip install git+https://github.com/lsdolab/csdl_om_connect.git@main\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "29ce4896",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:44:38.446746Z",
     "iopub.status.busy": "2026-10-02T14:44:38.446466Z",
     "iopub.status.idle": "2026-10-02T14:44:56.445361Z",
     "shell.execute_reply": "2026-10-02T14:44:56.444649Z"
    },
    "papermill": {
     "duration": 18.002252,
     "end_time": "2026-10-02T14:44:56.446356+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:44:38.444104+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output",
     "active-ipynb"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting git+https://github.com/lsdolab/csdl_om_connect.git@main\r\n",
      "  Cloning https://github.com/lsdolab/csdl_om_connect.git (to revision main) to /tmp/pip-req-build-qg9wbsdj\r\n",
      "  Running command git clone --filter=blob:none --quiet https://github.com/lsdolab/csdl_om_connect.git /tmp/pip-req-build-qg9wbsdj\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Resolved https://github.com/lsdolab/csdl_om_connect.git to commit 323a8ddcc7c8bc80d6e66dcd7492c74144f48508\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Installing build dependencies ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b\\"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b|"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b/"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n",
      "\u001b[?25hCollecting csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git (from csdl_om_connect==0.1.0)\r\n",
      "  Cloning https://github.com/LSDOlab/csdl_alpha.git to /tmp/pip-install-kkdiax4e/csdl-alpha_b873292616f04bb7813419f4570de525\r\n",
      "  Running command git clone --filter=blob:none --quiet https://github.com/LSDOlab/csdl_alpha.git /tmp/pip-install-kkdiax4e/csdl-alpha_b873292616f04bb7813419f4570de525\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Resolved https://github.com/LSDOlab/csdl_alpha.git to commit b3cee4ab8859de3e118e563de322fb81f43d698a\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Installing build dependencies ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b\\"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n",
      "\u001b[?25hCollecting modopt @ git+https://github.com/LSDOlab/modopt.git (from csdl_om_connect==0.1.0)\r\n",
      "  Cloning https://github.com/LSDOlab/modopt.git to /tmp/pip-install-kkdiax4e/modopt_444d5f5b4e72426d964c3f1ada0cb586\r\n",
      "  Running command git clone --filter=blob:none --quiet https://github.com/LSDOlab/modopt.git /tmp/pip-install-kkdiax4e/modopt_444d5f5b4e72426d964c3f1ada0cb586\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Resolved https://github.com/LSDOlab/modopt.git to commit 80b1e1fe0fcf103a5f8bbe53d0479a6563e5413c\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Installing build dependencies ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b\\"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n",
      "\u001b[?25hRequirement already satisfied: openmdao in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_om_connect==0.1.0) (3.45.2.dev0)\r\n",
      "Requirement already satisfied: jax in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_om_connect==0.1.0) (0.11.0)\r\n",
      "Requirement already satisfied: numpy in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (2.4.6)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting sympy (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Downloading sympy-1.14.0-py3-none-any.whl.metadata (12 kB)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting pytest (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n",
      "  Downloading pytest-9.1.1-py3-none-any.whl.metadata (7.6 kB)\r\n",
      "Requirement already satisfied: scipy in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (1.17.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting rustworkx (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Downloading rustworkx-0.18.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (10 kB)\r\n",
      "Requirement already satisfied: networkx in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (3.6.1)\r\n",
      "Requirement already satisfied: h5py in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (3.16.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting pydot (from csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n",
      "  Downloading pydot-4.0.1-py3-none-any.whl.metadata (11 kB)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting array_manager @ git+https://github.com/anugrahjo/array_manager.git@modopt (from modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0)\r\n",
      "  Cloning https://github.com/anugrahjo/array_manager.git (to revision modopt) to /tmp/pip-install-kkdiax4e/array-manager_ef9e633740974513b4b6191a5d7012cb\r\n",
      "  Running command git clone --filter=blob:none --quiet https://github.com/anugrahjo/array_manager.git /tmp/pip-install-kkdiax4e/array-manager_ef9e633740974513b4b6191a5d7012cb\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Running command git checkout -b modopt --track origin/modopt\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Switched to a new branch 'modopt'\r\n",
      "  branch 'modopt' set up to track 'origin/modopt'.\r\n",
      "  Resolved https://github.com/anugrahjo/array_manager.git to commit b5748d5180db3209cc5a0b534ddc072026e655af\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Installing build dependencies ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \b\\"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25l-\b \bdone\r\n",
      "\u001b[?25hRequirement already satisfied: matplotlib<4,>=3.4 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (3.11.1)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: contourpy>=1.0.1 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (1.3.3)\r\n",
      "Requirement already satisfied: cycler>=0.10 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (0.12.1)\r\n",
      "Requirement already satisfied: fonttools>=4.28.2 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (4.63.0)\r\n",
      "Requirement already satisfied: kiwisolver>=1.3.1 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (1.5.0)\r\n",
      "Requirement already satisfied: packaging>=20.0 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (26.3)\r\n",
      "Requirement already satisfied: pillow>=9 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (12.3.0)\r\n",
      "Requirement already satisfied: pyparsing>=3 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (3.3.2)\r\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (2.9.0.post0)\r\n",
      "Requirement already satisfied: six>=1.5 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from python-dateutil>=2.7->matplotlib<4,>=3.4->modopt @ git+https://github.com/LSDOlab/modopt.git->csdl_om_connect==0.1.0) (1.17.0)\r\n",
      "Requirement already satisfied: jaxlib<=0.11.0,>=0.11.0 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from jax->csdl_om_connect==0.1.0) (0.11.0)\r\n",
      "Requirement already satisfied: ml_dtypes>=0.5.0 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from jax->csdl_om_connect==0.1.0) (0.5.4)\r\n",
      "Requirement already satisfied: opt_einsum in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from jax->csdl_om_connect==0.1.0) (3.4.0)\r\n",
      "Requirement already satisfied: requests in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from openmdao->csdl_om_connect==0.1.0) (2.34.2)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting iniconfig>=1.0.1 (from pytest->csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Downloading iniconfig-2.3.0-py3-none-any.whl.metadata (2.5 kB)\r\n",
      "Requirement already satisfied: pluggy<2,>=1.5 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from pytest->csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (1.6.0)\r\n",
      "Requirement already satisfied: pygments>=2.7.2 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from pytest->csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0) (2.20.0)\r\n",
      "Requirement already satisfied: charset_normalizer<4,>=2 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from requests->openmdao->csdl_om_connect==0.1.0) (3.4.9)\r\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from requests->openmdao->csdl_om_connect==0.1.0) (3.18)\r\n",
      "Requirement already satisfied: urllib3<3,>=1.26 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from requests->openmdao->csdl_om_connect==0.1.0) (2.7.0)\r\n",
      "Requirement already satisfied: certifi>=2023.5.7 in /home/runner/work/OpenMDAO/OpenMDAO/.pixi/envs/dev/lib/python3.13/site-packages (from requests->openmdao->csdl_om_connect==0.1.0) (2026.7.22)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting mpmath<1.4,>=1.1.0 (from sympy->csdl_alpha @ git+https://github.com/LSDOlab/csdl_alpha.git->csdl_om_connect==0.1.0)\r\n",
      "  Downloading mpmath-1.3.0-py3-none-any.whl.metadata (8.6 kB)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading pydot-4.0.1-py3-none-any.whl (37 kB)\r\n",
      "Downloading pytest-9.1.1-py3-none-any.whl (386 kB)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading iniconfig-2.3.0-py3-none-any.whl (7.5 kB)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading rustworkx-0.18.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (2.4 MB)\r\n",
      "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/2.4 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m41.0 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m\r\n",
      "\u001b[?25h"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading sympy-1.14.0-py3-none-any.whl (6.3 MB)\r\n",
      "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/6.3 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.3/6.3 MB\u001b[0m \u001b[31m86.2 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m\r\n",
      "\u001b[?25hDownloading mpmath-1.3.0-py3-none-any.whl (536 kB)\r\n",
      "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/536.2 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m536.2/536.2 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m  \u001b[33m0:00:00\u001b[0m\r\n",
      "\u001b[?25h"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Building wheels for collected packages: csdl_om_connect, csdl_alpha\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Building wheel for csdl_om_connect (pyproject.toml) ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n",
      "\u001b[?25h  Created wheel for csdl_om_connect: filename=csdl_om_connect-0.1.0-py3-none-any.whl size=21874 sha256=690b5c99a1071cb31465e907993adadca18dc1528892794b80fb4a438c1e43f0\r\n",
      "  Stored in directory: /tmp/pip-ephem-wheel-cache-qn4cgdus/wheels/a9/b3/0d/780ee49cffd0334215845a8bb3433b1560c65d12b1adca2b55\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Building wheel for csdl_alpha (pyproject.toml) ... \u001b[?25l-"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b \bdone\r\n",
      "\u001b[?25h  Created wheel for csdl_alpha: filename=csdl_alpha-0.1.0-py3-none-any.whl size=292224 sha256=3a16c9f8ef934344eb9b41494437641098b1974b45ae9a207c12055ce6041f6e\r\n",
      "  Stored in directory: /tmp/pip-ephem-wheel-cache-qn4cgdus/wheels/2b/08/23/c0319bf7785b0e5ed29104507dbac7d304dcedf096f9ede981\r\n",
      "Successfully built csdl_om_connect csdl_alpha\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Installing collected packages: mpmath, sympy, rustworkx, pydot, iniconfig, pytest, csdl_alpha, csdl_om_connect\r\n",
      "\u001b[?25l"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r\n",
      "\u001b[?25h\r\n",
      "Successfully installed csdl_alpha-0.1.0 csdl_om_connect-0.1.0 iniconfig-2.3.0 mpmath-1.3.0 pydot-4.0.1 pytest-9.1.1 rustworkx-0.18.1 sympy-1.14.0\r\n"
     ]
    }
   ],
   "source": [
    "!pip install git+https://github.com/lsdolab/csdl_om_connect.git@main"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcea7a18",
   "metadata": {
    "papermill": {
     "duration": 0.14243,
     "end_time": "2026-10-02T14:44:56.591477+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:44:56.449047+00:00",
     "status": "completed"
    },
    "tags": []
   },
   "source": [
    "Using an CSDL Component in OpenMDAO is very simple. You only need to instantiate a `CSDLExplicitComponent` class passing it a CSDL Jax Simulator object and also lists of the input and output variables.\n",
    "\n",
    "The key to using a CSDL Component in OpenMDAO is to make sure the input and output variable names match both when creating the `CSDLExplicitComponent` object and also when setting the design variables, constraints, and objectives on the OpenMDAO driver. \n",
    "\n",
    "Here is the full script of the hybrid example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e7cd53fc",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:44:56.598034Z",
     "iopub.status.busy": "2026-10-02T14:44:56.597793Z",
     "iopub.status.idle": "2026-10-02T14:45:02.542907Z",
     "shell.execute_reply": "2026-10-02T14:45:02.542343Z"
    },
    "papermill": {
     "duration": 5.949705,
     "end_time": "2026-10-02T14:45:02.543752+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:44:56.594047+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1790952299.382950] [runnervm8df0l:8745 :0]        ib_iface.c:1269 UCX  ERROR mana_0: iface 0x563273ef87d0 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",
      "[1790952299.383214] [runnervm8df0l:8745 :0]      ucp_worker.c:1412 UCX  ERROR uct_iface_open(ud_verbs/mana_0:1) failed: Input/output error\n",
      "compiling 'run' function ... (682 nodes)\n",
      "GPU not found: 'Unknown backend: 'gpu' requested, but no platforms that are instances of gpu are present. Platforms present are: cpu', falling back to CPU\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[runnervm8df0l:08745] pml_ucx.c:313  Error: Failed to create UCP worker\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compiling 'compute_totals' function ... (1950 nodes)\n",
      "GPU not found: 'Unknown backend: 'gpu' requested, but no platforms that are instances of gpu are present. Platforms present are: cpu', falling back to CPU\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Optimization terminated successfully    (Exit mode 0)\n",
      "            Current function value: 23762.153677633076\n",
      "            Iterations: 140\n",
      "            Function evaluations: 392\n",
      "            Gradient evaluations: 140\n",
      "Optimization Complete\n",
      "-----------------------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Problem: problem\n",
       "Driver:  ScipyOptimizeDriver\n",
       "  success     : True\n",
       "  iterations  : 393\n",
       "  runtime     : 3.1414E+00 s\n",
       "  model_evals : 393\n",
       "  model_time  : 1.0362E+00 s\n",
       "  deriv_evals : 140\n",
       "  deriv_time  : 1.7432E+00 s\n",
       "  exit_status : SUCCESS"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import openmdao.api as om\n",
    "import csdl_alpha as csdl\n",
    "import numpy as np\n",
    "from csdl_om_connect import CSDLExplicitComponent\n",
    "\n",
    "############\n",
    "# CSDL Model\n",
    "############\n",
    "E0, L0, b0, vol0, F0 = 1.0, 1.0, 0.1, 0.01, -1.0\n",
    "n_el = 50\n",
    "rec = csdl.Recorder()\n",
    "rec.start()\n",
    "\n",
    "### add design variables ###\n",
    "x = csdl.Variable(name=\"x\", shape=(n_el,), value=1.0)\n",
    "\n",
    "### add objective ###\n",
    "E, L, b, vol = E0, L0, b0, vol0\n",
    "L_el = L / n_el\n",
    "n_nodes = n_el + 1\n",
    "\n",
    "# Moment of inertia\n",
    "I = b * x**3 / 12\n",
    "\n",
    "# Force vector\n",
    "F = np.zeros((n_nodes * 2,))\n",
    "F[-2] = F0\n",
    "\n",
    "# Stiffness matrix\n",
    "c_el = (\n",
    "    E\n",
    "    / L_el**3\n",
    "    * np.array(\n",
    "        [\n",
    "            [12, 6 * L_el, -12, 6 * L_el],\n",
    "            [6 * L_el, 4 * L_el**2, -6 * L_el, 2 * L_el**2],\n",
    "            [-12, -6 * L_el, 12, -6 * L_el],\n",
    "            [6 * L_el, 2 * L_el**2, -6 * L_el, 4 * L_el**2],\n",
    "        ]\n",
    "    )\n",
    ")\n",
    "\n",
    "K = csdl.Variable(name=\"K\", value=np.zeros((n_nodes * 2, n_nodes * 2)))\n",
    "for i in range(n_el):\n",
    "    K = K.set(\n",
    "        csdl.slice[2 * i : 2 * i + 4, 2 * i : 2 * i + 4],\n",
    "        K[2 * i : 2 * i + 4, 2 * i : 2 * i + 4] + c_el * I[i],\n",
    "    )\n",
    "u = csdl.solve_linear(K[2:, 2:], F[2:])\n",
    "c = csdl.vdot(F[2:], u)\n",
    "c.add_name(\"compliance\")\n",
    "\n",
    "### add constraints ###\n",
    "v = L_el * b * csdl.sum(x)\n",
    "v.add_name(\"volume\")\n",
    "\n",
    "rec.stop()\n",
    "\n",
    "cantilever_beam_sim = csdl.experimental.JaxSimulator(\n",
    "    recorder=rec,\n",
    "    additional_inputs=[x,],\n",
    "    additional_outputs=[c, v],\n",
    ")\n",
    "\n",
    "################\n",
    "# OpenMDAO Model\n",
    "################\n",
    "\n",
    "# Generate a CSDLExplicitComponent object from a CSDL Jax Simulator\n",
    "# Define input and output names\n",
    "# Both are defined as a list of strings of CSDL variable names.\n",
    "# The names must be valid names of the CSDL variables\n",
    "# exposed as `additional_inputs` and `additional_outputs` in the JaxSimulator.\n",
    "in_names = [\"x\",]\n",
    "out_names = [\"compliance\", \"volume\"]\n",
    "cantilever_beam_comp = CSDLExplicitComponent(\n",
    "    cantilever_beam_sim, in_names=in_names, out_names=out_names\n",
    ")\n",
    "\n",
    "# Define OpenMDAO Problem\n",
    "prob = om.Problem()\n",
    "prob.model.add_subsystem(\"cantilever_beam\", cantilever_beam_comp, promotes=[\"*\"])\n",
    "\n",
    "# Set the design variables, objective, and constraints\n",
    "# Since all the inputs and outputs were promoted, use promoted names\n",
    "prob.model.add_design_var(\"x\", lower=1e-2)\n",
    "prob.model.add_objective(\"compliance\")\n",
    "prob.model.add_constraint(\"volume\", equals=(vol0,))\n",
    "\n",
    "prob.setup()\n",
    "\n",
    "# setup and run the optimization\n",
    "prob.driver = om.ScipyOptimizeDriver(optimizer=\"SLSQP\", tol=1e-9, maxiter=200)\n",
    "prob.run_driver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "63439722",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-02T14:45:02.550232Z",
     "iopub.status.busy": "2026-10-02T14:45:02.549979Z",
     "iopub.status.idle": "2026-10-02T14:45:02.553863Z",
     "shell.execute_reply": "2026-10-02T14:45:02.553283Z"
    },
    "papermill": {
     "duration": 0.007478,
     "end_time": "2026-10-02T14:45:02.554378+00:00",
     "exception": false,
     "start_time": "2026-10-02T14:45:02.546900+00:00",
     "status": "completed"
    },
    "tags": [
     "remove-input",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "# Validate results\n",
    "opt_x = np.array([\n",
    "    0.14915759, 0.14764312, 0.14611338, 0.14456706, 0.14300427,\n",
    "    0.14142408, 0.13982619, 0.13820971, 0.13657403, 0.13491878,\n",
    "    0.13324254, 0.13154527, 0.12982591, 0.12808316, 0.12631659,\n",
    "    0.12452485, 0.122707, 0.12086176, 0.118988, 0.1170842,\n",
    "    0.11514902, 0.11318073, 0.11117753, 0.10913763, 0.10705892,\n",
    "    0.10493904, 0.10277539, 0.10056523, 0.09830546, 0.09599243,\n",
    "    0.09362241, 0.09119077, 0.08869255, 0.08612204, 0.08347229,\n",
    "    0.0807358, 0.07790325, 0.07496383, 0.07190449, 0.0687093,\n",
    "    0.06535832, 0.06182634, 0.05808047, 0.05407656, 0.04975294,\n",
    "    0.04501853, 0.03972914, 0.03363155, 0.02620191, 0.01610863,\n",
    "])\n",
    "opt_compliance = np.array([23762.15367702])\n",
    "assert np.allclose(prob.get_val(\"x\"), opt_x, atol=1e-6)\n",
    "assert np.allclose(prob.get_val(\"compliance\"), opt_compliance, atol=1e-6)\n"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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": 25.971549,
   "end_time": "2026-10-02T14:45:03.574281+00:00",
   "environment_variables": {},
   "exception": null,
   "input_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/openmdao_book/features/experimental/csdl_components.ipynb",
   "output_path": "/home/runner/work/OpenMDAO/OpenMDAO/openmdao/docs/_executed_book/features/experimental/csdl_components.ipynb",
   "parameters": {},
   "start_time": "2026-10-02T14:44:37.602732+00:00",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}