28f8ec1mesh-pde-solver: upload a quad mesh, solve PDEs on the surface in-browserJeremy Magland 1# mesh-pde-solver
3cc1e4cSupport triangle meshes; view-mode toolbar; drop upload size capJeremy Magland 3Upload a triangle or quad surface mesh, pick a PDE, tweak its right-hand side
28f8ec1mesh-pde-solver: upload a quad mesh, solve PDEs on the surface in-browserJeremy Magland 4and coefficients, and solve it **on the surface** — entirely in your browser.
5The mesh is converted to Gmsh format with [meshio](https://github.com/nschloe/meshio)
6(via [Pyodide](https://pyodide.org)), and the PDE is solved by
7[surfacefun](https://github.com/danfortunato/surfacefun) running on
8[numbl](https://numbl.org), a MATLAB-compatible runtime, in a web worker.
9The solution renders in a rotatable 3D view (drag to rotate, scroll to zoom).
11## PDEs
13- **Poisson (Laplace–Beltrami)** — Δu = f. On a closed surface the problem is
14 rank-deficient: f is projected to mean zero and the mean-zero solution is
15 returned. On an open surface, zero Dirichlet data is imposed.
16- **Helmholtz (variable coefficient)** — (Δ + c)u = f with c(x, y, z) an
17 arbitrary expression.
19The right-hand side f and coefficient c are MATLAB expressions in the surface
20coordinates x, y, z (elementwise operators: `.*`, `.^`, …), with presets to
21start from. The polynomial order per patch is adjustable (accuracy vs. time).
23## Meshes
25Uploads go through meshio, so any of `.msh .vtk .vtu .obj .off .ply .inp
3cc1e4cSupport triangle meshes; view-mode toolbar; drop upload size capJeremy Magland 26.mesh .bdf .avs` works — the mesh must contain triangle or quadrilateral
27cells (surfacefun computes on either patch type, but not both at once, so a
28mixed mesh has its quads split into triangles). Three sample meshes are
29bundled. The converted Gmsh file can be downloaded. Whether the surface is
30closed or open is detected from the edge connectivity.
32## How it works
3cc1e4cSupport triangle meshes; view-mode toolbar; drop upload size capJeremy Magland 341. `src/mesh/` — meshio in Pyodide parses the upload, keeps the triangle and
35 quad cells, and writes a canonical Gmsh MSH 4.1 ASCII file plus preview
36 arrays.
f4de30dSimplify the solver to run-per-solve; drop the uihtml event bridgeJeremy Magland 372. `src/engine/` — each solve boots a fresh managed numbl session
38 (`createNumblSession` from `numbl/browser`): numbl owns the worker and
39 VFS and bootstraps the [mip](https://github.com/mip-org) package manager.
40 The host stages `mesh.msh` and `params.json` and runs
41 [`matlab/main.m`](matlab/main.m) standalone — it begins with
42 `mip load --install surfacefun`, solves, and writes `result.json`, which
43 the host reads back before disposing the worker.
43c610bUse surfacemesh.import instead of the hand-rolled mesh readersJeremy Magland 443. `matlab/solve_pde.m` — loads the mesh with `surfacemesh.import`,
45 `resample`s it to the requested order, and solves with `surfaceop`.
3cc1e4cSupport triangle meshes; view-mode toolbar; drop upload size capJeremy Magland 464. `src/render/SurfaceView.tsx` — three.js view of the mesh or the
47 per-patch solution data with a parula colormap.
49The first visit downloads the Python runtime (~15 MB, browser-cached) and
50the surfacefun/chebfun packages (~28 MB). Installed MATLAB packages persist
51in IndexedDB across page loads (numbl wipes them after 24 h of inactivity),
52so later visits skip the package downloads.
54## Development
56```bash
57npm install
58npm run dev # local dev server
59npm run build # static build in dist/
60npm run engine-test # headless solver check in Node (no browser)
61python3 scripts/make_samples.py # regenerate public/samples/
62```
64The engine test runs the exact MATLAB project the worker runs, shimming
65numbl's synchronous-XHR `websave`/`webread` with curl (responses cached in
66`.cache/`), and checks a Poisson solve against an exact spherical-harmonic
67solution.
3cc1e4cSupport triangle meshes; view-mode toolbar; drop upload size capJeremy Magland 69Requires numbl >= 0.4.12 — `NumblSession.readFile` (0.4.10), enumeration-class
70support and the 1×1-tensor broadcast-assignment fix (0.4.11), which
71surfacefun's `surfacemesh.import` / `patchtype` depend on, and the 1×1-tensor
72gather-orientation fix (0.4.12), which surfacefun's `trianglepts` depends on.