Why does a bright ring of angular radius ≈22° so often circle the Sun or Moon through thin cirrus — the same size whatever the ice, and RED on its inside, the reverse of a rainbow? Bravais (1847) explained it as the minimum-deviation caustic of sunlight refracted through hexagonal ice crystals acting as 60° prisms, radius 21.84° at ice's n=1.31. Does that angle follow from nothing but Snell's law at two faces, with no minimum-deviation formula and no assumption that the ray passes symmetrically?
Units: degrees — angular radius of the small/22° halo = minimum deviation of a 60° ice prism at n = 1.31 (Greenler 1980; Tape 1994; Lynch & Livingston 2001; commonly quoted 21.8–21.84°)
▶ Run this simulationRead how it works
The 22° ice halo read off a raw Snell sweep: with ONLY refraction at two prism faces coded (no minimum-deviation formula, no symmetric-passage assumption), the deviation D(i)=i+e−A through a 60° ice prism (n=1.31) bottoms out at 21.8393° — the 22° halo — to rel 3.2e-5, and the symmetric passage i=e (40.92°) that makes it EMERGES on its own; the SAME machinery gives the 46° halo (45.73°) at a 90° prism and a hard total-internal-reflection ceiling at 99.5° (why 46° is the largest), dispersion puts red on the INNER edge (21.54° vs blue 22.07°, the reverse of the rainbow), and the naive 'halo = reflected sunlight' is falsified structurally: reflection D=180−2θ has |dD/dθ|=2 everywhere — no stationary point, no ring.
A hexagonal ice column presents pairs of side faces inclined at 60°, i.e. a 60° prism. A ray at incidence i refracts in (Snell: r1 = asin(sin i / n)), crosses to the far face at internal angle r2 = A − r1, and refracts out (e = asin(n sin r2)), leaving deviated by D(i) = i + e − A. Tumbling crystals present every incidence; the recovery SWEEPS i over the whole transmitting range and finds the minimum of D(i) by a fine grid scan + parabolic refine — it never evaluates the closed form 2·asin(n·sin(A/2)) − A, never writes 21.84, and never assumes symmetric passage (that i = e at the minimum is CHECKED, not fed in). n = 1.31 (ice Ih, visible) and A = 60° are the physical inputs; known_value is loaded from scripts/oracles/halo.reference.json only to score. The same sweep is run on a 90° prism (the 46° halo), on a 100° prism (the TIR ceiling), for red/blue ice indices (the colour split), and for the reflection rival D = 180° − 2θ. A 24-seed noisy 'sky' (quadratic vertex on a ±0.30° D(i) around its U-minimum) gives the uncertainty, and a uniform-orientation Monte-Carlo cloud shows the caustic pile-up. Gates H–M additionally EXECUTE the shipped src/modules/HaloModule.ts (sha256-pinned, TS-stripped, run via new Function with recorder Babylon/DOM stubs) and certify the on-screen display bit-for-bit against statics-built replicas and the oracle. 13 gates, ~0.4 s. ?world=halo.
D_min = 21.84° for ice (n = 1.31) — recovered, never coded, as the minimum of the two-face refraction deviation D(i) = i + e − A. Because dD/di = 0 there, tumbling crystals pile light up at D_min (a caustic) and none reaches smaller angles: a sharp ring, dark inside.
0.0052
the NOISELESS swept minimum of D(i) = 21.8393° (rel 3.2e-5 vs the cited 21.84°, floor set by the citation's 2-dp rounding — the numerical minimizer matches the analytic minimum deviation to ~1e-5°); the 24-seed noisy 'sky' recovery = 21.8229° ± 0.0052° (SE), worst seed 21.7731° (rel 3.1e-3). Both use only Snell at two faces — no minimum-deviation formula. The small −0.016° seed-mean bias is the quadratic vertex fit reading a slightly asymmetric U low; it is within tolerance and disclosed.
Bravais' 1847 minimum-deviation theory of the ice halo: the 22° halo is the minimum deviation of a 60° ice prism, 21.84° at n = 1.31, and the 46° halo the minimum deviation of a 90° prism, 45.7° (A. Bravais, J. École Polytechnique 18, 1 (1847); R. Greenler, 'Rainbows, Halos, and Glories', CUP 1980, Ch. 2; W. Tape, 'Atmospheric Halos', AGU 1994; Lynch & Livingston, 'Color and Light in Nature', CUP 2001, §5). It VALIDATES, not derives: the substrate is only Snell's law at the two prism faces (asin(sin i / n) in, asin(n sin r2) out) plus the geometric relation r2 = A − r1, and the halo angle, the symmetric passage, the 46° sibling, the colour reversal and the TIR ceiling are all recovered by MEASURING the minimum of D(i) — the closed form 2·asin(n sin(A/2)) − A appears only in scoring the apex sweep. Non-circularity: the generator maps (i, A, n) → D and finds min over i numerically; it contains no 21.84, no closed-form minimum, no A/2 shortcut, and does not assume i = e (that is a checked emergent fact); known_value is read only to score (tamper: known → 25 ⇒ exit 1 with the recovered 21.8393° unchanged). The decisive control — specular reflection D = 180° − 2θ giving |dD/dθ| = 2 with no stationary point through the same machinery — establishes that the ring needs refraction specifically, not merely ice in the sky. The REFRACTION sibling of ?world=rainbow's one-internal-reflection caustic (42°, red outer): same stationary-point-of-deviation idea, a prism instead of a sphere, 22° instead of 42°, red inner instead of outer. Distinct from ?world=snell (the law itself), ?world=mirage (a continuous graded index), ?world=tir (the reflection threshold) and ?world=rainbow (the drop caustic).
HONEST-MODULE CERTIFICATE (derisk gates H–M, zero module edits): the derisk EXECUTES the shipped src/modules/HaloModule.ts — sha256-pinned and mechanically stripped of TypeScript (25 exact strip pairs + 2 bulk prefixes, every count asserted), run via new Function against recorder Babylon/DOM stubs. (1) EXECUTED init measurement === statics replica BIT-FOR-BIT: the 22° minimum 21.83929990977303°, incidence-at-minimum 40.9196°, 46° sibling 45.7334°, red 21.5439°/blue 22.0670°, the measured refraction slope 2.39e-4, and all 221 cached D(i) chart points. (2) The rings are drawn at EXACTLY the recovered angles — torus diameters recomputed from the executed measurement, including the disclosed ×8 red↔blue legibility gap (the ring radii themselves are true). (3) 600 real fixedUpdate/render engine calls at fl(1/120) are bit-exact at EVERY call: spin accumulator, all 34 crystal rotations, 150 %4-cadence HUD writes each bit-equal to the replica; the %8 chart branch is DEAD (post-increment _frame ≡ 1 mod 4 there — 7th world in a row with this cadence) and proven HARMLESS: statics-only, exactly 1 write at init, frozen SVG === replica === a fresh executed _buildChart(). (4) Shown digits '21.839°/40.92°/45.73°/21.54°/22.07°' are cert-pinned yet EARNED: every executed value differs bit-for-bit from the cited constants, and the live sweep MOVES under symmetry-breaking probes (n=1.32 → 22.60°, A=70° → 27.42°). (5) The 10×-LIGHTER display sweep (I_GRID 40000 vs the oracle's 400000) is PRICED with ZERO noise term (the module has NO RNG): the parabolic-vertex refine crushes the resolution stage to |Δ| ≤ 2.2e-14° on all four angles (red/blue bit-identical to the oracle's), vertex position Δ 2.2e-8°, all gated; the module's refraction slope (3000-point grid vs oracle's 4000) sits under its own derived finite-difference ceiling |D''|·h. (6) ONE law-fed display element, disclosed and reconciled — correcting this finding's earlier wording ('shown from the same sweep'): the rival's shown |dD/dθ| = 2 is CODED analytically in the module (this._reflSlope = 2, the exact derivative of D = 180° − 2θ), not measured on screen; the oracle measures it numerically (2.000000000, |Δ| ≤ 1e-9 gated), and the falsification verdict rests on the LIVE-measured refraction slope →0, never on the coded constant. (7) The executed measurement block is answer-free (no 21.8/45.7/40.9/21.5/22.0 literals, no closed form, no A/2 shortcut; 6 M.I_GRID + 5 M.N_ICE disclosed instrument refs) with a planted-violation self-test. Tamper tests surgical: known→25 fails only scoring gates A/E with the recovery unchanged; cert-sha only H; exec-ulp only K. Screen scale and tumbling crystals remain schematic, disclosed on-screen.
npm run derisk -- halo (scripts/halo-derisk.mjs)scripts/oracles/halo.reference.jsonA. Bravais, 'Mémoire sur les halos et les phénomènes optiques qui les accompagnent', J. École Polytechnique 18, 1 (1847) — the minimum-deviation theory. R. Greenler, 'Rainbows, Halos, and Glories' (CUP, 1980), Ch. 2 — 22° halo at 21.84° (n = 1.31) and the 46° halo. W. Tape, 'Atmospheric Halos' (AGU, 1994). D. K. Lynch & W. Livingston, 'Color and Light in Nature' (2nd ed., CUP, 2001), §5 (radius 21.84°, red inner edge). L. Cowley, Atmospheric Optics (atoptics.co.uk): 22° halo inner radius ≈ 21.8°.