Skip to content

md-basics tutorials: statistical mechanics you can watch; DriveFS mount tests + truncation fix#89

Merged
andeplane merged 1 commit into
masterfrom
md-basics-tutorials
Jul 8, 2026
Merged

md-basics tutorials: statistical mechanics you can watch; DriveFS mount tests + truncation fix#89
andeplane merged 1 commit into
masterfrom
md-basics-tutorials

Conversation

@andeplane

Copy link
Copy Markdown
Collaborator

Six new tutorials (md-basics/)

Statistical mechanics made visible — each notebook takes one famous piece of physics and makes it happen live in the browser. All simulation decks were prototyped and validated in node against the real wasm first, then every notebook verified headlessly (playwright, real browser, full cell-by-cell execution):

Notebook The physics Validated result
01-maxwell-boltzmann Every atom starts at the same speed; collisions assemble the M-B distribution (H-theorem live) T stays at v₀²/2; arcsine → Gaussian
02-condensation Quench a 2D vapor below coexistence; droplets nucleate and coarsen (colored by pe/atom) latent heat visible in pe(t); optional KOKKOS "go big" cell
03-real-vs-ideal-gas Measure Z = P/ρT across (ρ, T); overlay B₂(T) computed in numpy from the pair potential virial line matches at low ρ; Boyle T ≈ 3.42
04-reversibility-and-chaos Loschmidt's paradox: flip every velocity, un-melt a crystal; then find the chaos horizon return error 1e-12 at 500 steps → 3.6 at 16000
05-thermal-conductivity Müller-Plathe imposed flux + ave/chunk profile from a file → κ κ ≈ 6 (2D LJ liquid), clean tent profile
06-polymer-chains numpy-built FENE bead-spring chains; Rg ~ N^ν ν ≈ 0.63 vs SAW 0.588 (finite-size, discussed in the text)

Linked from the index page (new section) and NOTEBOOK_TUTORIALS.md (Series 1 marked partially shipped).

DriveFS file-sync: full branch tests + a real bug fix

tests/drivefs-mount.spec.ts extracts the _MOUNT_DRIVEFS_JS snippet from the Python bindings and unit-tests it against the real wasm filesystem with a mocked JupyterLite ContentsAPI — 33 tests covering every reachable branch:

  • toAPIPath: cwd inside /drive (prefix), exactly /drive, outside /drive, cwd() throwing, and per-call re-evaluation
  • node_ops: lookup hit/miss, mknod (file + dir), getattr, setattr (mode / timestamp / size), rename, unlink, rmdir, readdir, symlink→EPERM, readlink→EINVAL
  • stream_ops: open existing / missing+write (create) / missing+read (ENOENT), close with/without write flags (put vs no-put), read (normal / past-EOF), write (grow / in-place), llseek (SEEK_CUR / SEEK_END / negative→EINVAL), append mode
  • mount + re-mount (unmount branch)
  • LAMMPS end-to-end: write_dump, fix ave/time + close, fix ave/chunk + unfix, read_data/runFile of store-seeded files, and re-run overwrite

Bug found and fixed: truncation reaches the filesystem as a node-level setattr({size}) (Emscripten strips O_TRUNC before the stream opens), which the proxy ignored — re-opening an existing output file with "w" kept the stale tail of the previous longer content, so re-running any notebook that writes output files could corrupt them. setattr now honors attr.size (shrink / zero / extend), with regression tests for all three.

The remaining unreachable branches are defensive fallbacks (documented in the spec header); the pyodide-only Python glue (_mount_drivefs caching/fallback) is exercised by the headless notebook integration runs.

Test plan

  • npx vitest run tests/drivefs-mount.spec.ts — 33/33
  • npx vitest run tests/lammps.spec.ts tests/client.inject.spec.ts — no regressions
  • Headless browser runs: all 6 new notebooks + index, basics/02, basics/05, materials/01 — all pass with the fixed bindings

🤖 Generated with Claude Code

Six new notebooks under md-basics/ — statistical mechanics you can
watch, each validated headlessly in a real browser:

- 01-maxwell-boltzmann: every atom starts at the same speed; the M-B
  distribution assembles itself (WCA gas, arcsine → Gaussian vx).
- 02-condensation: quench a 2D vapor below coexistence; droplets
  nucleate and coarsen, colored by pe/atom. Optional KOKKOS "go big"
  cell with the basics/04 isolation check + fallback.
- 03-real-vs-ideal-gas: measure Z = P/ρT across (ρ, T), overlay the
  second virial coefficient computed in numpy from the pair potential.
- 04-reversibility-and-chaos: Loschmidt's paradox live — flip every
  velocity and un-melt a crystal (RMS return error ~1e-12), then find
  the chaos horizon where the return fails (positions matched by atom
  id, since LAMMPS re-sorts atoms in memory).
- 05-thermal-conductivity: Müller-Plathe flux + ave/chunk temperature
  profile read from a file → κ ≈ 6 for the 2D LJ liquid.
- 06-polymer-chains: numpy-generated FENE bead-spring data files,
  Rg ~ N^ν with the Flory exponent from a log-log fit.

tests/drivefs-mount.spec.ts unit-tests the DriveFS mount snippet from
the Python bindings against the real wasm filesystem with a mocked
JupyterLite ContentsAPI — every reachable branch of toAPIPath (all four
cwd cases, re-evaluated per call), node_ops, stream_ops, and mounting,
plus LAMMPS end-to-end cases (write_dump, ave/time + close, ave/chunk +
unfix, read_data of Python-written files, re-run overwrite).

The tests exposed a real bug, now fixed: truncation arrives as a
node-level setattr size change (Emscripten strips O_TRUNC before
stream open), which the proxy ignored — so re-opening an existing
output file with "w" kept the stale tail of the previous, longer
content. setattr now honors attr.size (shrink, zero, and extend).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andeplane andeplane merged commit 72135b7 into master Jul 8, 2026
3 checks passed
@andeplane andeplane deleted the md-basics-tutorials branch July 8, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant