{ "cells": [ { "cell_type": "markdown", "id": "dae1650b", "metadata": {}, "source": [ "# 24 · Subspace Mixed FEM (MFEM)\n", "\n", "We simulate an elastic 2D beam dropping under gravity, pinned at its left edge,\n", "**two ways**:\n", "\n", "* **Full-space FEM** — the classic recipe. One Newton solve per timestep on\n", " the elastic + inertial + pin energy, written as a function of the deformed\n", " positions.\n", "* **Subspace Mixed FEM (MFEM)** — the method of\n", " [Trusty et al., *Subspace Mixed FEM*](https://www.dgp.toronto.edu/projects/subspace-mfem/).\n", " We solve in a small **skinning-eigenmode subspace** and introduce an\n", " **auxiliary stretch variable** so the elastic energy stays element-local and\n", " cheap, even though the subspace basis is dense.\n", "\n", "Each method is packaged as a small simulator object: a `FEMBeam` baseline that\n", "drives `newton_solver` on one energy, and an `MFEMBeam` that drives `sqp_mfem`\n", "on the mixed energy and its Hessian/gradient blocks.\n", "\n", "## Why a subspace, and why \"mixed\"?\n", "\n", "A reduced model writes every vertex position as\n", "\n", "$$\n", "\\mathbf{x} = B\\,\\mathbf{u} + \\mathbf{q},\n", "$$\n", "\n", "where $B$ is a tall **dense** basis (here, skinning eigenmodes) and $\\mathbf{u}$\n", "is a handful of reduced weights. Stepping then solves for $\\mathbf{u}$ only, which\n", "is great — until you evaluate the elastic energy. The elastic Hessian in the\n", "subspace is $B^\\top H B$: dense, and expensive to assemble because $H$ couples\n", "the deformation gradient $F = \\nabla(B\\mathbf{u})$ across *all* elements.\n", "\n", "**Mixed FEM** breaks that coupling. Introduce a per-element auxiliary\n", "**stretch** variable $\\mathbf{a}$ (the symmetric part of $F$, one small vector\n", "per cubature element) and demand that it agree with the actual deformation:\n", "\n", "$$\n", "S\\big(F(\\mathbf{u})\\big) = \\mathbf{a}.\n", "$$\n", "\n", "Now the elastic energy is a function of $\\mathbf{a}$ **alone** — fully\n", "*element-local*, so its Hessian $H_z$ is block-diagonal and trivial to build.\n", "The only thing tying $\\mathbf{a}$ back to the dense subspace is the constraint,\n", "whose Jacobian $G_u$ is cheap. We minimize the Lagrangian\n", "\n", "$$\n", "\\min_{\\mathbf{u},\\,\\mathbf{a}}\\; E_\\text{inertia}(\\mathbf{u}) + E_\\text{elastic}(\\mathbf{a}) + E_\\text{pin}(\\mathbf{u}) \\quad\\text{s.t.}\\quad S(F(\\mathbf{u})) = \\mathbf{a}.\n", "$$" ] }, { "cell_type": "code", "execution_count": 1, "id": "2fda25b0", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:26.547603Z", "iopub.status.busy": "2026-06-09T05:44:26.547328Z", "iopub.status.idle": "2026-06-09T05:44:27.056232Z", "shell.execute_reply": "2026-06-09T05:44:27.056016Z" } }, "outputs": [ { "data": { "text/plain": [ "{'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'}" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import scipy as sp\n", "import matplotlib.pyplot as plt\n", "from matplotlib import animation\n", "\n", "import simkit as sk\n", "from simkit.solvers import sqp_mfem, newton_solver\n", "from simkit.energies import (\n", " elastic_energy_S, elastic_gradient_S, elastic_hessian_S, # element-local (stretch) energy\n", " elastic_energy_z, elastic_gradient_z, elastic_hessian_z, ElasticEnergyZPrecomp, # FEM (subspace) energy\n", " quadratic_energy, quadratic_gradient, quadratic_hessian, # pin + gravity\n", " kinetic_energy_be, kinetic_gradient_be, kinetic_hessian_be, # backward-Euler inertia\n", ")\n", "import utils\n", "\n", "# sparse @ on some scipy/numpy combos emits spurious 'divide by zero in matmul'\n", "# warnings; the arithmetic is exact. Silence them for a clean notebook.\n", "np.seterr(all=\"ignore\")" ] }, { "cell_type": "markdown", "id": "d3ea8509", "metadata": {}, "source": [ "## The mesh, subspace, and cubature\n", "\n", "A long thin beam. We build:\n", "\n", "* `B` — a **skinning-eigenmode** subspace (`sk.skinning_eigenmodes`).\n", " `x = B @ u + q`, with `q` the rest geometry, so `u = 0` is the rest pose.\n", "* `cI, cW` — **spectral cubature** points and weights\n", " (`sk.spectral_cubature`): a sparse subset of elements (with weights) at which\n", " we evaluate the elastic energy, instead of all of them." ] }, { "cell_type": "code", "execution_count": 2, "id": "5220a57c", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:27.057359Z", "iopub.status.busy": "2026-06-09T05:44:27.057283Z", "iopub.status.idle": "2026-06-09T05:44:27.148204Z", "shell.execute_reply": "2026-06-09T05:44:27.147987Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "320 vertices, 546 triangles, 640 full DOFs\n", "subspace dim = 60, cubature points = 400\n" ] } ], "source": [ "X, T = utils.triangulated_grid(nx=40, ny=8, width=3.0, height=0.5)\n", "n, dim = X.shape\n", "q = X.reshape(-1, 1) # rest geometry offset: x = B u + q\n", "\n", "ym, pr, rho, h = 1e5, 0.45, 1e3, 1e1 # Young's modulus, Poisson, density, timestep\n", "material = \"macklin-mueller-neo-hookean\"\n", "\n", "# skinning-eigenmode subspace + spectral cubature\n", "m, k = 10, 400\n", "mu_tet = np.full((T.shape[0], 1), float(ym))\n", "W, E, B = sk.skinning_eigenmodes(X, T, m, mu=mu_tet)\n", "cI, cW, _ = sk.spectral_cubature(X, T, W, k, return_labels=True)\n", "print(f\"{n} vertices, {T.shape[0]} triangles, {n*dim} full DOFs\")\n", "print(f\"subspace dim = {B.shape[1]}, cubature points = {cI.shape[0]}\")" ] }, { "cell_type": "markdown", "id": "7e252147", "metadata": {}, "source": [ "## Shared precomputation\n", "\n", "Both methods share the reduced mass matrix $B^\\top M B$ (backward-Euler inertia)\n", "and the deformation-gradient operator restricted to the cubature elements,\n", "`GJB` (so `F = GJB @ u + GJq`). The MFEM method additionally needs the\n", "**symmetric-stretch map** `Ci` (extracts the symmetric stretch $S(F)$) and a\n", "constraint metric `w` weighting each stretch component by its cubature volume." ] }, { "cell_type": "code", "execution_count": 3, "id": "3622ad3b", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:27.149210Z", "iopub.status.busy": "2026-06-09T05:44:27.149150Z", "iopub.status.idle": "2026-06-09T05:44:27.154517Z", "shell.execute_reply": "2026-06-09T05:44:27.154331Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "pinned 8 vertices on the left edge\n" ] } ], "source": [ "# --- material (Lame) on cubature elements ---\n", "mu_lame, lam_lame = sk.ympr_to_lame(ym, pr)\n", "mu = np.full((T.shape[0], 1), mu_lame)[cI]\n", "lam = np.full((T.shape[0], 1), lam_lame)[cI]\n", "vol = cW.reshape(-1, 1)\n", "\n", "# --- inertia: reduced mass matrix ---\n", "Mn = sk.massmatrix(X, T, rho=rho)\n", "Mv = sp.sparse.kron(Mn, sp.sparse.identity(dim))\n", "kin_pre = B.T @ Mv @ B\n", "\n", "# --- deformation gradient at cubature elements: F = GJB u + GJq ---\n", "G = sk.selection_matrix(cI, T.shape[0])\n", "Ge = sp.sparse.kron(G, sp.sparse.identity(dim*dim))\n", "J = sk.deformation_jacobian(X, T)\n", "GJB = Ge @ J @ B\n", "GJq = Ge @ J @ q\n", "\n", "# --- MFEM-only: symmetric stretch map + constraint metric ---\n", "C, Ci = sk.symmetric_stretch_map(cI.shape[0], dim)\n", "w = np.kron(vol, np.array([[1., 1., 2.]]).T) # dim==2: (s_xx, s_yy, s_xy) weights\n", "Wd = sp.sparse.diags(w.flatten())\n", "Wi = sp.sparse.diags(1.0 / w.flatten()) # inverse constraint metric\n", "nz = B.shape[1] # number of subspace (position) DOFs\n", "na = Ci.shape[0] # number of stretch auxiliary DOFs\n", "\n", "# --- external forcing: gravity (constant) + a stiff pin on the left edge ---\n", "bg = -sk.gravity_force(X, T, a=-9.81, rho=rho).reshape(-1, 1)\n", "bI = np.where(X[:, 0] <= X[:, 0].min() + 1e-6)[0]\n", "Qp, bp = sk.dirichlet_penalty(bI, X[bI, :], n, 1e8)\n", "BQB = B.T @ Qp @ B # subspace pin quadratic\n", "# The pin penalises absolute positions x = B u + q. Substituting that into\n", "# 0.5 x^T Qp x + bp^T x leaves a linear term B^T (Qp q + bp) in u -- the Qp q\n", "# cross-term anchors the pin at the rest offset q. Dropping it would pull the\n", "# beam toward the origin and inflate the rest shape.\n", "Bb = B.T @ (Qp @ q + bp + bg) # subspace pin linear (anchored at q) + gravity\n", "print(f\"pinned {len(bI)} vertices on the left edge\")\n", "\n", "# Augmented-Lagrangian penalty weight (0 = plain Lagrangian SQP); studied later.\n", "rho_aug = 0.0" ] }, { "cell_type": "markdown", "id": "c8bb6b2e", "metadata": {}, "source": [ "## The MFEM simulator and its blocks\n", "\n", "We solve for the stacked state $\\mathbf{p} = [\\mathbf{u};\\,\\mathbf{a};\\,\\boldsymbol{\\lambda}]$\n", "— subspace positions, per-cubature stretch auxiliaries, and the **Lagrange\n", "multipliers** $\\boldsymbol{\\lambda}$ of the constraint $\\mathbf{c}=S(F(\\mathbf u))-\\mathbf a=0$.\n", "`sqp_mfem` minimises the **augmented-Lagrangian** merit\n", "\n", "$$\n", "E \\;=\\; \\underbrace{\\psi_S(\\mathbf a) + \\tfrac{1}{2h^2}\\|\\mathbf u-\\tilde{\\mathbf u}\\|_M^2 + \\mathrm{quad}(\\mathbf u)}_{\\text{objective}}\n", "\\;+\\; \\boldsymbol{\\lambda}^\\top W\\mathbf c \\;+\\; \\tfrac{1}{2}\\,\\rho_{\\text{aug}}\\,\\mathbf c^\\top W\\mathbf c,\n", "$$\n", "\n", "updating the primal $[\\mathbf u;\\mathbf a]$ and overwriting $\\boldsymbol\\lambda$ with the freshly\n", "computed multiplier each iteration. The simulator exposes:\n", "\n", "* `energy(p)` — the scalar merit, written as a sum of named terms\n", " (`E_elastic`, `E_kinetic`, `E_quad` pin+gravity, `E_lag`, `E_aug`).\n", "* `grad_blocks(p) -> [f_u, f_z, f_ll]` — the **objective + penalty** gradient\n", " w.r.t. positions and stretch (the multiplier coupling $+G_u\\boldsymbol\\lambda$,\n", " $-W\\boldsymbol\\lambda$ is added by the solver), and the weighted constraint residual\n", " $f_{\\lambda}=W\\mathbf c$.\n", "* `hess_blocks(p) -> [H_u, H_z, G_u, G_z, G_zi]` — position Hessian (inertia + pin\n", " $+\\,\\rho_{\\text{aug}}G_uW^{-1}G_u^\\top$, a Gauss-Newton penalty term), block-diagonal stretch\n", " Hessian $H_z+\\rho_{\\text{aug}}W$, constraint Jacobian $G_u=\\frac{\\partial S}{\\partial u}^\\top W$,\n", " $G_z=-W$, and $G_z^{-1}$.\n", "\n", "`rho_aug` is an optional augmentation that can stabilise the line search; we study\n", "its effect on convergence below." ] }, { "cell_type": "code", "execution_count": 4, "id": "55995b1e", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:27.155473Z", "iopub.status.busy": "2026-06-09T05:44:27.155427Z", "iopub.status.idle": "2026-06-09T05:44:27.159406Z", "shell.execute_reply": "2026-06-09T05:44:27.159230Z" } }, "outputs": [], "source": [ "class MFEMBeam:\n", " \"\"\"Subspace mixed FEM: drives `sqp_mfem` on the stacked state [u; a; ll].\"\"\"\n", "\n", " def __init__(self, GJB, GJq, Ci, kin_pre, BQB, Bb, w, Wd, Wi, h, mu, lam, vol,\n", " material, nz, na, dim, B, X, T, q, rho_aug=0.0):\n", " self.GJB, self.GJq, self.Ci = GJB, GJq, Ci\n", " self.kin_pre, self.BQB, self.Bb = kin_pre, BQB, Bb\n", " self.w, self.Wd, self.Wi = w, Wd, Wi\n", " self.h, self.mu, self.lam, self.vol = h, mu, lam, vol\n", " self.material, self.nz, self.na, self.dim = material, nz, na, dim\n", " self.B, self.X, self.T, self.q = B, X, T, q\n", " self.rho_aug = rho_aug\n", "\n", " def split(self, p):\n", " nz, na = self.nz, self.na\n", " return p[:nz], p[nz:nz+na], p[nz+na:] # u (positions), a (stretch), ll (multiplier)\n", "\n", " def energy(self, p, z_curr, z_prev, ra):\n", " u, a, ll = self.split(p)\n", " A = a.reshape(-1, self.dim*(self.dim+1)//2)\n", " F = (self.GJB @ u + self.GJq).reshape(-1, self.dim, self.dim)\n", " c = self.Ci @ sk.stretch(F) - a # stretch constraint residual\n", " wc = self.w * c # = W c\n", " E_elastic = elastic_energy_S(A, self.mu, self.lam, self.vol, self.material)\n", " E_kinetic = kinetic_energy_be(u, z_curr, z_prev, self.kin_pre, self.h)\n", " E_quad = quadratic_energy(u, self.BQB, self.Bb) # pin + gravity\n", " E_lag = float((ll.T @ wc)[0, 0]) # ll^T W c\n", " E_aug = 0.5 * ra * float((c.T @ wc)[0, 0]) # 0.5 rho c^T W c\n", " return E_elastic + E_kinetic + E_quad + E_lag + E_aug\n", "\n", " def grad_blocks(self, p, z_curr, z_prev, ra):\n", " u, a, ll = self.split(p)\n", " A = a.reshape(-1, self.dim*(self.dim+1)//2)\n", " F = (self.GJB @ u + self.GJq).reshape(-1, self.dim, self.dim)\n", " wc = self.w * (self.Ci @ sk.stretch(F) - a)\n", " dsdz = sk.stretch_gradient_dz(u, self.GJB, Ci=self.Ci, dim=self.dim, GJq=self.GJq)\n", " # d/du of 0.5 rho c^T W c is rho * dsdz @ (W c) = rho * dsdz @ wc\n", " # (NOT G_u @ wc = dsdz @ W @ wc, which double-weights the off-diagonals by W).\n", " g_kinetic = kinetic_gradient_be(u, z_curr, z_prev, self.kin_pre, self.h)\n", " g_quad = quadratic_gradient(u, self.BQB, self.Bb)\n", " g_aug = ra * (dsdz @ wc)\n", " f_u = g_kinetic + g_quad + g_aug\n", " f_z = elastic_gradient_S(A, self.mu, self.lam, self.vol, self.material).reshape(-1, 1) - ra * wc # dc/da = -I\n", " f_ll = wc # constraint residual (W c)\n", " return [f_u, f_z, f_ll]\n", "\n", " def hess_blocks(self, p, z_curr, z_prev, ra):\n", " u, a, ll = self.split(p)\n", " A = a.reshape(-1, self.dim*(self.dim+1)//2)\n", " dsdz = sk.stretch_gradient_dz(u, self.GJB, Ci=self.Ci, dim=self.dim, GJq=self.GJq)\n", " G_u = dsdz @ self.Wd\n", " H_inertia = kinetic_hessian_be(self.kin_pre, self.h)\n", " H_pin = quadratic_hessian(self.BQB)\n", " H_pen = ra * (G_u @ self.Wi @ G_u.T)\n", " H_u = H_inertia + H_pin + H_pen\n", " H_z = sp.sparse.block_diag([hh for hh in elastic_hessian_S(A, self.mu, self.lam, self.vol, self.material)]) + ra * self.Wd\n", " G_z = -self.Wd\n", " G_zi = sp.sparse.diags(1.0 / G_z.diagonal())\n", " return [H_u, H_z, G_u, G_z, G_zi]\n", "\n", " def rest_state(self):\n", " u = sk.project_into_subspace(self.X.reshape(-1,1) - self.q, self.B,\n", " M=sp.sparse.kron(sk.massmatrix(self.X, self.T), sp.sparse.identity(self.dim)))\n", " ncub = self.na // (self.dim*(self.dim+1)//2) # number of cubature points\n", " a = np.ones((ncub, self.dim*(self.dim+1)//2))\n", " a[:, self.dim:] = 0.0 # identity stretch\n", " ll = np.zeros((self.na, 1)) # zero multiplier\n", " return u, a.reshape(-1, 1), ll\n", "\n", " def step(self, z_curr, z_prev, a, ll):\n", " p = np.vstack([z_curr, a, ll])\n", " p = sqp_mfem(p,\n", " lambda pp: self.energy(pp, z_curr, z_prev, self.rho_aug),\n", " lambda pp: self.hess_blocks(pp, z_curr, z_prev, self.rho_aug),\n", " lambda pp: self.grad_blocks(pp, z_curr, z_prev, self.rho_aug),\n", " tolerance=1e-6, max_iter=30, do_line_search=True)\n", " return self.split(p)\n", "\n", "mfem = MFEMBeam(GJB, GJq, Ci, kin_pre, BQB, Bb, w, Wd, Wi, h, mu, lam, vol,\n", " material, nz, na, dim, B, X, T, q, rho_aug=rho_aug)" ] }, { "cell_type": "markdown", "id": "c2dafa55", "metadata": {}, "source": [ "### Verifying the blocks (finite differences)\n", "\n", "Before trusting the solve, check the blocks against central finite differences of\n", "the scalar merit $E(\\mathbf p)$:\n", "\n", "* `grad_blocks` reproduce $\\nabla E$ once the multiplier coupling the solver adds\n", " ($+G_u\\boldsymbol\\lambda$, $+G_z\\boldsymbol\\lambda$) is included — for\n", " $\\rho_{\\text{aug}}=0$ **and** $\\rho_{\\text{aug}}>0$.\n", "* $H_z=\\partial^2E/\\partial\\mathbf a^2$ exactly.\n", "* $H_u$ is a **Gauss-Newton** Hessian: it matches $\\partial^2E/\\partial\\mathbf u^2$\n", " exactly at $\\boldsymbol\\lambda=0,\\rho_{\\text{aug}}=0$ and stays SPD (what the\n", " condensed solve needs) for all $\\rho_{\\text{aug}}\\ge 0$.\n", "\n", "The same checks live in `tests/test_mfem_blocks.py`." ] }, { "cell_type": "code", "execution_count": 5, "id": "453e24a9", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:27.160322Z", "iopub.status.busy": "2026-06-09T05:44:27.160275Z", "iopub.status.idle": "2026-06-09T05:44:50.703790Z", "shell.execute_reply": "2026-06-09T05:44:50.703568Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "relative finite-difference errors (smaller is better):\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "rho_aug= 0: merit gradient PASS (6.0e-11) H_z PASS (7.4e-11)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "rho_aug= 50: merit gradient PASS (6.8e-11) H_z PASS (7.4e-11)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "H_u exact at ll=0, rho_aug=0: PASS (7.2e-12 relative)\n", " H_u SPD (rho_aug= 0)? FAIL (min eigenvalue -9.80e-07)\n", " H_u SPD (rho_aug= 50)? PASS (min eigenvalue 2.99e-05)\n", " H_u SPD (rho_aug= 10000)? PASS (min eigenvalue 4.34e-03)\n" ] } ], "source": [ "from simkit.gradient_cfd import gradient_cfd\n", "def _dense(M):\n", " return np.asarray(M.todense()) if sp.sparse.issparse(M) else np.asarray(M)\n", "def _tag(r, tol=1e-4):\n", " return \"PASS\" if r < tol else \"FAIL\"\n", "\n", "_rng = np.random.default_rng(0)\n", "_u, _a, _ll = mfem.rest_state()\n", "_u = _u + 0.05 * _rng.standard_normal(_u.shape)\n", "_a = _a + 0.05 * _rng.standard_normal(_a.shape)\n", "_ll = 0.05 * _rng.standard_normal(_ll.shape)\n", "_zc = _zp = mfem.rest_state()[0]\n", "\n", "def _verify(ra):\n", " p = np.vstack([_u, _a, _ll])\n", " f_u, f_z, f_ll = mfem.grad_blocks(p, _zc, _zp, ra)\n", " H_u, H_z, G_u, G_z, G_zi = mfem.hess_blocks(p, _zc, _zp, ra)\n", " # full merit gradient = blocks + the multiplier coupling sqp_mfem adds internally\n", " g_analytic = np.vstack([f_u + G_u @ _ll, f_z + G_z @ _ll, f_ll])\n", " g_fd = gradient_cfd(lambda pp: np.array([mfem.energy(pp.reshape(-1,1), _zc, _zp, ra)]),\n", " p.flatten(), 1e-6).reshape(-1, 1)\n", " r_g = np.linalg.norm(g_fd - g_analytic) / (np.linalg.norm(g_fd) + 1e-12)\n", " # H_z is the exact stretch-block Hessian d(f_z)/da\n", " Hz_fd = gradient_cfd(lambda aa: mfem.grad_blocks(np.vstack([_u, aa.reshape(-1,1), _ll]),\n", " _zc, _zp, ra)[1].flatten(), _a.flatten(), 1e-6)\n", " r_Hz = np.linalg.norm(Hz_fd - _dense(H_z)) / (np.linalg.norm(_dense(H_z)) + 1e-12)\n", " print(f\"rho_aug={ra:6.0f}: merit gradient {_tag(r_g)} ({r_g:.1e}) H_z {_tag(r_Hz)} ({r_Hz:.1e})\")\n", "\n", "print(\"relative finite-difference errors (smaller is better):\")\n", "_verify(0.0)\n", "_verify(50.0)\n", "\n", "# H_u is Gauss-Newton: exact at ll=0, rho_aug=0; SPD for any rho_aug>=0\n", "_p0 = np.vstack([_u, _a, np.zeros_like(_ll)])\n", "_Hu0 = mfem.hess_blocks(_p0, _zc, _zp, 0.0)[0]\n", "_Hu_fd = gradient_cfd(lambda uu: mfem.grad_blocks(np.vstack([uu.reshape(-1,1), _a, np.zeros_like(_ll)]),\n", " _zc, _zp, 0.0)[0].flatten(), _u.flatten(), 1e-6)\n", "_rHu = np.linalg.norm(_Hu_fd - _dense(_Hu0)) / (np.linalg.norm(_dense(_Hu0)) + 1e-12)\n", "print(f\"H_u exact at ll=0, rho_aug=0: {_tag(_rHu)} ({_rHu:.1e} relative)\")\n", "for _ra in (0.0, 50.0, 1e4):\n", " _Hu = _dense(mfem.hess_blocks(np.vstack([_u,_a,_ll]), _zc, _zp, _ra)[0])\n", " _mineig = np.linalg.eigvalsh(0.5*(_Hu+_Hu.T)).min()\n", " print(f\" H_u SPD (rho_aug={_ra:7.0f})? {'PASS' if _mineig>0 else 'FAIL'} (min eigenvalue {_mineig:.2e})\")" ] }, { "cell_type": "markdown", "id": "748e0dd3", "metadata": {}, "source": [ "## The FEM baseline\n", "\n", "The classic recipe: one `newton_solver` per timestep on inertia + the subspace\n", "elastic energy `elastic_energy_z` (no auxiliary variable, no constraint) + the\n", "pin/gravity term. We package it as `FEMBeam`, whose `energy / gradient / hessian`\n", "sum their terms one per line, exactly like the standardized simulators." ] }, { "cell_type": "code", "execution_count": 6, "id": "b265e405", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:50.704710Z", "iopub.status.busy": "2026-06-09T05:44:50.704652Z", "iopub.status.idle": "2026-06-09T05:44:50.707693Z", "shell.execute_reply": "2026-06-09T05:44:50.707487Z" } }, "outputs": [], "source": [ "class FEMBeam:\n", " \"\"\"Full-space FEM in the subspace: one `newton_solver` per backward-Euler step.\"\"\"\n", "\n", " def __init__(self, B, q, Ge, J, kin_pre, BQB, Bb, h, mu, lam, vol, material, dim, X, T):\n", " self.el_pre = ElasticEnergyZPrecomp(B, q, Ge, J, dim)\n", " self.kin_pre, self.BQB, self.Bb = kin_pre, BQB, Bb\n", " self.h, self.mu, self.lam, self.vol = h, mu, lam, vol\n", " self.material = material\n", " self.B, self.q, self.X, self.T, self.dim = B, q, X, T, dim\n", "\n", " def energy(self, z, z_curr, z_prev):\n", " E_kinetic = kinetic_energy_be(z, z_curr, z_prev, self.kin_pre, self.h)\n", " E_elastic = elastic_energy_z(z, self.mu, self.lam, self.vol, self.material, self.el_pre)\n", " E_quad = quadratic_energy(z, self.BQB, self.Bb)\n", " return E_kinetic + E_elastic + E_quad\n", "\n", " def gradient(self, z, z_curr, z_prev):\n", " g_kinetic = kinetic_gradient_be(z, z_curr, z_prev, self.kin_pre, self.h)\n", " g_elastic = elastic_gradient_z(z, self.mu, self.lam, self.vol, self.material, self.el_pre)\n", " g_quad = quadratic_gradient(z, self.BQB, self.Bb)\n", " return g_kinetic + g_elastic + g_quad\n", "\n", " def hessian(self, z, z_curr, z_prev):\n", " H_kinetic = kinetic_hessian_be(self.kin_pre, self.h)\n", " H_elastic = elastic_hessian_z(z, self.mu, self.lam, self.vol, self.material, self.el_pre)\n", " H_quad = quadratic_hessian(self.BQB)\n", " return H_kinetic + H_elastic + H_quad\n", "\n", " def rest_state(self):\n", " return sk.project_into_subspace(self.X.reshape(-1,1) - self.q, self.B,\n", " M=sp.sparse.kron(sk.massmatrix(self.X, self.T), sp.sparse.identity(self.dim)))\n", "\n", " def step(self, z_curr, z_prev, **kw):\n", " v = (z_curr - z_prev) / self.h\n", " z0 = z_curr + v * self.h\n", " return newton_solver(z0,\n", " lambda zz: self.energy(zz, z_curr, z_prev),\n", " lambda zz: self.gradient(zz, z_curr, z_prev),\n", " lambda zz: self.hessian(zz, z_curr, z_prev),\n", " tolerance=1e-6, max_iter=30, do_line_search=True, **kw)\n", "\n", "fem = FEMBeam(B, q, Ge, J, kin_pre, BQB, Bb, h, mu, lam, vol, material, dim, X, T)" ] }, { "cell_type": "markdown", "id": "08bba3e0", "metadata": {}, "source": [ "## Step both simulations through time\n", "\n", "Backward-Euler dynamics: each step minimizes the (energy + inertia) objective\n", "about the current/previous reduced state. We record the full-space vertex\n", "trajectory $x = B\\,u + q$ for each method, looping explicitly over the 120 steps." ] }, { "cell_type": "code", "execution_count": 7, "id": "a99127d3", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:44:50.708501Z", "iopub.status.busy": "2026-06-09T05:44:50.708446Z", "iopub.status.idle": "2026-06-09T05:47:45.838194Z", "shell.execute_reply": "2026-06-09T05:47:45.837982Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MFEM tip y: -3.5230 -> -3.3435\n", "FEM tip y: -3.3421 -> -3.3435\n" ] } ], "source": [ "num_steps = 120\n", "\n", "# --- MFEM trajectory ---\n", "u, a, ll = mfem.rest_state()\n", "z_curr, z_prev = u.copy(), u.copy()\n", "mfem_frames = []\n", "for _ in range(num_steps):\n", " u_next, a, ll = mfem.step(z_curr, z_prev, a, ll)\n", " z_prev, z_curr = z_curr.copy(), u_next.copy()\n", " mfem_frames.append((B @ z_curr).reshape(-1, dim) + q.reshape(-1, dim))\n", "\n", "# --- FEM trajectory ---\n", "z = fem.rest_state()\n", "z_curr, z_prev = z.copy(), z.copy()\n", "fem_frames = []\n", "for _ in range(num_steps):\n", " z_next = fem.step(z_curr, z_prev)\n", " z_prev, z_curr = z_curr.copy(), z_next.copy()\n", " fem_frames.append((B @ z_curr).reshape(-1, dim) + q.reshape(-1, dim))\n", "\n", "tip = int(np.argmax(X[:, 0]))\n", "print(\"MFEM tip y: %.4f -> %.4f\" % (mfem_frames[0][tip,1], mfem_frames[-1][tip,1]))\n", "print(\"FEM tip y: %.4f -> %.4f\" % (fem_frames[0][tip,1], fem_frames[-1][tip,1]))\n", "assert np.all(np.isfinite(mfem_frames[-1])) and np.all(np.isfinite(fem_frames[-1]))" ] }, { "cell_type": "markdown", "id": "d4d1d9a3", "metadata": {}, "source": [ "## Regularization study: convergence vs `rho_aug`\n", "\n", "How does the augmented-Lagrangian weight $\\rho_{\\text{aug}}$ affect the number of\n", "SQP iterations to converge? Each step here converges fast, so we **stress** the\n", "solve with a large timestep ($h=0.1$, a big single step from rest) and sweep\n", "$\\rho_{\\text{aug}}$, counting iterations by wrapping `hess_blocks` in a call\n", "counter (one call per SQP iteration).\n", "\n", "The trade-off (textbook augmented Lagrangian): small-to-moderate $\\rho_{\\text{aug}}$\n", "is cheap, but **too large** a value makes the penalty Hessian dominate the\n", "condensed solve, degrading conditioning and slowing convergence until it stalls.\n", "A modest $\\rho_{\\text{aug}}$ is a safety net for harder steps where the plain\n", "($\\rho_{\\text{aug}}=0$) Lagrangian line search stalls; the optimal value is\n", "problem-dependent." ] }, { "cell_type": "code", "execution_count": 8, "id": "0a3742fa", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:47:45.839250Z", "iopub.status.busy": "2026-06-09T05:47:45.839194Z", "iopub.status.idle": "2026-06-09T05:47:52.173148Z", "shell.execute_reply": "2026-06-09T05:47:52.172920Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rho_aug = 0: 59 SQP iterations\n", "rho_aug = 1: 59 SQP iterations\n", "rho_aug = 10: 60 SQP iterations (hit max_iter -- stalled)\n", "rho_aug = 100: 60 SQP iterations (hit max_iter -- stalled)\n", "rho_aug = 1000: 60 SQP iterations (hit max_iter -- stalled)\n", "rho_aug = 10000: 60 SQP iterations (hit max_iter -- stalled)\n", "rho_aug = 100000: 60 SQP iterations (hit max_iter -- stalled)\n", "rho_aug = 1000000: 60 SQP iterations (hit max_iter -- stalled)\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "h_study = 1.0 # large timestep => one genuinely hard step\n", "rho_sweep = [0.0, 1.0, 10.0, 100.0, 1e3, 1e4, 1e5, 1e6]\n", "MAXIT = 60\n", "\n", "_u0, _a0, _ll0 = mfem.rest_state()\n", "_zc, _zp = _u0.copy(), _u0.copy()\n", "\n", "mfem_study = MFEMBeam(GJB, GJq, Ci, kin_pre, BQB, Bb, w, Wd, Wi, h_study,\n", " mu, lam, vol, material, nz, na, dim, B, X, T, q)\n", "\n", "iters = []\n", "for ra in rho_sweep:\n", " _cnt = {\"n\": 0}\n", " def _hb(pp, _ra=ra):\n", " _cnt[\"n\"] += 1\n", " return mfem_study.hess_blocks(pp, _zc, _zp, _ra)\n", " p = np.vstack([_u0, _a0, _ll0])\n", " sqp_mfem(p, lambda pp, _ra=ra: mfem_study.energy(pp, _zc, _zp, _ra),\n", " _hb, lambda pp, _ra=ra: mfem_study.grad_blocks(pp, _zc, _zp, _ra),\n", " tolerance=1e-6, max_iter=MAXIT, do_line_search=True)\n", " iters.append(_cnt[\"n\"])\n", "\n", "for ra, it in zip(rho_sweep, iters):\n", " tag = \" (hit max_iter -- stalled)\" if it >= MAXIT else \"\"\n", " print(f\"rho_aug = {ra:9.0f}: {it:2d} SQP iterations{tag}\")\n", "\n", "labels = [\"0\", \"1\", \"10\", \"100\", \"1e3\", \"1e4\", \"1e5\", \"1e6\"]\n", "plt.figure(figsize=(6.5, 4))\n", "plt.plot(range(len(rho_sweep)), iters, \"o-\", color=\"tab:blue\")\n", "plt.axhline(MAXIT, ls=\"--\", c=\"0.6\", lw=1, label=f\"max_iter ({MAXIT}) = stalled\")\n", "plt.xticks(range(len(rho_sweep)), labels)\n", "plt.xlabel(r\"augmentation weight $\\rho_{\\mathrm{aug}}$\")\n", "plt.ylabel(\"SQP iterations to converge\")\n", "plt.title(\"Augmented-Lagrangian regularization study (single hard step)\")\n", "plt.legend(); plt.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "id": "e1034348", "metadata": {}, "source": [ "## Compare a few frames\n", "\n", "The two methods agree closely: the pinned beam swings down and oscillates under\n", "gravity. MFEM reproduces the FEM motion while solving only in the small subspace\n", "with an element-local elastic energy." ] }, { "cell_type": "code", "execution_count": 9, "id": "5c05b335", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:47:52.174165Z", "iopub.status.busy": "2026-06-09T05:47:52.174110Z", "iopub.status.idle": "2026-06-09T05:47:52.250325Z", "shell.execute_reply": "2026-06-09T05:47:52.250116Z" } }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sel = [0, num_steps//4, num_steps//2, num_steps-1]\n", "fig, axes = plt.subplots(len(sel), 1, figsize=(7, 1.8*len(sel)), sharex=True, sharey=True)\n", "for ax, fi in zip(axes, sel):\n", " ax.triplot(fem_frames[fi][:,0], fem_frames[fi][:,1], T, color=\"0.7\", lw=0.6)\n", " ax.triplot(mfem_frames[fi][:,0], mfem_frames[fi][:,1], T, color=\"C0\", lw=0.6)\n", " ax.plot([], [], color=\"0.7\", label=\"FEM\"); ax.plot([], [], color=\"C0\", label=\"MFEM\")\n", " ax.set_title(f\"step {fi}\", fontsize=9); ax.set_aspect(\"equal\"); ax.legend(loc=\"upper right\", fontsize=7)\n", "fig.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "id": "d897884d", "metadata": {}, "source": [ "## Animation\n", "\n", "A side-by-side animation of the dropping beam (FEM in gray, MFEM in blue)." ] }, { "cell_type": "code", "execution_count": 10, "id": "73400a33", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:47:52.251283Z", "iopub.status.busy": "2026-06-09T05:47:52.251226Z", "iopub.status.idle": "2026-06-09T05:47:53.110938Z", "shell.execute_reply": "2026-06-09T05:47:53.110690Z" } }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "allpts = np.concatenate(mfem_frames + fem_frames, axis=0)\n", "xmin, ymin = allpts.min(0) - 0.1; xmax, ymax = allpts.max(0) + 0.1\n", "\n", "fig, ax = plt.subplots(figsize=(7, 3))\n", "ax.set_xlim(xmin, xmax); ax.set_ylim(ymin, ymax); ax.set_aspect(\"equal\")\n", "fem_lines = ax.triplot(fem_frames[0][:,0], fem_frames[0][:,1], T, color=\"0.7\", lw=0.6)\n", "mfem_lines = ax.triplot(mfem_frames[0][:,0], mfem_frames[0][:,1], T, color=\"C0\", lw=0.6)\n", "ax.plot([], [], color=\"0.7\", label=\"FEM\"); ax.plot([], [], color=\"C0\", label=\"MFEM\")\n", "ax.legend(loc=\"upper right\")\n", "\n", "def draw(fi):\n", " ax.clear()\n", " ax.set_xlim(xmin, xmax); ax.set_ylim(ymin, ymax); ax.set_aspect(\"equal\")\n", " ax.triplot(fem_frames[fi][:,0], fem_frames[fi][:,1], T, color=\"0.7\", lw=0.6)\n", " ax.triplot(mfem_frames[fi][:,0], mfem_frames[fi][:,1], T, color=\"C0\", lw=0.6)\n", " ax.set_title(f\"drop under gravity - step {fi}\", fontsize=10)\n", " return []\n", "\n", "anim = animation.FuncAnimation(fig, draw, frames=range(0, num_steps, 2), interval=60, blit=False)\n", "utils.show_video(fig, anim, \"media/24_compare.mp4\", fps=24)" ] }, { "cell_type": "markdown", "id": "266200a8", "metadata": {}, "source": [ "## So why did we do all this? — iterations to converge\n", "\n", "We compare the solver iterations for a single backward-Euler step as the material\n", "stiffens: **full Newton** on the FEM energy vs the **SQP** on the MFEM blocks.\n", "\n", "A caveat, stated up front: **iteration count is not where the mixed method wins.**\n", "Full Newton converges quadratically and is hard to beat on raw count — here\n", "MFEM is comparable (slightly fewer), and if you push the per-step deformation hard\n", "the local-global SQP actually needs *more*. The real payoff is the **cost of each\n", "iteration**: MFEM evaluates the elastic energy / gradient / Hessian at only the\n", "`k` cubature points (not all `T` triangles) and condenses the element-local stretch,\n", "so each iteration is far cheaper and — crucially — **independent of mesh\n", "resolution**. The subspace shrinks the linear solve to `m` DOFs; the cubature shrinks\n", "the elastic assembly from `T` elements to `k`." ] }, { "cell_type": "code", "execution_count": 11, "id": "7eda74fb", "metadata": { "execution": { "iopub.execute_input": "2026-06-09T05:47:53.111911Z", "iopub.status.busy": "2026-06-09T05:47:53.111843Z", "iopub.status.idle": "2026-06-09T05:47:54.588566Z", "shell.execute_reply": "2026-06-09T05:47:54.588343Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ym = 1e+04: FEM Newton = 15 iters, MFEM SQP = 40 iters\n", "ym = 1e+05: FEM Newton = 21 iters, MFEM SQP = 40 iters\n", "ym = 1e+06: FEM Newton = 27 iters, MFEM SQP = 24 iters\n", "ym = 1e+07: FEM Newton = 11 iters, MFEM SQP = 5 iters\n", "ym = 1e+08: FEM Newton = 3 iters, MFEM SQP = 3 iters\n", "ym = 1e+09: FEM Newton = 3 iters, MFEM SQP = 3 iters\n", "\n", "Per iteration the FEM solve touches all 546 triangles and a 60-dof system;\n", "MFEM touches only 400 cubature points (1x fewer) and condenses the stretch element-locally.\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# One backward-Euler step from rest; sweep stiffness, count solver iterations.\n", "ym_sweep = [1e4, 1e5, 1e6, 1e7, 1e8, 1e9]\n", "u0, a0, ll0 = mfem.rest_state()\n", "z_curr = z_prev = u0\n", "\n", "fem_its, mfem_its = [], []\n", "for ym_i in ym_sweep:\n", " mu_i, lam_i = sk.ympr_to_lame(ym_i, pr)\n", " mu_s = np.full((T.shape[0], 1), mu_i)[cI]\n", " lam_s = np.full((T.shape[0], 1), lam_i)[cI]\n", "\n", " fem_s = FEMBeam(B, q, Ge, J, kin_pre, BQB, Bb, h, mu_s, lam_s, vol, material, dim, X, T)\n", " mfem_s = MFEMBeam(GJB, GJq, Ci, kin_pre, BQB, Bb, w, Wd, Wi, h, mu_s, lam_s, vol,\n", " material, nz, na, dim, B, X, T, q, rho_aug=rho_aug)\n", "\n", " # FEM: full-Newton iterations to converge\n", " _, info = fem_s.step(z_curr, z_prev, return_info=True)\n", " fem_its.append(info[\"iters\"] + 1)\n", "\n", " # MFEM: SQP iterations to converge (count hess_blocks calls = iterations)\n", " _cnt = {\"n\": 0}\n", " def _hb(pp):\n", " _cnt[\"n\"] += 1\n", " return mfem_s.hess_blocks(pp, z_curr, z_prev, rho_aug)\n", " p = np.vstack([z_curr, a0, ll0])\n", " sqp_mfem(p, lambda pp: mfem_s.energy(pp, z_curr, z_prev, rho_aug),\n", " _hb, lambda pp: mfem_s.grad_blocks(pp, z_curr, z_prev, rho_aug),\n", " tolerance=1e-6, max_iter=40, do_line_search=True)\n", " mfem_its.append(_cnt[\"n\"])\n", "\n", "for ym_i, fi, mi in zip(ym_sweep, fem_its, mfem_its):\n", " print(f\"ym = {ym_i:.0e}: FEM Newton = {fi} iters, MFEM SQP = {mi} iters\")\n", "print(f\"\\nPer iteration the FEM solve touches all {T.shape[0]} triangles and a \"\n", " f\"{B.shape[1]}-dof system;\\nMFEM touches only {cI.shape[0]} cubature points \"\n", " f\"({T.shape[0]/cI.shape[0]:.0f}x fewer) and condenses the stretch element-locally.\")\n", "\n", "plt.figure(figsize=(6.5, 4))\n", "plt.semilogx(ym_sweep, fem_its, \"o-\", label=\"FEM (full Newton)\")\n", "plt.semilogx(ym_sweep, mfem_its, \"s-\", label=\"MFEM (SQP)\")\n", "plt.xlabel(\"Young's modulus (material stiffness)\")\n", "plt.ylabel(\"iterations to converge (one step)\")\n", "plt.title(\"Iterations to converge vs stiffness\")\n", "plt.ylim(bottom=0); plt.legend(); plt.tight_layout(); plt.show()" ] }, { "cell_type": "markdown", "id": "d49522cf", "metadata": {}, "source": [ "## Takeaways\n", "\n", "* **Mixed FEM** trades the dense subspace elastic Hessian for an element-local\n", " one ($H_z$ block-diagonal) plus a cheap constraint, so each iteration is a\n", " single small dense subspace solve.\n", "* The **flat `sqp_mfem`** solver eliminates the Lagrange multiplier: you give it\n", " $[\\mathbf{u};\\mathbf{a}]$ and the five Hessian blocks\n", " `[H_u, H_z, G_u, G_z, G_zi]`, and it condenses the diagonal $G_z$ into the\n", " position update internally.\n", "* Each method is a small simulator object — `FEMBeam` driving `newton_solver`,\n", " `MFEMBeam` driving `sqp_mfem` — built from the same flat simkit pieces,\n", " plus the stretch map and constraint for MFEM.\n", "\n", "See `examples/interactive_demos/012_interactive_mixed_fem.py` for a live,\n", "mouse-draggable version of this solver.\n", "\n", "* The augmented-Lagrangian gradient w.r.t. positions is $\\rho_{\\text{aug}}\\,\\frac{\\partial S}{\\partial u}^\\top W\\mathbf c$ — weighting the residual by $W$ **once**, matching the $\\tfrac12\\rho_{\\text{aug}}\\mathbf c^\\top W\\mathbf c$ penalty and its Gauss-Newton Hessian (`tests/test_mfem_blocks.py` pins this down).\n", "* `rho_aug` trades line-search robustness against conditioning: a modest value rescues stalls on hard steps, but too large a value slows the solve.\n", "\n", "" ] } ], "metadata": { "kernelspec": { "display_name": "simkit", "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.9" } }, "nbformat": 4, "nbformat_minor": 5 }