λWAVES
A playable hydrogen shadow. The 140 exact eigenstates of hydrogen with n ≤ 7, reconstructed on the GPU as a wave field you
can play like an instrument: tune amplitudes, phases and viewpoints, then watch the eigenmodes interfere and the cloud move.
Small molecules are solved live (Hartree–Fock and Kohn–Sham LDA) or opened from a library of precomputed records.
Live: lambdawaves.magic-commons.com · a Magic Commons
project · GPL-3.0-only · interface kit MIR
Status: 0.9.9-beta. What is verified and what is not is in
shipping readiness; deployment is in DEPLOY.md.
What it is
The core is exact. λWAVES holds the hydrogen closed forms for n ≤ 7 — all 140 (n, l, m) states, with Condon–Shortley-phase
complex spherical harmonics, and evolves them by the one operation a diagonal Hamiltonian permits: multiplying each coefficient by
e^{-iE_n t}. For field-free hydrogen nothing is integrated, so nothing drifts. What does step in time is named where it runs:
MOLECULES' RUN (real-time TDHF), MO-REGISTRY's DRIVE and SONG and the FLOW tracers integrate; INTER-SHELL STARK is an eigensolve over
the 140 labels; VIBRATE moves the nuclei by a closed-form cos ωt and the density by one linear step. The node gate
(tests/hydrogen.test.mjs) reads the radial norms within 3e-9 of 1 (its bound 1e-6, by quadrature) and the table-typed anchors
within 3e-16 (its bound 1e-12).
The GPU does presentation: lab/field.js reconstructs ψ on an N³ rgba16float grid straight from the closed-form mode tables (no
basis textures), and a ray-march presenter draws density, phase, Re ψ, Im ψ or a difference. Measured on an RTX 3070 (headless
Firefox, 1920 × 994, batches of at least 2.5 s, 2026-09-24): presenting the default 1s + 2p_z at 96³ and 160 steps takes 3.25 ms per
frame in the phase view and 2.10 ms for density, and reconstructing it 0.1 ms; reconstructing all 91 labels of the n ≤ 6 set took
1.43 ms at 96³ and 3.40 ms at 128³ (measured before n = 7 was added; the 140-label figure has not been re-measured). The grid is held
to the CPU in each picture's own metric at 64³ (tests/field-law.browser-test.mjs, bounds in tests/helpers/field-law.mjs, read on
that RTX 3070 in Firefox): hydrogen 1s + 2p_z against the closed form — |Δψ| RMS ≤ 3e-6, 99.8 % of voxels ≤ 2e-5, the worst voxel
≤ 2e-4; water (H₂O, STO-3G) against the f64 density of the same solve — |Δρ|/ρ RMS ≤ 1e-3, the worst voxel's |Δρ|/ρ ≤ 2e-3, the worst
|Δρ| ≤ 3e-4 of ρmax. Every stored component lies within one rgba16float step of its f64 value plus the kernel's own f32 error.
Around that sits the instrument: a rack of windows (STATE, SPECTRUM, ORBIT, PLANE, KEPLER, VORTEX, MOLECULES, MO-REGISTRY, WIGNER,
RADIATION, …), a transport with one clock, a modulation rack with drag-to-patch macros, a timeline, NODES, presets, projects,
shareable state links, film rendering, FILE › EXPORT SHAPE (GLB · OBJ · STL, the density isosurface on screen) and EXPORT GRID
(NPZ · Gaussian cube, ψ on the grid) — see docs/EXPORT.md — and an offline-capable PWA.
It requires a working WebGPU adapter in a secure context. Browser support varies by OS, GPU and driver; see the
WebGPU compatibility reference.
Run it
tools/serve.sh # https://127.0.0.1:8700/lab/ (or: npm run serve)
tools/serve-lan.sh # the same, reachable from a tablet or phone on the local network
Requirements: Node 22+, Python 3 and OpenSSL (the local server makes its own self-signed certificate on first run), and a browser
with WebGPU. The lab is a static tree of ES modules with no build step: what you edit is what the browser runs. For a first look,
open FOLDERS (O) and choose a demo under DEMOS — WAVE DANCER PROTOTYPE, STAR LOOP, BENZENE π or WATER ESP — each opens ready to play.
Tests and gates
npm test (./test.sh node) runs every node suite — the mathematics against closed forms and PySCF fixtures, the file and state
laws, and the PWA integrity check — plus the state-scope and hint checks; npm run test:browser (./test.sh browser) drives the
real interface in headless Firefox with WebGPU against one owned HTTPS server (Firefox and geckodriver on PATH; LW_PORT and
GD_PORT choose free ports, occupied ports are refused). The field's pixels are held by a digest gate, tools/perf/digest-lock.mjs,
which compares each frame against two recorded fixtures in tests/fixtures/. After any edit under lab/, run node tests/pwa.test.mjs --write: the service
worker derives its cache name from its precache hashes, and a stale hash would serve returning visitors the old bytes.
./test.sh legacy runs the historical gate in tests/legacy/, which asserts superseded behaviour and is not part of the release gate.
Requirements and limitations
| |
|---|
| Needs | A browser with WebGPU in a secure context (https or localhost): Chrome/Edge 113+, Firefox 141+, Safari 26 / iPadOS 26. There is no WebGL fallback: without WebGPU the page shows a notice instead of the lab. |
| Runs well on | A desktop GPU (measured on an RTX 3070: about 3 ms per frame at 96³) and an M-series iPad (the quality governor drops ray steps, then the grid, under load). |
| Physics | Exact hydrogen (n ≤ 7, 140 states), plus MOLECULES: Hartree–Fock in vendored Gaussian bases (STO-3G for H–Kr; 6-31+G* for H, C, N, O, F molecules up to 46 Cartesian AOs) — RHF for closed shells, UHF for the 7 open shells — and Kohn–Sham LDA (Slater + VWN5) up to benzene's 36 STO-3G AOs. 98 molecules: 61 solved live (59 enabled; CuH and ZnH₂ are listed and disabled, their RHF reference is not a minimum) and 37 opened from the library, which holds 38 records — 37 solved here and compared with PySCF, C₆₀'s energy PySCF's own (the table below). RPA and TDA spectra, and real-time TDHF. MO-REGISTRY plays orbital packets or many-electron TD-CIS states, drives them with a field, and shows their current. Nuclei are fixed except under VIBRATE (one harmonic normal mode); the wavefunction methods stop at single excitations, and LDA's correlation is the VWN5 functional's. Geometries are fixed: measured for the live molecules (each entry names its source; AlH₃'s is not a measurement), computed for 36 of the 38 records. Five early windows (QCD, H₂⁺, HELIUM, H₂, ELECTROSTATICS) were removed in 0.5.0; an older project that used one opens on a placeholder and says so (docs/LEGACY-WINDOWS.md). Every system λWAVES plays is a row of the catalogue on the MODEL sheet (186 rows, lab/catalogue.js), with its status — EXACT, NUMERICAL or UNCHECKED — and its oracle test. |
| Not yet verified | A device matrix beyond one desktop, the installed-PWA update on a real device, a real microphone for the AUDIO source, and a screen-reader pass — see shipping readiness. No independent code review has been made. |
Against PySCF
A molecule's energy is NUMERICAL: checked against PySCF on the same atoms and the same basis decimals, never against experiment
(tests/fixtures/oracles/README.md says what each fixture holds and which script in tools/oracles/ wrote it). A
library record is written only if the app's solve is within 1e-8 Eh of PySCF's (tools/orbital-library.mjs). A live molecule is
compared on the device; the node gate re-solves every enabled one in STO-3G and reads its agreement back from the STATUS line
(tests/status.test.mjs), and holds a bound on these: every enabled closed shell up to 14 STO-3G AOs plus HBr, Br₂, C₂H₄ and C₆H₆ at
max(1e-9, 3e-12·|E|) Eh (tests/molecules.test.mjs, tests/chem-sweep.test.mjs), every open shell at 1e-8 Eh (tests/uhf.test.mjs),
the 6-31+G* molecules up to 27 AOs at 1e-9 Eh (tests/basis-631.test.mjs) and the LDA eight at 1e-6 Eh (tests/rks.test.mjs). The
tables are written by node tools/pyscf-table.mjs.
38 library records — the app's solve beside PySCF's on the record's own atoms (PySCF 2.14.0, cart=True, the vendored Basis Set Exchange decimals, bohr; Δ = app − PySCF in Eh, as stored):
| molecule | basis | AO | method | E (app), Eh | E (PySCF), Eh | Δ, Eh | geometry |
|---|
| C₆H₆ · benzene | STO-3G | 36 | RHF | -227.89100646418083 | -227.89100646418058 | -2.5579538487363607e-13 | experimental |
| C₃H₇NO₂ · alanine | STO-3G | 37 | RHF | -317.67874534511134 | -317.67874534511066 | -6.821210263296962e-13 | computed-reference |
| C₃H₇NO₃ · serine | STO-3G | 42 | RHF | -391.5289775312513 | -391.5289775312844 | 3.3082869776990265e-11 | optimised-here |
| C₃H₇NO₂S · cysteine | STO-3G | 46 | RHF | -710.8695451911605 | -710.8695451913395 | 1.7905676941154525e-10 | optimised-here |
| C₅H₉NO₂ · proline | STO-3G | 49 | RHF | -393.71065517305675 | -393.71065517295614 | -1.0061285138363019e-10 | optimised-here |
| C₄H₉NO₃ · threonine | STO-3G | 49 | RHF | -430.07571912211637 | -430.07571912251154 | 3.951754479203373e-10 | computed-reference |
| C₅H₁₁NO₂ · valine | STO-3G | 51 | RHF | -394.85853402566505 | -394.8585340256826 | 1.7564616427989677e-11 | optimised-here |
| C₄H₇NO₄ · aspartic acid | STO-3G | 52 | RHF | -502.7860820160869 | -502.78608201566465 | -4.2223291529808193e-10 | optimised-here |
| C₄H₈N₂O₃ · asparagine | STO-3G | 53 | RHF | -483.21790965638434 | -483.2179096562219 | -1.624584911041893e-10 | computed-reference |
| C₆H₁₃NO₂ · isoleucine | STO-3G | 58 | RHF | -433.4053799418369 | -433.40537994232943 | 4.925482244289014e-10 | computed-reference |
| C₆H₁₃NO₂ · leucine | STO-3G | 58 | RHF | -433.4398947224981 |
61 molecules solved live — the app's energy is computed on your device and compared there (the STATUS line prints the agreement), so the table holds PySCF's (PySCF 2.14.0 RHF and PySCF 2.14.0 UHF in STO-3G, PySCF 2.14.0 in 6-31+G*, PySCF 2.14.0 RKS lda,vwn on the app's grid; "no oracle": the card offers it and no PySCF number is on file; "—": not offered):
| molecule | AO (STO-3G) | method | STO-3G, Eh | 6-31+G*, Eh | RKS LDA (STO-3G), Eh |
|---|
| H₂ · dihydrogen | 2 | RHF | -1.1167061373496687 | -1.126740337407633 | no oracle |
| LiH · lithium hydride | 6 | RHF | -7.862023874015301 | — | no oracle |
| HF · hydrogen fluoride | 6 | RHF | -98.5707576634785 | -100.01485739573144 | -98.24584098961836 |
| N₂ · dinitrogen | 10 | RHF | -107.49588788341214 | -108.94572499706774 | -107.14784546338231 |
| CO · carbon monoxide | 10 | RHF | -111.22458955706387 | -112.7415387235556 | no oracle |
| F₂ · difluorine | 10 | RHF | -195.96746083720126 | -198.68096270349432 | no oracle |
| LiF · lithium fluoride | 10 | RHF | -105.36247144106767 | — | no oracle |
| NaH · sodium hydride | 10 | RHF | -160.30218654395708 | — | no oracle |
| HCl · hydrogen chloride | 10 | RHF | -455.1348097026879 | — | no oracle |
| Cl₂ · dichlorine | 18 | RHF | -909.1116063077275 | — | no oracle |
| NaCl · sodium chloride | 18 | RHF | -614.5241755564492 | — | no oracle |
| O₂ · dioxygen | 10 | UHF | -147.6352300151407 | no oracle | — |
| NO · nitric oxide | 10 | UHF | -127.53039956873471 | no oracle | — |
| OH · hydroxyl radical | 6 | UHF | -74.3626375456123 | no oracle | — |
| B₂ · diboron | 10 | UHF | -48.42116526893494 | — | — |
| BeH₂ · beryllium dihydride |
Accessibility
Every control is a real button or slider with a name, a value and arrow-key steps; windows are landmarks; the canvas is described in
one sentence that changes only when the instrument's state changes. This was checked by a headless browser, not by a person using a
screen reader. A photosensitivity notice stands before the first frame. A flash guard then holds the four routes that set the
picture's brightness — EXPOSURE, GAMMA, STAGE and KNEE — to three flashes a second whenever a modulator drives them, and says so in
METERS; it has no off switch. It is partial: HUE, a molecule's KICK, the register's morph and the camera are not held, so a patch on
those can still flash. Please open an issue for anything unreachable or unreadable.
Privacy
λWAVES is a static site with no accounts and no analytics. Nothing you make is sent anywhere: projects, notes and settings live in
your browser's localStorage, audio you drop on the TIMELINE in IndexedDB (mir-assets), and anything else in files you export
yourself. After the page loads it asks its own origin for a new build at most every 30 minutes, and fetches the records, volumes,
pictures, demos and measured lines you open, keeping them in Cache Storage for offline use. An image in an imported notebook is
fetched from wherever the note points (SECURITY.md says what that host learns). The microphone is opened only when you add an AUDIO
device to the modulation rack, its signal never leaves the page, and it is released when the last AUDIO device is removed; Web MIDI
reconnects at launch only where a mapping was saved and the browser already grants it. Cloudflare serves the files and keeps its own
ordinary server logs. SECURITY.md lists every request.
The documents
| File | What it is |
|---|
CHANGELOG.md | What changed between releases, newest first; generated by node tools/changelog.mjs. |
CONTRIBUTING.md | The rules for a change, the gate, and where things live. |
SECURITY.md | Every request the page makes, what stays on your device, and how to report a problem. |
DEPLOY.md · RELEASING.md | Deployment to Cloudflare, and how a release is cut. |
SHIPPING-READINESS.md · ACCEPTANCE-MATRIX.md | What is verified, what is not, and the evidence per device. |
LEGAL-PROVENANCE.md | Every shipped component's origin, licence and copyright holder, and the authorship record. |
docs/EXPORT.md | The shape and grid exports. |
|
The interface kit
The interface — tokens, materials, widgets, gestures, window chrome and the modulation window — is MIR, Magic Commons' kit,
adopted into lab/mir/ and lab/fonts/ from its own repository. λWAVES keeps only its own selectors in lab.css and skin.css.
CONTRIBUTING.md gives the rule for those folders, and MIR-MANIFEST.json lists which bytes are the kit's.
AI disclosure
λWAVES was built with AI coding agents — principally Claude Code with Anthropic's Claude models, with OpenAI Codex and Google Gemini
for parts of the code and the graphics — under the direction of its author, Joshua Hosain. Its claims rest on what can be checked —
the physics against closed forms and PySCF, the node and browser suites, and the pixel gates — rather than on any claim of authorship.
The authorship record (commit identities, attribution trailers, AI-generated assets) is in LEGAL-PROVENANCE.md.
Citing
CITATION.cff has the reference (GitHub shows it as "Cite this repository").
Branches
main — the release. It moves only when a release is cut; see docs/release/RELEASING.md.
dev — development.
Licence
GNU General Public License v3.0 only — Copyright 2026 Joshua Hosain. See LICENSE.
Third-party notices are in NOTICE: Spinwerad 0.3, Roboto 3.015, STIX Two Math 2.0.2, KaTeX 0.16.11 and its fonts,
marked 12.0.2, the notebook's Spectral, Playfair Display and Alegreya SC; the Basis Set Exchange records and NIST's measured lines are
credited there as data.
A reference, not a dependency: ChronusQ (Williams-Young et al., WIREs Comput. Mol.
Sci. 10, e1436 (2020)) is the real-time electronic-structure package λWAVES' molecular propagation studied and cites. ChronusQ is
released under GPL v2 and λWAVES under GPL-3.0-only, so it is read and cited, never merged: no ChronusQ code is in this tree (NOTICE).