Principles
LUMA has one rule: nothing is pre-recorded. Every readout, table row and graph point is computed from a mathematical model of the apparatus, in the browser, at the moment you ask for it. Time-dependent experiments (projectile, pendulum, reaction kinetics) integrate their differential equations numerically with the classical fourth-order Runge–Kutta method (RK4). Static experiments (circuits, optics, gases) solve their governing equations directly, or by bisection/Newton iteration where they are non-linear.
"Measured" values are not the same as the model's exact values: they pass through a simulated instrument that adds Gaussian reading noise and rounds to a display resolution (see below). This is deliberate. Comparing an experimental value with a theoretical one, computing a percentage error, and deciding whether the discrepancy is explained by the instruments is the point of laboratory work, and it only makes sense if the two can differ.
The source is plain ES modules with no libraries: one engine per experiment under js/experiments/, a plotting module, a report module, a store, and an accessibility module.
Instruments and the noise model
Each instrument is defined by a display resolution, a relative noise (σ as a fraction of the reading) and an absolute noise floor. A reading is quantise(true + N(0, σ), resolution) with σ = √((rel × |true|)² + abs²). Noise is drawn from a seeded pseudo-random generator (mulberry32 with Box–Muller), seeded per session. Live readouts on the apparatus show the quantised value without noise; "Take measurement" draws a fresh noisy sample. Manufactured resistors additionally carry a fixed ±1 % tolerance, deterministic per slot and nominal value, so repeated readings of the same circuit are consistent but not exactly nominal.
| Instrument | Used in | Resolution | Noise σ (relative) | Noise floor (absolute) |
|---|---|---|---|---|
| Measuring tape | Projectile (range) | 0.01 m | 0.2 % | 0.005 m |
| Height gauge | Projectile (max height) | 0.01 m | 0.3 % | 0.005 m |
| Photogate timer | Projectile (time of flight) | 0.01 s | 0.1 % | 0.008 s |
| Photogate stopwatch | Pendulum (n periods) | 0.01 s | 0.1 % | 0.012 s |
| Digital ammeter | Ohm, series, parallel, LED | 0.1 mA | 0.5 % | 0.05 mA |
| Digital voltmeter | Ohm, series, LED | 0.01 V | 0.3 % | 0.005 V |
| Optical protractor | Refraction | 0.5° | — | 0.3° |
| Concentration probe | Reaction rate | 0.001 M | 0.4 % | 0.0005 M |
| Pressure transducer | Gas laws | 0.1 kPa | 0.2 % | 0.05 kPa |
| Volume scale | Gas laws | 0.01 L | 0.2 % | 0.005 L |
| Platinum thermometer | Gas laws | 0.1 K | — | 0.2 K |
Projectile motion
Model. Point mass launched from height h₀ at speed v₀ and angle θ, under gravity g, optionally with quadratic air drag per unit mass k (m⁻¹):
ẍ = −k |v| ẋ ÿ = −g − k |v| ẏ
Integration. RK4 with Δt = 2 ms on the state (x, y, ẋ, ẏ). The landing instant is found by linear interpolation across the last step where y crosses zero. Time is scaled so that long flights complete in about six seconds of real time.
Theory shown. Drag-free analytic values: T = [v₀ sin θ + √(v₀² sin² θ + 2 g h₀)] / g, R = v₀ cos θ · T, H = h₀ + (v₀ sin θ)² / 2g. When drag is enabled the simulation deviates from these — which is the intended lesson.
Graphs. Live trajectory against the analytic parabola; range and time of flight against launch angle with the theoretical curve; measured range against theoretical range with a linear fit (slope 1 = agreement).
Simple pendulum
Model. Full nonlinear pendulum with viscous damping:
θ̈ = −(g / L) sin θ − (b / m) θ̇
Integration. RK4 with Δt = 1 ms. Period boundaries are the positive-going zero crossings of θ (interpolated within the step), which is what a photogate at the bottom of the swing detects. The run stops after ten periods or 30 s.
Theory shown. Small-angle T₀ = 2π√(L/g), and the exact-period series T = T₀ (1 + θ₀²/16 + 11θ₀⁴/3072 + 173θ₀⁶/737280). The stopwatch measures the total time for n periods and divides, so timing noise shrinks as 1/n.
Graphs. θ(t) against the small-angle cosine; T vs L; T² vs L with a fit whose slope is 4π²/g; T vs amplitude against the exact series and the small-angle constant.
Ohm's law
Model. I = V / R_total with R_total the series sum of 1–4 nominal resistors, each perturbed by its fixed ±1 % tolerance. Ideal source and wires.
Graphs. I vs V with a least-squares line whose slope is 1/R; V vs I (slope R); measured vs theoretical current. The report extracts R from the fit and compares it with the nominal value.
Refraction and Snell's law
Model. n₁ sin i = n₂ sin r. If (n₁/n₂) sin i > 1 there is no refracted ray and the beam is totally internally reflected; the critical angle sin θc = n₂/n₁ is reported when n₁ > n₂. Both media are adjustable between 1.00 and 2.50; the nearest named material is displayed. Monochromatic light — no dispersion.
Graphs. sin r vs sin i with fit (slope n₁/n₂); r vs i with the Snell curve.
Series circuit
Model. R_total = ΣRᵢ (actual values with tolerance), I = V/R_total, Vᵢ = I·Rᵢ. Each measurement records the ammeter reading and a voltmeter reading across every element, so Kirchhoff's voltage law (ΣVᵢ = V) can be checked with noisy data.
Graphs. Voltage drop vs resistance for the latest row (slope = current); total current vs supply (slope = 1/R_total); ΣV vs V.
Parallel circuit
Model. 1/R_eq = Σ 1/Rᵢ; branch currents Iᵢ = V/Rᵢ; supply current V/R_eq. Every branch has its own ammeter, so Kirchhoff's current law (ΣIᵢ = I) can be tested.
Graphs. Branch current vs conductance 1/R (slope = V); total current vs supply (slope = 1/R_eq); ΣIᵢ vs I.
LED circuit
Model. Shockley diode equation with n·V_T = 0.05 V, with the saturation current fitted so that the chosen colour reaches its rated forward voltage at 20 mA:
I = I_s (e^{V_d / nV_T} − 1), V = V_d + I R
The operating point is found by bisection on V_d. The simple textbook estimate I ≈ (V − V_f)/R is shown alongside as the "linear" theory so that its failure near turn-on and at high current is visible. LED brightness is rendered proportional to I/I_max; states OK, OFF (I < 1 mA) and OVERCURRENT (I > I_max) are shown as text and as a warning box, never by colour alone. The recommended series resistor for a target current is (V − V_f)/I_target rounded up to the E12 series.
| LED | V_f at 20 mA | I_max |
|---|---|---|
| Red (AlGaInP) | 1.8 V | 20 mA |
| Yellow | 2.0 V | 20 mA |
| Green (InGaN) | 2.1 V | 20 mA |
| Blue | 3.0 V | 20 mA |
| White | 3.2 V | 25 mA |
Reaction rate
Model. A single reactant A → products with rate law −d[A]/dt = k[A]ⁿ (n = 1 by default; 2 available as an advanced option) and an Arrhenius rate constant:
k = A · exp(−Eₐ / (R T)), catalyst: Eₐ → Eₐ − ΔEₐ
Integration. RK4 on [A] with a sub-step no larger than 1/2000 of the run. The run length is chosen so that most of the reactant is consumed (4/k for first order, 19/(k[A]₀) for second order, capped between 5 s and 1 h of simulated time) and is compressed into about 12 s of real time. A probe samples [A] two hundred times per run.
Measurement. The initial rate is −b from a least-squares quadratic c = a + b t + q t² through the (noisy) probe samples in the first 10 % of the run — a tangent-at-zero estimate that does not suffer the bias of a straight line through a curved trace. Probe noise is amplified by this differentiation, which is why repeated runs scatter by a few per cent.
Graphs. Live [A](t) against the analytic solution; ln(rate) vs ln[A]₀ (slope = order); ln(rate) vs 1/T (slope = −Eₐ/R); rate vs [A]₀.
Gas laws
Model. Ideal gas PV = nRT (R = 8.314 J mol⁻¹ K⁻¹) as the theory, and — when a real gas is selected — van der Waals behaviour as the "actual" gas in the cylinder:
(P + a n² / V²)(V − n b) = n R T
Constants (a in Pa·m⁶·mol⁻², b in m³·mol⁻¹): He 0.00346 / 2.38×10⁻⁵; N₂ 0.137 / 3.87×10⁻⁵; CO₂ 0.364 / 4.27×10⁻⁵; NH₃ 0.4225 / 3.71×10⁻⁵. In isobaric mode the volume is found from the held pressure by Newton iteration. Three processes are provided: isothermal (vary V, read P), isochoric (vary T, read P) and isobaric (vary T, read V); the control that the process holds fixed is disabled and explained.
Graphs. P vs V with the ideal isotherm; P vs 1/V (slope nRT); P vs T (slope nR/V, intercept → absolute zero); V vs T (slope nR/P); compressibility Z = PV/nRT vs P.
Error analysis and reports
Every data row stores the measured value, the theoretical value and error % = |measured − theoretical| / |theoretical| × 100. The report gives the mean percentage error over all rows.
Uncertainty is stated for the most recent group of rows taken at identical settings. With one or two readings it is the single-reading instrument uncertainty, √((resolution/2)² + σ²). With three or more readings it is the standard error of the mean, s/√n, never smaller than the instrument uncertainty divided by √n. Linear fits report slope, intercept, R² and, where n > 2, the standard error of the slope.
The report has nine sections — objective, set-up, measurements, graphs (rendered as SVG), calculations with the formula, the substituted numbers and the result, result summary, error analysis with likely sources, observations, and a conclusion. The conclusion is generated from your data: it states the level of agreement, checks whether the deviation is within instrument noise, and comments on systematic effects it can detect (drag, large amplitudes, catalyst, real-gas behaviour, overcurrent). It can be printed, downloaded as a self-contained HTML file, or exported as JSON containing the parameters, rows, observations, analysis and graph data.
Accessibility
Keyboard
Every control is a native element (button, range, number, select, checkbox, textarea) so the browser provides the full keyboard model: Tab/Shift+Tab to move, Enter/Space to activate, arrow keys to change a slider by one step, Page Up/Down for larger steps, Home/End to jump to the limits. Each slider has a paired numeric field for typing an exact value. Focus is always visible (a 3 px ring, yellow in high-contrast mode). The report opens in a native dialog that traps focus and closes with Escape. Each page has a skip link.
Screen readers
All controls are labelled with the quantity and unit; sliders expose aria-valuetext with the unit. The apparatus SVG has a role of image with a text description that updates with the settings. A single polite live region announces: run start/stop/complete, each measurement (with the key values), warnings, and — during a run — a summary of the first three readouts at most once every three seconds, so the reader is not flooded by animation frames. Warnings use role status (or alert for overcurrent). The "Describe this graph" button writes a textual description (series, trend, minima/maxima, fit and its meaning) to a polite live region beneath the graph; the same description is set as the canvas's accessible name.
Vision
High-contrast mode switches to a pure black background, white text, brighter accent colours and stronger borders, and removes the background grid. Text is set in rem units and the layout survives 200 % zoom (panels stack). Colour never carries information alone: theoretical readouts are also marked "(th)", LED state is text, warnings have an icon and the word "Warning"/"Error", and graph series use distinct dash patterns and markers with a text legend.
Motion
Reduced-motion mode is on automatically when the operating system requests it and can be toggled on any page. In this mode the run loop is not animated: Start computes the whole run at once and shows the final state and trace, and a Step button advances the simulation by a quarter of a second of scaled time so the evolution can still be examined. Moving charge markers and gas particles are drawn static.
Simplified interface
Simplified mode hides advanced parameters (marked ADV) and shows a task strip with one instruction at a time and Previous/Next buttons; the controls the current task refers to are outlined. All three preferences persist in local storage and apply before the first paint on every page.
Limitations
- Models are idealised: no wire resistance or source impedance in circuits, no dispersion in optics, no heat transfer or reverse reaction in kinetics, a single van der Waals correction for real gases.
- Noise is Gaussian and stationary. Real instruments drift, have offset errors and are occasionally misread; LUMA models none of these.
- Numerical integration is accurate to far better than instrument noise at the step sizes used, but the pendulum run is capped at 30 s and the reaction at one hour of simulated time.
- The reaction-rate experiment is a single hypothetical reaction with adjustable constants, not a specific named reaction.
- Downloads (CSV, HTML, JSON) rely on the browser allowing file downloads; the print view relies on pop-ups being allowed. If either is blocked the interface says so.
- All data lives in the browser's local storage. Nothing is uploaded, which also means nothing is backed up: export reports you want to keep.
For teachers
Each experiment includes a task sequence (visible in Simplified mode) that follows a conventional practical: set up, run, measure, vary one variable, fit, conclude. Reasonable 40-minute sessions are, for example: Ohm's law with five voltages and a fit; the pendulum at four lengths for g from the T² vs L slope, then one large-amplitude run to discuss the small-angle approximation; reaction kinetics at four concentrations for the order, then four temperatures for Eₐ.
Because measurements are noisy, students can take repeated readings at the same settings and see the reported uncertainty change from an instrument estimate to a standard error at three readings. The JSON export contains everything a student did, including timestamped observations, which makes it usable as evidence of practical work. The advanced parameters (gravity, damping, activation energy, reaction order, gas type) allow you to set a "mystery" configuration for students to determine from data.
Data and privacy
LUMA stores your preferences, last-used parameters, data rows and observations per experiment in localStorage under the key luma:v1. No analytics, no cookies, no network requests other than fetching the page, its scripts and the fonts. Clearing site data in your browser removes everything.