Bounded, commuting, trace-preserving — and validated

Trace-preservingfinite-element projections

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.

Runtime deps
0
Pure ESM kernel
Form degrees
4
Π⁰ · Π¹ · Π² · Π³
Point location
O(log N)
Balanced AABB
License
MIT
Open source

Capabilities

Everything you need to project onto the discrete de Rham complex.

One library. Four form degrees. Three trace spaces. Zero transpilation. The same code runs in Node 24+, the browser, and the sandboxed playground.

Core

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.

Checked by hundreds of unit tests and a validation suite
Section 6.3

Exact boundary traces

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.

Checked by hundreds of unit tests and a validation suite
Weights

Boundary weight cascade

Vertex, edge, and face duality functionals on P¹, N₀, and RT₀, built from the barycenter tent μ and the local mass matrix on each star.

Checked by hundreds of unit tests and a validation suite
Kernel

Zero runtime dependencies

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.

Performance

AABB point location

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.

Checked by hundreds of unit tests and a validation suite
Extensibility

Any polynomial degree

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.

Checked by hundreds of unit tests and a validation suite

Get started

One npm install,
then the API is the math.

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.

  • Pure ESM, ES2024 syntax — no Babel, no SWC
  • ESM and UMD bundles ship on npm
  • Hand-written .d.ts for every module
  • Runs in the browser via the UMD bundle on jsDelivr
terminal
01# Node 24+ (Node 26 recommended)
02npm install traceprojector

Architecture

Built on a clean decomposition.

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

Πˡ=Π_∂ˡ+Π_ringˡ·(I − Π_∂ˡ)

Π_∂ˡ prescribes the boundary data exactly. Π_ringˡ is the interior projector with vanishing trace. Together they form a single, commuting operator.

Π_∂ˡ

Boundary projector

Prescribes the boundary data exactly. Built on Alfeld (boundary faces) or Worsey–Farin (bulk tet) splits.

Π_ringˡ

Interior projector

Zero-trace interior operator: bounded local problems on stars of cells, vanishing trace on the boundary. Decouples from boundary geometry.

Boundary weight cascade
ζ⁰₀,ᵥ on P¹

eq. 6.25 — vertex scalar duality

ζ¹₀,ₑ on N₀

eq. 6.31 — Whitney edge tangential

ζ²₀,ƒ on RT₀

eq. 6.36 — Raviart–Thomas face flux

Commuting diagram
grad Π⁰ = Π¹ grad
curl Π¹ = Π² curl
div Π² = Π³ div

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.

Live in browser

Compare the operators.
On your own mesh, in your browser.

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”.

Open the full playgroundNo install. Runs entirely in your browser.
traceprojector / playground
u(x, y, z) = sin(x) cos(y) e^z
Building tetrahedral mesh…
Drag to rotate · Scroll to zoom

API surface

A small surface.
Four form degrees.

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 reference
new 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

Small surface. Honest numbers.

Everything you need to evaluate traceprojector before you import it. No marketing gymnastics, no inflated benchmarks.

600+unit tests

Plus a numerical validation suite

One test per claim of the papers, fixed tolerances

0deps

Runtime dependencies

Hand-rolled linear-algebra kernel

O(log N)per query

Point-in-tet lookup

Balanced AABB tree

l = 0,1,2,3form degrees

Discrete de Rham complex

Π⁰ · Π¹ · Π² · Π³

MIT licensed · Open source · v0.1.0

Ready to project?

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