Pure-client port — runs entirely in the browser, no server - #10
Draft
cakirmert wants to merge 7 commits into
Draft
Pure-client port — runs entirely in the browser, no server#10cakirmert wants to merge 7 commits into
cakirmert wants to merge 7 commits into
Conversation
Reimplement the Dash app as plain HTML/CSS/JS that runs entirely in the visitor's browser: * PHREEQC compiled to WebAssembly via Emscripten (1.7 MB engine, 46 KB preloaded phreeqc.dat). Validated against phreeqpython on 7 reference cases at 0.1% tolerance, plus 3 realistic 8-input water compositions. * Seawater carbonate system ported to vanilla JS (Mehrbach 73 + Mucci 83 constants). Validated against PyCO2SYS within 5% across 7 cases. * DIC vs pCO2 grid precomputed once with phreeqpython, shipped as JSON. * All other pages (charge balance, forsterite, Lasaga, XRF, Bjerrum, legal) ported as static HTML/JS. * Markdown narrative + LaTeX equations preserved via marked + KaTeX. Build chain (emsdk, iphreeqc source, CMake build tree) is gitignored; the full reproducible recipe is in static/BUILD.md. GitHub Actions workflow added to deploy static/ to GitHub Pages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The carbonic-acid Bjerrum sweep was aborting on every pH step. Two bugs: 1. The PHASES Fix_H+ definition was placed AFTER an END separator, which means PHREEQC tried to evaluate the EQUILIBRIUM_PHASES block in simulation 1 before Fix_H+ was defined. That's an unrecoverable abort, and once the persistent IPhreeqc instance hit it, every subsequent RunString call also aborted. 2. EQUILIBRIUM_PHASES needs a reactant (HCl or NaOH) that PHREEQC can only DISSOLVE, never precipitate back. Fixing pH below natural requires HCl; above natural requires NaOH. The previous code always used HCl, so half the sweep had no usable proton source. Fix: - Get natural pH once at startup with a baseline solve. - For each target pH, emit ONE simulation containing PHASES + SOLUTION + EQUILIBRIUM_PHASES + SELECTED_OUTPUT in that order (no END between). - Pick HCl when target < natural, NaOH when target >= natural. Verified end-to-end: 141 pH steps over [0, 14] all converge in 179 ms on a single persistent IPhreeqc instance, fractions match textbook Bjerrum (CO2/HCO3 50:50 at pH 6.3, HCO3/CO3 50:50 at pH 10.3). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi Lukas,
I had a go at reworking the site so it can be served as plain static
files (no Flask/Dash, no Python backend, no database). Everything is in
static/; the Dash app at the repo root is untouched.Live preview
A GitHub Actions workflow deploys the
static/folder to GitHub Pages onevery push. Live preview from my fork:
https://cakirmert.github.io/multipage_website/
When you merge, you can flip Settings → Pages → Source to "GitHub Actions"
once and your repo will deploy itself the same way.
How it works
browser. Numerically validated against
phreeqpythonto 6+ significantfigures on pH and dissolved-carbon totals (7 reference cases pass at
0.1 % tolerance, 3 realistic 8-input water compositions pass at 5 %).
Mucci 83 constants). Within 5 % of
PyCO2SYSacross 7 reference cases.DIC vs pCO2ships a precomputed 51 × 61 grid for instant interactivity.Bjerrum,XRF,Charge balance,Forsterite,Lasagaare pure-JSports of the existing math.
marked+KaTeX.Things you'll likely want to change before going public
with DigitalOcean as alternative. Pick whichever you actually use and
delete the other (and update wording if needed).
the wording may need tightening.
assets/,no changes. Confirm they're the ones you want.
assets/*.md. If any have updated since (Rimstidt 2012, Lasaga 1994,Mehrbach references, etc.), the source files in
static/assets/markdown/are what to edit.co2sys.jsconstants — uses Mehrbach 73 refit (PyCO2SYSopt_k_carbonic=4). Current PyCO2SYS default is Sulpis 2020(
opt=16). If you want exact parity with current PyCO2SYS, theconstant set in
static/js/co2sys.jsneedsupdating; I picked the older one because it's well-documented and
gives clean closed-form pK1/pK2 expressions.
How to read this PR
static/README.md— overview + quickstartstatic/BUILD.md— exactly how the WASM-PHREEQCbinary was built (the build chain is gitignored to keep the diff
reasonable; this doc is the recipe to reproduce)
static/test/— three Node validators that diff thein-browser output against direct Python runs
Why a draft PR
So you can review at your pace; happy to address feedback or split it
into smaller PRs if that's easier.