...
running...
How to use
A cold injection well (blue) pushes water through the rock to a hot production well (red). The red lines are streamlines of the flow; the blue part of each line is the region already cooled. The shortest path between the wells is cooled first, so the production temperature (top plot) starts dropping when that cold front arrives and keeps falling as slower paths break through.
Try: double the well spacing and the first breakthrough is delayed four times (time grows with d squared); pump faster and the lifetime shrinks in proportion; raise porosity and the cold front is delayed because more water has to be heated; lower the injection temperature to see the power fall.
The science
Between a source and a sink the pore velocity of the water follows from potential flow: v(r) = Q/(2π h φ) [ (r − ri)/|r − ri|² − (r − rp)/|r − rp|² ] where Q is the volumetric rate, h the aquifer thickness and φ the porosity. Along the axis the travel time is t = ∫ dx / v = (2π h φ / Q) · d²/6 = π h φ d² / (3Q) (leading term; the tiny well radius is excluded). A cold front moves slower than the water because the rock must be cooled too: R = [ (1−φ) ρrcr + φ ρwcw ] / (φ ρwcw), tthermal = R · twater and the produced power is P = ρw cw Q (Tprod − Tinj).
Simplifications: a sharp thermal front with full local equilibrium between rock and water, no heat conduction from the over- and underlying rock (which in reality prolongs the life), no buoyancy or natural flow, homogeneous isotropic rock, and equal flux in each of the 48 streamlines. The production temperature is the flow-weighted mix of the streamlines that have broken through.
What is checked and why you can trust it
Every time the page loads, and whenever you press Re-run check, the simulation evaluates its own mathematics against an independent reference, such as a closed-form formula, a finite-difference derivative or an exhaustive count. Each line above reports PASS or FAIL together with the measured numbers, so you can see by how much it agrees. Results are also published on window.__msChecks for automated testing. The check never uses the same code path as the animation it validates, otherwise it would only confirm itself.
How to read a failure: a FAIL line means the measured discrepancy exceeded the stated tolerance for the current slider values. Try Reset, then move the sliders back toward their defaults; if a check still fails at the defaults it is a bug worth reporting. Tolerances are chosen from the numerical method itself, never tuned to make a test pass: round-off level (1e-9) for exact algebra, about 1e-3 for finite differences and Monte Carlo estimates with a few hundred thousand samples, and a documented margin for stochastic learning runs.
Reproducibility: the particle and pen simulations use the browser random generator for initial positions, so exact pixels differ between visits, but the checks depend only on mathematics and not on those positions. Fixed wave tables (curl noise) and fixed grammars (L-system) are deterministic.
This is an educational model. It shows the mechanism clearly, but it is deliberately simplified; the science panel lists what was left out.