Data-driven subspace simulation
We begin with a soft body whose motion takes 280 position values to describe. Then we watch what it actually does, learn the smaller structure hidden in those motions, and use it to simulate the same body with fewer coordinates: first with PCA, then with a neural subspace. By the end, all three run side by side in the browser.
This interactive note explores how a deformable body can be simulated through a compact family of shapes learned from data. It compares a full finite-element reference with two reduced models: a linear PCA subspace and a stiffness-conditioned neural subspace. Both retain the same hyperelastic force model while replacing the full dynamical state with a much smaller one. The complete experiment—data collection, model training, simulation, and visualization—runs in the browser with WebGPU.
- Full configuration
- 140 nodes / 280 positional DOFs
- Dataset
- 4 launches × 2 materials × 12 snapshots
- Reduced configuration
- 2–16 generalized coordinates
- Neural decoder
- (q, μ) → 24 → 280
Terminology. A degree of freedom is one independent scalar variable of the configuration. A coordinate is the number used to express that variable in a chosen parameterization. Thus x ∈ ℝ280 represents 280 positional DOFs; q ∈ ℝk contains k generalized coordinates—the k DOFs of the reduced model. A rank-k PCA basis and a decoder with latent dimension k therefore both produce k generalized coordinates.
What is a subspace?
If we think of every possible shape the body can take as a point in a high-dimensional space, a subspace is a smaller family of shapes within that space. Subspace simulation restricts the body's motion to this family and solves how the whole shape moves through it, rather than advancing every vertex independently.
Why simulate in a subspace?
Move the expensive solve into fewer variables.
Deformable simulation normally solves for the motion of every vertex. A subspace represents the body's motion with a much smaller set of variables, turning the large system into a small reduced solve. As the mesh grows, the cost of solving for every positional DOF rises quickly; in many deformable-body problems, moving the solve into this smaller space produces measurable speedups.[11][12]
Fit a compact model from observations of the system.
A snapshot sequence may come from a high-resolution solver, motion capture, cameras, or instrumented experiments. Learning a compact parameterization identifies a low-dimensional kinematic model. Inputs, forces, and richer measurements can extend the same workflow toward dynamic or material identification. Here the snapshots are simulated and the Neo-Hookean force law remains specified; the learned object is the kinematic manifold.[3][4]
140 nodes · 234 triangles · 280 positional DOFs
Building the full-space solver.
It starts with one triangle. Rest edges form Dm; current edges form Ds. Their ratio F = DsDm−1 measures local stretch, shear, and rotation. J = det(F) is the signed area ratio and must remain positive.
ψ is strain energy per unit rest area. This compressible Neo-Hookean density—a hyperelastic model whose energy resists stretch and area change—is evaluated in two dimensions. μ controls shear, λ controls area change, and the experiment uses λ = 3μ.[1][13]
[[+1.00, +0.15], [+0.00, +0.85]][[+1.00, +0.15], [+0.00, +0.85]][[+1.00, +0.00], [+0.00, +1.00]]- J = det(F)
- 1.000
- Rest area
- 0.425
- Signed area
- 0.425
- ψ(F)
- 0.000
Differentiating ψ with respect to F gives the first Piola–Kirchhoff stress P = μ(F − F−T) + λ ln(J)F−T. P is the derivative ∂ψ/∂F; it converts an element's deformation into forces measured against its rest shape. Multiplying P by the rest-shape gradients yields three vertex forces whose sum is zero before external forces are added.
let F = Ds * inverse(Dm);
let J = determinant(F);
let inverseTranspose = transpose(inverse(F));
let P = mu * (F - inverseTranspose)
+ lambda * log(J) * inverseTranspose;
// Each rest-shape gradient maps P to one nodal force.
triangleForce[i] = -restArea * P * gradN[i];Numerical safeguardThe exact energy used near element collapse
Write the volumetric term as φ(J) = −μ ln J + ½λ(ln J)². The live shader uses J0 = 0.16 and continues that function linearly below the threshold:
φc(J) = φ(J0) + φ′(J0)(J − J0), J < J0
This piecewise energy produces the shader's J* = max(J, 0.16) stress exactly. A quadratic barrier ψb = 14μ[min(J − 0.24, 0)]² contributes Pb = 28μ min(J − 0.24, 0) cof(F). Both energies and their stresses are continuous; their tangents change at the thresholds. The explicit rollout stays above J = 0.24.
These continuations make the small explicit demo robust near collapse. Invertible and stable finite-element formulations provide broader treatments for large deformation and inversion.[20][21]
01B · Many triangles become one coupled system.
A triangle only knows about its three vertices. The body appears when all 234 triangles share vertices and their energy contributions are added.
fint(x) = −∇E(x)
x contains the 280 vertex-position values, and At is triangle t's rest area. Differentiating the total energy gathers every neighboring triangle's contribution into the force at each shared vertex.
Gravity, contact, and damping join that elastic force, giving Mẍ = f(x, ẋ). The mesh now has 280 coupled positional DOFs. This is the full-space problem we want to reduce.
A = M / h² + ∇²E(x)
An implicit step finds the next configuration through a coupled equilibrium solve. For a step of duration h, r(x) is its residual, Δx is one Newton correction, and A = ∂r/∂x is its tangent matrix. The displayed A is the conservative mass-plus-elastic part; fully implicit damping and contact add their own tangent terms. Each iteration has a 280 × 280 matrix whose elastic blocks are sparse because a triangle couples only its three vertices.
The figure shows the structural pattern of the implicit Newton matrix. A numerical value may be zero at a particular configuration; the plotted entries are the positions that triangle coupling can populate.
The live reference uses a lumped mass matrix—one diagonal mass per vertex—and eight small semi-implicit substeps per display frame. Because M is diagonal, a = M−1f is an independent division at each vertex. The solver then advances velocity and position.
Choose how to build the reduced space
Let’s collect the data first.
Reduced models can be data-driven or data-free. Sharp et al., for example, learn reduced-order kinematics directly from the governing energy, without a snapshot dataset.[8] This article follows the data-driven route: record full-order meshes, then use them to construct the PCA basis and the conditioned neural decoder.
Four area-preserving launch deformations are run at μ = 7 and μ = 15. We save the initial mesh and eleven later snapshots from each trajectory. The resulting matrix X ∈ ℝ96×280contains the full positions the reduced models should represent.
Corresponding soft and stiff trajectories share a launch and sampling time. The neural model later gives each synchronized pair one code and supplies stiffness as a separate input.
copyBufferToBuffer(position, dataset[firstSample]);
for (let step = 0; step < 440; step++) {
advanceFullOrder(stiffness);
if ((step + 1) % 40 === 0) {
copyBufferToBuffer(position, dataset[nextSample]);
}
}96 recorded meshes · 280 position values each
How many ways did the body really move?
Overlay the 96 meshes we just collected. Every snapshot contains 280 position values, yet those values do not wander independently: when the body bends, many vertices move together. If those coordinated displacements repeat, we can store the patterns once and describe each mesh with only a few weights.
First average the recorded meshes to get x̄. Subtract that average from each snapshot and what remains is a displacement field: one arrow per vertex showing how that shape differs from x̄. PCA searches all 96 fields for the directions that account for the most variation. Each direction ui is a whole-body displacement mode—not one vertex moving, but all 140 moving together in a learned pattern.
For this experiment, each position is weighted by the square root of its lumped nodal mass before PCA, so the fit respects how mass is distributed across the body. Keeping the first k modes forms Uk = [u1 … uk]. A mesh is then rebuilt as x(q) = x̄ + Ukq, where q contains the k signed mode weights.
Recorded motion is one way to find these directions. Classical modal analysis derives small-vibration modes around an equilibrium; modal derivatives extend them toward larger deformations. We use mass-weighted PCA here because it extracts the recurring motions from the data we just collected.[12]
q = UkTM(x − x̄)
M is the diagonal lumped mass matrix and I is the k × k identity. The first equation fixes the scale of every mode; the second finds the closest mesh the basis can represent in the same mass metric. The rank-4 PCA basis retains more than 99% of the mass-weighted variance in this dataset. Every mode, decoder initialization, and reported error in this article was regenerated with this mass-weighted basis.
Average mesh
The average vertex positions across all 96 recorded meshes.
Mode basis
k learned whole-body displacement patterns arranged as columns.
Mode weights
k signed numbers—the generalized coordinates of the reduced model.
var x = mean[node];
for (var k = 0u; k < latentK; k++) {
x += basis[node * MAX_K + k] * q[k];
}Build a full deformation by hand.
The coral outline below is one recorded mesh. Each slider changes one qi, scaling an entire displacement field. Four numbers produce all 280 reconstructed position values.
We can rebuild a deformation from q. How do those weights become a simulation?
The decoded shape x(q) = x̄ + Uq describes every mesh shape available to the reduced body. We can then evaluate elasticity, gravity, damping, and contact on that full mesh, producing the 280-value force vector f.
What should this force do to the few weights q? Take one weight qk and increase it slightly. Every vertex moves along mode uk. The dot product ukTf measures how much the full force favors that motion, giving the force acting on qk. A positive value accelerates the body toward larger qk; a negative value accelerates it toward smaller qk. For conservative forces, the same number is −∂E/∂qk: the downhill slope of the full energy along that mode.
-16.6178Mq = UTMU
fq = UTf
here: Mq = I, so q̈ = fq
Doing this for every mode gives fq = UTf: k forces acting on k weights. The full mesh's inertia becomes Mq = UTMU = I because the basis is mass-orthonormal. For any other basis, the k × k reduced mass matrix remains in the solve. Here each generalized force gives the corresponding weight acceleration; integration advances them and x̄ + Uq becomes the next mesh. An implicit solver uses the same reduced energy slopes while minimizing its time-step objective over q.
fq = transpose(U) * fullForce;
// Uᵀ M U = I after mass-weighted PCA.
qAcceleration = fq;
qVelocity += dt * qAcceleration;
q += dt * qVelocity;The linear subspace has one fixed set of directions.
U is the same for every shape and for both material conditions. A deformation family that bends away from this plane requires additional modes. Material, pose, boundary conditions, and actuation must also fit inside the same fixed generalized-coordinate system. This is where we replace the plane with a learned deformation map.
From a fixed basis to a learned manifold
Going neural.
Keep q as the compact coordinates and replace x̄ + Uq with a neural decoder x(q, c). Its local motion directions can change across the deformation family and respond to a known condition such as material stiffness c. During simulation, these local directions take the role that the PCA modes played in force projection and reduced dynamics.[17]
Before the implementation, let's recap the architecture.
This experiment uses an auto-decoder: a latent-variable model containing a decoder network and a table of trainable latent codes. Training instance i owns an unknown code qi. Gradient descent optimizes every qi together with the shared decoder weights θ so Dθ(qi, ci) reconstructs the observed target xi. An autoencoder obtains its code from a learned encoder qi = Eφ(xi), whose weights are φ.[5]
xi is a full observation, qi is its optimized latent location, ci is any known condition, and θ is shared by every instance. In the live trainer, R adds 10−6 L2 decay to the input and output weights, 3 × 10−4 smoothing between adjacent codes on each trajectory, and 10−6 L2 decay to the codes.
Observation
The full target that training asks the decoder to reconstruct.
Latent code
A free k-vector locating training instance i on the learned family.
Shared / known
θ is learned across every instance; condition cᵢ is supplied with the data.
The shared weights describe the learned family; each code selects one point on it. Several observations can share condition c while their optimized codes give them distinct latent locations. A new measured observation can receive a q by optimizing it with θ fixed or through an encoder. During simulation, q becomes the dynamic configuration advanced by the physics solve.
04A · Use the latent code as this body's generalized coordinates.
Here x is a 280-value mesh configuration, q ∈ ℝk is its vector of learned generalized coordinates, and c is a known material condition. The MLP gθ maps (q, c) to a 280-value displacement. The rest configuration xrest anchors the chart:
Subtracting gθ(0, c) anchors q = 0 at the rest mesh for every c. The network is the direct map (q, c) → 24 tanh units → 280 displacement values; x(q, c) is its decoded configuration.
04B · Let material stiffness reshape the learned subspace.
A condition is an extra known input that lets the decoder change its family of shapes with a property we choose. Here that property is material stiffness. During simulation, stiffness does two jobs. The Neo-Hookean model uses it to calculate forces, and the decoder uses it to shape the space in which those forces are solved. A soft and stiff snapshot recorded from the same launch and time share one latent code qj. The code identifies the motion sample; the stiffness condition tells the decoder which material version of that state to produce.
The dataset therefore has 96 snapshots but only 48 codes. Values between the two training stiffnesses ask the decoder to interpolate. Sharing codes assumes the paired trajectories remain comparable over time; the diagnostic in Section 02 shows when they begin to separate.
PCA initializes the latent codes and a near-linear set of MLP weights so browser training begins from a well-scaled chart. Adam then updates the codes and every decoder weight. The trained runtime map is the MLP, and its learned launch code initializes q at the start of a rollout. PCA supplies the initialization. This low-to-full neural kinematic map is the subspace representation used by direct neural reduced models.[6][8]
let base = tanh(bias[h] + conditionWeight[h] * c);
let hidden = tanh(bias[h] + conditionWeight[h] * c
+ dot(latentWeight[h], qCode[j]));
scaledPrediction[d] += outputWeight[d, h] * (hidden - base);
scaledTarget[d] = 4.0 * (pairedSnapshot[j][materialIndex][d] - rest[d]);
error[d] = scaledPrediction[d] - scaledTarget[d];
adamUpdate(qCode[j], latentGradient);
adamUpdate(weights, decoderGradient);The factor four is a numerical training scale used by the shader; runtime decoding multiplies the MLP output by ¼ and restores the displacement to its physical scale. Across 3,000 Adam steps, the weight learning rate decays from 0.008 toward 0.0008 and the code learning rate from 0.00025 toward 0.000025.
04C · Turn the learned map into a reduced solver.
At the current q, each column of the decoder Jacobian JD(q, c) = ∂x/∂q is one 280-value motion produced by changing a single neural coordinate. These state-dependent directions take the place of the fixed PCA modes. Their dot products with the assembled force give the generalized forces, and their mass-weighted dot products give the reduced inertia.[6][7][17]
JDTMJD is the dense k × k tangent mass matrix. The Jacobian changes as q moves, so ẍ = JDq̈ + J̇Dq̇. The term J̇Dq̇ accounts for that curved path. Solving gives q̈; integration advances q̇ and q before the next complete mesh is decoded.
GPU deep diveFactor the projection through 24 hidden units
The one-hidden-layer architecture was chosen for its derivatives as well as its capacity. Its Jacobian and curvature are analytic, and every runtime matrix can be factored through the 24-value hidden state.
G = transpose(W2) * M * W2; // cache after training
JD = W2 * diag(tanhPrime(z)) * Wq / 4; // exact 280 × k Jacobian
A = diag(tanhPrime(z)) * Wq; // 24 × k local tangent
b = tanhSecond(z) * square(Wq * qVelocity); // hidden curvature
hiddenForce = transpose(W2) * fullForce - G * b / 4;
fq = transpose(A) * hiddenForce / 4;
Mq = transpose(A) * G * A / 16;G depends only on the trained output weights and nodal masses, so it is computed once after training. Runtime projection stays inside the 24-dimensional hidden space and the k reduced coordinates. The 280 × k Jacobian never occupies a buffer, and all substeps for one display frame share one WebGPU compute pass.
The live solver uses two common safeguards. Light regularization keeps the reduced solve stable when the decoder's local motion directions become nearly redundant. A trust region keeps q near the part of the learned space represented in training. The validation panel also repeats a new motion without the main regularizer, showing how strongly that safeguard affects the rollout.
The model sees soft and stiff material during training, then simulates a stiffness between them. This checks whether the condition changes the learned shape family smoothly.
The model starts from a fifth launch that never enters PCA or neural training. This checks whether the learned subspace can represent a nearby motion it did not memorize.
Both rollouts are compared against the full simulation over time. Training is accepted only if the meshes remain finite, preserve triangle orientation, and stay physically bounded.
Reconstructing recorded meshes is only the first test. A useful neural subspace must also remain smooth enough for forces to project through it and stable enough to roll forward. That is why we judge the decoder by complete simulations as well as reconstruction loss.[9]
One simulation step, side by side
Stage breakdown.
A reduced simulation is a hybrid pipeline. Geometry, material forces, contact, and rendering still use the complete 140-vertex mesh. The compact coordinates take over for the acceleration solve and integration, then produce the next complete mesh.
The main difference is the route through one step. The full-order method carries x and v straight through the solve. PCA and the auto-decoder first decode q, assemble the same mesh forces, project them back to q, and advance q before decoding again. The table follows those routes stage by stage.
Here x and v are full position and velocity vectors; q and q̇ are reduced position and velocity; a and q̈ are their accelerations; subscript 0 marks initialization; c is the fixed material condition; JD = ∂x/∂q is the decoder Jacobian; and h is one integration substep.
| Stage | Full order280 positional DOFs | PCAk generalized coordinates | Auto-decoderk generalized coordinates · c fixed |
|---|---|---|---|
| 01Initialize | fullx₀, v₀ | reducedq₀ = UᵀM(x₀ − x̄) | reducedlearned q₀ |
| 02Decode kinematics | fullx and v are stored | reduced→full x = x̄ + Uq | reduced→full x = x(q, c) |
| 03Assemble force | fullf(x, v) ∈ ℝ²⁸⁰ | fullsame f(x, v) | fullsame f(x, v) |
| 04Project + solve | fulla = M⁻¹f | full→reduced q̈ = Uᵀf | full→reduced Mqq̈ = JDᵀ(f − MJ̇Dq̇) |
| 05Integrate | fullv ← v + h a | reducedq̇ ← q̇ + h q̈ | reducedq̇ ← q̇ + h q̈ |
| 06Render | fulldraw x | reduced→full decode q, draw x | reduced→full decode (q, c), draw x |
In this experiment, the reduced models can use less time resolution. The full mesh contains fast, element-scale deformation modes, so one 1 / 90 s display frame is divided into eight 1 / 720 s updates. PCA and the neural subspace omit those high-frequency directions and remain stable with one 1 / 90 s update. That removes seven force, projection, and integration passes per frame in addition to shrinking the state from 280 positional DOFs to k generalized coordinates. On larger, finer meshes, the full-space stability limit and the cost of each solve make both savings increasingly important.
The live comparison begins in matched-contact mode, where all three methods use the same floor-and-wall penalty forces. A stabilized-reference option adds node-wise position and velocity projection to the full solver after integration. RMS values in that mode include the resulting contact-model difference. Robust reduced contact is a separate model-reduction problem.[14]
Executable experiment
Collect, train, then run the three solvers.
All three solvers use the same floor-and-wall penalty response; RMS is directly comparable.
- PCA variance retained
- —
- Decoder coordinate MSE · su²
- —
- Browser training time
- —
- Midpoint μ = 11 · PCA vertex RMS
- —
- Midpoint μ = 11 · neural vertex RMS
- —
- Unseen launch · initial neural fit
- —
- Unseen launch · PCA vertex RMS
- —
- Unseen launch · neural vertex RMS
- —
- Unseen neural · ε scale 0
- —
Where the time goes on this device
The 140-node body fits in one 256-invocation workgroup. Rest-shape triangle operators and node adjacency are cached once. PCA assigns sixteen lanes to every modal dot product; its mass-orthonormal basis makes the reduced mass the identity. The neural kernel reduces every hidden projection over eight lanes and builds independent reduced-mass entries in parallel. One dispatch advances a complete substep for each method.
Every measured row advances the same 1 / 90 s of simulated time per frame. The full solver uses eight 1 / 720 s substeps; PCA and the neural solver each use one 1 / 90 s step. The frame column also includes one 512 × 512 render and one queue submission. The simulation column batches 180 equivalent frames into one command buffer and omits rendering. Twelve warm-up frames are excluded from both measurements.
This 140-node reference uses a diagonal explicit full-space update. PCA and the neural model still evaluate all 234 triangles, followed by decoding and force projection. The reduced rows now do that work once per frame instead of eight times; the benchmark measures whether those saved passes outweigh their decoding and projection overhead on this device.
Large implicit systems move substantial work into the linear solve, where reducing 280—or millions of—unknowns to k changes the cost. Cubature and ECSW also replace the all-triangle force pass with a weighted sample [2] [15].
Results are measured locally in this browser with k = 4 generalized coordinates. Simulation and rendering are included in frame FPS; display refresh pacing is excluded. Every row advances the same simulated duration. Contact mode: matched penalty.
Where the reduction leads
We began with a soft body whose state required 280 positional DOFs. We recorded how it moved, then built two reduced models that could approximate the same motion using only four generalized coordinates. PCA gave us a fixed linear family of shapes. The neural decoder made that family more expressive and allowed material stiffness to reshape it.
The central idea is now visible: describe the body using a smaller family of shapes, then solve its motion within that family. As systems grow, fewer unknowns and larger stable time steps can provide substantial speedups. When the subspace is learned from data, it can also capture behavior observed in a high-fidelity simulator or a physical system.
The space beyond this experiment is large. Contacts produce local deformations that a reduced model may never have seen. Complex materials require richer shape families. Models learned from physical measurements must handle noise, incomplete observations, and unknown dynamics. Generalization, contact handling, hyper-reduction, and learning from real data remain active research directions. Continuous neural fields are also extending reduced models beyond one fixed mesh.[18][19]
Robotics gives these questions new urgency. Training robots requires enormous amounts of simulation, while deployment demands models that closely reflect the physical system. Performance and system identification therefore meet in the same problem. Subspace simulation addresses both, which may be where this long-standing idea finds its most consequential role.
- Li, Jiang, Luo, Du, Yu, Kovačič, and Xie. Physics-Based Simulation, reduced-DOF solid tutorial. Version 1.0.3, 2026.
- An, Kim, and James. “Optimizing Cubature for Efficient Integration of Subspace Deformations.” 2008.
- Bai et al. “Dynamic Mode Decomposition for Compressive System Identification.” 2017.
- Abdulali, Atadjanov, Lee, and Jeon. “Measurement-based Hyper-elastic Material Identification and Real-time FEM Simulation for Haptic Rendering.” VRST, 2019.
- Park et al. “DeepSDF: Learning Continuous Signed Distance Functions for Shape Representation.” 2019. Auto-decoder formulation.
- Fulton et al. “Latent-space Dynamics for Reduced Deformable Simulation.” 2019.
- Shen et al. “High-order Differentiable Autoencoder for Nonlinear Model Reduction.” 2021.
- Sharp et al. “Data-Free Learning of Reduced-Order Kinematics.” 2023.
- Lyu, Zhao, Xian, Cen, Cai, and Fang. “Accelerate Neural Subspace-Based Reduced-Order Solver of Deformable Simulation by Lipschitz Optimization.” ACM TOG, 2024.
- Epic Games. “Machine Learning Cloth Simulation Overview.” Unreal Engine documentation.
- Krysl, Lall, and Marsden. “Dimensional Model Reduction in Non-linear Finite Element Dynamics of Solids and Structures.” 2001.
- Barbič and James. “Real-Time Subspace Integration for St. Venant–Kirchhoff Deformable Models.” 2005.
- Sifakis and Barbič. “FEM Simulation of 3D Deformable Solids: A Practitioner’s Guide to Theory, Discretization and Model Reduction.” 2012.
- Sheth et al. “Fully Momentum-Conserving Reduced Deformable Bodies with Collision, Contact, Articulation, and Skinning.” 2015.
- Farhat, Chapman, and Avery. “Structure-Preserving, Stability, and Accuracy Properties of the Energy-Conserving Sampling and Weighting Method.” 2015.
- Holden, Duong, Datta, and Nowrouzezahrai. “Subspace Neural Physics: Fast Data-Driven Interactive Simulation.” SCA, 2019.
- Lee and Carlberg. “Model Reduction of Dynamical Systems on Nonlinear Manifolds Using Deep Convolutional Autoencoders.” Journal of Computational Physics 404, 2020.
- Chen et al. “CROM: Continuous Reduced-Order Modeling of PDEs Using Implicit Neural Representations.” ICLR, 2023.
- Chang, Chen, Wang, Chiaramonte, Carlberg, and Grinspun. “LiCROM: Linear-Subspace Continuous Reduced Order Modeling with Neural Fields.” SIGGRAPH Asia, 2023.
- Irving, Teran, and Fedkiw. “Invertible Finite Elements for Robust Simulation of Large Deformation.” SCA, 2004.
- Smith, de Goes, and Kim. “Stable Neo-Hookean Flesh Simulation.” ACM TOG 37(2), 2018.