Method
What the silo is, how the four measurements are made, which numbers are identifiable and which are not, and where the colour on this page came from. Every figure on this site is produced by code in this repository from a stated seed or a stated block.
The silo
Soft-sphere discrete element, after Cundall & Strack (1979). Grains carry a linear spring-dashpot normal contact and a tangential spring with history, capped by Coulomb friction:
F_n = k_n·δ − γ_n·v_n no cohesion, no tension
F_t = −k_t·ξ − γ_t·v_t, |F_t| ≤ μ·F_n
ξ is the accumulated tangential displacement of that contact — a
spring with history, not a drag. The distinction is the whole model: a viscous
tangential force lets go the instant sliding stops, so a bed built on one flows like a
liquid and can never arch. Static friction is what holds an arch up, and static
friction is a spring.
- Grains in the silo on the front page
- 440
- Grains in the packing measurement
- 516
- Radius spread
- ±10%, to stop the bed crystallising
- Normal stiffness k_n
- 2000
- Friction μ, grain and wall
- 0.5
- Timestep
- 5 × 10⁻⁴ — a hundredth of a contact
- Packing fraction reached
- 0.852, overlaps 0.46% of a diameter
- Corrected for overlap
- 0.844
- Coordination number
- 3.48
The grains are deliberately unequal. Identical discs in two dimensions crystallise into a triangular lattice within seconds of settling, and a crystal is a different material — it discharges in bursts along its own lattice planes. A soft-sphere packing fraction is also quoted with its overlaps, because without them it is a number you can push past the geometric limit by softening the springs.
Run it yourself
The same solver, with the orifice on a slider. Everything below is computed in your tab from the width you choose — including whether it arches, which you can make happen by taking the gate under 4.5 grain widths and waiting.
- Grains through
- 0
- Rate
- —
- Under a tenth of exit speed
- —
- State
- flowing
Friction is on the slider because it is what makes an arch possible at all. Take it to zero and the bed becomes a liquid: it will not arch at any width, and its rate starts caring about how full it is.
The exponent this experiment cannot measure
Beverloo's law says the rate goes as (D − k·d)^β, with
β = 3/2 in two dimensions. Two free parameters, nine precisely measured rates. Fit
them, and you get a confident wrong answer.
Letting both float and taking the best R² returns β = 2.059 ± 0.038 with k pinned at zero: an exponent wrong by a third, quoted to four figures, with a standard error that says it is certain. Nothing is wrong with the fit. The residual cannot see the error, because the data do not contain the answer.
So the law is not fitted here. It is decomposed, and each
factor is measured on its own: rate = φ · w_eff · v.
What is left is the flowing width, and it comes out linear in the orifice with an empty rim of 2.02 grain diameters — a Beverloo k a laboratory would recognise. The exponent is then a consequence of two measurements rather than a knob. The site publishes the ridge instead of the exponent, because the ridge is what the experiment actually determined.
Confidence classes
A structural design code does not print a load and leave you to guess where it came from. Every figure on this site carries one of these, and the build fails if one is published without.
Measured
Read from a public Base node by a script in this repository, at a stated block, with no API key and no proxy in the path. Re-runnable by anyone; it will not return the same numbers, because the chain has moved.
Computed
Produced by the discrete element model in js/granular.js from a stated seed. Deterministic: the same seed returns the same figure on any machine, and the build recomputes it rather than trusting the last answer.
Assumed
A parameter chosen, or a value taken from published work rather than reproduced here. Everything in this class is a place the site could be wrong without any of its own checks noticing.
Symbols
| Symbol | Unit | Meaning |
|---|---|---|
| d | — | grain diameter. Every length on this site is in these. |
| D | d | orifice width — the gate. |
| W | d | bin width. |
| h | d | head: the height of material above the orifice. |
| φ | — | packing fraction: how much of a volume is grain rather than gap. |
| k | d | the empty rim at the orifice that grain centres do not enter. |
| β | — | the exponent in Beverloo's law. Three halves in two dimensions. |
| γ | — | the exponent of discharge rate on head. Exactly ½ for a liquid. |
| μ | — | friction coefficient, grain on grain and grain on wall. |
| g | — | gravity. Set to 1, so time is in units of √(d/g). |
| W(D) | grains/√(d/g) | discharge rate. |
Every check the build runs
These are imported from tools/verify-model.mjs and
tools/palette.mjs rather than transcribed, so this page cannot name a
check that does not exist. Any failure fails the build.
- PASS exit speed goes as a square root of the aperture, not linearlyexponent 0.555 ± 0.024 against D, R² 0.9876; theory brackets 0.50–0.73
- PASS packing in the aperture does not depend on the apertureφ from 0.654 to 0.679 across a 2.1× range of D
- PASS the flowing width is linear in the orifice (R² ≥ 0.99)w_eff = 1.199·D − 2.42, R² 0.9977 ⇒ an empty rim of 2.02 d
- PASS Beverloo with β held at 3/2 fits the nine rates (R² ≥ 0.99)k = 1.828 d, R² = 0.9964, residual 0.38 grains per √(d/g)
- PASS a plain power law with no offset fits them just as wellβ = 2.059 ± 0.038, R² = 0.9976
- PASS the exponent is NOT identifiable from these ratesβ spans 1.24–2.06 for a total R² spread of 0.00608 over a 2.1× range of D
- PASS the empty rim is one a laboratory would recognise (0.5 – 3 d)2.02 d from the decomposition, 1.828 d from the held fit
- PASS head exponent is far below a liquid's ½ — every bin with head leftγ = 0.171 ± 0.035 over 14 bins, head ×7.9; Torricelli is exactly 0.5
- PASS head exponent is far below a liquid's ½ — after the first 2 binsγ = 0.135 ± 0.036 over 12 bins, head ×6.9; Torricelli is exactly 0.5
- PASS the answer does not depend on where the start-up is cutγ = 0.171 with the first bins, 0.135 without
- PASS the head range measured is at least fourfoldhead 51.3 → 6.5 d, a factor of 7.9
- PASS clogging vanishes at or below D/d = 5first orifice with no arch in 12 runs: D/d = 4.5
- PASS clogging probability falls with orifice width2.5:67% 3:58% 3.5:33% 4:33% 4.5:0% 5:0% 6:0%
- PASS a fifth or more of the bed is standing still at half drained32.2% of what remains has never moved; peak 68.8%
- PASS the floor stops feeling extra weight — Janssen saturationover the tested range the weight grew ×14.8 and the load on the floor grew ×6.2
- PASS an exponential saturation describes it (R² ≥ 0.97)λ = 23.7 d, p∞ = 219.0, R² = 0.9943
- PASS the implied stress ratio K is a plausible one (0.2 – 1.2)K = 0.42 from λ = W/(2μK)
- PASS at the deepest fill the walls carry most of the weight59% of the weight never reaches the floor
- PASS packing is granular once its overlaps are taken off (0.78 – 0.86)φ 0.8518, mean overlap 0.46% of d → 0.8439; coordination 3.48
Where the colour came from
The palette is the thesis in another medium. Grind a solid finer and it gets lighter and less saturated. Nothing was added and nothing was removed: the absorption per unit path is a property of the material and does not change. What changes is how far light travels between scattering events.
The model is Kubelka–Munk, the standard two-flux treatment of an opaque diffusing
layer: R∞ = 1 + K/S − √((K/S)² + 2K/S), with the scattering coefficient
going as one over the grain size. So grain diameter is the one parameter that moves a
pigment along its own ramp — the same material, divided more finely, looks like
more.
Hue comes from the absorber, not from that one parameter: a one-parameter family is a line, and a line is not a palette. The ground is a two-band absorber — the shape that makes vegetation green. The accents are a broad blue band (dry grain), its complement (aeration air) and an absorption edge (rust, and the thing that stops). Every lightness that has to clear a contrast target is solved for that target rather than nudged until it looked right.
- PASS ȳ peaks at 555 nm (photopic maximum)554.3 nm
- PASS x̄ peaks at 600 nm ± 6599.8 nm
- PASS z̄ peaks at 446 nm ± 8448.3 nm
- PASS a flat 50% reflector has no huechroma 0.00000
- PASS K/S → 0 gives R∞ → 10.999965
- PASS K/S → ∞ gives R∞ → 00.00e+0
- PASS sward: finer grind is lighter, monotonically0.881 > 0.840 > 0.788 > 0.725 > 0.651 > 0.570
- PASS husk: finer grind is lighter, monotonically0.879 > 0.842 > 0.797 > 0.744 > 0.684 > 0.615
- PASS oxide: finer grind is lighter, monotonically0.734 > 0.662 > 0.585 > 0.508 > 0.434 > 0.365
- PASS vent: finer grind is lighter, monotonically0.746 > 0.672 > 0.590 > 0.506 > 0.425 > 0.352
- PASS flint: finer grind is lighter, monotonically0.833 > 0.774 > 0.702 > 0.618 > 0.527 > 0.439
- PASS sward: chroma falls as it is ground finer0.1368 at d=8 → 0.0927 at d=0.25
- PASS the four coloured absorbers are ≥ 35° apart in huesward 123° / husk 68° / oxide 24° / vent 265°
- PASS hex round-trips to within 1% in L0.7444 → 0.7430
- PASS body ink on --deep ≥ 7:115.41:1
- PASS body ink on --ground2 ≥ 7:114.22:1
- PASS body ink on --ground ≥ 7:112.88:1
- PASS body ink on --plate ≥ 7:111.18:1
- PASS body ink on --plate2 ≥ 7:19.52:1
- PASS faintest ink on --plate2 ≥ 4.5:14.90:1
- PASS --ink reached its solved target of 11.2:111.20:1
- PASS --ink2 reached its solved target of 9.5:19.52:1
- PASS --ink3 reached its solved target of 7:16.99:1
- PASS --faint reached its solved target of 4.9:14.90:1
- PASS every sibling ground differs by ≥0.05 in L or ≥40° in hueclosest call is ANNEAL — ΔL 0.093, Δh 71° (too neutral to count)
- PASS the ground is green (OKLCh hue 105–145)126.7°
- PASS the ground sits at L 0.255 ± 0.010.2546
- PASS --husk on --plate2 ≥ 4.5:1 as text4.618:1
- PASS --vent on --plate2 ≥ 4.5:1 as text4.606:1
- PASS --oxide on --plate2 ≥ 4.5:1 as text4.631:1
- PASS --deep on --husk-mark ≥ 7:18.423:1
- PASS --deep on --vent-mark ≥ 7:18.399:1
- PASS --deep on --oxide-mark ≥ 7:18.323:1
- PASS surface steps are between 0.030 and 0.055 in L0.038 0.037 0.043 0.043
- PASS the published grind ramp is monotone in L0.570 < 0.651 < 0.725 < 0.788 < 0.840 < 0.881