diff --git a/demo/multiphysics-optimization/demo.ipynb b/demo/multiphysics-optimization/demo.ipynb new file mode 100644 index 00000000..910cf78f --- /dev/null +++ b/demo/multiphysics-optimization/demo.ipynb @@ -0,0 +1,1004 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1313879b", + "metadata": {}, + "source": [ + "# Multi-Physics Pipeline with End-to-End Gradient Optimization\n", + "\n", + "In this tutorial, you will learn how to:\n", + "\n", + "1. Build two independent physics Tesseracts from different domains -- a thermal solver and a structural solver.\n", + "2. Compose them into a two-way coupled pipeline with Tesseract-JAX, where each solver feeds back into the other.\n", + "3. Compute end-to-end gradients through the coupled iteration with `jax.grad`, and validate them against finite differences.\n", + "4. Perform gradient-based optimization of a thermoelastic inverse-design problem using `scipy.optimize`.\n", + "5. Switch to implicit differentiation for constant-memory gradients via the implicit function theorem.\n", + "\n", + "## Context\n", + "\n", + "Many engineering systems are *multi-physics*: their behaviour emerges from the interaction of several physical processes, each usually modelled by its own specialized solver. A classic example is *thermoelasticity* -- a temperature field makes a material expand, the resulting deformation changes the geometry, and the changed geometry in turn changes how heat flows. Neither solver is correct on its own; the answer lives in the coupling between them.\n", + "\n", + "Designing such systems means solving inverse problems through the coupled physics: *what inputs produce the behaviour we want, once everything has settled into equilibrium?* Answering that efficiently requires gradients through the full coupled chain. Traditionally this means either a fragile hand-coded adjoint or rewriting every solver into one monolithic codebase.\n", + "\n", + "Tesseracts offer a different path, and that is what this demo shows:\n", + "\n", + "- **Separation of solvers** --- each physics component is its own Tesseract, with its own implementation, dependencies, and AD strategy. Teams can develop and ship them independently.\n", + "- **Composition with autodiff** --- because each Tesseract exposes its derivatives, Tesseract-JAX wires them into a single differentiable pipeline. `jax.grad` then propagates gradients through the entire two-way coupling automatically --- no manual adjoint, no monolithic rewrite.\n", + "- **JAX interoperability** --- the coupled iteration is expressed with `jax.lax.scan`, and standard JAX and optimization tooling applies directly to the composed pipeline.\n", + "\n", + "We demonstrate this on a thermoelastic inverse-design problem: find the heat-source location and intensity that produce a set of target temperatures, *after* the thermal and structural solvers have reached a coupled equilibrium." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "06fd4954", + "metadata": {}, + "outputs": [], + "source": [ + "# Install additional requirements for this notebook\n", + "%pip install -r requirements.txt -q" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5bb76f54", + "metadata": {}, + "outputs": [], + "source": [ + "import jax\n", + "import jax.numpy as jnp\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from scipy.optimize import minimize\n", + "from tesseract_jax import apply_tesseract\n", + "\n", + "from tesseract_core import Tesseract\n", + "\n", + "jax.config.update(\"jax_enable_x64\", True)" + ] + }, + { + "cell_type": "markdown", + "id": "d5f9d3bd", + "metadata": {}, + "source": [ + "## Step 1: Build and serve the solver Tesseracts\n", + "\n", + "Each solver is a standalone Tesseract module with its own `tesseract_api.py`:\n", + "\n", + "- **`thermal_solver`** solves the 2D steady-state heat equation for a Gaussian heat source. When a displacement field is supplied (from the structural solver), it deforms the mesh accordingly --- this is what makes the coupling two-way.\n", + "- **`structural_solver`** solves 2D linear thermoelasticity: given a temperature field, it returns the displacement and stress fields produced by thermal expansion.\n", + "\n", + "We use the `tesseract build` CLI to build each module into a container image. Building can take a few minutes the first time, as the images bundle their dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e7cbfe3c", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[?25l\u001b[37m⠋\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠙\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠹\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K \u001b[1;2m[\u001b[0m\u001b[34mi\u001b[0m\u001b[1;2m]\u001b[0m Building image \u001b[33m...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[37m⠹\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠸\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠼\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠴\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠦\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠧\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠇\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠏\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠋\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠙\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠹\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠸\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠼\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠴\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠦\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠦\u001b[0m \u001b[37mProcessing\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[?25h\r", + "\u001b[1A\u001b[2K \u001b[1;2m[\u001b[0m\u001b[34mi\u001b[0m\u001b[1;2m]\u001b[0m Built image sh\u001b[1;92ma256:628f\u001b[0m2f2ce6f1, \u001b[1m[\u001b[0m\u001b[32m'thermal-solver:0.1.0'\u001b[0m, \u001b[32m'thermal-solver:latest'\u001b[0m\u001b[1m]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\"thermal-solver:0.1.0\", \"thermal-solver:latest\"]\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[?25l\u001b[37m⠋\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K \u001b[1;2m[\u001b[0m\u001b[34mi\u001b[0m\u001b[1;2m]\u001b[0m Building image \u001b[33m...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[37m⠋\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠙\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠹\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠸\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠼\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠴\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠦\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠧\u001b[0m \u001b[37mProcessing\u001b[0m\r", + "\u001b[2K\u001b[37m⠇\u001b[0m \u001b[37mProcessing\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[?25h\r", + "\u001b[1A\u001b[2K \u001b[1;2m[\u001b[0m\u001b[34mi\u001b[0m\u001b[1;2m]\u001b[0m Built image sh\u001b[1;92ma256:36ae\u001b[0mc53ccce6, \u001b[1m[\u001b[0m\u001b[32m'structural-solver:0.1.0'\u001b[0m, \u001b[32m'structural-solver:latest'\u001b[0m\u001b[1m]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\"structural-solver:0.1.0\", \"structural-solver:latest\"]\n" + ] + } + ], + "source": [ + "%%bash\n", + "# Build both solver Tesseracts into container images\n", + "tesseract build thermal_solver/\n", + "tesseract build structural_solver/" + ] + }, + { + "cell_type": "markdown", + "id": "382df23c", + "metadata": {}, + "source": [ + "Next we load the built images and start a server for each one using the Tesseract Python SDK. This gives us two running Tesseract instances we can call from Python. We keep references to both so we can compose them in the following steps." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5b94d0e0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thermal solver: 2D steady-state heat equation solver with Gaussian source parameterization\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Structural solver: 2D linear thermoelastic stress solver with compliance objective\n" + ] + } + ], + "source": [ + "# Load the built images and start a server for each Tesseract\n", + "thermal = Tesseract.from_image(\"thermal-solver\")\n", + "structural = Tesseract.from_image(\"structural-solver\")\n", + "\n", + "thermal.serve()\n", + "structural.serve()\n", + "\n", + "print(\"Thermal solver:\", thermal.openapi_schema[\"info\"][\"description\"])\n", + "print(\"Structural solver:\", structural.openapi_schema[\"info\"][\"description\"])" + ] + }, + { + "cell_type": "markdown", + "id": "d357b55e", + "metadata": {}, + "source": [ + "## Step 2: Test a forward evaluation with Tesseract-JAX\n", + "\n", + "Before coupling the solvers, let's verify each one works and visualize the physics. The `apply_tesseract` function from [tesseract-jax](https://github.com/pasteurlabs/tesseract-jax) makes a served Tesseract callable as a JAX-compatible function -- which is what later lets us differentiate through it.\n", + "\n", + "We run the thermal solver for a centered heat source, then feed its temperature field into the structural solver to obtain the resulting displacement and stress." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "eb352133", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABWMAAAGPCAYAAAA5ncKaAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAnnFJREFUeJzt3QmYFNW5+P+3umdHGDYFQRAXIioICkJAE/SGiJEYyaLEeAXRkGsibiRERQUTkqBRuPiPRIIJan5XhZhEYtTgVSIaAwbZrhq3uAGibCIMzMBMT1f9n7dI9/QMPcw5XV0z0z3fT56KdM1b1dXVVedUnT71HsfzPE8AAAAAAAAAAKGKhLt6AAAAAAAAAICiMRYAAAAAAAAAmgGNsQAAAAAAAADQDGiMBQAAAAAAAIBmQGMsAAAAAAAAADQDGmMBAAAAAAAAoBnQGAsAAAAAAAAAzYDGWAAAAAAAAABoBjTGAgAAAAAAAEAzoDEWAAAAAAAAAJoBjbEAAAAA2oQXXnhBzj//fOnRo4c4jiNLliwJ/T03b94s//mf/yldunSR0tJSGTBggKxevTr09wUAAK0TjbEAAAAA2oTKykoZOHCgzJs3r1ne79NPP5UzzjhDCgsL5S9/+Yu8/vrrMnv2bOnUqVOzvD8AAGh9HM/zvJbeCAAAAABoTtoz9rHHHpOxY8cm51VXV8vNN98sjzzyiOzatUv69+8vd9xxh5x11lkZvceNN94of//73+Vvf/tbFrccAADkMnrGAgAAAICITJ48WVauXCmLFi2SV155RS688EI599xz5V//+ldG++fxxx+XIUOG+Os54ogj5NRTT5X77ruPfQ0AQBtGz1gAAAAA0tZ7xm7cuFGOPfZY/7+aUzZh1KhRMnToUPnZz35m/R4lJSX+f6dMmeI3yL788sty7bXXyvz582XChAlZ/DQAACBXFLT0BgAAAABAS3v11VclHo/LZz7zmXrzNXWBDr6l3nzzTTnxxBMPuZ4bbrhBbr/9dv/fruv6PWMTDbnaM/a1116jMRYAgDaMNAVAHrnzzjv9Hh3RaFQGDRrkz+vTp49cdtllGfcYue2225qM0xiNBYBcEHaZpWWulr1o2x544AH/OPvggw+a5f2C1Pc4YO/evf411Jo1a2T9+vXJ6Y033pC7777bj9HrLH19qOn73/9+cpceeeSRctJJJ9XbxdqYq71vAeQX03snAKAxFvUqD5Np+fLlbXav/fKXv/Rvrlqj//3f/5Uf/vCH/oi9999/f0aP0gFArjZ4JSZ9JFgfLx49erT8f//f/yd79uxp6U1EiqeeeqpN36i25usIHOi1qj1jt23bJscff3y9qXv37v4uKioqkn79+h1yOvzww5O7U6/L3nrrrXq79+2335ajjz6aXY427ytf+YqUlZUdsq6+5JJL/PPuk08+afbrihdffPGgv+v457169fL//uUvf1nywcMPPyxz585t6c0A2hTSFCDp//2//1dvb/z2t7+VZ5555qD5TT2ale83UV27dm2VPU/++te/SiQSkd/85jf+BUuC3gDofADIZz/+8Y/lmGOOkVgsJlu2bPF/OLzuuutkzpw5/gA6p5xySjL2lltu8Uc4R8s0xs6bN69NNMheeuml8s1vflOKi4tz4jqiLfV+feedd5Kv33//fb/3a+fOnf30BNrwM378eJk9e7bfOLt9+3ZZtmyZX4aMGTPG+v2uv/56GTFihP8j+UUXXSSrVq2SBQsW+BPQ1un59uc//9nP3aznXUNVVVXypz/9yR9EL5EqpLnoj7vaSHnmmWfWm//888/Lhx9+WK9sT9i3b58UFOReE4t+Tk2fotdNAJpH7pUUCM1//ud/1nv90ksv+Y2xDefnC/1Vc//+/VJaWpoX26G9OHQdqQ2xKt2FAgDkmy996Ut+XsaEm266yf+RSnutaM8bfXQ4Uc7qjVIu3iwht+jj7jqhdVm9erWcffbZydc6sJbSwbS0R5w+XfSTn/zETzWwefNmv/H8s5/9bMY94E4//XS/oUnLpMSPRtoDTRuhgLZO6+f27dv7jYHpGmO1IbaysrJFzpfzzjtPHn30Uf8pm9RrBt3WwYMHy44dOxodsC+f6X2r3m/S2QcIhu5ysKKDEOgF5Mknn+xXNt26dZP/+q//kk8//fSgvGV60ao9k/TmWG+ABwwYkExx8Mc//tF/revQymzdunX1ltceI4cddpi89957/qOm7dq18x871YtYbbwMsk1PP/10cpt+9atf+X/TC+//+I//kCOOOMJvvNTcXvfee+9By//zn//0fw1NPLpy1llnHTL/YLp8cYfajl27dvm/SOqjL7od+ljcHXfc4X/GQ9H30M+gFyuJbUs8Bpkuh1ym76P0cR29sdB9fdxxxyW3HQBa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b1//+tet9ztaN8+L+1Omgizb6nhAI6666iq9Qjxo/oIFC7zBgwd7paWlXvv27b0BAwZ4P/zhD72PPvooGXP00Ud7Y8aMOWhZXZ+uN9X777/vz7/zzjuT8yZMmOC1a9fOe/fdd71zzjnHKysr87p16+bNmDHDi8fjWd0m9fjjj3unnHKKV1JS4vXp08e74447vIULF/rbpduXsGXLFn8d+h76t5EjRyb/tmbNGm/YsGFeUVGR17t3b2/OnDne/ffff9A6DrUde/bs8W666Sbv+OOP99fTtWtXb8SIEd5dd93l1dTUpF2m4T5rSN9P/5bJ++i26z5P9fzzz/v7Wpc79thjvfnz5/sxFCe5bffu3f53uHv3Zj1CMpp02QPr2N3SHwdtSKKcTUxaNnXv3t374he/6N19991eRUXFQcs0LLOWLVvmXXDBBV6PHj385fW/F198sff2228nY5577jl/mUceecQvP4844gi/ztHyfMOGDfXWr2Wulr2pfvOb33h9+/b1iouLvX79+vnb3VjZqfXPqaee6sd26tTJr2ueeeaZejG6PaNHj/bKy8v9uuu4447zLrvsMm/16tVN1gu6vpNPPvmg+enqJ5P6Il093lg9Ultb61199dXe4Ycf7jmO02TdEfR64sMPP/S++tWveh07dvT31YUXXuhfG6Sr3/Q40P2un1P3569//Wvv+9//vr9/m3rvdPVtumuAbFxH6HXQj370I+/II4/0j8GzzjrLe+211wLV98isztzyVm+v6qM+GU+6fKb15t69e5PXuRdddJF33nnn8TUi582bN88/J4YOHZr273pv+I1vfMMv07Vs1rgnnniiXkyivn700UfT1hFarh5Kotx9+eWXreun1Lqlurramzp1qjdw4EC/zNf6WP/9y1/+8qB1rVu3zvva177mdenSxa/7dd16Xmu9ZLuuVKbLaXnyrW99y9+v+hkS1zCN7ctsbvd7773nXX755X69q99p586dvbPPPtt79tlnD/nZkJv15rZP7vb2xxZkPOny+XK/6ej/tXSDMNCQ9uDQXhvpHnsAkH36iJA+Grl794ZAA3iVlx/tP45E3lnkm+XLl8vZZ5/tP3WRzadA0Lpp6oh//vOfafOlo+1K1JkfvXVU4AG8epzwYaB6U3MFa49C7QH+ne98J+NtAQAg7Hpzy47ZgQfw6t71+3lxv0ma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ZuoolQMHDvTz8mzbti1tfFVVlV/h3X777Y1Wis8//7xcddVV8tJLL8kzzzwjsVhMzjnnHKmsNB9BFQAA0zQFQSYAANqMLA3g1aFDh3pTwxQFqqioSAYPHizLli2re3vX9V8PHz487ebp/NR4pfeTjcWrDz/80M8Ze+SRR4bfGGvTi0lpzyVNbFtaWup3J77++utl//79mbw1ACCPGmNtR7jUHq933nmn/3hIukpXLV26VC677DI5+eST/cbdBx54QDZu3OgncG8p1JsAkH9ciQSecDDqTADIU1lqjDWlnX7uu+8+efDBB+WNN97wB9vSDjp676nGjx9fr1fttdde699Lzp49288rq6kPVq9eLZMnT/b/vnfvXpk6darf6eeDDz7wG24vuOACOf744/0ORTYKMu3FpDfM2hCrDa36pvoIqD4O2tDDDz8sN954o39jPWLECHn77bf9m2R9vFRvwgEA+ZUz1iSheuoIl6kVYFMjXGZCH11RnTt3lpZAvQkA+SnuOf4UZHnUR50JAHk+fleAnLGe5bLjxo2T7du3y/Tp0/1BuAYNGuQ3tiYG6dIOO3r/maBtltqGecstt/gDc/Xt21eWLFki/fv39/+uaQ9eeeUVv3F3165d0qNHD/8JzJkzZzbaUShrjbGpvZiUNso++eSTfmOrNro2tGLFCjnjjDPkW9/6lv9ae9RefPHF8o9//MP2rQEAOcA0oXomI1za0kdRrrvuOr8eSlSizY16EwAA6kwAQPObPHlysmdrQzroVkMXXnihP6WjT/s//fTTWdkuq2djEr2YtNeSaS8mbVnWZRKpDN577z156qmn5Lzzzgu67QCArIsHSFEQN06o3lw0d+xrr70mixYtapH3p94EgPxFztjsos4EgDzXzGkKWjOrnrGZ9GLSHrG63Jlnnime50ltba1ceeWVfpffxlRXV/tTQuKR16hh63Gh8ScSKbOIbWcY19FinV0sYg/PsdjOIcSWhvXl2qzXRswitso8dJ/hendavL1N7HaL2BKLWD3Hw+CG8JXZZL2uzPI+CPehRm1Q9QLt6UQi9aZkMsKlDf0F9IknnpAXXnhBjjrqKGkJzVFvNlZnegUF4kWbruZrS83PvJhpRaixhxnGdTjQiG+isLzuczbliI57jWOPar/LOPboMvPSsnfxJ8axPQs/NY7tUWAW2yVivr/aR8xL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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Run the thermal solver for a centered heat source\n", + "thermal_out = apply_tesseract(\n", + " thermal,\n", + " {\n", + " \"source_x\": jnp.float32(0.5),\n", + " \"source_y\": jnp.float32(0.5),\n", + " \"source_intensity\": jnp.float32(10.0),\n", + " \"source_width\": np.float32(0.1),\n", + " \"displacement\": jnp.zeros((30, 30, 2), dtype=jnp.float32),\n", + " \"conductivity\": np.float32(1.0),\n", + " \"boundary_temp\": np.float32(0.0),\n", + " },\n", + ")\n", + "temperature = np.asarray(thermal_out[\"temperature\"])\n", + "\n", + "# Feed the temperature field into the structural solver\n", + "structural_out = apply_tesseract(\n", + " structural,\n", + " {\n", + " \"temperature\": thermal_out[\"temperature\"],\n", + " \"youngs_modulus\": np.float32(200.0),\n", + " \"poissons_ratio\": np.float32(0.3),\n", + " \"thermal_expansion\": np.float32(1e-3),\n", + " },\n", + ")\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(14, 4))\n", + "im0 = axes[0].imshow(temperature.T, origin=\"lower\", extent=[0, 1, 0, 1], cmap=\"hot\")\n", + "axes[0].set_title(\"Temperature field\")\n", + "plt.colorbar(im0, ax=axes[0])\n", + "\n", + "disp_mag = np.linalg.norm(np.asarray(structural_out[\"displacement\"]), axis=-1)\n", + "im1 = axes[1].imshow(disp_mag.T, origin=\"lower\", extent=[0, 1, 0, 1], cmap=\"viridis\")\n", + "axes[1].set_title(\"Displacement magnitude\")\n", + "plt.colorbar(im1, ax=axes[1])\n", + "\n", + "s = np.asarray(structural_out[\"stress\"])\n", + "von_mises = np.sqrt(\n", + " s[:, :, 0] ** 2 - s[:, :, 0] * s[:, :, 1] + s[:, :, 1] ** 2 + 3 * s[:, :, 2] ** 2\n", + ")\n", + "im2 = axes[2].imshow(von_mises.T, origin=\"lower\", extent=[0, 1, 0, 1], cmap=\"inferno\")\n", + "axes[2].set_title(\"Von Mises stress\")\n", + "plt.colorbar(im2, ax=axes[2])\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "d2b18a38", + "metadata": {}, + "source": [ + "## Step 3: Set up the thermoelastic inverse problem\n", + "\n", + "Now we pose the inverse-design problem: **find the heat-source location and intensity that produce a set of target temperatures at four sensor locations, after the thermoelastic coupling has converged.**\n", + "\n", + "This cannot be solved with the thermal solver alone. The displacement from thermal expansion deforms the geometry, which changes the temperature field, which changes the displacement, and so on. The two solvers must be iterated to a coupled equilibrium, and the gradients we need run through that entire iteration.\n", + "\n", + "We express the coupled equilibrium as a fixed-point iteration with `jax.lax.scan`: at each step the thermal solver runs on the current displacement, and the structural solver runs on the resulting temperature. The design variables are the source position $(x, y)$ and the log-intensity $\\log(q)$ (3 parameters), and the objective is the squared temperature error at the sensors:\n", + "\n", + "$$\\mathcal{L}(\\theta) = \\sum_i \\left(T_{\\text{sensor}_i} - T_{\\text{target}_i}\\right)^2,$$\n", + "\n", + "evaluated after the coupling has converged." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "080b7e06", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sensor positions (approx):\n", + " (0.26, 0.26) -> T_target = 0.010\n", + " (0.26, 0.71) -> T_target = 0.020\n", + " (0.71, 0.26) -> T_target = 0.020\n", + " (0.71, 0.71) -> T_target = 0.050\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Objective at initial guess: 6.175695e-03\n" + ] + } + ], + "source": [ + "# Sensor locations (grid indices) and target temperatures\n", + "SENSORS = [(8, 8), (8, 22), (22, 8), (22, 22)]\n", + "TARGETS = [jnp.float32(0.01), jnp.float32(0.02), jnp.float32(0.02), jnp.float32(0.05)]\n", + "\n", + "# Approximate physical positions of sensors (for visualization)\n", + "sensor_positions = [(i / 31, j / 31) for i, j in SENSORS]\n", + "print(\"Sensor positions (approx):\")\n", + "for (sx, sy), t in zip(sensor_positions, TARGETS, strict=False):\n", + " print(f\" ({sx:.2f}, {sy:.2f}) -> T_target = {float(t):.3f}\")\n", + "\n", + "N_COUPLING_ITERS = 3\n", + "\n", + "\n", + "def coupled_objective(params):\n", + " \"\"\"Two-way coupled thermoelastic inverse problem.\n", + "\n", + " params: [source_x, source_y, log_intensity]\n", + " Returns: sum of squared temperature errors at sensor locations.\n", + "\n", + " Non-differentiable constants are passed as numpy (np.float32) rather than\n", + " JAX arrays. Inside lax.scan, JAX traces all array inputs uniformly and\n", + " cannot tell which are constants; keeping them as numpy arrays leaves them\n", + " opaque to the tracer, so the backward pass never tries to differentiate them.\n", + " \"\"\"\n", + " source_x, source_y, log_intensity = params[0], params[1], params[2]\n", + " intensity = jnp.exp(log_intensity)\n", + "\n", + " temp = jnp.zeros((30, 30), dtype=jnp.float32)\n", + " disp = jnp.zeros((30, 30, 2), dtype=jnp.float32)\n", + "\n", + " def coupling_step(carry, _):\n", + " _temp, disp = carry\n", + " thermal_out = apply_tesseract(\n", + " thermal,\n", + " {\n", + " \"source_x\": source_x,\n", + " \"source_y\": source_y,\n", + " \"source_intensity\": intensity,\n", + " \"source_width\": np.float32(0.15),\n", + " \"displacement\": disp,\n", + " \"conductivity\": np.float32(1.0),\n", + " \"boundary_temp\": np.float32(0.0),\n", + " },\n", + " )\n", + " structural_out = apply_tesseract(\n", + " structural,\n", + " {\n", + " \"temperature\": thermal_out[\"temperature\"],\n", + " \"youngs_modulus\": np.float32(200.0),\n", + " \"poissons_ratio\": np.float32(0.3),\n", + " \"thermal_expansion\": np.float32(1e-3),\n", + " },\n", + " )\n", + " return (thermal_out[\"temperature\"], structural_out[\"displacement\"]), None\n", + "\n", + " (final_temp, _), _ = jax.lax.scan(\n", + " coupling_step, (temp, disp), None, length=N_COUPLING_ITERS\n", + " )\n", + "\n", + " loss = jnp.float32(0.0)\n", + " for (si, sj), target in zip(SENSORS, TARGETS, strict=False):\n", + " loss = loss + (final_temp[si, sj] - target) ** 2\n", + " return loss\n", + "\n", + "\n", + "# Test the forward pass\n", + "p0 = jnp.array([0.2, 0.2, jnp.log(5.0)], dtype=jnp.float32)\n", + "print(f\"\\nObjective at initial guess: {float(coupled_objective(p0)):.6e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f2853978", + "metadata": {}, + "source": [ + "## Step 4: Compute end-to-end gradients\n", + "\n", + "Because `apply_tesseract` exposes each Tesseract as a native JAX operation, `jax.grad` differentiates through the entire coupled iteration -- through both solvers and through `lax.scan` -- automatically. There is no manual adjoint to derive and no need to merge the solvers into one codebase." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "0a6ee1ac", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Gradients at initial guess:\n", + " d(loss)/d(source_x) = 2.295040e-02\n", + " d(loss)/d(source_y) = 2.295040e-02\n", + " d(loss)/d(log_intensity) = 8.693030e-03\n" + ] + } + ], + "source": [ + "grad_fn = jax.grad(coupled_objective)\n", + "\n", + "grads = grad_fn(p0)\n", + "print(\"Gradients at initial guess:\")\n", + "print(f\" d(loss)/d(source_x) = {float(grads[0]):.6e}\")\n", + "print(f\" d(loss)/d(source_y) = {float(grads[1]):.6e}\")\n", + "print(f\" d(loss)/d(log_intensity) = {float(grads[2]):.6e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "4dc02fe9", + "metadata": {}, + "source": [ + "### Validate the gradients against finite differences\n", + "\n", + "To confirm the end-to-end gradients are correct, we compare them against a central finite-difference approximation of the same objective. The relative error should be small for all three design variables." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fb6b7b25", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " AD FD Rel. Error\n", + "d(loss)/d(source_x) 2.295040e-02 2.296176e-02 4.95e-04\n", + "d(loss)/d(source_y) 2.295040e-02 2.295477e-02 1.90e-04\n", + "d(loss)/d(log_intensity) 8.693030e-03 8.677598e-03 1.78e-03\n" + ] + } + ], + "source": [ + "eps = 1e-4\n", + "fd_grads = []\n", + "for i in range(3):\n", + " p_plus = p0.at[i].add(eps)\n", + " p_minus = p0.at[i].add(-eps)\n", + " fd_grads.append(\n", + " (coupled_objective(p_plus) - coupled_objective(p_minus)) / (2 * eps)\n", + " )\n", + "\n", + "names = [\"d(loss)/d(source_x)\", \"d(loss)/d(source_y)\", \"d(loss)/d(log_intensity)\"]\n", + "print(f\"{'':32s} {'AD':>14s} {'FD':>14s} {'Rel. Error':>12s}\")\n", + "for name, ad, fd in zip(names, grads, fd_grads, strict=False):\n", + " rel_err = abs(float(ad) - float(fd)) / (abs(float(fd)) + 1e-30)\n", + " print(f\"{name:32s} {float(ad):14.6e} {float(fd):14.6e} {rel_err:12.2e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "3a073ba8", + "metadata": {}, + "source": [ + "## Step 5: Optimize the design with gradients\n", + "\n", + "We now solve the inverse problem with a gradient-based optimizer (L-BFGS-B from `scipy.optimize`), feeding it the end-to-end gradients we just validated. For comparison, we also run a gradient-free optimizer (Nelder-Mead) on the same problem. Both search over the same 3 design variables: source position $(x, y)$ and log-intensity." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "28581cfa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running L-BFGS-B (gradient-based)...\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Source: (0.673, 0.673)\n", + " Intensity: 2.73\n", + " Objective: 3.168823e-06\n", + " Evaluations: 29\n", + "\n", + "Running Nelder-Mead (gradient-free)...\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Source: (0.673, 0.673)\n", + " Intensity: 2.73\n", + " Objective: 3.168773e-06\n", + " Evaluations: 250\n", + "\n", + "Speedup: 250/29 = 8.6x fewer evaluations with gradients\n" + ] + } + ], + "source": [ + "eval_history_grad = []\n", + "eval_history_free = []\n", + "\n", + "\n", + "def objective_and_grad(x):\n", + " p = jnp.array(x, dtype=jnp.float32)\n", + " obj = coupled_objective(p)\n", + " g = grad_fn(p)\n", + " eval_history_grad.append(float(obj))\n", + " return float(obj), np.array([float(g[i]) for i in range(3)])\n", + "\n", + "\n", + "def objective_only(x):\n", + " p = jnp.array(x, dtype=jnp.float32)\n", + " obj = coupled_objective(p)\n", + " eval_history_free.append(float(obj))\n", + " return float(obj)\n", + "\n", + "\n", + "x0 = np.array([0.2, 0.2, np.log(5.0)])\n", + "bounds = [(0.05, 0.95), (0.05, 0.95), (np.log(1.0), np.log(50.0))]\n", + "\n", + "print(\"Running L-BFGS-B (gradient-based)...\")\n", + "result_grad = minimize(\n", + " objective_and_grad,\n", + " x0,\n", + " method=\"L-BFGS-B\",\n", + " jac=True,\n", + " bounds=bounds,\n", + " options={\"maxiter\": 100},\n", + ")\n", + "print(f\" Source: ({result_grad.x[0]:.3f}, {result_grad.x[1]:.3f})\")\n", + "print(f\" Intensity: {np.exp(result_grad.x[2]):.2f}\")\n", + "print(f\" Objective: {result_grad.fun:.6e}\")\n", + "print(f\" Evaluations: {len(eval_history_grad)}\")\n", + "\n", + "print(\"\\nRunning Nelder-Mead (gradient-free)...\")\n", + "result_free = minimize(\n", + " objective_only,\n", + " x0,\n", + " method=\"Nelder-Mead\",\n", + " options={\"maxiter\": 500, \"xatol\": 1e-6, \"fatol\": 1e-15},\n", + ")\n", + "print(f\" Source: ({result_free.x[0]:.3f}, {result_free.x[1]:.3f})\")\n", + "print(f\" Intensity: {np.exp(result_free.x[2]):.2f}\")\n", + "print(f\" Objective: {result_free.fun:.6e}\")\n", + "print(f\" Evaluations: {len(eval_history_free)}\")\n", + "\n", + "print(\n", + " f\"\\nSpeedup: {len(eval_history_free)}/{len(eval_history_grad)} \"\n", + " f\"= {len(eval_history_free) / max(len(eval_history_grad), 1):.1f}x fewer evaluations with gradients\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0242ec0f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAHqCAYAAACZcdjsAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAnxZJREFUeJzt3Qd4U2XbB/A76aQtbYGWvQVEtiIqLlBQcOPEjai4QMGtrwru+amgorxuceLE14UKMhRREEQFBNlDWkopdNKVnO/6P+EkJ7NJmzTr/7uu0OTkJDlJTsu5z/3c92PSNE0TIiIiIiKiBjA35MFEREREREQMLIiIiIiIKCiYsSAiIiIiogZjYEFERERERA3GwIKIiIiIiBqMgQURERERETUYAwsiIiIiImowBhZERERERNRgDCyIiIiIiKjBGFgQUdBcccUV0rlzZ6dlJpNJ7r///oj6lN988021Xb/99ptEk6FDh6oLRc++BuvXr5eTTz5ZsrKy1DbOnj1b4k2wv5stW7ao58TvcmMK1+sSRQsGFkQxYPPmzTJhwgTp0aOHpKWlqUuvXr1k/Pjx8ueff0qse++992Tq1Knh3gyKA/XZ18aMGSN//fWXPPLII/L222/L4YcfLrHo66+/jsjArj74N4WofhLr+TgiihBffvmljB49WhITE+WSSy6R/v37i9lslrVr18qnn34qL730kgo8OnXqFJbt279/v9q2UB8ErFq1SiZNmhTS16HIFon7GrZpyZIlcs8996jgP5YhsJg+fbrH4CLY3w3+nuE5k5KSpDG/51C/LlG0Y2BBFMU2btwoF154ofrPbt68edKmTRun+5944gl58cUXVaDhS3l5uaSnp4dkG1NTU0PyvBSd4m1f2717t/qZnZ0d1s8m3IL93WA4Uji+73C9LlG04FAooij25JNPqoORN954wy2oAJwhvOmmm6RDhw5OY9MzMjJUUHLqqadK06ZNVaYDfvzxRzn//POlY8eOkpKSoh538803qzN0rjBOvE+fPuo/Wfz87LPP/B5b/e+//8qVV14prVq1Uq/Tu3dvef31153WWbBggXrshx9+qIaQtG/fXr3WsGHDZMOGDfb1UHPw1VdfydatW9X6uLiOvfemoqJCrr32WmnRooVkZmbK5ZdfLnv37nVa5/PPP5fTTjtN2rZtq7b1oIMOkoceekgsFovbOPpzzz1XWrdurbYT24ugr7i42Gm9d955RwYOHChNmjSR5s2bq3W2b9/utm0vv/yyei2sd8QRR6jvxh/4Lk444QS35VarVdq1ayfnnXeefdkHH3ygtgX7AN5/3759Zdq0aXW+xp49e+Syyy5Tj8EBM4b6/PHHH25jz+N9X8O26JnC22+/3Wl93Ifba9askYsvvliaNWsmxx57bMD7ya+//iojR45U9RsYAjlkyBBZvHix+KOgoECuuuoq9dng/SLb+dZbb3msKfi///s/efbZZ9X7wTbhdXBG3/hdI1uhfw/6xdt3o7//f/75Ry699FK1/bm5uXLfffeJpmnqvZ511llqH8Pv1NNPP+1xu/T9Tf8OPV2M35E/v8++vmdvNRY//PCDHHfccSowxO8Etv3vv/92Wkd/z9in8HlhPbzvsWPHqr9FRLGAGQuiKB8G1a1bNznyyCMDelxtba2MGDFCHcjggAEHJPDRRx+p/+Cuv/56dbC9dOlSef7552XHjh3qPt13332nDqJRx/HYY4+pA03854gDsrrs2rVLjjrqKPUfLIaG4GDim2++UQc4JSUlbkMPHn/8cZVxue2229RBOoIpHJzigAowxATLsY048AEczPoDr4//3PEf/rp169SwMRxM6AcpgAMIPN8tt9yifuIAYvLkyWpbn3rqKbVOdXW1+jyrqqrkxhtvVAdCOKDF97Nv3z518AA4aMWB0wUXXCBXX321OpuNz/f444+X33//3X5W+7XXXlMBz9FHH60+j02bNsmZZ56pDjCNQaInGBaH95Ofn6+2Q/fTTz/Jzp071QEqfP/993LRRRepg2dktgAHQjgonThxotfnR4ByxhlnqH0D+0nPnj3VwRqCC0/ieV8755xz1HeKgAmfNYIr1/URXHXv3l0effRRdUAdyH6CffGUU05RAciUKVPUtuMkw4knnqgCNwSk3iCAwwE0DnLx2XTp0kV97jjgxT7rug/MnDlTSktLVd1WZWWlCkDxOqgdQWCC/RX7F/Yr1JH4C/vrIYccoj57HMw//PDDaj//73//q54f++a7776rvpNBgwapz8ATPIfr6+J94Pe2ZcuW9mX+/D4H+j3PnTtXfQ9du3ZVv3v4bPF9HXPMMbJixQq34BPfKz5v7M+4/9VXX1XbqP8eEkU1jYiiUnFxMY5CtFGjRrndt3fvXm337t32S0VF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IuIhY2GstyAiIopFV1xxhTroe/zxx52W4yAQy6PpgN7T+4DTTjtN3Xf//fdLJPjf//4nu3btkgsvvFDdLioqkhtvvFEOPvhgNfN3x44d5aabbpLi4mKnx+E9uF4++OADp3UWLFgghx12mKSkpEi3bt3kzTfflGiSnJwst912m9x5552N8noMLLwYP368rFmzRpYtW9YoX0SsqnHKWLDGgoiIYl9qaqo88cQTsnfvXol0OKPtTYcOHdwOpP/991+ZN2+etGnTRiLFc889J2PHjhWz2XZYu3PnTnX5v//7P1m1apV6D3PmzJGrrrrK7bFvvPGG5OXl2S+jRo2y37d582YVRJ1wwgmycuVKlTm5+uqr5dtvv5Vocskll8hPP/0kq1evDvlrMbCgkDIOf2KNBRERNbp920V2rnRccDvEhg8fLq1bt5bHHnvM53o42DvuuOPUWXUcxOOsenl5udf1169fL0OGDFGBC0ZVfP/9927rbN++XS644ALJzs6W5s2by1lnnSVbtmxxyqjg4PmRRx6Rtm3bqrP63px++ulSWFgoixcvti9766235OSTT5aWLVs6rVtVVaXOjLdr107S09PlyCOPVGf7dXv27JGLLrpI3Z+WliZ9+/aV999/3+k58N4vv/xyycjIUIHL008/LXXZvXu3/PDDD3LGGWfYl/Xp00c++eQTteyggw6SE088Ub3fL774Qmpra50ej88J35V+wWermzFjhnTp0kVtxyGHHCITJkyQ8847T5599tl6f6//+c9/1Gfjqn///vLggw+q6zipfdJJJ0lOTo5kZWWp73zFihU+g0NsGz4zbH+nTp2c9r1mzZrJMccc45aNCQUGFhRSnHmbiIjCBkHECwNFXh7iuOB2iIOLhIQEefTRR+X555+XHTt2eFxn48aNMnLkSDn33HPlzz//lFmzZqkDUhwgemK1WlXAgKEtv/76qzrodR3eUlNTIyNGjJCmTZvKjz/+qAICHKTjdYyZCWQc1q1bpwKTL7/80uv7wGvhbDfO6utw9v/KK690WxfbvWTJEnXwivdz/vnnq9dFMASVlZUycOBA+eqrr1QW4ZprrpHLLrtMli5dan+O22+/XRYuXCiff/65fPfddyow8XVADfjMEKjgwN8XDIPKzMyUxMREtxEqOIA/4ogj5PXXXxdNc5wQxftBkGiEzxfLvdlYx/eK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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(8, 5))\n", + "ax.semilogy(\n", + " eval_history_grad,\n", + " \"o-\",\n", + " label=f\"L-BFGS-B ({len(eval_history_grad)} evals)\",\n", + " linewidth=2,\n", + " markersize=4,\n", + ")\n", + "ax.semilogy(\n", + " eval_history_free,\n", + " \"s-\",\n", + " label=f\"Nelder-Mead ({len(eval_history_free)} evals)\",\n", + " linewidth=2,\n", + " markersize=3,\n", + ")\n", + "ax.set_xlabel(\"Function evaluations\")\n", + "ax.set_ylabel(\"Objective (sensor temperature error)\")\n", + "ax.set_title(\"Gradient-based vs gradient-free optimization\")\n", + "ax.legend()\n", + "ax.grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "7fbd7f5b", + "metadata": {}, + "source": [ + "## Step 6: Visualize the optimized design\n", + "\n", + "Finally, we run the optimized design through the thermal solver once more and plot the resulting temperature field, overlaying the sensor locations with their achieved and target temperatures and the recovered source position." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "63e93ffe", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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zKgSERERkSExo0pERETkEDOqemFGlYiIiIgMiYEqERERERkSb/0TEREROcRb/3phRpWIiIiIDIkZVSIiIiKHOISqXphRJSIiIiJDypKRI/RMKVzW3Qnv76Xz8iKbxuWzO6EMOXVe3hnryOWEMuTReXmRV+Py+dPBZ3BGGTw8DXBya/2SinFCGSK0LR4Vrr0IdzQuH6C9CLiicflLTiiDM74ntQhzQi5Tf9EuLokxPqURMaNKRERERIaUYTOqREREREnDVv96YUaViIiIiAyJGVUiIiIih5hR1QszqkRERERkSMyoEhERETnEflT1wowqERERERkSM6pEREREDrGOql6YUSUiIiIiQ2JGlYiIiMghZlT1wowqERERERkSM6pEREREDjGjqhdmVImIiIjIkJhRJSIiInKIGVW9MKNKRERERIaUYTOqbgAypXBZdye8v5fG5bM5oQw5NS6fywll0LoOHyeUIa/G5fM7oQwFNS5fyAllKKJx+aIal3fTuhGcsSGcsTPzGODk9nDCIDxahWtb3OO29iIUuq5x+YtOKMN9fb+nnSFU4/KBTshl6o8jU+mFGVUiIiIiMqQMm1ElIiIiSnpeV+7Fuoox8sZGxIwqERERERkSA1UiIiIiMiTe+iciIiJyiLf+9cKMKhEREREZEjOqRERERA4xo6oXZlSJiIiIyJCYUSUiIiJyiB3+64UZVSIiIiIyJGZUiYiIiBKto+rK3B47/E8IM6pEREREZEjMqBIRERE5xIyqXphRJSIiIiJDYkaViIiIyCFmVPXCjCoRERERGVKWjByhpzRK93DC+7trXD67E8qQU+PyuZxQhjwal8/vhDJoXUcRJ5ShuM7LC2+tO6OkxuV9NS7vjDIUMcABlcsAXzAxTihDqMblA5xQhksalz+lvQiFTmhcwfW0vyuypYv28NGWhyvXT/Ywo0pEREREhpRhM6pEREREScORqfTCjCoRERERGRIzqkRERESJ1pTN5MJtZIyauEbEjCoRERERGRIDVSIiIqJEM56ufiTftGnT4OvrCy8vL9SrVw/79+93OP+qVatQsWJFNX+1atWwefPmOK+//fbbyJQpU5xH8+bNdT02GKgSERERpTErVqyAv78/RowYgcOHD6NGjRpo1qwZbt68aXf+PXv2oGPHjujRoweOHDmCNm3aqMeJE3H7UJPA9MaNG7GP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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Run the optimized design through the thermal solver\n", + "opt = result_grad.x\n", + "thermal_opt = apply_tesseract(\n", + " thermal,\n", + " {\n", + " \"source_x\": jnp.float32(opt[0]),\n", + " \"source_y\": jnp.float32(opt[1]),\n", + " \"source_intensity\": jnp.float32(np.exp(opt[2])),\n", + " \"source_width\": np.float32(0.15),\n", + " \"displacement\": jnp.zeros((30, 30, 2), dtype=jnp.float32),\n", + " \"conductivity\": np.float32(1.0),\n", + " \"boundary_temp\": np.float32(0.0),\n", + " },\n", + ")\n", + "temp_opt = np.asarray(thermal_opt[\"temperature\"])\n", + "\n", + "fig, ax = plt.subplots(figsize=(7, 6))\n", + "im = ax.imshow(temp_opt.T, origin=\"lower\", extent=[0, 1, 0, 1], cmap=\"hot\")\n", + "plt.colorbar(im, ax=ax, label=\"Temperature\")\n", + "\n", + "# Plot sensor locations and achieved vs target temperatures\n", + "for (si, sj), target in zip(SENSORS, TARGETS, strict=False):\n", + " px, py = si / 31, sj / 31\n", + " achieved = float(temp_opt[si, sj])\n", + " ax.plot(px, py, \"wo\", markersize=10, markeredgecolor=\"blue\", markeredgewidth=2)\n", + " ax.annotate(\n", + " f\"T={achieved:.3f}\\n(target={float(target):.3f})\",\n", + " xy=(px, py),\n", + " xytext=(5, 5),\n", + " textcoords=\"offset points\",\n", + " fontsize=8,\n", + " color=\"white\",\n", + " fontweight=\"bold\",\n", + " bbox=dict(boxstyle=\"round,pad=0.2\", facecolor=\"black\", alpha=0.7),\n", + " )\n", + "\n", + "# Plot optimized source location\n", + "ax.plot(\n", + " float(opt[0]),\n", + " float(opt[1]),\n", + " \"r*\",\n", + " markersize=20,\n", + " markeredgecolor=\"white\",\n", + " markeredgewidth=1,\n", + ")\n", + "ax.annotate(\n", + " f\"Source\\n({float(opt[0]):.2f}, {float(opt[1]):.2f})\\nq={float(np.exp(opt[2])):.1f}\",\n", + " xy=(float(opt[0]), float(opt[1])),\n", + " xytext=(10, -20),\n", + " textcoords=\"offset points\",\n", + " fontsize=9,\n", + " color=\"red\",\n", + " fontweight=\"bold\",\n", + " bbox=dict(boxstyle=\"round,pad=0.2\", facecolor=\"white\", alpha=0.8),\n", + ")\n", + "\n", + "ax.set_title(\"Optimized temperature field with sensor locations\")\n", + "ax.set_xlabel(\"x\")\n", + "ax.set_ylabel(\"y\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "afa3d626", + "metadata": {}, + "source": [ + "## Step 7: Constant-memory gradients with implicit differentiation\n", + "\n", + "The unrolled `lax.scan` above stores every intermediate state for backpropagation, so memory grows as $\\mathcal{O}(N)$ in the number of coupling iterations. For large problems -- fine meshes, many iterations -- that becomes the bottleneck.\n", + "\n", + "*Implicit differentiation* avoids it. At the converged fixed point $(T^*, D^*) = G(T^*, D^*, \\theta)$, the implicit function theorem gives the sensitivity without replaying the iteration: the backward pass solves a single linear system instead of backpropagating through $N$ steps.\n", + "\n", + "Concretely, if $v = \\partial \\mathcal{L} / \\partial (T^*, D^*)$ is the loss gradient with respect to the fixed point, then\n", + "\n", + "$$\\lambda = \\left(I - \\partial G / \\partial (T, D)\\right)^{-T} v, \\qquad \\partial \\mathcal{L} / \\partial \\theta = \\lambda^\\top \\, \\partial G / \\partial \\theta.$$\n", + "\n", + "We solve for $\\lambda$ by fixed-point iteration on the adjoint equation -- the same structure as the forward solve, but linear. We wrap this in a `jax.custom_vjp` so that `jax.grad` uses the implicit backward pass automatically, while the forward pass still composes the two Tesseracts through `apply_tesseract`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "ba1d047e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Forward pass comparison:\n", + " Unrolled: 6.1756954528e-03\n", + " Implicit: 6.1756954528e-03\n", + " Match: True\n" + ] + } + ], + "source": [ + "def coupled_objective_implicit(params):\n", + " \"\"\"Same inverse problem, but differentiated via the implicit function theorem.\n", + "\n", + " Forward pass: iterate G to convergence (no scan intermediates stored for AD).\n", + " Backward pass: solve adjoint equation (I - dG/d(T,D))^T λ = v via fixed-point iteration.\n", + " \"\"\"\n", + " source_x, source_y, log_intensity = params[0], params[1], params[2]\n", + " intensity = jnp.exp(log_intensity)\n", + "\n", + " def G(temp_disp, params_inner):\n", + " \"\"\"One coupling step: (temp, disp) -> (new_temp, new_disp).\n", + "\n", + " params_inner is (source_x, source_y, intensity) — the differentiable parameters.\n", + " \"\"\"\n", + " _temp, disp = temp_disp\n", + " sx, sy, q = params_inner\n", + " thermal_out = apply_tesseract(\n", + " thermal,\n", + " {\n", + " \"source_x\": sx,\n", + " \"source_y\": sy,\n", + " \"source_intensity\": q,\n", + " \"source_width\": np.float32(0.15),\n", + " \"displacement\": disp,\n", + " \"conductivity\": np.float32(1.0),\n", + " \"boundary_temp\": np.float32(0.0),\n", + " },\n", + " )\n", + " structural_out = apply_tesseract(\n", + " structural,\n", + " {\n", + " \"temperature\": thermal_out[\"temperature\"],\n", + " \"youngs_modulus\": np.float32(200.0),\n", + " \"poissons_ratio\": np.float32(0.3),\n", + " \"thermal_expansion\": np.float32(1e-3),\n", + " },\n", + " )\n", + " return (thermal_out[\"temperature\"], structural_out[\"displacement\"])\n", + "\n", + " @jax.custom_vjp\n", + " def solve_fixed_point(params_inner):\n", + " \"\"\"Run fixed-point iteration to convergence, return the fixed point.\"\"\"\n", + " temp = jnp.zeros((30, 30), dtype=jnp.float32)\n", + " disp = jnp.zeros((30, 30, 2), dtype=jnp.float32)\n", + "\n", + " def step(carry, _):\n", + " return G(carry, params_inner), None\n", + "\n", + " (final_temp, final_disp), _ = jax.lax.scan(\n", + " step, (temp, disp), None, length=N_COUPLING_ITERS\n", + " )\n", + " return (final_temp, final_disp)\n", + "\n", + " def solve_fwd(params_inner):\n", + " fixed_point = solve_fixed_point(params_inner)\n", + " # Save fixed point and params for backward pass (NOT intermediates)\n", + " return fixed_point, (fixed_point, params_inner)\n", + "\n", + " def solve_bwd(res, g):\n", + " \"\"\"Implicit differentiation backward pass.\n", + "\n", + " g = (v_temp, v_disp) — cotangents w.r.t. the fixed point.\n", + "\n", + " We need to solve: (I - dG/d(T,D))^T λ = v for λ,\n", + " then compute: dL/dθ = λ^T · dG/dθ.\n", + "\n", + " We solve for λ by iterating: λ_{k+1} = v + (dG/d(T,D))^T λ_k.\n", + " This converges if the forward iteration is contractive.\n", + " \"\"\"\n", + " (fixed_temp, fixed_disp), params_inner = res\n", + " v_temp, v_disp = g\n", + "\n", + " # Define G_state: maps (temp, disp) -> (new_temp, new_disp) at fixed params\n", + " def G_state(temp_disp):\n", + " return G(temp_disp, params_inner)\n", + "\n", + " # Solve adjoint: λ = v + (dG/d(T,D))^T λ via fixed-point iteration\n", + " def adjoint_step(lam, _):\n", + " lam_temp, lam_disp = lam\n", + " # Compute (dG/d(T,D))^T @ λ via VJP\n", + " _, vjp_G_state = jax.vjp(G_state, (fixed_temp, fixed_disp))\n", + " dGT_lam = vjp_G_state((lam_temp, lam_disp))[0]\n", + " # λ_{k+1} = v + (dG/d(T,D))^T λ_k\n", + " new_lam_temp = v_temp + dGT_lam[0]\n", + " new_lam_disp = v_disp + dGT_lam[1]\n", + " return (new_lam_temp, new_lam_disp), None\n", + "\n", + " N_ADJOINT_ITERS = 20 # typically converges faster than forward\n", + " lam_init = (v_temp, v_disp)\n", + " (lam_temp, lam_disp), _ = jax.lax.scan(\n", + " adjoint_step, lam_init, None, length=N_ADJOINT_ITERS\n", + " )\n", + "\n", + " # Now compute dL/dθ = λ^T · dG/dθ via VJP of G w.r.t. params\n", + " def G_params(p):\n", + " return G((fixed_temp, fixed_disp), p)\n", + "\n", + " _, vjp_G_params = jax.vjp(G_params, params_inner)\n", + " grad_params = vjp_G_params((lam_temp, lam_disp))[0]\n", + " return (grad_params,)\n", + "\n", + " solve_fixed_point.defvjp(solve_fwd, solve_bwd)\n", + "\n", + " # --- Use the implicit fixed-point solve ---\n", + " final_temp, _final_disp = solve_fixed_point((source_x, source_y, intensity))\n", + "\n", + " loss = jnp.float32(0.0)\n", + " for (si, sj), target in zip(SENSORS, TARGETS, strict=False):\n", + " loss = loss + (final_temp[si, sj] - target) ** 2\n", + " return loss\n", + "\n", + "\n", + "# Verify forward pass matches the unrolled version\n", + "loss_implicit = coupled_objective_implicit(p0)\n", + "loss_unrolled = coupled_objective(p0)\n", + "print(\"Forward pass comparison:\")\n", + "print(f\" Unrolled: {float(loss_unrolled):.10e}\")\n", + "print(f\" Implicit: {float(loss_implicit):.10e}\")\n", + "print(f\" Match: {jnp.allclose(loss_unrolled, loss_implicit)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "eeed02dd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unrolled Implicit FD Impl vs FD\n", + "d(loss)/d(source_x) 2.295040e-02 2.295042e-02 2.296176e-02 4.94e-04\n", + "d(loss)/d(source_y) 2.295040e-02 2.295042e-02 2.295477e-02 1.90e-04\n", + "d(loss)/d(log_intensity) 8.693030e-03 8.693032e-03 8.677598e-03 1.78e-03\n" + ] + } + ], + "source": [ + "# Compare gradients: implicit vs unrolled vs finite differences\n", + "grad_implicit = jax.grad(coupled_objective_implicit)(p0)\n", + "grad_unrolled = jax.grad(coupled_objective)(p0)\n", + "\n", + "# Finite differences as ground truth\n", + "eps = 1e-4\n", + "fd_grads_check = []\n", + "for i in range(3):\n", + " p_plus = p0.at[i].add(eps)\n", + " p_minus = p0.at[i].add(-eps)\n", + " fd_grads_check.append(\n", + " (coupled_objective_implicit(p_plus) - coupled_objective_implicit(p_minus))\n", + " / (2 * eps)\n", + " )\n", + "\n", + "names = [\"d(loss)/d(source_x)\", \"d(loss)/d(source_y)\", \"d(loss)/d(log_intensity)\"]\n", + "print(f\"{'':32s} {'Unrolled':>14s} {'Implicit':>14s} {'FD':>14s} {'Impl vs FD':>12s}\")\n", + "for name, u, im, fd in zip(\n", + " names, grad_unrolled, grad_implicit, fd_grads_check, strict=False\n", + "):\n", + " rel_err = abs(float(im) - float(fd)) / (abs(float(fd)) + 1e-30)\n", + " print(\n", + " f\"{name:32s} {float(u):14.6e} {float(im):14.6e} {float(fd):14.6e} {rel_err:12.2e}\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "3ffc182c", + "metadata": {}, + "source": [ + "### Why this matters: memory scaling\n", + "\n", + "With the unrolled approach, JAX stores the full state at every coupling iteration for backpropagation, so memory scales as $\\mathcal{O}(N \\times \\text{state size})$.\n", + "\n", + "With implicit differentiation, the forward pass runs to convergence and discards the intermediates; the backward pass solves the adjoint equation at the fixed point only, with no replay of the iteration. Memory scales as $\\mathcal{O}(\\text{state size})$, independent of $N$.\n", + "\n", + "For this 30×30 demo the difference is negligible, but for production-scale problems -- large meshes and many coupling iterations -- it is what keeps the backward pass within the available memory." + ] + }, + { + "cell_type": "markdown", + "id": "0f1e401b", + "metadata": {}, + "source": [ + "## Takeaways\n", + "\n", + "In this tutorial, we composed two independent physics Tesseracts into a two-way coupled pipeline and solved a thermoelastic inverse-design problem with end-to-end gradients. The key points:\n", + "\n", + "1. **Independent solvers, composed.** The thermal and structural solvers are separate Tesseracts -- separate `tesseract_api.py`, separate container, separate dependencies. Tesseract-JAX wires them into one differentiable pipeline with `apply_tesseract`, no monolithic rewrite required.\n", + "\n", + "2. **Gradients through two-way coupling.** The coupled equilibrium is a `jax.lax.scan` over alternating solver calls. Because each Tesseract exposes its derivatives, `jax.grad` propagates gradients through the entire iteration automatically, and the result matches finite differences.\n", + "\n", + "3. **Gradients make optimization tractable.** Using the end-to-end gradients, L-BFGS-B solves the inverse problem in far fewer evaluations than the gradient-free Nelder-Mead baseline.\n", + "\n", + "4. **Implicit differentiation for scale.** Wrapping the coupled solve in a `jax.custom_vjp` and solving the adjoint equation at the fixed point gives constant-memory gradients -- $\\mathcal{O}(1)$ in coupling iterations instead of $\\mathcal{O}(N)$ -- without changing the forward composition.\n", + "\n", + "5. **The pattern generalizes.** Wrap each physics component as a Tesseract, compose with `apply_tesseract`, and differentiate with JAX. The same recipe applies to any multi-component, multi-physics differentiable pipeline." + ] + }, + { + "cell_type": "markdown", + "id": "a5df9f57", + "metadata": {}, + "source": [ + "### What's next\n", + "\n", + "- **Add more physics.** Introduce a third coupled solver (e.g. a fluid or electromagnetic field) and let the gradients flow through all of them.\n", + "- **Scale up.** Increase the mesh resolution and the number of coupling iterations, and run the Tesseracts on a GPU.\n", + "- **Swap an implementation.** Because the pipeline composes Tesseracts by reference, you can replace a solver with a different image -- a higher-fidelity model or a learned surrogate -- without touching the optimization code.\n", + "- **Explore other demos.** See the [shape optimization](fem-shape-optimization.ipynb) and [data assimilation](data-assimilation.ipynb) demos for other ways to compose Tesseracts with JAX.\n", + "\n", + "Questions? Feedback? Please reach out through the [Tesseract Community Forum](https://si-tesseract.discourse.group/)." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "fd545d2b", + "metadata": {}, + "outputs": [], + "source": [ + "# Shut down the Tesseract servers\n", + "thermal.teardown()\n", + "structural.teardown()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/demo/multiphysics-optimization/requirements.txt b/demo/multiphysics-optimization/requirements.txt new file mode 100644 index 00000000..1e4b0690 --- /dev/null +++ b/demo/multiphysics-optimization/requirements.txt @@ -0,0 +1,6 @@ +jax[cpu]==0.5.2 +equinox==0.13.6 +matplotlib==3.10.9 +scipy==1.17.1 +tesseract-jax==0.3.0 +tesseract-core[runtime] diff --git a/demo/multiphysics-optimization/structural_solver/tesseract_api.py b/demo/multiphysics-optimization/structural_solver/tesseract_api.py new file mode 100644 index 00000000..8c82ab8a --- /dev/null +++ b/demo/multiphysics-optimization/structural_solver/tesseract_api.py @@ -0,0 +1,273 @@ +# Copyright 2025 Pasteur Labs. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Structural solver Tesseract: 2D linear thermoelastic stress on a rectangular plate. + +Given a temperature field, computes thermal strain, solves for displacement +via a finite-difference discretization of the linear elasticity equations, +and returns the stress field, displacement, and a scalar objective +(compliance = u^T K u, a standard structural optimization objective). + +The displacement output feeds back to the thermal solver for two-way coupling. +""" + +from typing import Any + +import equinox as eqx +import jax +import jax.numpy as jnp +from pydantic import BaseModel, Field + +from tesseract_core.runtime import Array, Differentiable, Float32 +from tesseract_core.runtime.tree_transforms import filter_func, flatten_with_paths + +NX = 30 +NY = 30 + + +class InputSchema(BaseModel): + temperature: Differentiable[Array[(NX, NY), Float32]] = Field( + description="Temperature field from thermal solver (NX x NY)" + ) + youngs_modulus: Float32 = Field(description="Young's modulus", default=200.0) + poissons_ratio: Float32 = Field(description="Poisson's ratio", default=0.3) + thermal_expansion: Float32 = Field( + description="Coefficient of thermal expansion", default=1e-3 + ) + + +class OutputSchema(BaseModel): + displacement: Differentiable[Array[(NX, NY, 2), Float32]] = Field( + description="Displacement field (NX x NY x 2)" + ) + stress: Differentiable[Array[(NX, NY, 3), Float32]] = Field( + description="Stress field (NX x NY x 3: sigma_xx, sigma_yy, sigma_xy)" + ) + objective: Differentiable[Array[(), Float32]] = Field( + description="Scalar compliance objective" + ) + + +def _compute_strain_from_displacement(u, dx, dy): + """Compute strain tensor components from displacement field via central differences.""" + ux = u[:, :, 0] + uy = u[:, :, 1] + + # Strain: eps_xx = du_x/dx, eps_yy = du_y/dy, eps_xy = 0.5*(du_x/dy + du_y/dx) + eps_xx = jnp.gradient(ux, dx, axis=0) + eps_yy = jnp.gradient(uy, dy, axis=1) + eps_xy = 0.5 * (jnp.gradient(ux, dy, axis=1) + jnp.gradient(uy, dx, axis=0)) + + return eps_xx, eps_yy, eps_xy + + +def _thermal_strain(temperature, alpha): + """Isotropic thermal strain: eps_thermal = alpha * T.""" + return alpha * temperature + + +def _stress_from_strain(eps_xx, eps_yy, eps_xy, eps_thermal, E, nu): + """Plane stress constitutive relation with thermal strain.""" + # Mechanical strain = total strain - thermal strain + mech_xx = eps_xx - eps_thermal + mech_yy = eps_yy - eps_thermal + mech_xy = eps_xy # thermal strain is isotropic, no shear component + + # Plane stress stiffness + c = E / (1 - nu**2) + sigma_xx = c * (mech_xx + nu * mech_yy) + sigma_yy = c * (nu * mech_xx + mech_yy) + sigma_xy = E / (2 * (1 + nu)) * 2 * mech_xy + + return sigma_xx, sigma_yy, sigma_xy + + +def _solve_elasticity_jacobi(temperature, E, nu, alpha, n_iters=500): + """Solve 2D linear elasticity with thermal loading via damped Jacobi. + + Simplified: treats the thermal load as a body force and iterates + the equilibrium equations on a staggered grid. + """ + nx, ny = temperature.shape + dx = 1.0 / (nx + 1) + dy = 1.0 / (ny + 1) + + # Lame parameters for plane stress + mu = E / (2 * (1 + nu)) + lam = E * nu / ((1 + nu) * (1 - nu)) # plane stress effective lambda + + # Thermal body force: f_i = -(lambda + 2*mu) * alpha * dT/dx_i + thermal_coeff = (lam + 2 * mu) * alpha + fx = thermal_coeff * jnp.gradient(temperature, dx, axis=0) + fy = thermal_coeff * jnp.gradient(temperature, dy, axis=1) + + # Padded displacement (zero Dirichlet BCs) + u = jnp.zeros((nx + 2, ny + 2, 2)) + omega = 0.6 # relaxation factor + + def iteration(u, _): + ux = u[:, :, 0] + uy = u[:, :, 1] + + # Equilibrium: (lambda + 2*mu) * d2u_x/dx2 + mu * d2u_x/dy2 + # + (lambda + mu) * d2u_y/dxdy = -fx + # Simplified Jacobi update for ux on interior + ux_new = ( + (lam + 2 * mu) * (ux[2:, 1:-1] + ux[:-2, 1:-1]) / dx**2 + + mu * (ux[1:-1, 2:] + ux[1:-1, :-2]) / dy**2 + + fx + ) / (2 * (lam + 2 * mu) / dx**2 + 2 * mu / dy**2) + + uy_new = ( + mu * (uy[2:, 1:-1] + uy[:-2, 1:-1]) / dx**2 + + (lam + 2 * mu) * (uy[1:-1, 2:] + uy[1:-1, :-2]) / dy**2 + + fy + ) / (2 * mu / dx**2 + 2 * (lam + 2 * mu) / dy**2) + + u_interior = jnp.stack([ux_new, uy_new], axis=-1) + u_new = u.at[1:-1, 1:-1].set(omega * u_interior + (1 - omega) * u[1:-1, 1:-1]) + return u_new, None + + u_final, _ = jax.lax.scan(iteration, u, None, length=n_iters) + return u_final[1:-1, 1:-1] + + +@eqx.filter_jit +def apply_jit(inputs: dict) -> dict: + temperature = inputs["temperature"] + E = inputs["youngs_modulus"] + nu = inputs["poissons_ratio"] + alpha = inputs["thermal_expansion"] + + dx = 1.0 / (NX + 1) + dy = 1.0 / (NY + 1) + + # Solve for displacement + displacement = _solve_elasticity_jacobi(temperature, E, nu, alpha) + + # Compute strain and stress + eps_xx, eps_yy, eps_xy = _compute_strain_from_displacement(displacement, dx, dy) + eps_thermal = _thermal_strain(temperature, alpha) + sigma_xx, sigma_yy, sigma_xy = _stress_from_strain( + eps_xx, eps_yy, eps_xy, eps_thermal, E, nu + ) + + stress = jnp.stack([sigma_xx, sigma_yy, sigma_xy], axis=-1) + + # Compliance objective: sum of squared displacement weighted by stiffness + # (simplified proxy for u^T K u) + objective = jnp.sum(displacement**2) + + return { + "displacement": displacement.astype(jnp.float32), + "stress": stress.astype(jnp.float32), + "objective": objective.astype(jnp.float32), + } + + +def apply(inputs: InputSchema) -> OutputSchema: + return apply_jit(inputs.model_dump()) + + +def abstract_eval(abstract_inputs: Any) -> Any: + is_shapedtype_dict = lambda x: type(x) is dict and (x.keys() == {"shape", "dtype"}) + is_shapedtype_struct = lambda x: isinstance(x, jax.ShapeDtypeStruct) + + jaxified_inputs = jax.tree.map( + lambda x: jax.ShapeDtypeStruct(**x) if is_shapedtype_dict(x) else x, + abstract_inputs.model_dump(), + is_leaf=is_shapedtype_dict, + ) + dynamic_inputs, static_inputs = eqx.partition( + jaxified_inputs, filter_spec=is_shapedtype_struct + ) + + def wrapped_apply(dynamic_inputs: Any) -> Any: + inputs = eqx.combine(static_inputs, dynamic_inputs) + return apply_jit(inputs) + + jax_shapes = jax.eval_shape(wrapped_apply, dynamic_inputs) + return jax.tree.map( + lambda x: ( + {"shape": x.shape, "dtype": str(x.dtype)} if is_shapedtype_struct(x) else x + ), + jax_shapes, + is_leaf=is_shapedtype_struct, + ) + + +@eqx.filter_jit +def jvp_jit( + inputs: dict, + jvp_inputs: tuple[str], + jvp_outputs: tuple[str], + tangent_vector: dict, +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, jvp_outputs) + return jax.jvp( + filtered_apply, + [flatten_with_paths(inputs, include_paths=jvp_inputs)], + [tangent_vector], + )[1] + + +def jacobian_vector_product( + inputs: InputSchema, + jvp_inputs: set[str], + jvp_outputs: set[str], + tangent_vector: dict[str, Any], +) -> Any: + return jvp_jit( + inputs.model_dump(), + tuple(jvp_inputs), + tuple(jvp_outputs), + tangent_vector, + ) + + +@eqx.filter_jit +def vjp_jit( + inputs: dict, + vjp_inputs: tuple[str], + vjp_outputs: tuple[str], + cotangent_vector: dict, +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, vjp_outputs) + _, vjp_func = jax.vjp( + filtered_apply, flatten_with_paths(inputs, include_paths=vjp_inputs) + ) + return vjp_func(cotangent_vector)[0] + + +def vector_jacobian_product( + inputs: InputSchema, + vjp_inputs: set[str], + vjp_outputs: set[str], + cotangent_vector: dict[str, Any], +) -> Any: + return vjp_jit( + inputs.model_dump(), + tuple(vjp_inputs), + tuple(vjp_outputs), + cotangent_vector, + ) + + +@eqx.filter_jit +def jac_jit( + inputs: dict, + jac_inputs: tuple[str], + jac_outputs: tuple[str], +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, jac_outputs) + return jax.jacrev(filtered_apply)( + flatten_with_paths(inputs, include_paths=jac_inputs) + ) + + +def jacobian( + inputs: InputSchema, + jac_inputs: set[str], + jac_outputs: set[str], +) -> Any: + return jac_jit(inputs.model_dump(), tuple(jac_inputs), tuple(jac_outputs)) diff --git a/demo/multiphysics-optimization/structural_solver/tesseract_config.yaml b/demo/multiphysics-optimization/structural_solver/tesseract_config.yaml new file mode 100644 index 00000000..0d123698 --- /dev/null +++ b/demo/multiphysics-optimization/structural_solver/tesseract_config.yaml @@ -0,0 +1,6 @@ +name: "structural-solver" +version: "0.1.0" +description: "2D linear thermoelastic stress solver with compliance objective" + +build_config: + target_platform: "native" diff --git a/demo/multiphysics-optimization/structural_solver/tesseract_requirements.txt b/demo/multiphysics-optimization/structural_solver/tesseract_requirements.txt new file mode 100644 index 00000000..8f33da03 --- /dev/null +++ b/demo/multiphysics-optimization/structural_solver/tesseract_requirements.txt @@ -0,0 +1,2 @@ +jax[cpu]==0.5.2 +equinox diff --git a/demo/multiphysics-optimization/test_solvers.py b/demo/multiphysics-optimization/test_solvers.py new file mode 100644 index 00000000..29e34176 --- /dev/null +++ b/demo/multiphysics-optimization/test_solvers.py @@ -0,0 +1,260 @@ +"""Smoke tests for multiphysics demo solvers.""" + +import sys + +sys.path.insert(0, "thermal_solver") +sys.path.insert(0, "structural_solver") + +import jax +import jax.numpy as jnp + +jax.config.update("jax_enable_x64", True) + +import structural_solver.tesseract_api as structural_api # noqa: E402 +import thermal_solver.tesseract_api as thermal_api # noqa: E402 + + +def test_thermal_forward(): + print("=== Thermal solver forward pass ===") + from thermal_solver.tesseract_api import InputSchema as ThermalInput + + inputs = ThermalInput( + source_x=0.5, + source_y=0.5, + source_intensity=10.0, + displacement=jnp.zeros((30, 30, 2), dtype=jnp.float32), + ) + out = thermal_api.apply(inputs) + temp = out["temperature"] + print( + f" Shape: {temp.shape}, range: [{float(temp.min()):.4f}, {float(temp.max()):.4f}]" + ) + assert temp.shape == (30, 30) + assert float(temp.max()) > 0 + print(" PASSED") + return temp + + +def test_structural_forward(temperature): + print("\n=== Structural solver forward pass ===") + from structural_solver.tesseract_api import InputSchema as StructuralInput + + inputs = StructuralInput(temperature=temperature) + out = structural_api.apply(inputs) + print(f" Displacement: {out['displacement'].shape}, Stress: {out['stress'].shape}") + print(f" Objective: {float(out['objective']):.6e}") + assert out["displacement"].shape == (30, 30, 2) + assert out["stress"].shape == (30, 30, 3) + print(" PASSED") + + +def test_one_way_gradient(): + print("\n=== One-way coupled gradient ===") + + def pipeline(source_x, source_y): + thermal_out = thermal_api.apply_jit( + { + "source_x": source_x, + "source_y": source_y, + "source_intensity": jnp.float32(10.0), + "source_width": 0.1, + "displacement": jnp.zeros((30, 30, 2), dtype=jnp.float32), + "conductivity": 1.0, + "boundary_temp": 0.0, + } + ) + structural_out = structural_api.apply_jit( + { + "temperature": thermal_out["temperature"], + "youngs_modulus": 200.0, + "poissons_ratio": 0.3, + "thermal_expansion": 1e-3, + } + ) + return structural_out["objective"] + + grad_fn = jax.grad(pipeline, argnums=(0, 1)) + sx, sy = jnp.float32(0.3), jnp.float32(0.7) + grads = grad_fn(sx, sy) + + eps = jnp.float32(1e-4) + fd_x = (pipeline(sx + eps, sy) - pipeline(sx - eps, sy)) / (2 * eps) + fd_y = (pipeline(sx, sy + eps) - pipeline(sx, sy - eps)) / (2 * eps) + + rel_err_x = abs(float(grads[0]) - float(fd_x)) / (abs(float(fd_x)) + 1e-30) + rel_err_y = abs(float(grads[1]) - float(fd_y)) / (abs(float(fd_y)) + 1e-30) + print(f" Rel error: x={rel_err_x:.2e}, y={rel_err_y:.2e}") + assert max(rel_err_x, rel_err_y) < 1e-2, "Gradient error too large" + print(" PASSED") + + +def test_two_way_gradient(): + print("\n=== Two-way coupled gradient (lax.scan) ===") + + def coupled_pipeline(source_x, source_y): + temp = jnp.zeros((30, 30), dtype=jnp.float32) + disp = jnp.zeros((30, 30, 2), dtype=jnp.float32) + + def coupling_step(carry, _): + _temp, disp = carry + thermal_out = thermal_api.apply_jit( + { + "source_x": source_x, + "source_y": source_y, + "source_intensity": jnp.float32(10.0), + "source_width": 0.1, + "displacement": disp, + "conductivity": 1.0, + "boundary_temp": 0.0, + } + ) + structural_out = structural_api.apply_jit( + { + "temperature": thermal_out["temperature"], + "youngs_modulus": 200.0, + "poissons_ratio": 0.3, + "thermal_expansion": 1e-3, + } + ) + return ( + thermal_out["temperature"], + structural_out["displacement"], + ), structural_out["objective"] + + _, objectives = jax.lax.scan(coupling_step, (temp, disp), None, length=3) + return objectives[-1] + + grad_fn = jax.grad(coupled_pipeline, argnums=(0, 1)) + sx, sy = jnp.float32(0.3), jnp.float32(0.7) + grads = grad_fn(sx, sy) + + eps = jnp.float32(1e-4) + fd_x = (coupled_pipeline(sx + eps, sy) - coupled_pipeline(sx - eps, sy)) / (2 * eps) + fd_y = (coupled_pipeline(sx, sy + eps) - coupled_pipeline(sx, sy - eps)) / (2 * eps) + + rel_err_x = abs(float(grads[0]) - float(fd_x)) / (abs(float(fd_x)) + 1e-30) + rel_err_y = abs(float(grads[1]) - float(fd_y)) / (abs(float(fd_y)) + 1e-30) + print(f" Rel error: x={rel_err_x:.2e}, y={rel_err_y:.2e}") + assert max(rel_err_x, rel_err_y) < 1e-2, "Gradient error too large" + print(" PASSED") + + +def test_implicit_differentiation(): + print("\n=== Implicit differentiation vs unrolled ===") + + def G(temp_disp, params): + _temp, disp = temp_disp + sx, sy, q = params + thermal_out = thermal_api.apply_jit( + { + "source_x": sx, + "source_y": sy, + "source_intensity": q, + "source_width": jnp.float32(0.15), + "displacement": disp, + "conductivity": 1.0, + "boundary_temp": 0.0, + } + ) + structural_out = structural_api.apply_jit( + { + "temperature": thermal_out["temperature"], + "youngs_modulus": 200.0, + "poissons_ratio": 0.3, + "thermal_expansion": 1e-3, + } + ) + return (thermal_out["temperature"], structural_out["displacement"]) + + N_ITERS = 3 + SENSORS = [(8, 8), (8, 22), (22, 8), (22, 22)] + TARGETS = [ + jnp.float32(0.01), + jnp.float32(0.02), + jnp.float32(0.02), + jnp.float32(0.05), + ] + + def make_loss(temp): + loss = jnp.float32(0.0) + for (si, sj), target in zip(SENSORS, TARGETS, strict=False): + loss = loss + (temp[si, sj] - target) ** 2 + return loss + + # Unrolled version + def unrolled(params): + sx, sy, log_q = params[0], params[1], params[2] + q = jnp.exp(log_q) + temp = jnp.zeros((30, 30), dtype=jnp.float32) + disp = jnp.zeros((30, 30, 2), dtype=jnp.float32) + + def step(carry, _): + return G(carry, (sx, sy, q)), None + + (final_temp, _), _ = jax.lax.scan(step, (temp, disp), None, length=N_ITERS) + return make_loss(final_temp) + + # Implicit version + def implicit(params): + sx, sy, log_q = params[0], params[1], params[2] + q = jnp.exp(log_q) + + @jax.custom_vjp + def solve(p): + temp = jnp.zeros((30, 30), dtype=jnp.float32) + disp = jnp.zeros((30, 30, 2), dtype=jnp.float32) + + def step(carry, _): + return G(carry, p), None + + (ft, fd), _ = jax.lax.scan(step, (temp, disp), None, length=N_ITERS) + return (ft, fd) + + def fwd(p): + fp = solve(p) + return fp, (fp, p) + + def bwd(res, g): + (ft, fd), p = res + vt, vd = g + + def G_state(td): + return G(td, p) + + def adj_step(lam, _): + _, vjp_fn = jax.vjp(G_state, (ft, fd)) + dGT = vjp_fn(lam)[0] + return (vt + dGT[0], vd + dGT[1]), None + + (lt, ld), _ = jax.lax.scan(adj_step, (vt, vd), None, length=20) + + def G_params(pp): + return G((ft, fd), pp) + + _, vjp_p = jax.vjp(G_params, p) + return (vjp_p((lt, ld))[0],) + + solve.defvjp(fwd, bwd) + final_temp, _ = solve((sx, sy, q)) + return make_loss(final_temp) + + p0 = jnp.array([0.3, 0.7, jnp.log(8.0)], dtype=jnp.float32) + grad_u = jax.grad(unrolled)(p0) + grad_i = jax.grad(implicit)(p0) + + for i, name in enumerate(["sx", "sy", "log_q"]): + rel = abs(float(grad_i[i]) - float(grad_u[i])) / (abs(float(grad_u[i])) + 1e-30) + print( + f" {name}: unrolled={float(grad_u[i]):.6e} implicit={float(grad_i[i]):.6e} rel_err={rel:.2e}" + ) + assert rel < 1e-3, f"Implicit gradient for {name} deviates too much: {rel:.2e}" + print(" PASSED") + + +if __name__ == "__main__": + temp = test_thermal_forward() + test_structural_forward(temp) + test_one_way_gradient() + test_two_way_gradient() + test_implicit_differentiation() + print("\nAll smoke tests passed.") diff --git a/demo/multiphysics-optimization/thermal_solver/tesseract_api.py b/demo/multiphysics-optimization/thermal_solver/tesseract_api.py new file mode 100644 index 00000000..3c9911c9 --- /dev/null +++ b/demo/multiphysics-optimization/thermal_solver/tesseract_api.py @@ -0,0 +1,233 @@ +# Copyright 2025 Pasteur Labs. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Thermal solver Tesseract: 2D steady-state heat equation on a rectangular plate. + +Solves -k * laplacian(T) = q(x, y) with Dirichlet boundary conditions using +a finite-difference discretization on a regular grid. The heat source is a +Gaussian blob with parameterized location and intensity. + +When displacement is provided (from a structural solver), the mesh is deformed +accordingly, introducing geometry-dependent coupling for two-way +thermoelastic problems. +""" + +from typing import Any + +import equinox as eqx +import jax +import jax.numpy as jnp +from pydantic import BaseModel, Field + +from tesseract_core.runtime import Array, Differentiable, Float32 +from tesseract_core.runtime.tree_transforms import filter_func, flatten_with_paths + +# Grid resolution (interior nodes). Kept moderate for demo speed. +NX = 30 +NY = 30 + + +class InputSchema(BaseModel): + source_x: Differentiable[Float32] = Field( + description="Heat source x-location (0-1, fraction of plate width)" + ) + source_y: Differentiable[Float32] = Field( + description="Heat source y-location (0-1, fraction of plate height)" + ) + source_intensity: Differentiable[Float32] = Field( + description="Heat source intensity", default=10.0 + ) + source_width: Float32 = Field(description="Heat source Gaussian width", default=0.1) + displacement: Differentiable[Array[(NX, NY, 2), Float32]] = Field( + description="Displacement field from structural solver (NX x NY x 2). " + "Zero for the first coupling iteration.", + default=None, + ) + conductivity: Float32 = Field(description="Thermal conductivity", default=1.0) + boundary_temp: Float32 = Field( + description="Dirichlet boundary temperature", default=0.0 + ) + + +class OutputSchema(BaseModel): + temperature: Differentiable[Array[(NX, NY), Float32]] = Field( + description="Steady-state temperature field on interior nodes" + ) + + +def _make_grid(nx: int, ny: int): + """Create a unit-square grid of interior node positions.""" + x = jnp.linspace(0, 1, nx + 2)[1:-1] + y = jnp.linspace(0, 1, ny + 2)[1:-1] + X, Y = jnp.meshgrid(x, y, indexing="ij") + return X, Y + + +def _gaussian_source(X, Y, cx, cy, intensity, width): + """Gaussian heat source centered at (cx, cy).""" + r2 = (X - cx) ** 2 + (Y - cy) ** 2 + return intensity * jnp.exp(-r2 / (2 * width**2)) + + +def _solve_heat_jacobi(source, conductivity, boundary_temp, n_iters=500): + """Solve 2D Poisson equation via damped Jacobi iteration. + + This is intentionally simple — not the fastest solver, but fully + differentiable through JAX and easy to understand. + """ + nx, ny = source.shape + dx = 1.0 / (nx + 1) + dy = 1.0 / (ny + 1) + dx2 = dx**2 + dy2 = dy**2 + coeff = 1.0 / (2.0 * conductivity * (1.0 / dx2 + 1.0 / dy2)) + + T = jnp.full((nx + 2, ny + 2), boundary_temp) + + def iteration(T, _): + T_padded = T + laplacian = (T_padded[2:, 1:-1] + T_padded[:-2, 1:-1]) / dx2 + ( + T_padded[1:-1, 2:] + T_padded[1:-1, :-2] + ) / dy2 + T_interior = coeff * (conductivity * laplacian + source) + T_new = T_padded.at[1:-1, 1:-1].set(T_interior) + return T_new, None + + T_final, _ = jax.lax.scan(iteration, T, None, length=n_iters) + return T_final[1:-1, 1:-1] + + +@eqx.filter_jit +def apply_jit(inputs: dict) -> dict: + X, Y = _make_grid(NX, NY) + + # Deform grid if displacement is provided + displacement = inputs.get("displacement") + if displacement is not None: + X = X + displacement[:, :, 0] + Y = Y + displacement[:, :, 1] + + source = _gaussian_source( + X, + Y, + inputs["source_x"], + inputs["source_y"], + inputs["source_intensity"], + inputs["source_width"], + ) + + temperature = _solve_heat_jacobi( + source, + inputs["conductivity"], + inputs["boundary_temp"], + ) + + return {"temperature": temperature.astype(jnp.float32)} + + +def apply(inputs: InputSchema) -> OutputSchema: + return apply_jit(inputs.model_dump()) + + +def abstract_eval(abstract_inputs: Any) -> Any: + is_shapedtype_dict = lambda x: type(x) is dict and (x.keys() == {"shape", "dtype"}) + is_shapedtype_struct = lambda x: isinstance(x, jax.ShapeDtypeStruct) + + jaxified_inputs = jax.tree.map( + lambda x: jax.ShapeDtypeStruct(**x) if is_shapedtype_dict(x) else x, + abstract_inputs.model_dump(), + is_leaf=is_shapedtype_dict, + ) + dynamic_inputs, static_inputs = eqx.partition( + jaxified_inputs, filter_spec=is_shapedtype_struct + ) + + def wrapped_apply(dynamic_inputs: Any) -> Any: + inputs = eqx.combine(static_inputs, dynamic_inputs) + return apply_jit(inputs) + + jax_shapes = jax.eval_shape(wrapped_apply, dynamic_inputs) + return jax.tree.map( + lambda x: ( + {"shape": x.shape, "dtype": str(x.dtype)} if is_shapedtype_struct(x) else x + ), + jax_shapes, + is_leaf=is_shapedtype_struct, + ) + + +@eqx.filter_jit +def jvp_jit( + inputs: dict, + jvp_inputs: tuple[str], + jvp_outputs: tuple[str], + tangent_vector: dict, +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, jvp_outputs) + return jax.jvp( + filtered_apply, + [flatten_with_paths(inputs, include_paths=jvp_inputs)], + [tangent_vector], + )[1] + + +def jacobian_vector_product( + inputs: InputSchema, + jvp_inputs: set[str], + jvp_outputs: set[str], + tangent_vector: dict[str, Any], +) -> Any: + return jvp_jit( + inputs.model_dump(), + tuple(jvp_inputs), + tuple(jvp_outputs), + tangent_vector, + ) + + +@eqx.filter_jit +def vjp_jit( + inputs: dict, + vjp_inputs: tuple[str], + vjp_outputs: tuple[str], + cotangent_vector: dict, +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, vjp_outputs) + _, vjp_func = jax.vjp( + filtered_apply, flatten_with_paths(inputs, include_paths=vjp_inputs) + ) + return vjp_func(cotangent_vector)[0] + + +def vector_jacobian_product( + inputs: InputSchema, + vjp_inputs: set[str], + vjp_outputs: set[str], + cotangent_vector: dict[str, Any], +) -> Any: + return vjp_jit( + inputs.model_dump(), + tuple(vjp_inputs), + tuple(vjp_outputs), + cotangent_vector, + ) + + +@eqx.filter_jit +def jac_jit( + inputs: dict, + jac_inputs: tuple[str], + jac_outputs: tuple[str], +) -> Any: + filtered_apply = filter_func(apply_jit, inputs, jac_outputs) + return jax.jacrev(filtered_apply)( + flatten_with_paths(inputs, include_paths=jac_inputs) + ) + + +def jacobian( + inputs: InputSchema, + jac_inputs: set[str], + jac_outputs: set[str], +) -> Any: + return jac_jit(inputs.model_dump(), tuple(jac_inputs), tuple(jac_outputs)) diff --git a/demo/multiphysics-optimization/thermal_solver/tesseract_config.yaml b/demo/multiphysics-optimization/thermal_solver/tesseract_config.yaml new file mode 100644 index 00000000..10c7c11f --- /dev/null +++ b/demo/multiphysics-optimization/thermal_solver/tesseract_config.yaml @@ -0,0 +1,6 @@ +name: "thermal-solver" +version: "0.1.0" +description: "2D steady-state heat equation solver with Gaussian source parameterization" + +build_config: + target_platform: "native" diff --git a/demo/multiphysics-optimization/thermal_solver/tesseract_requirements.txt b/demo/multiphysics-optimization/thermal_solver/tesseract_requirements.txt new file mode 100644 index 00000000..8f33da03 --- /dev/null +++ b/demo/multiphysics-optimization/thermal_solver/tesseract_requirements.txt @@ -0,0 +1,2 @@ +jax[cpu]==0.5.2 +equinox diff --git a/docs/content/demo/demo.md b/docs/content/demo/demo.md index 8b05b53c..bbc8fc4d 100644 --- a/docs/content/demo/demo.md +++ b/docs/content/demo/demo.md @@ -10,6 +10,7 @@ data-assimilation.ipynb lorenz_tesseract.md cfd-optimization.ipynb fem-shape-optimization.ipynb +multiphysics-optimization.ipynb JAX Rosenbrock Minimization PyTorch Rosenbrock Minimization JAX RBF Fitting @@ -58,6 +59,11 @@ Optimize the initial velocity field of a 2D Navier-Stokes simulation so its vort Compose a geometry Tesseract (PyVista, finite-difference gradients) with a FEM Tesseract (jax-fem) to optimize structural bar configurations for minimum compliance. ::: +:::{grid-item-card} Multi-Physics Optimization +:link: multiphysics-optimization.html + +Couple independent thermal and structural Tesseracts into a two-way thermoelastic pipeline and solve an inverse-design problem with end-to-end gradients — including constant-memory gradients via implicit differentiation. +::: :::: diff --git a/docs/index.md b/docs/index.md index c5dc1705..d19de0e1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -263,6 +263,17 @@ Compose a geometry Tesseract with a FEM solver Tesseract for end-to-end parametric structural optimization. ::: +:::{grid-item-card} Multi-Physics Optimization +:link: content/demo/multiphysics-optimization +:link-type: doc +:class-card: demo-card +:img-top: static/demo-multiphysics.svg +:class-img-top: demo-schematic invert-on-dark + +Couple thermal and structural Tesseracts into a two-way thermoelastic +pipeline and solve an inverse-design problem with end-to-end gradients. +::: + :::: :::{div} landing-cta diff --git a/docs/static/demo-multiphysics.svg b/docs/static/demo-multiphysics.svg new file mode 100644 index 00000000..44cbf430 --- /dev/null +++ b/docs/static/demo-multiphysics.svg @@ -0,0 +1,51 @@ + + + + + + + + + θ (source) + + + + + + + + + + Thermal + + + + + T + + + D + + + + + + Structural + + + + + + + + + + + + loss + + + + + ∇ through coupled iteration +