Full 3D de Rham complex
Π⁰ over H¹, Π¹ over H(curl), Π² over H(div), Π³ over L². The complete discrete de Rham complex, lowest order, lowest friction.
A small, dependency-free JavaScript reference implementation of Π⁰, Π¹, Π², Π³ for the 3D de Rham complex. Commuting projections that keep the boundary values, or stay stable for rough data. Built for engineers who care about the math, with the evidence next to the claims.
What you can do
Every recipe is a short program that runs, shown with what it prints and what it costs. The test suite runs them, so they say what the library does today.
Capabilities
One library. Four form degrees. Three trace spaces. Zero transpilation. The same code runs in Node 24+, the browser, and the sandboxed playground.
Π⁰ over H¹, Π¹ over H(curl), Π² over H(div), Π³ over L². The complete discrete de Rham complex, lowest order, lowest friction.
StableProjector and the canonical operators reproduce the vertex values u(v), edge circulations ∫_e u·t ds and face fluxes ∫_f u·n dA on every boundary simplex to machine precision. TracePreservingProjector keeps the discrete trace while asking for less of u there.
Vertex, edge, and face duality functionals on P¹, N₀, and RT₀, built from the barycenter tent μ and the local mass matrix on each star.
LU solve, 3×3 inverse, barycentric gradients, surface differential operators — every kernel routine is hand-rolled in pure JavaScript.
Hot-path code paths. Sub-millisecond per projection on 10k tetrahedra.
O(log N) point-in-tet queries after a one-time balanced tree build. Pick any point inside the unit cube and get the projected value in microseconds.
Canonical interpolation of any degree is cheap. The locally bounded Arnold–Guzmán projection and the trace-preserving operator reach any degree too, at the cost of a local solve per entity (seconds at degree 1). Hand-written .d.ts for every module.
Get started
npm install,No build step. No transpiler. No peer-dep negotiation. Drop the lib into any Node 24+ project, hand it your vertices and tetrahedra, and call project(u, point, cell, l) for the form degree you need — the guide shows how to choose the operator and check the result.
01# Node 24+ (Node 26 recommended)02npm install traceprojectorArchitecture
Every projector splits into a boundary-preserving part and an interior ring part. Both are computed in stable local solves on Alfeld- or Worsey–Farin-subdivided patches — no global system, no iterative refinement.
The master equation
Π_∂ˡ prescribes the boundary data exactly. Π_ringˡ is the interior projector with vanishing trace. Together they form a single, commuting operator.
Prescribes the boundary data exactly. Built on Alfeld (boundary faces) or Worsey–Farin (bulk tet) splits.
Zero-trace interior operator: bounded local problems on stars of cells, vanishing trace on the boundary. Decouples from boundary geometry.
eq. 6.25 — vertex scalar duality
eq. 6.31 — Whitney edge tangential
eq. 6.36 — Raviart–Thomas face flux
The discrete operators {grad, curl, div} and the projectors {Π⁰, Π¹, Π², Π³} commute term-by-term on every mesh.
Algorithm and analysis from Ern, Guzmán, Potu (2026) — arXiv:2604.28103.
The playground runs the library in your browser. Give five operators a field that is infinite at a vertex and see which ones can read it, measure the commuting and boundary-value residuals with their cost, load a Gmsh mesh, refine it, and copy the program that reproduces the run.
Operators side by side
Canonical, bounded, stable and trace-preserving, in a worker, with the cost shown.
Your mesh
A cube, pasted JSON or an ASCII Gmsh .msh file; bad input is an error that says why.
3D viewer and convergence plot
Still there, under “Project a function”.
API surface
Pick the operator that gives the guarantees you need, then call project. No event emitters, no stream lifecycle — every call is deterministic.
Read the full API referencenew StableProjector(vertices, tetrahedra)Bounded interior, exact boundary values. project(u, point, cell, l) evaluates the projection of a field at a point.
new BoundedCommutingProjector(vertices, tetrahedra)Locally L²-bounded and commuting for every input; keeps no boundary values.
new CanonicalProjector(vertices, tetrahedra, { degree })Interpolation onto Lagrange, Nédélec, Raviart–Thomas or discontinuous spaces of any degree.
new HigherOrderProjector(vertices, tetrahedra, { degree })The Arnold–Guzmán projection: any degree, locally bounded, commuting for every L² field.
new TracePreservingProjector(vertices, tetrahedra, { degree })The papers' operator: bounded, commuting, keeps the discrete trace. Above the lowest order it is evaluated field by field with local(u, du, l).
parseGmsh(text)Reads an ASCII Gmsh .msh file (2.2 or 4.1, first-order tetrahedra) into the two arrays every operator takes.
new Locator(mesh).findTetrahedron(point)Point location in O(log N) after a one-time tree build. Returns the cell and the barycentric coordinates.
new Projector(mesh, whitney).projectAtPoint(u, point, l)The canonical lowest-order projection with point location handled internally.
By the numbers
Everything you need to evaluate traceprojector before you import it. No marketing gymnastics, no inflated benchmarks.
Plus a numerical validation suite
One test per claim of the papers, fixed tolerances
Runtime dependencies
Hand-rolled linear-algebra kernel
Point-in-tet lookup
Balanced AABB tree
Discrete de Rham complex
Π⁰ · Π¹ · Π² · Π³
Spin up the playground, pick a function, and watch the trace projectors do their thing on a live tetrahedral mesh — all in your browser, no install required.
⌘ npm install traceprojector