/ concept-collection / turing-surface-cache
Sign in
concept-collection / turing-surface-cache
turing-surface-cache / README.md
152 lines · 7.5 KBCodeBlameHistory
3Reaction-diffusion systems (Turing patterns) on curved closed surfaces,
4evaluated at a chosen end time, with the solutions shared between all visitors
5through a cloud cache.
7This is a trimmed fork of
8[turing-surface](https://github.com/concept-collection/turing-surface), which
9solves the same systems live and freely tunable. What this app changes is the
10contract: every setting is a choice from a short list, so each combination of
11choices names exactly one solution. Solutions already in the shared cache load
12by themselves as the choices are browsed; a combination nobody has computed
13shows empty surfaces, and nothing runs until the user presses **Compute
14solution**, which runs the solver locally (in the browser, on WebGPU),
15watching the pattern form and stopping at exactly the requested time. Users
16who hold an upload API key contribute their locally-computed solutions back,
17so the next visitor who asks for the same combination gets it in a second
18rather than a minute.
20## The discrete parameter space
481eeb9Add Brusselator and Allen-Cahn modelsJeremy Magland 22Three models ship, all in turing-surface's 6-transform flux form —
23Schnakenberg (the default), Brusselator, and Allen–Cahn — on three geometries
24(sphere, ellipsoid, peanut). The Algorithm-4 reference variant is deliberately
25absent: it solves the same equations as Schnakenberg and would only duplicate
26cache entries under different hashes. The choices, defined in
29| setting | choices |
30|---|---|
481eeb9Add Brusselator and Allen-Cahn modelsJeremy Magland 31| Schnakenberg | a: 0.05/**0.1**/0.15/0.2 · b: 0.7/**0.9**/1.1/1.3 · D₁: 1.6e-4/**4e-4**/1e-3 · D₂: 3.2e-3/**8e-3**/2e-2 · dt: 0.02/**0.05**/0.1 |
32| Brusselator | A: 2/**3**/4 · B: 7/**9**/11 · D₁: 1.7e-3/**3.33e-3**/6.7e-3 · D₂: 8.3e-3/**1.67e-2**/3.3e-2 · dt: 0.01/**0.02**/0.05 |
33| Allen–Cahn | ε²: 5e-4/**1e-3**/2e-3 · dt: 0.01/**0.02**/0.05 |
4f822e1turing-surface-cache: reaction-diffusion solutions at a chosen end time, shared through a cloud cacheJeremy Magland 34| geometry | sphere, **ellipsoid** (axes each 0.6/1/1.5), peanut (waist 0.4/0.6/0.8, stretch 0/0.6/1.2) |
35| seed | **1**–5 |
36| end time | **100**, 200, 400, 800, 1600 |
481eeb9Add Brusselator and Allen-Cahn modelsJeremy Magland 38The model, unlike every other choice, is compiled into the GPU session, so
39switching it pays a recompile of a second or two; everything else swaps into
40the running session. Allen–Cahn evolves one species, so it shows one panel
41where the others show two.
4f822e1turing-surface-cache: reaction-diffusion solutions at a chosen end time, shared through a cloud cacheJeremy Magland 43(Defaults in bold.) The numerical-scheme settings are fixed — lmax 63, 8
44solve iterations, seed wavelength λ = 0.5 — but are recorded in every cache
45key, so offering them as choices later invalidates nothing.
47The whole selection is mirrored into the URL fragment, every value written
48explicitly, so reloading returns to the same combination and a shared link
49opens on the same spec (and, when cached, the same solution) for whoever
50follows it. A "Reset to defaults" button puts every choice back.
52Every end time is an exact multiple of every dt, so a run to T = 800 passes
53exactly through t = 100, 200 and 400. Those intermediate states are captured
54as the run passes them and, for an uploading user, encoded and uploaded in
55the background while the run continues: one long run populates four cache
56entries, and the earlier ones are already shared before the run finishes. The same structure works in the other
57direction: the state is Markovian in the spectral coefficients, so before
58computing anything the app looks for the longest cached shorter run of the
59same spec and continues from its final state, computing only the remainder.
60Asking for T = 1600 when T = 800 is cached costs half the run, and the t = 0
61initial state travels inside every file of the chain, so a continuation
62writes files identical in kind to a from-scratch run.
64## How the cache works
66The page's whole state is one small spec object (model, parameters, geometry,
67seed, end time, scheme settings, plus the app name and a format version). Its
68canonical JSON — keys sorted at every level — is hashed with SHA-256, and the
69hash is the object name:
71```
72https://tempory.net/tmpbucket/turing-surface-cache/v1/schnakenberg/<sha256>.h5
73```
75A lookup is therefore a single GET with no index or API, and a 404 means a
76miss. The path carries the app name, format version and model in the clear so
77that future cleanup (lifecycle rules, prefix deletes) never has to open a file
78to know what it belongs to; the hash input includes the version string, so a
79format change moves every object rather than silently colliding with the old
80ones.
82Uploads go through the [tmpbucket](https://github.com/scratchrealm/tmpbucket)
83Worker: the client presents the API key and a file name, receives a presigned
84R2 PUT URL, and uploads directly. Only holders of the key can write; everyone
85can read. The key is entered in the page and kept in localStorage.
87## The cache file
89Cache files are HDF5, written in the browser with
90[h5wasm](https://github.com/usnistgov/h5wasm) and readable from Python with
91h5py. The layout is turing-surface's reference-file layout (see
92`docs/ellipsoid-reference-spec.md` there) extended with the cache's identity
93at the root, so a cache file is *also* a valid reference file — it can be
94loaded straight into turing-surface's "Compare against uploaded data" mode:
96```
97/ attrs: app, format_version, spec_json, model, species,
98 created_utc, adapter
99├─ backend/ attrs: adapter, runtime, precision
100├─ spec/ attrs: geometry, lmax, seed, steps, niter, lam3, t_end
101│ ├─ params/ attrs: a, b, D1, D2, dt
102│ └─ geometry_params/ attrs: the geometry's params
103├─ grid/ attrs: lmax, mmax, nlat, nphi, nlm
104├─ geometry/ Gx, Gy, Gz float32[2·nlm]
105├─ initial/ U, V (spectral state at t = 0) float32[2·nlm]
106└─ final/ U, V (at the end time) float32[2·nlm]
107```
109`spec_json` is the exact string that was hashed into the object name, and the
110reader verifies it matches what was asked for. The initial state is included
111so a file fully defines its run; the coefficients are the spherical-harmonic
112convention documented in turing-surface (orthonormal + Condon-Shortley,
113m-major, [re, im] interleaved). At lmax 63 a file is about 90 KB.
115Note that the solver is deterministic given the spec only to fp32 round-off:
116different GPUs round differently, so a cached solution and a local recompute
117agree closely but not bit-for-bit. The cache stores whichever trusted user
118computed a combination first, and the file records which adapter that was.
120## Development
122```
123npm install
124npm run dev # local dev server
125npm run build # type-check + production build to dist/
126```
128numbl is a local `file:../../numbl` dependency, exactly as in turing-surface —
129a sibling checkout of [numbl](https://github.com/flatironinstitute/numbl) is
130required, reached through the `numbl-src` alias in
131[`vite.config.ts`](vite.config.ts). See turing-surface's README for the
132details; nothing about the arrangement changed here.
134Checks:
136- `node scripts/check-app.mjs` — end-to-end in headless Chrome (SwiftShader
137 WebGPU) with the cloud cache mocked: a miss computes locally and produces
138 the .h5 (verified with h5py), a fresh page loads that .h5 as a hit, and a
139 third page asking for a longer end time warm-starts from it. The pages use
140 the `?tend=` query hook, which substitutes short test end times for the
141 UI's list. This is what CI runs.
142- `node scripts/check-live.mjs [url]` — smoke-check a deployed URL against
143 the real cache.
144- `node scripts/screenshot.mjs out.png [light|dark] [tEnd]` — screenshot
145 after the boot-time solve.
147Deployed to GitHub Pages by `.github/workflows/deploy.yml` on push to `main`.
149## License
151CECILL-2.1 (inherited from SHTNS via shtns-webgpu, whose sources are
152vendored under `src/sht/`).
moveopenescclose