# Testing Harold Aspden's Aether Physics Against Modern Measurements

**A working record of claims, checks, corrections and extrapolations**

By Doug Westmoreland (project lead: direction and review) and Claude, Anthropic (research and analysis) · Working paper, version 2.4, 31 October 2026

---

## Abstract

Harold Aspden (1927–2011) developed an aether theory over five decades that claims to derive the fine-structure constant, Planck's constant, the proton/electron mass ratio, the constant of gravitation G and several nuclear properties from a lattice of charges filling space. This paper records a systematic examination of that work. Each claim was first evaluated on its own terms, then tested against measurements made since the 1990s, then (where useful) refined or extended on the assumption that the foundation has some merit. Finally, the chance that a framework of this kind would produce its reported agreements by coincidence was estimated by counting how many formulas built from the same ingredients land as close to the measured values.

The main findings, revised in version 2.3 to judge the theory as one at an early stage of development, are:

1. **Many significant digits in critical areas.** From one lattice and a few integers, Aspden's formulas reach seven significant digits for the fine-structure constant and the proton/electron mass ratio. The Standard Model takes both numbers from measurement and does not attempt to derive them. His formulas reach six to eight digits for the muon/electron mass ratio, the deuteron moment and the proton and neutron magnetic moments. His proton/electron ratio (1975) and muon ratio (1983) were closer to today's values than the measurements of their day. His neutron moment, −44/23 (1986), is still within 1.6σ of today's value.
2. **Strongest where mainstream calculation is hardest.** Section 12.1 scores his numbers side by side with QED and the Standard Model. For the seven quantities set mainly by the strong force, his numbers are nearer the measured values than today's lattice-QCD calculations in all seven, with more digits right in six. Where the electromagnetic and weak forces do the work, QED and the Standard Model are decisively better.
3. **A theory at an early stage of development.** Aspden worked for five decades, but largely alone, and his theory never had the refinement a research community gives a mainstream theory. QED's prediction of the electron's magnetic moment began in 1948 as Schwinger's one-term formula, right to about three digits. It reached ten digits through seventy years of calculation by many physicists. Aspden's formulas should be read the same way, as leading-order results whose corrections have not been worked out.
4. **Not yet exact, and partly tuned.** As published, 44 of the 48 numbers scored miss today's measurements by more than twice their uncertainty. That alone does not rule a theory out. Bohr's formula for the hydrogen atom misses its ionization energy by millions of standard deviations, yet it was a real step. Scored by the same standard, the Standard Model's own predictions are within 2σ for 2 of 17. But about 40% of Aspden's digits came from selections and revisions made with the measurement of the day in view, and a few from numbers that already encode the answer. Of the 27 numbers he compared with data, 20 sit nearer the value he used than today's. Allowing for the formulas he could have tried, the odds of matching α, mp/mₑ, the deuteron moment and G all this closely by chance are about 1 in 2,000 under central assumptions (range 1 in 30 to 1 in 430,000). That is suggestive, not decisive. The results with the most digits beyond chance are 1/α and mp/mₑ, which involve no late tuning, and the neutron's 44/23, which rests on a model that fails elsewhere.
5. **Sound workmanship.** His arithmetic and lattice calculations are generally sound. Several unexplained steps follow from his own rules, including the 1.875 cluster and the finite-size term in his α derivation, which is exact for a quon that excludes the background.
6. **Parts excluded on physical grounds, not on precision.** These need rethinking rather than refining:
  - His aether-drag and anti-expansion claims, his claim that the constants shift in steps with energy or temperature, and his 1969 aether account of Mercury's perihelion are excluded by modern experiments and observations, mostly by factors of hundreds to thousands.
  - His own frame for light, carried with the Earth but not turning with it, is excluded by rotating-cavity experiments by a factor of about 1,500.
  - His lattice cannot carry light. Treated with Coulomb's and Maxwell's laws it is a plasma whose frequency is exactly the electron's Compton frequency, and his orbit is its natural oscillation. The same plasma would block all light below 511 keV, equivalent to giving the photon the electron's mass, 5 × 10²³ times the measured limit (section 15).
  - His Rydberg-constant argument against time dilation (1980, 1996) matches Einstein to order (v/c)² but is excluded at order (v/c)⁴ by fast-ion experiments.
  - His 1983 cavity-electron Lamb-shift formula is 6σ from the 2019 measurement and 20% off for ionised helium. The limited range of gravity he drew from the same papers is excluded by Gaia's measurement of the solar system's acceleration toward the galactic centre.
7. **Our corrections, tested out of sample.** Replacing his 1.875 cluster with an ejected charge of exactly two electron masses improves his G from 320 ppm to 34 ppm below the recommended value. The same change makes his muon lifetime much worse (+0.1% becomes +68%), so it is not adopted.
8. **The question remains open.** No accepted theory derives α, mp/mₑ or G from first principles. A search of every text on the site found no first-principles calculation of the Earth's surface gravity and no non-relativistic account of hydrogen's fine structure. The work worth doing next is a correction programme derived from his own lattice and written down before comparing with data, together with predictions registered in advance for measurements now under way: G, the muon/electron mass ratio and the neutron moment.

Companion papers rebuild the aether's smallest units step by step (Part 1 and its supplement), test his particle numbers and his remarks on quarks (Part 2), and score every number against QED and the Standard Model (the scorecard, *Aspden's Numbers at a Glance*); see section 15. The tests in this paper and Part 1 are listed step by step in a separate test register.

---

## Revision history

| Version | Date | Changes |
|---|---|---|
| 1.0 | 30 Oct 2026 | Initial record |
| 1.1 | 30 Oct 2026 | Full program listings and outputs added (Appendix C) |
| 1.2 | 30 Oct 2026 | Improved G cluster of exactly 2 mₑ adopted, with the rationale from Aspden's own work (section 7.5). The finite-size term in the α derivation is shown to be exact in Aspden's model, withdrawing the version 1.1 claim that refining it breaks the α agreement (section 5.3). New script `alpha_finite_size.py` |
| 1.3 | 30 Oct 2026 | Probability analysis redone with one consistent null model and the corrections in place, including the joint chance of all four constants at once (section 11). Restored aspden.org bibliography added to sources and next steps |
| 1.4 | 30 Oct 2026 | Proton/electron ratio and Rydberg constant examined, including his claim that constants shift with energy or temperature, tested against white-dwarf, solar and quasar spectra (section 6); his 1983 charge-inequality explanation tested against neutrality limits; α³/2 numerical lead recorded; Mercury's perihelion objection added (section 9). New script `environment_constants.py` |
| 1.5 | 30 Oct 2026 | *Physics without Einstein* chapters 4–7, Energy Science Report No. 6 and the 1983 papers 1983c and 1983d read in full from supplied scans. Section 9 expanded: the 1969 aether-sphere account of Mercury's perihelion (wrong sign; fails for the other planets and the double pulsar), the cavity-resonant electron's anomalous moments and Lamb shift, the "absolute gravitational potential" at the Earth's surface, and the search for a first-principles g = 9.8 m/s². Rydberg passage still not found (section 6.3). New scripts `cavity_1983.py` and `mercury_aether.py` |
| 1.6 | 30 Oct 2026 | Cavity-electron formula traced to its three modelling choices and tested against 20 alternatives (section 9.3). Site-wide index of Aspden's papers and books compiled (532 entries) and prepared for publication on aetherscience.org; new leads for the Rydberg passage listed (section 14). New script `cavity_variants.py` |
| 1.7 | 30 Oct 2026 | Complete copy of the site obtained from the server; paper index rebuilt from it (547 entries, nothing missing). The Rydberg/Einstein passage found ("Atomic Spectra and the Moving Atom", 1996, and *Physics Unified*, 1980) and tested against fast-ion time-dilation experiments (section 9.6). Searches of all site texts close the g = 9.8 m/s² and fine-structure questions. New script `moving_atom.py` |
| 2.0 | 30–31 Oct 2026 | Section 15 updated for Part 1 v1.4 (objections U37–U40) and its supplement Part 1A: the self-consistent model shows the quon lattice is a plasma that blocks light below 511 keV. Out-of-sample test of the doubled electron (section 7.6). Every use of the 1.875 cluster in the site's texts was found. Besides G there are two: the 1986j "upsilon" at 6.1 GeV, a particle later shown not to exist, and the 2003 muon lifetime, which gets worse (+0.1% becomes +68%). The 1986 meson papers do not otherwise use the cluster, as section 7.5 had assumed. The improved G is now treated as unsupported in the summary figures (sections 11.3, 11.4, 13 and 14). New script `out_of_sample.py` |
| 2.1 | 31 Oct 2026 | Aspden's own frame for light is now credited to him in sections 3.1 and 3.3: in *Physics Unified* (1980, ch. 9) it travels with the Earth but does not turn with it, and in 1983 he named the test himself, saying that a laboratory's West–East speed of "some 350 m/s at 40oN" showing up in light-speed measurements would refute Einstein. Rotating cavities exclude it by a factor of about 1,500. Section 3.1 points to Part 1A, section 13.5, which works through the c/2 backflow in Tutorial Note 18. Section 15 updated for Part 1 v1.5 (input I1 split; U41, the postulate that the frames move at c relative to each other, cancels out of α) and Part 1A v1.2 (Aspden's texts on c/2 and on the Earth's own aether, three figures) |
| 2.4 | 31 Oct 2026 | Byline changed to name Doug Westmoreland as project lead (direction and review), with Claude (Anthropic) for research and analysis, in this paper and its companions. Part 2 and the scorecard published (section 15.3 and 15.4) |
| 2.3 | 31 Oct 2026 | Abstract revised to judge the theory as one at an early stage of development and to credit what it gets right. Version 2.2's first finding, that every derived constant misses today's measurements by far more than its uncertainty so the theory as a literal account is ruled out, is withdrawn as worded. Four of the 48 numbers scored are within 2σ. A miss by more than the measurement error shows a formula is not exact, which is also true of leading-order theories such as Bohr's atom, and the Standard Model fails the same test for 15 of its 17 predictions. The exclusions on physical grounds are kept and grouped as finding 6. The figures in the abstract and section 12.1 that come from the scorecard's digit audit were checked by an independent reviewer (Opus, extra effort) before publication, and its corrections are applied. For example, the integer 273 is no longer described as encoding the pion mass, and 44/23 is no longer called a single simple choice |
| 2.2 | 31 Oct 2026 | Preliminary statement comparing Aspden with QED and the Standard Model added as section 12.1, with finding (9) in the abstract and a bullet in section 13. It draws on the companion scorecard (*Aspden's Numbers at a Glance*, draft 0.4, not yet published), which scores Aspden's numbers and the mainstream predictions the same way and traces where each prediction's digits come from. The neutron–proton mass difference in section 12's table is now set beside Aspden's value |
| 1.9 | 30 Oct 2026 | Companion paper *Aspden's Aether from the Bottom Up, Part 1: The Smallest Units* written (31 tests, U01–U31) and summarised in section 15. Section 5.3 adds the photon unit's relativistic speeds and magnetic coupling as a fifth assumption that α depends on, and §11.4 adds the resulting caution. A test register listing all 94 tests in both papers is added. Compiling it found errors in this paper, all now corrected: −4,000σ not −3,800σ for α today (§10); NIST-26 −256 ppm (§7.3); −35 ppm for the 1.9993 mₑ row (§7.5); version 1.6's mixed-unit figure −8.6 ppm (§8); the Lamb-shift correction factors −1.17% (§9.3); the series attribution (§9.3); the 7/4 triplet is not heavy-centred (§7.5, §8); the G history range and the removed claim that it tracked the measurements (§7.2); 5×10⁻¹³ at 300 m/s (§3.1); 9% eccentricity factor (§9.2); 5,700 times (§9.4). Also removed: the claims that the cluster rules were fixed before G was computed and that two independent routes led to 2 mₑ (§7.4). The chance-calculation assumptions are now stated (§11.1). New scripts `aether_units.py` and `lattice_dynamics.py` |
| 1.8 | 30 Oct 2026 | Neutron–proton mass difference recompared in Aspden's own units: −18.4 ppm (−63σ) today, −0.2σ in 1984; version 1.6's mixed-unit figure, there given as −8.2 ppm, is −8.6 ppm (section 8). Prepared for publication on aetherscience.org with dated analysis notes on the pages examined. New script `np_mass.py` |

---

## 1. Purpose and method

The investigation was asked to suspend judgment about Aspden's conclusions and to look at the evidence as presented, then seek independent evidence from the 1990s to the present. The working rules were:

- Read each argument and check its internal logic and arithmetic before comparing it with data.
- Compare predictions with modern measurements, stating the size of any disagreement in parts per million (ppm) and in standard deviations (σ).
- Where an approximation looked crude, try to improve it and record whether the result got better or worse.
- Where a step looked unexplained, look for a justification inside Aspden's own framework before calling it arbitrary.
- Treat speculative extensions as leads, not evidence, and record every variant tried, including failures, so that the number of attempts is visible.
- Estimate the probability of chance agreement explicitly rather than by impression.

All numerical work was done in Python scripts summarised in Appendix A and listed in full, with their output, in Appendix C, so every number here can be regenerated.

---

## 2. Sources examined

| Source | Status |
|---|---|
| aetherscience.org Tutorial Notes 14–20 | Read in full |
| Tutorial Notes 5–10 and 13 | Read from category listing pages (5 and 13 partially) |
| Tutorial Notes 1–4, 11, 12 | Not reachable (site serves a generic page for individual note links) |
| *Physics without Einstein* (1969), chapters 4–7 (aetherscience.org scans) | Read in full by OCR from copies supplied 30 October 2026; equations checked against the page images. Other chapters not yet seen |
| Energy Science Report No. 6, "Power from Space: Inertia and Gravitation" | Read in full (text PDF) |
| Whole site, from a read-only copy of the server files made on 30 October 2026 (all 678 published posts and pages, the file list of 7,274 files, the books and bibliography folders, and the WordPress export) | Indexed completely: 547 entries, with every post, page and PDF accounted for. The April 2026 WordPress conversion turned the scanned books into readable text pages, so all book chapters were searchable. 98 scanned PDFs (845 pages) were also OCR'd |
| 1983c "The Lamb Shift for a Cavity-Resonant Electron" and 1983d "The Determination of Absolute Gravitational Potential" (*Lett. Nuovo Cimento* 36, 364 and 37, 169) | Read in full by OCR; equations checked against the page images |
| aspden.org front page (2007 commentary on *Creation: The Physical Truth*) | Read; most internal links return 404 |
| 1995 "Discovery of Virtual Inertia" note (aetherscience.org papers listing) | Read |
| Aspden 1981 (*Phys. Lett. A* 85, 411) and 1982 (*Spec. Sci. Tech.* 5, 421) mirror-reflection papers | Abstracts and secondary accounts only |
| Restored aspden.org mirror (aetherscience.org/www-aspden-org/), including the paper bibliography (177 entries, 1951–2002) | Restored 30 October 2026; bibliography read. The 1986e and 1986j pages give abstracts; their full text is in the PDF appendix to *Aether Science Papers* |
| Paper pages 1975a, 1983i and 1988b; Aspden Research Paper No. 4 (2005) | Abstracts and commentary read; the 1975 proton formula confirmed |
| Q&A "The Fifth Question: What is a Neutrino?" | Read: the claim that N falls with energy or thermal activity |
| Lecture 2 "Why Einstein Was Wrong" and appendix; *The Theory of Gravitation* (1960); *Physics without Einstein* centenary review (2005) and chapter 5–6 commentaries | Read for Mercury's perihelion; no discussion of the Rydberg constant found |
| Lecture 30 "The Aspden Effect" | Located on the restored site (aetherscience.org/category/lectures/Le30/le30.html); not yet read |
| Tutorial Notes 1–4, 11, 12 | Not yet located on the restored site |

---

## 3. Light-speed and aether-drag claims

### 3.1 Tutorial Note 18: Michelson–Morley revisited

**Claim.** The Earth drags the aether with it, while a counterflowing component keeps the aether's total momentum at zero. Combining this momentum balance with a refractive-index argument, Aspden obtains a light speed of c relative to the moving Earth, explaining the null result without relativity.

**Assessment on its own terms.** Michelson–Morley alone does not rule out every aether: Lorentz's aether, with length contraction built in, predicts the same null result. However, the derivation in Note 18 drops second-order terms, while the Michelson–Morley effect is itself second order, and the refractive index used is a scalar density effect. The step to light moving at "c relative to that moving system" in every direction is asserted by calling the result a vector rather than derived. In effect, the argument assumes the aether moves with the apparatus (Stokes's complete-drag aether). Part 1A, section 13.5, works through the note step by step: the backflow speed u = c/2, taken from the quons' orbital speed, is exactly what makes the drag complete in the forward direction, but a density change speeds light equally in every direction, so relative to the Earth light would go at c ahead and c + 2v behind, and the Michelson–Morley signal would be the full ½(v/c)².

**Modern test.** An aether that moves with the Earth's centre but does not rotate with it is Aspden's own picture: in *Physics Unified* (1980, ch. 9) the Earth's electromagnetic reference frame "is a non-rotating frame of reference which moves linearly with the space lattice", and ring-laser results require the same (section 3.3). It passes a mid-latitude laboratory at roughly 300 m/s. Aspden named this test himself in 1983: if a laboratory's West–East speed, "some 350 m/s at 40oN", showed up in light-speed measurements confined to the laboratory, "this would clearly refute Einstein's theory" (paper 1983b on the site). Without length contraction, a rotating Michelson–Morley apparatus should then show a signal fixed in the laboratory of about ½(v/c)² ≈ 5×10⁻¹³ (4.5×10⁻¹³ at Berlin's 283 m/s), at twice the rotation rate.

| Experiment | Result |
|---|---|
| Brillet & Hall (1979) | A "spurious" lab-fixed signal of about 2×10⁻¹³ that Aspden interpreted as Earth-rotation anisotropy |
| Herrmann et al. (2009), rotating optical cavities, Berlin | Lab-fixed signals at twice the rotation rate below 3×10⁻¹⁶; overall anisotropy limit about 1×10⁻¹⁷ |
| Nagel et al. (2015), rotating sapphire microwave resonators | Orientation-dependent frequency change (9.2 ± 10.7)×10⁻¹⁹ |

The Brillet–Hall anomaly did not reappear when the experiment was repeated with better equipment. The drag model is excluded by more than three orders of magnitude.

### 3.2 The mirror-reflection objection (1981–1982)

**Claim.** Light reflecting from a mirror that moves through the aether is deflected, and laser anisotropy experiments are unreliable unless this is included. Aspden argued this explains the Brillet–Hall signal.

**Findings.**

- Michelson and Morley treated reflection from the moving mirror in their 1887 paper, and the second-order treatment was debated again by Hicks and by Morley and Miller around 1902.
- Klauber (2004) pointed out that Brillet and Hall measured only frequency, and a change in reflected-ray angle does not change a frequency measured in the apparatus frame.
- Using Aspden's own coefficient (0.262 × ½v²/c²), the predicted signal at Berlin's latitude is about 1×10⁻¹³, roughly 400 times above the observed limit of 3×10⁻¹⁶.
- Sapphire resonators that use no separate mirrors also see nothing at the 10⁻¹⁸ level.

The objection concerns mirrors, not lenses, as had been remembered.

### 3.3 Extension: a nested-vortex aether

**Hypothesis (proposed during this investigation).** Rotating matter drags the surrounding aether into a spinning disk: Earth's inside the Sun's, the Sun's inside the galaxy's, with boundary conditions that might hide simple signals. Aspden's own version is close to this: "a sphere of aether lattice such as is coextensive with body Earth and rotates with body Earth", inside a larger space domain with its own spin axis (reply to Allyn Shell, Feedback Note 4), while the frame that light travels in moves with the Earth but does not turn (section 3.1; Part 1A, section 1.3).

**Findings.**

- General relativity already predicts that a spinning mass drags local frames. Gravity Probe B measured −37.2 ± 7.2 milliarcseconds per year against a prediction of −39.2, and LARES-2 (2026) measured Earth's frame dragging to 0.2%. The effect is tiny and fixed by mass and spin, leaving no adjustable boundary conditions.
- Two surface measurements rule out the vortex version without needing to know the flow elsewhere. Ring lasers such as Wettzell's sense Earth's full rotation to 48 parts per billion, so the surface aether is not co-rotating. Rotating cavities limit aether flow past the Berlin laboratory to about 7 m/s.
- By Stokes's theorem, the rotation ring lasers see across the polar cap north of Berlin requires the aether's motion relative to the ground around that latitude to average about 280 m/s, roughly 40 times the cavity limit.
- The only exit is to give light Lorentz contraction and time dilation relative to the aether. That aether then reproduces every prediction of relativity and becomes undetectable.

### 3.4 Redshift without expansion (Notes 18 and 10)

**Claim (Note 18).** Light loses frequency in proportion to distance in a static aether, mimicking cosmic expansion.

| Test | Result |
|---|---|
| Supernova light-curve stretching, Dark Energy Survey (2024), 1,504 type Ia supernovae | Stretch exponent b = 1.003 ± 0.005 (stat) ± 0.010 (sys); a static aether predicts b = 0 |
| CMB temperature at cluster redshifts, Planck SZ data | Deviation parameter β = 0.013 ± 0.011, consistent with expansion |
| Internal consistency | A frequency that falls with distance at constant speed requires wave crests to disappear in transit; the note's two-field equations supply no mechanism |

Credit: Aspden's relation between wave energy and frequency implies surface-brightness dimming as (1+z)⁴, the same as expansion, so the classic Tolman test that rules out ordinary "tired light" does not directly refute his version.

**Claim (Note 10).** Galaxies sit in "space domains" with different lattice integers N, producing Tifft's quantized redshift steps of about 72 km/s.

Each unit step in N changes α by 90 ppm. ESPRESSO measured Δα/α = 1.3 ± 1.3 (stat) ± 0.4 (sys) ppm toward a quasar absorber at z = 1.15, about 70 times smaller than one step. Note 20 states that distant regions sit at N = 1841, 1839, which would imply shifts of 180 ppm or more. The claim is also internally inconsistent: it says all spectral lines shift in the same proportion, which cannot hold if α changes. Tifft's periodicity has not been independently confirmed; a 2dF survey test of galaxy–quasar pairs found none.

---

## 4. The rotating-magnet "Aspden effect" (1995)

**Report.** In "Discovery of Virtual Inertia" (*New Energy News*, February 1995), an 800 g rotor driven at 3,250 rpm held about 15 J of kinetic energy but drew about 300 J of extra energy when started from rest, the surge dying away over about two minutes. After running five minutes or more, a restart within a minute or so needed only about 30 J, in either the same or the opposite direction. Aspden proposed that something ethereal, with about 20 times the rotor's effective mass density, spins with the rotor and decays over minutes.

**Findings.**

- The effect does not depend on direction, which counts against a spinning-medium interpretation: an aether left spinning one way should help a same-direction restart and resist a reversal.
- The extra energy, about 2.5 W over two minutes, is typical of warm-up losses in small motors. Grease redistribution and heating in rolling bearings is a strong conventional candidate that the report does not rule out; bearing housings judged cool by touch cannot exclude a few degrees of internal warming.
- The report is in a newsletter, with no description of how energy was measured, no error bars, and no independent replication found.
- The closest modern tests, gyroscopes and ring lasers beside rotating rings and superconductors (Tajmar 2006–2011; Graham et al. 2008), found signals later attributed to acoustic noise, or nulls.

---

## 5. Planck's constant and the fine-structure constant

### 5.1 Aspden's derivation (Tutorial Notes 7 and 8)

1. Space is a simple cubic lattice of cells of side d, each holding a "quon" of charge e in a uniform background of opposite charge. Each quon circles in an orbit of radius r at speed c/2.
2. The quon's electric potential must be at its smallest non-negative value. Summing the lattice and background potentials, adding the displacement energy 8π(r/d)² (in units of e²/d) and a small correction for the quon's finite size, fixes r/d.
3. A 3×3×3 block of quons is a spinning "photon unit" with moment of inertia 36 m₀d². Its energy equals the orbital rate c/2r times its angular momentum; it radiates at four times its spin rate (four-fold symmetry); centripetal force balances the lattice restoring force 4πe²/d³ acting over displacement 2r. Together:

```
h = 288 π² e² r / (d c)        so        h c / (2π e²) = 144 π (r/d)
```

4. The quon-to-electron size ratio cubed, N = [(9/8)(d/r)²]³, counts how many electron-sized charges a quon could transmute into. It must be odd (net unit charge) and must sit at or below the zero-potential value (non-negative energy). This gives:

```
1/α = h c / (2π e²) = 108 π (8/N)^(1/6),   with N = 1843
```

### 5.2 Checks

| Step | Finding |
|---|---|
| Printed force balance | Contains a typo and is not dimensionally consistent. With the evident correction, m₀(c/2r)²·r = (4πe²/d³)(2r), symbolic algebra reproduces h = 288π²e²r/(dc) exactly |
| Lattice energy | Recomputed exactly for an infinite lattice: Ewald site potential −2.8372974795 plus the whole-cell boundary term π/6 gives −2.3136987 e²/d |
| Resulting r/d | 0.3028737692, matching Aspden's 1972 computer value (0.302875) |
| Pure-lattice 1/α | 137.016865, 140 ppm below the measured value |
| Size ratio N | 1844.538. His rule (odd, at or below the zero-potential value) selects 1843. The nearest odd integer would have been 1845, so 1843 follows from his rule rather than being picked to fit |
| Final 1/α | 137.0359148 versus the measured 137.035999177(21): −0.615 ppm. Neighbouring odd N values sit 181 ppm away |

Because h and e have exact defined values in the SI since 2019, a prediction of ħc/e² is a prediction of 1/α. Aspden's ħ is therefore 0.6 ppm low.

### 5.3 The finite-size correction, in detail

The step most sensitive to modelling is a small term for the quon's finite size. Aspden adds

```
ΔE = ∫₀ᵇ 4π σ e x dx = 2π σ e b²  =  (d/r)⁴ / 4608π   (in units of e²/d, using d/b = 96π(r/d)²)
```

Each background shell at radius x (charge 4πx²σ dx) contributes 4πσx dx to the potential at the centre, so the term is exactly e times the potential at the centre of a spherical hole of radius b in the background: a point quon sitting in a void the size of itself. It is only 0.36% of the energy budget, but the integer step magnifies it. Because N ∝ (r/d)⁻⁶, his rule selects 1843 only if the term's coefficient F (Aspden: F = 1) lies between 0.922 and 1.023, so the term must be right to within −7.8% / +2.3%.

**Correction to version 1.1.** Version 1.1 reported that averaging the correction over the quon's own charge distribution reduces it to one-sixth and destroys the α agreement. That calculation spread the quon's charge through background charge filling the quon's own volume. Aspden's model does not allow this: his charges exclude the continuum (the same principle that makes gravitons into voids in his G theory), and his integral already assumes the void. Inside a spherical void the surrounding charge produces a constant potential, so any spherically symmetric quon charge distribution has exactly the energy of a point quon at the centre. The consistent refinement therefore reproduces his term exactly (F = 1), and the α result stands.

| Treatment of the quon's size | F | Pure-lattice 1/α | Odd integer | Final 1/α |
|---|---|---|---|---|
| Point quon in its own void (Aspden) | 1 | 137.0169 | 1843 | 137.0359 (−0.6 ppm) |
| Spread quon in its own void (consistent refinement) | 1 exactly | 137.0169 | 1843 | 137.0359 (−0.6 ppm) |
| Spread quon with no void (version 1.1; inconsistent with his model) | 1/6 | 137.2202 | 1827 | 137.2352 (+1,454 ppm) |
| No finite-size term | 0 | 137.2606 | 1823 | 137.2853 (+1,819 ppm) |
| Standard mean-zero potential reference instead of whole cells | 1 | 151.85 | 995 | 151.86 |

The voids in neighbouring cells are a second-order effect. They occupy 0.02% of each cell and could change F by at most about 0.04%, far inside the allowed window.

**What α still depends on.** Four assumptions carry the result:

1. Charges exclude the background continuum (the void). His G theory uses the same principle, which counts in its favour as internal consistency.
2. The potential is measured relative to empty space outside a block of whole cells (the π/6 term). This is physically defensible but essential.
3. The quon's energy-radius constant is 1/3, half the electron's 2/3. This fixes d/b = 96π(r/d)² and is what puts N near 1843 at all.
4. The odd, round-down integer rule.
5. The photon unit's moment of inertia 36m₀d², which treats its 27 quons as slow rigid point masses. At the spin rate Ω/4 the outer quons move at 0.41c and 0.58c. With the speed-dependence of mass that Aspden accepted, the angular momentum rises by about 19% and 1/α becomes about 163. The omitted effects are 10³–10⁵ times larger than the 0.6 ppm gap. His restoring-force coefficient 4πσq, by contrast, is exactly what Maxwell's equations give for an unbounded lattice (companion paper, tests U20–U31). Treating the lattice as an endless crystal does not remove the problem. Magnetic coupling between the moving quons adds a further 9–29% to the photon unit's inertia (U29), and the simple cubic lattice itself is electrostatically unstable (U28).

For the lattice alone to give α exactly, with no integer step, F would need to be 0.922; no reason for that value was found.

### 5.4 Connection to established physics

Aspden's orbit radius r = ħ/(2mc) is exactly the amplitude of the "zitterbewegung" (trembling motion) that Dirac's equation predicts for the electron. His orbital speed is c/2, giving half Dirac's zitterbewegung frequency. The same length is the range of vacuum polarization in quantum electrodynamics. The companion paper (section 15, tests U01–U02) follows this further, and shows why the same scale is fatal to the lattice as a carrier of light (tests U10–U16).

---

## 6. The proton/electron mass ratio and the Rydberg constant

### 6.1 Aspden's derivation (1975)

**Derivation.** The lattice charge-volume count gives a "dimuon" energy Q = 944784 π² / 1843^(4/3) = 412.6658 electron masses. A proton P and dimuon Q in contact, as Thomson spheres, have minimum combined energy when Q/P = √(3/2) − 1, so P = Q / (√(3/2) − 1). The formula is confirmed by the abstract of Aspden and Eagles (*Il Nuovo Cimento* 30A, 235, 1975), which gives M/mₑ = 1836.15232 against the then-measured 1836.15152(70).

**Result.** P = 1836.152316 versus the measured 1836.152673426: −0.19 ppm. No new adjustable number enters: N = 1843 is already fixed by α. This is the strongest single result in the corpus.

### 6.2 His explanation of the residual (1983)

In "The Assessment of a Theory for the Proton-Electron Mass Ratio" (*Lett. Nuovo Cimento* 38, 423, 1983), Aspden attributed the small remaining discrepancy to the proton and electron charges differing in magnitude by 1.07 parts in 10⁷, an effect of the electron displacing aether continuum charge. Matter is far more neutral than that: an acoustic measurement on SF₆ gas (Bressi et al. 2011) finds |q_p + q_e|/e = (−0.1 ± 1.1) × 10⁻²¹. His explanation is excluded by a factor of about 10¹⁴, so the residual remains unexplained in his framework.

### 6.3 The Rydberg constant

In his framework the Rydberg constant follows from α by the standard relation hcR∞ = (α²/2) mₑc². His α gives a Rydberg energy of 13.6057099 eV against the measured 13.605693122990(15) eV: 1.23 ppm high, about a million times the measurement uncertainty.

The passage where Aspden discusses the Rydberg constant in connection with Einstein's theory has been found, using the copy of the site supplied on 30 October 2026. It is "Atomic Spectra and the Moving Atom" (*Aether Science Papers*, 1996, pp. 41–47), with an earlier version in *Physics Unified* (1980), chapter 3. Its appendix links the same electrodynamic law to the perihelion of the planets. It is examined, and tested against modern experiments, in section 9.6.

Neither version explains the hydrogen fine structure. A search of the text of all 678 posts and pages on the site found no non-relativistic derivation of the fine structure; *Modern Aether Science* (1972, ch. 7) mentions it only as one of the results that "flow out of the Dirac formalism in an almost miraculous fashion". 1983c uses the Rydberg levels as given to derive the Lamb shift (section 9.3).

The physics that links the two topics is Sommerfeld's 1916 calculation. Treating the electron's relativistic mass increase in a Kepler orbit makes the orbit precess, and that precession produces the hydrogen fine structure. The same calculation for Mercury gives πGM☉/(c²p) per orbit, where p is the orbit's semi-latus rectum, which is one-sixth of the observed relativistic advance: 7.16 of the 42.98 arcseconds per century. General relativity supplies the rest through space curvature. Any argument that the fine structure and Mercury's perihelion are inconsistent under Einstein's theory turns on this factor of six. The other "R" beside his Mercury discussion is the R of his equation (5.9), the radius of a planet's aether region (section 9.2).

### 6.4 Are these constants temperature sensitive?

In "The Fifth Question: What is a Neutrino?" (Q&A), Aspden states that the lattice integer N falls in integer steps as energy or thermal activity rises in a region of space. Through his formulas every constant then changes in discrete steps:

| Quantity | Scaling with N | Change for one step (N 1843 → 1842) |
|---|---|---|
| α | N^(1/6) | −90 ppm |
| mp/mₑ | N^(−4/3) | +724 ppm |
| Rydberg energy in units of mₑc² | N^(1/3) | −181 ppm |
| Spectral-line frequencies (his Note 10 scaling) | N^(4/9) | 72 km/s apparent velocity |
| Spectral-line frequencies (his revised radio scaling) | N^(1/9) | 18 km/s apparent velocity |

Under the odd-integer rule of section 5, the smallest step is two units, doubling every entry. Measurements in hot and distant environments test this directly:

| Environment | Quantity | One step predicts | Measured | Disagreement |
|---|---|---|---|---|
| White dwarf GD133 (H₂ at 11,800 K) | Δμ/μ | +724 ppm | (−27 ± 47) ppm | 16σ |
| White dwarf G29-38 (H₂ at 14,500 K) | Δμ/μ | +724 ppm | (−58 ± 38) ppm | 21σ |
| White dwarf G191-B2B (Fe V lines) | Δα/α | −90 ppm | (42 ± 16) ppm | 8σ |
| White dwarf G191-B2B (Ni V lines) | Δα/α | −90 ppm | (−61 ± 58) ppm | 0.5σ |
| The Sun (5,800 K photosphere), lines after the 633 m/s gravitational redshift | line shift | 18,078 m/s (or 72,307 m/s) | residual (5 ± 6) m/s | 3,000σ (or 12,000σ) |
| Absorbing galaxy in front of a quasar, z = 0.89 (methanol, 7.5 billion years ago) | Δμ/μ | +724 ppm | (−0.10 ± 0.13) ppm | 5,600σ |
| Quasar absorber at z = 1.15 (ESPRESSO) | Δα/α | −90 ppm | (1.3 ± 1.4) ppm | 68σ |

Only the less precise Ni V measurement is compatible with a step. If "energy or thermal activity" includes stellar temperatures, the claim is excluded by the white dwarfs and the Sun; if it means only the aether energy of distant regions, the galaxy absorbers exclude it. Either way the proton/electron ratio and the Rydberg constant do not shift in the steps his theory requires.

### 6.5 A numerical lead for the proton residual

The remaining −0.19 ppm residual equals α³/2 to within 0.05%. Multiplying his proton mass by (1 + α³/2) gives 1836.152673243 against the measured 1836.152673426(32): 1 part in 10¹⁰, or −5.7σ. Among 60 simple candidate corrections (α to α⁴ times small fractions and powers of π), a match this close has about a 1-in-300 chance. Nothing in his theory motivates an α³/2 term, and it was found by searching for a correction, so it is recorded as an unexplained numerical coincidence to examine, not adopted.

---

## 7. The constant of gravitation G

### 7.1 Aspden's derivation (Tutorial Notes 6, 8, 9)

Gravity is the electrodynamic attraction between the "holes" that gravitons, moving at c relative to matter, make in the aether's background charge. A body's gravitational charge √G·M equals the background charge its gravitons displace. With Thomson-sphere gravitons this gives:

```
√G = 4π (e/mₑ) g⁻⁴ / (108π)³,      g = graviton mass / electron mass
```

The graviton mass comes from a chain: lattice → dimuon (412.666) → proton (1836.1523) → taon = two proton–dimuon pairs at minimum energy minus an ejected 1.875 cluster (3484.94) → graviton = taon / x, where 3x⁴ + x³ = 1 (x = 0.688408), giving g = 5062.318 and G = 6.67216 × 10⁻¹¹ m³ kg⁻¹ s⁻².

The whole chain reduces to one closed formula:

```
g = [ 2(3 + √(3/2)) · 944784 π² / 1843^(4/3) − 15/8 ] / x
```

### 7.2 Checks and corrections

| Item | Finding |
|---|---|
| Reproduction | The rebuild reproduces every value in Aspden's Note 9 table |
| Note 20 table | Rows printed as g = 5600–5603 should read 5060–5063 |
| The 1.875 cluster | Exactly the energy of three touching electron-sized charges in a +−+ line (3 − 9/8). His charge bookkeeping requires an ejected cluster with net unit charge, so this is the most defensible choice by his own rules |
| Taons per graviton | Only two works. One, three or four taons give G = 3.50, 8.52 or 9.70 |
| Sensitivity | G goes as g⁻⁸, so one electron mass in the taon shifts G by 2,296 ppm. All modern G measurements lie within about a quarter of an electron mass of each other on this scale |
| Taon vs tau | His taon (3484.94 mₑ) is not the measured tau lepton (3477.37 mₑ); he treats it as a separate virtual particle, so it has no independent check |
| History | His published G moved between 6.6676 and 6.686 across his writings (1966: 6.6676; Note 8: 6.668; Note 9: 6.672; Note 20, 1998: 6.686). The measured values of the time are not compared here, so whether these changes followed the measurements is not shown |

### 7.3 Comparison with measurements

| Measurement | G (×10⁻¹¹) | Aspden 6.67216 | "Doubled electron" variant 6.67408 |
|---|---|---|---|
| CODATA 2018/2022 | 6.67430(15) | −320 ppm (−14σ) | −34 ppm (−1.5σ) |
| HUST-TOS-18 | 6.674184(78) | −26σ | −1.4σ |
| HUST-AAF-18 | 6.674484(78) | −30σ | −5.2σ |
| UWash-00 | 6.674255(92) | −23σ | −1.9σ |
| UZur-06 | 6.67425(12) | −17σ | −1.4σ |
| UCI-14 | 6.67435(13) | −17σ | −2.1σ |
| BIPM-14 | 6.67554(16) | −21σ | −9.2σ |
| JILA-10 (corrected) | 6.67260(25) | −1.8σ | +5.9σ |
| LENS-14 (atom interferometry) | 6.67191(99) | +0.3σ | +2.2σ |
| NIST-26 (rebuilt BIPM apparatus) | 6.67387 | −256 ppm | +31 ppm |

### 7.4 Extrapolations tried, assuming the foundation has merit

| Variant | Basis | Result |
|---|---|---|
| Surface-charge electron (k = 1/2) | Improve the Thomson model | Proton 2361.5, G = 0.47 (fails) |
| Uniform-ball electron (k = 3/5) | Improve the Thomson model | Proton 1945.3, G = 2.99 (fails) |
| k tuned to give the proton exactly | k = 0.6666662, within 0.7 ppm of 2/3 | G changes by only −4 ppm |
| Lattice integer set to give α exactly | N = 1842.993 | Proton worsens to +4.7 ppm; G = 6.67190 |
| All 22 charge-conserving clusters on his cubic lattice | His rules: touching sites, alternating signs, net charge ±1 (the measured G was known to this analysis throughout) | Only two land among measured values: straight line 1.875 (6.67216) and L-shape 2.0303 (6.67454) |
| Orientation average of the 15 three-charge arrangements | 3 straight + 12 L; his deuteron model also averages states | Cluster 1.9993, G = 6.67406 |
| Equal weight per shape | Alternative averaging | G = 6.67335 (−6σ; fails) |
| Straight triplet with charges in orbital motion | Reduce attraction by (1 − v²/c²), v = c/2 | G = 6.67647 (+14σ; fails) |
| "Doubled electron" | His dimuon and duon rule: a charge shrunk to half its radius has twice the energy; one unit of charge, exactly 2 mₑ | G = 6.67408 |
| Composite-rule tweak | Factor 3 changed to 2.99962 | Would fit, but no mechanism found |

Two routes, the orientation average and the doubled electron, give a cluster of about 2 electron masses. Both were found with the measured G known; an earlier working script already printed the cluster each measurement requires (2.0146 mₑ for CODATA). Section 7.5 sets out why Aspden's own work favours exactly 2 mₑ and adopts it as the improved form of his formula.

### 7.5 Improved choice: an ejected charge of exactly two electron masses

The published chain subtracts 1.875 mₑ, the rest energy of three touching charges in a +−+ line. Four features of Aspden's own published work point instead to an ejected charge of exactly 2 mₑ:

1. **The dimuon and duon rule.** In Tutorial Notes 9 and 16 the dimuon, the quantity from which both his proton and his graviton are built, is a single charge carrying about the energy of two muons (412.67 mₑ, against 413.54 mₑ for two muons). In *Creation: The Physical Truth* (2006) the duon is a single charge carrying twice the proton's mass. Both come from one rule: a charge that contracts to half its radius doubles its energy. Applied to the electron, the same rule gives a single charge with exactly 2 mₑ, the electron member of a family he already uses at the muon and proton scales.
2. **Factor-of-two families from his transmutation rule.** Note 17's energy-conserving pair-creation condition, 2/3a = 2/3b − 1/(b+c) + 2/3c, gives c = 2b when a = b: a particle form can produce a charged form of exactly half its energy at no energy cost. This makes factor-of-two steps (1, 2, 4 … mₑ) the natural family of charge forms in his theory. The 1.875 triplet, by contrast, is a bound composite with no special status.
3. **The deuteron precedent.** In his deuteron model (1986; 2006) he averages over configurations with fixed weights, and the interaction energies of his two triplets, 7/4 mₑ (p e⁻ e⁺) and 9/4 mₑ (e⁺ p̄ e⁺), average to exactly 2 mₑ, which he says balances the mass of an added electron–positron pair. Applying the same averaging to the 15 ways three touching charges can sit on his cubic lattice (3 straight, 12 L-shaped) gives 1.9993 mₑ.
4. **Moving particles (supporting).** Note 14 describes a fast particle spending part of each cycle compacted, holding all its energy in a contracted form. An electron carrying 2 mₑ is that compacted state at γ = 2, the same object as reason 1.

The 2 mₑ charge also satisfies the charge bookkeeping that justified 1.875: it carries one unit of charge, so a charged taon remains.

**Effect on the chain.**

| Ejected charge | Taon (mₑ) | Graviton g | G (×10⁻¹¹) | Versus CODATA 6.67430(15) |
|---|---|---|---|---|
| 1 mₑ (bare electron) | 3485.8156 | 5063.5894 | 6.65877 | −2,326 ppm |
| 1.875 mₑ (Aspden's triplet) | 3484.9406 | 5062.3184 | 6.67216 | −320 ppm (−14σ) |
| 2 mₑ (doubled electron, improved) | 3484.8156 | 5062.1368 | 6.67408 | −34 ppm (−1.5σ) |
| 4 mₑ (next family member) | 3482.8156 | 5059.2315 | 6.70480 | +4,570 ppm |
| 1.9993 mₑ (orientation-averaged lattice triplet) | 3484.8163 | 5062.1379 | 6.674065 | −35 ppm (−1.6σ) |

With the doubled electron, G lies within about 2σ of the CODATA value and of four of the five most precise experiments (HUST-TOS-18, UWash-00, UZur-06, UCI-14), and 31 ppm above NIST's 2026 result. Only the 2 mₑ member of the doubling family lands near the measured value. Nothing else in the chain changes: the proton, the composite rule and the taon-versus-tau mismatch are unaffected.

**Improved formula.**

```
g = [ 2(3 + √(3/2)) · 944784 π² / 1843^(4/3) − 2 ] / x,     3x⁴ + x³ = 1
√G = 4π (e/mₑ) g⁻⁴ / (108π)³     →     G = 6.67408 × 10⁻¹¹ m³ kg⁻¹ s⁻²
```

**Status and test.** This is adopted as the improved form of Aspden's G formula. It was identified after the measured value was known; section 11 allows for this by including every variant tried in its test family. The decisive test is consistency: wherever Aspden's other derivations eject or subtract a 1.875 cluster (the 1986 *Hadronic Journal* particle masses), the same replacement must be made, and those results must improve, or at least not worsen. That test has now been run (section 7.6): the replacement finds no support.

### 7.6 Out-of-sample test of the doubled electron

**The rule.** This was written in section 7.5 before the test was run: wherever Aspden uses the 1.875 cluster elsewhere, put 2 in its place, change nothing else, and compare with the measurement he compared with. If the doubled electron reflects something real in his framework, those results should improve, or at least not worsen. Nothing in them was tuned during this investigation.

**Where the 1.875 appears.** Before any replacement was computed, all 719 texts on aetherscience.org were searched for 1.875 and 15/8: posts, pages, the static archive and the 98 OCR'd scans. Five texts matched. Two use 15/8 as an unrelated series coefficient. The other three use the in-line three-charge factor 3 − ¾ − ¾ + ⅜:

| Where | What the 1.875 does | With 1.875 (his) | With 2 | Compared with | Result |
|---|---|---|---|---|---|
| Tutorial Note 9 (G chain) | Ejected +−+ electron cluster | G = 6.672161 (−320 ppm) | G = 6.674076 (−34 ppm) | CODATA 6.67430(15) | In-sample: 2 was chosen here, so this cannot count |
| 1986j, *Hadronic J.* 9, 153, p. 154 | Three g∗ (3259 MeV) in a line: (g∗:g∗:g∗) | 6110.6 MeV | 6518.0 MeV | The "upsilon of 6.1 GeV" announced in 1976 | No test possible. E288's 6 GeV peak (Hom et al. 1976) was not confirmed by its own 1977 data and was withdrawn (the "Oops-Leon"); the real upsilon is at 9460.4 MeV |
| *The Physics of Creation* (2003), ch. 3 | Three muon-derived charges in a line, energy 1.875 × ∛3 = 2.704 muon units; sets his 17:8 ratio | Lifetime 2.19908 μs (+0.095%) | Lifetime 3.69445 μs (+68%) | PDG 2.1969811(22) μs | Worse |

**The muon lifetime, step by step.** The step-by-step rebuild reproduces his own numbers exactly: 17:8, then 2.199 μs.
1. **The triplet's energy.** Three charges sharing a muon's charge volume each carry ∛3 times the energy. In a line the triplet's energy is 1.875 × ∛3 = 2.7042 muon units.
2. **The threshold multiple.** The first multiple within 1 part in 1,000 of an integer is 17 × 2.7042 = 45.97.
3. **Shed energy.** Each triplet formed sheds 3 − 2.7042 = 0.2958.
4. **Raising a triplet to the separated form.** Raising one triplet to the separated form, (3 − ¾)∛3 = 3.2451, needs 0.2958 + 0.2451. Two shed quanta cover that ("2(0.2958) exceeds (0.2958 + 0.2451)"). So 17 triplets yield 8 separated forms.
5. **The lifetime.** Only separated forms decay, so the chance of decay is 8/25. The lifetime is (25/8)(3/4π)²(108π)⁶ h/mₑc² = 2.199 μs.

With 2 in place of 1.875:
1. The triplet's energy is 2.8845.
2. The threshold multiple is again 17 (17 × 2.8845 = 49.04).
3. Each triplet sheds only 0.1155.
4. Raising one triplet now needs four shed quanta, so 17 triplets yield only 4 separated forms.
5. The lifetime becomes (21/4)/(25/8) times longer: 3.694 μs, 68% above the measured value.

**Score.** Of the two out-of-sample uses, none improves, one is much worse, and one cannot be tested. Section 7.5 also assumed that the 1986 *Hadronic Journal* papers eject 1.875 clusters. They do not, apart from the upsilon line above. The 1986e meson paper uses in-line three-charge systems with unequal energies, which the rule does not cover. Extending the rule to them would add a new free choice, so it was not done.

**Conclusion.** Strictly, the test shows that the doubled electron and Aspden's other uses of 1.875 cannot both be sound. Either 2 is not a correction to his framework, or the derivations it was tested on are not good physics in the first place; his own description of the muon argument as "somewhat complicated" leaves the second possibility open. Either way, the doubled electron gains no support outside G. It stands as a fit to G alone, to be kept on record and revisited if a sounder derivation that uses the cluster turns up. The summary figures in sections 11.3, 11.4, 13 and 14 now say so. His own 1.875 is not vindicated either: its one testable out-of-sample use, the muon lifetime, works, but at +0.095% it is about 950 times the measurement's uncertainty from today's value. Its other use matched a particle that does not exist, which also shows how readily this kind of correlation can be found.

The script is `out_of_sample.py` (Appendix C.15).

---

## 8. The deuteron model (2007 commentary; 1986 *Hadronic Journal* paper)

**Model.** The deuteron spends time in three states, each a straight chain of touching Thomson charges:

- A: positron, antiproton, positron, antiproton, positron (weight 2)
- B: proton, electron, positron, antiproton, with a satellite positron (weight 1; core neutral)
- C: proton, electron, proton, with a satellite electron–positron pair (weight 4)

**Rebuild.** Treating protons as points reproduces his core mass deficits of 11/8, 9/8 and 10/8 electron masses exactly, and his triplet interaction energies of 7/4 (p e⁻ e⁺) and 9/4 (e⁺ p̄ e⁺). The weighted deficit is 71/56.

| Version | Magnetic moment (μN) | Versus measured 0.8574382311(48) |
|---|---|---|
| Aspden: (6/7)·2 / [2 − (71/56)/1836] | 0.8574389 | +0.79 ppm |
| Measured mass ratio in place of 1836 | 0.8574389 | +0.76 ppm |
| Protons given their own Thomson radius (refinement) | 0.8574385 | +0.33 ppm |

The refinement closes 57% of the gap. Most of the moment comes from the simple fraction 6/7 (itself 344 ppm low); the only non-trivial number in the formula, the weighted deficit, is accurate to 0.22% (0.10% refined), so the ppm-level figure overstates the precision of the physics.

**Neutron–proton mass difference** (1986d, now read in full from the site copy). The Thomson-charge model gives (mₙ − mₚ)/mₑ = 2.5309419. Aspden converted this with the 1984 electron mass to 1.2933214 MeV. The theory predicts the ratio, so the fair test is against the measured ratio (`np_mass.py`): it agreed with the 1984 value 2.530948(31) to −2.4 ppm (−0.2σ) and is −18.4 ppm (−63σ) from today's 2.53098857(74). Version 1.6 compared his MeV figure with today's MeV value, which mixes units and understated the gap (−8.6 ppm). The step-by-step derivation, which includes an α-dependent subtraction of (3/47)/137, has not yet been checked.

---

## 9. Other claims

### 9.1 Tutorial and lecture claims

| Claim | Finding |
|---|---|
| Muon lifetime (Note 15), simple "virtual muon hit" model | 2.251 μs at the real muon mass versus 2.197 μs measured: +2.5%. A more elaborate version in *Physics Unified* was not available |
| Electrodynamic force law (Note 13) | Allows a net linear force between charges; no numerical prediction to test |
| Meson lifetimes 6.25% below relativistic values near γ = 2 (Note 14) | Not yet checked |
| Graviton at 2.587 GeV (Notes 16, 20) | Treated as a hidden virtual particle; no direct test |
| Mercury's perihelion (Lecture 2): Einstein holds the angular-momentum term constant despite relativistic mass increase, and solar oblateness could destroy his result | In general relativity that term is defined per unit proper time, which already includes the mass increase; special relativity alone supplies one-sixth of the advance (about 7 arcseconds per century) and space curvature the rest. MESSENGER ranging measures the Sun's oblateness as J₂ = (2.4 ± 0.2) × 10⁻⁷, which contributes 0.03 arcseconds per century, 0.07% of the 42.98 arcsecond relativistic term, and pins the relativistic parameters to within 2.5 × 10⁻⁵ of Einstein's values. Aspden's own 1960 aether formula gave 44.3 arcseconds per century, and his later retardation argument reproduces Gerber's 1898 formula, which is identical to Einstein's. His 1969 account is examined in section 9.2 |

### 9.2 Mercury's perihelion in *Physics without Einstein* (1969)

Chapter 5 of the book gives a third Aspden account of Mercury, different from his 1960 formula and his later retardation argument.

**The mechanism.**

- Each planet carries a sphere of aether ("space-time lattice") a little larger than the planet.
- The lattice moves with the planet, but its centre of mass must stay at rest. It therefore sheds substance that streams backward through it and re-forms behind.
- Lattice and stream together carry a net angular momentum of −(2/5)MR²ω about the Sun. M and R are the lattice's mass and radius, and ω is the planet's orbital angular velocity.
- Conserving the total for planet plus aether gives a perihelion advance per revolution of (8π/5)(M/P)(R/X)², where P is the planet's mass and X its distance from the Sun.

**His fit.** He guessed that Mercury's lattice extends 10% beyond its surface, comparable to the height of the Earth's ionosphere. He took the anomaly as 38 arcseconds per century after Dicke's 1967 correction for solar oblateness, and inferred a lattice density of "about 150 g/cc". Chapter 6 derives 144 g/cc independently, from the lattice spacing and his lattice-particle mass of mₑ/24.52, and he presents the match as confirmation.

**Checks** (`mercury_aether.py`, Appendix C):

- **Arithmetic.** His inputs give 143.8 g/cc, so the two routes agree even more closely than he said. The agreement rests on two inputs that do not survive. The 10% boundary was a guess, and the density varies as the inverse fifth power of the boundary radius, so a 10% change in the guess moves it by 60%. The 38"/cy relied on Dicke's oblateness, which helioseismology and MESSENGER have since shown to be about 100 times smaller (J₂ ≈ 2.2–2.4 × 10⁻⁷, worth 0.03"/cy). With today's 42.98"/cy, the required density is 190 g/cc. Alternatively, to keep 144 g/cc the boundary must sit 16% above the surface.
- **Sign.** Integrating an orbit under his conservation law, (r² − k)dθ/dt = constant with k = (2/5)(M/P)R², moves the perihelion *backward*, not forward, by about 9% more than his formula gives (an eccentricity factor his formula omits). Net aether angular momentum opposite to the orbit acts like an extra outward force falling as 1/r⁵, and such a force makes orbits regress. To produce an advance, the aether's net angular momentum must run *with* the orbit. That sign is the first fix needed if the idea is pursued.

**The other planets.** With the sign fixed, the same density and the same 10% rule predict:

| Planet | General relativity ("/cy) | Aspden mechanism ("/cy) | Ratio | Boundary needed to match |
|---|---|---|---|---|
| Mercury | 42.98 | 32.65 | 0.76 | 1.16 × radius |
| Venus | 8.62 | 23.32 | 2.7 | 0.90 × radius |
| Earth | 3.84 | 7.91 | 2.1 | 0.95 × radius |
| Mars | 1.35 | 0.72 | 0.53 | 1.25 × radius |
| Jupiter | 0.062 | 12.3 | 198 | 0.38 × radius |
| Saturn | 0.014 | 1.96 | 144 | 0.41 × radius |

Observed perihelion motions agree with general relativity for all six planets. The EPM2017 ephemerides limit any additional motion to formal uncertainties of 0.003–0.3 milliarcseconds per century for the rocky planets, 0.07 for Saturn and 34 for Jupiter; realistic limits are 10–50 times larger. The aether-sphere mechanism misses Venus by 15 arcseconds per century and Jupiter by 12. Matching each planet separately needs boundaries from 0.38 to 1.25 times the planet's radius, sometimes below its surface, so no single rule fits.

**Structure.** General relativity's advance per orbit depends only on the Sun's mass and the size of the orbit, 6πGM☉/(c²a(1−e²)), and that is the dependence the planets show. Aspden's advance depends on the planet's own size and density and not on the Sun at all. The double pulsar PSR J0737−3039 makes the difference stark. Two neutron stars about 24 km across orbit every 2.5 hours, and the orbit advances by 16.9° a year, as general relativity predicts from their masses. A 144 g/cc aether sphere around a body 10¹² times denser than that contributes about 10⁻¹⁶ degrees a year.

For the nested-vortex idea of section 3.3, the lesson is that whatever aether a body carries cannot add measurably to its orbital angular momentum. Even with generous ephemeris limits, Saturn's orbit holds any such contribution below about 1% of what Aspden's mechanism predicts, and the double pulsar shows that relativistic precession scales with the central mass.

### 9.3 The cavity-resonant electron: anomalous moments and the Lamb shift (1983)

**The model.** In 1983c, building on his 1977–82 papers, Aspden models the electron as a charge at the centre of a spherical cavity. Radial waves at the Compton frequency run between an inner radius r and an outer radius R ≈ h/2mc. He sets πr² to half the Thomson cross-section, because only magnetic radiation escapes, which gives r = (2/√3)e²/mc². The magnetic anomaly arises because the electron's spin mass excludes the field energy outside R. The result is a = 1/(2π/α − 1 + 4/√3) for the electron; for the muon the cavity resonates on the inside wall, which flips the sign of the 4/√3 term.

**The Lamb shift.** For the hydrogen Lamb shift, he argues that field energy flowing through the cavity of an orbiting electron adds angular momentum (2/3)(α/2π)mR²ω. That shifts the azimuthal quantum number of the 2P state by δn₀, which shifts its energy by 2hcR∞δn₀ (his eq. 13). The leading result is (4π/15)α³R∞c, which is 1,071.0 MHz. He then applies:

- a factor (1 + 2α/(√3π)) for the exact cavity radius;
- a factor 1/(1 + 2α), attributed to "reasons a little beyond the scope of this paper";
- the nuclear-mass factor.

With these he obtains 1,057.848 MHz, against the 1981 measurement of 1,057.845(9) MHz.

**Checks** (`cavity_1983.py`, Appendix C):

| Quantity | Aspden | Measured | Difference |
|---|---|---|---|
| Electron anomaly aₑ, with today's α | 0.0011596462 | 0.00115965218059(13) (2023) | −5.2 ppm, i.e. −6.0 × 10⁻⁹. QED with α from rubidium atoms: −0.3 × 10⁻¹² |
| Muon anomaly aμ | 0.0011658912 | 0.001165924(9) (CERN 1979); 0.001165920705(147) (Fermilab 2025) | −3.9σ in 1983, when he called it "exact accord"; −25 ppm, about −200σ, today |
| Muon minus electron | 6.245 × 10⁻⁶ | 6.269 × 10⁻⁶ | −0.4% |
| Hydrogen 2S₁/₂–2P₁/₂ Lamb shift, today's constants | 1,057.849 MHz | 1,057.845(9) (1981); 1,057.8298(32) (2019) | +0.5σ; +6.0σ |
| He⁺ 2S–2P Lamb shift, same formula scaled as Z⁴ | 16,700–16,900 MHz | 14,041.9(1.5) MHz | +19% to +21% |

- **The series.** Expanded in powers of α/π, his electron formula gives 0.5, −0.32735, +0.2143, … against QED's 0.5, −0.32848, +1.1812, … The second-order coefficient agrees with QED's to 0.34%, a notable coincidence for a formula from a cavity picture. The third-order coefficient is 5.5 times too small. Term by term against QED, his anomaly differs by +6.09 × 10⁻⁹ at second order, −12.12 × 10⁻⁹ at third and +0.05 × 10⁻⁹ at fourth. So the third-order deficit is twice the net 6 × 10⁻⁹ shortfall, and the small second-order difference adds an error as large as the whole shortfall in the other direction.
- **The muon.** His sign switch reproduces the measured muon–electron difference to 0.4%, although his formula contains no muon mass. In QED that difference comes from muon/electron mass logarithms and hadronic loops. The absolute muon value is far outside today's errors. The next part shows that the 0.4% follows from the electron fit and is not an independent success.
- **The Lamb shift.** The 1981 agreement came after two correction factors totalling −1.17% (−1.23% with the nuclear-mass factor), one of them explicitly deferred. The 2019 measurement, which agrees with QED and with the proton radius from muonic hydrogen, lies 19 kHz below his value.
- **Step (13).** He takes the energy shift as 2hcR∞δn₀/n₀³ with n₀ = 1, stating without derivation that the energy "includes a term hcR′/n₀²". In the Bohr–Sommerfeld theory he says he is tracing, the energy depends on the azimuthal number only through the principal number n, which gives 2hcR∞δn₀/n³ with n = 2. That is 8 times smaller, 132 MHz.
- **Helium.** He wrote that "much now depends upon the development of this method to explain other transitions". Ionised helium is the most direct such test, and the formula misses it by 20%. QED gets He⁺ right because its main term carries a logarithm, ln(1/(Zα)²), that shrinks as the nuclear charge rises.

**Derived or chosen?** (`cavity_variants.py`, Appendix C). His equations (1)–(7) reproduce (8) exactly, so the 4/√3 is derived from three modelling choices:

1. **A half-wavelength standing wave** between the two radii. This is forced: a full or quarter wave would move the leading term away from Schwinger's α/2π.
2. **An inner radius from half the Thomson cross-section**, justified by his claim that only the magnetic half of the Larmor radiation is scattered.
3. **The spin-mass form** a = mc²/(mc² − E_out) − 1, which supplies the −1.

The table below varies the last two: seven natural inner radii (zero, half the classical radius, the Thomson-sphere radius, a quarter or half or all of the Thomson cross-section, and the classical radius) times three mass forms, 21 variants in all.

| Variant | aₑ | aμ (no new freedom) |
|---|---|---|
| Half Thomson cross-section, spin-mass form (Aspden) | −5.2 ppm | −25.6 ppm |
| Thomson-sphere radius, a = E_out/mc² | −33 ppm | −2,324 ppm |
| Classical radius, spin-mass form | +354 ppm | −386 ppm |
| Every other variant (18) | 354 ppm or more | 76 ppm or more |

- **The electron.** His choice is the only variant within 30 ppm. The chance that one of 21 such constants lands this close to an arbitrary target is about 1 in 29: a modest coincidence, not a strong one.
- **The muon is a genuine prediction, and it fails.** Once the electron fixes the construction, the muon has no free parameter. The data need a constant of 2.305 for the electron and 2.331 for the muon, a 1.1% asymmetry that a symmetric ± construction cannot give. QED gets that asymmetry from ln(mμ/mₑ).
- **The difference is not independent.** The muon–electron difference depends only on the sum of the two constants, which the electron fit already pins to 0.4%. His alternative muon formula, for a muon "created by charge pair annihilation" (1983d, footnote eq. 4), does worse at −40 ppm.
- **The second-order coefficient.** It agrees with QED's to 0.34%, but the target, −1.3139 in units of (α/2π)², sits among many simple numbers. Among the 21 variants its counterpart is the same constant judged above, so it is not a separate success either.

### 9.4 The absolute gravitational potential at the Earth's surface (1983)

**His claim.** In 1983d Aspden adds a gravitational term to his g-factor formula:

```
g/2 = (1 + φ/2c²) · (1 + 1/(2π/α − 1 + 4/√3))
```

Here φ is the magnitude of the absolute gravitational potential, energy per unit mass, where the electron sits. His reasoning is that the negative gravitational energy sets a threshold for thermal energy. Under equal partition this gives the electron a kinetic energy ½mφ that lies outside its cavity and so changes the g-factor.

- **Route 1.** The 1979 measured g and α give φ = 10.25 × 10¹² cm²/s² (his figure; 10.23 recomputed from his inputs).
- **Route 2.** Setting φm* = kT, with the 2.7 K cosmic background and m* = 0.04 mₑ, gives 10.24 × 10¹² (his figure; 10.23 recomputed). He took m* from the measured light-hole mass in germanium and identified it with his aether lattice particle.
- **Conclusion.** The solar system contributes 9.49 × 10¹² at the Earth's surface, almost all of it from the Sun. He concluded that the rest of the universe adds only 8% more, and therefore that gravity has a limited range of "a few hundred light years".

| Route | φ (10¹² cm²/s²) |
|---|---|
| 1979 g-factor, 1979 α (his inputs) | 10.23 |
| 2023 g-factor, α from Rb or Cs atom recoil | 10.74 |
| 2023 g-factor, his own lattice α | 9.46 |
| 3 K route, T = 2.72548 K, m* = 0.04 mₑ | 10.33 |
| 3 K route, T = 2.72548 K, his lattice particle mₑ/24.52 | 10.13 |
| Solar system at the Earth's surface | 9.50 |

- **The number is set by α, not gravity.** φ/2c² ≈ 6 × 10⁻⁹ is exactly the size of his g-factor formula's shortfall (section 9.3). The inferred excess over the solar system is 13% with today's α and 0% with his own lattice α, so φ moves with the α input at the level of one part in 10⁹. In effect, φ measures the error in his formula.
- **QED leaves no room.** QED with α from atom-recoil experiments reproduces aₑ to 3 × 10⁻¹³ with no gravitational term. Any φ term must then be below about 2 × 10⁹ cm²/s². That is about 5,700 times smaller than his value and smaller than the Earth's own potential at its surface, 6.3 × 10¹¹.
- **It would vary through the year.** His φ includes the Sun's potential, which varies by ±1.7% over the year as the Earth–Sun distance changes. That would move g/2 by ±8 × 10⁻¹¹, about 600 times the uncertainty of the 2023 measurement. A drift that size would be hard to miss in a result quoted to 0.13 parts per trillion and consistent with the 2008 Harvard value.
- **The range of gravity.** The Sun orbits the galaxy at about 230 km/s, so the galaxy's potential at the Sun is at least v² = 5.3 × 10¹⁴ cm²/s², 56 times the solar-system value. A range of a few hundred light-years would make the galactic centre's pull, from 26,000 light-years away, negligible. Gaia measured the solar system's acceleration directly from quasar proper motions: (2.32 ± 0.16) × 10⁻¹⁰ m/s², pointing toward the galactic centre, matching the 2.1 × 10⁻¹⁰ expected from the Sun's orbit. Gravity therefore acts with full strength over at least 26,000 light-years.
- **The 3 K agreement has loosened.** The two routes agreed to 0.1% in 1983. With today's background temperature and either value of m*, they differ by 4–9%.

### 9.5 Is there a first-principles g = 9.8 m/s²?

None was found. A search of the text of every post and page on the site for 981 cm/s², 9.8 m/s² and 32 ft/s² finds only a passing mention of the value of g in Lecture 16, in a critique of someone else's theory. The likely source of the recollection is 1983d. Its summary speaks of "the absolute value of φ at the Earth's surface", and in text versions of the scan the Greek φ is rendered as "g": the OCR in this investigation did exactly that. The paper also concerns the electron g-factor. What it computes, however, is a gravitational potential, not the acceleration, and it uses the measured G, Earth mass and radius for the solar-system part.

The Earth's surface gravity is g = GM⊕/R⊕², less a latitude-dependent centrifugal term. Satellite tracking measures GM⊕ = 3.986004418 × 10¹⁴ m³/s² to about 2 parts in 10⁹. A theory of G alone therefore changes only the inferred mass of the Earth, not g. Deriving 9.8 m/s² from first principles would need the Earth's mass and radius from theory, which nothing in the corpus attempts.

### 9.6 The Rydberg constant and the moving atom (1980, 1996)

This is the passage on the Rydberg constant and Einstein's theory. It appears twice:

- **"Atomic Spectra and the Moving Atom"**, pages 41–47 of the *Aether Science Papers* commentary (1996). Physics Letters A rejected it in September 1995; Aspden prints the referee's report with it.
- **An earlier form** in *Physics Unified* (1980), chapter 3, equation (56).

The 1996 appendix ties the same electrodynamic force law to "the correct form of the law of gravity, even with the planetary perihelion refinements", citing *Physics Unified* chapter 2. There, retardation of the gravitational energy reproduces Einstein's orbit equation (section 9.1).

**His argument.** Atomic clocks in motion are not slowed by time dilation; instead, the Bohr energy levels of a moving atom change. The Rydberg energy is the electrostatic interaction energy less the electron's kinetic energy, so whatever motion does to those two terms shifts the spectrum.

- **1980 version:** only the kinetic term gains relativistic mass, so R(v)/R(0) = 2 − γ, where γ = 1/√(1 − v²/c²).
- **1996 version:** three effects combine. The electrodynamic force between nucleus and electron offsets the Coulomb force by β² = 1 − v²/c². The electron's mass rises as 1/β. And the quantised quantity is the "charge velocity moment" vr rather than angular momentum. The energy of the electrodynamic interaction cannot be gathered into the photon in time, so it drops out. Together these give R(v)/R(0) = (2 − β²)β³.

Both factors agree with Einstein's β to order (v/c)². They first differ at order (v/c)⁴: the 1996 factor is exactly β(1 − v⁴/c⁴). He argued that the experiments of his day could not tell the two apart, and he was right. At the ion speeds then used (v/c ≲ 0.03), the difference is below one part in a million.

**Test** (`moving_atom.py`, Appendix C). Fast-ion Ives–Stilwell experiments compare the line seen along the beam with the line seen against it. The product of the two frequencies is unchanged in special relativity. For a clock slowed by a factor F, it changes by (Fγ)² − 1.

| Experiment | Ion speed | Measured | Aspden 1980 | Aspden 1996 |
|---|---|---|---|---|
| Heidelberg storage ring, Li⁺ (2003, 2007) | 0.064 c | 0, within ±3.4 × 10⁻¹⁰ | −8.4 × 10⁻⁶ (2.5 × 10⁴σ) | −3.4 × 10⁻⁵ (9.8 × 10⁴σ) |
| GSI storage ring, Li⁺ (Botermann et al. 2014) | 0.338 c | (1.5 ± 2.3) × 10⁻⁹ | −7.8 × 10⁻³ (3.4 × 10⁶σ) | −2.6 × 10⁻² (1.1 × 10⁷σ) |

Both versions are excluded. Two further points:

- **An aether theory need not fail this test.** Lorentz's own aether electrodynamics gives time dilation exactly. What fails is Aspden's particular force law applied to the Bohr atom.
- **No account of fine structure.** Neither version addresses the hydrogen fine structure, which special relativity (through Sommerfeld and Dirac) accounts for (section 6.3).

---

## 10. Timeline: predictions versus improving measurements

| Quantity | Aspden | 1973 measured | 1986 measured | Today |
|---|---|---|---|---|
| 1/α | 137.035915 (1972) | 137.03604(11): −1.1σ | 137.0359895(61): −12σ | 137.035999177(21): about −4,000σ |
| mp/mₑ | 1836.15232 (1975) | 1836.15152(70): +1.1σ | 1836.152701(37): −10σ | 1836.152673426(32): about −11,000σ |
| G | 6.6722 | 6.6720(41): +0.04σ | 6.67259(85): −0.5σ | 6.67430(15): −14σ |
| (mₙ − mₚ)/mₑ | 2.5309419 (1986) | n/a | 2.530948(31) (1984): −0.2σ | 2.53098857(74): −63σ |

Each value agreed with the data when published and failed as precision improved, the usual signature of a formula fitted at the precision of its time. In Aspden's favour, the proton measurement moved toward his value after 1975 rather than away from it.

---

## 11. How likely are these agreements by chance?

### 11.1 Method

The question is whether a toolkit as flexible as Aspden's would produce agreements this close even if his physics were wrong. For each constant, every formula of the same kind he used was generated, and the expected number landing within his accuracy of the measured value was counted. One null model is applied to every constant: the measured value is unrelated to the toolkit. Two estimates bracket the answer:

- **Global:** the target is placed at random within the range the toolkit's formulas span. This counts it as part of the hit that the target fell where his formulas are.
- **Local:** uses the density of formulas right at the target. This is more conservative: it takes for granted that the target sits where formulas pile up (for the deuteron, beside the simple fraction 6/7) and asks only about the final digits.

For α, which comes from one formula with an integer, the range comes instead from the number of structural variants he could have chosen (65 to 650). The corrections from sections 5, 7 and 8 are in place: α with his finite-size term (exact in his model), G with the 2 mₑ ejected charge, and the deuteron with protons given their Thomson radius. For G, the test family includes every cluster idea tried during this investigation, so the after-the-fact choice is paid for in the count. The script is `coincidence.py` (Appendix C).

Two assumptions behind these numbers are worth stating. The α estimate assumes the target could have fallen anywhere within one decade (it divides by ln 10). The four chances are also combined as if independent, although α, the proton ratio and G share the integer 1843 and the same lattice. Both choices are open to challenge, and neither has been varied here.

### 11.2 Each constant on its own

| Constant (corrections in place) | His miss | Test family | Chance of a hit this close |
|---|---|---|---|
| 1/α | −0.615 ppm | Odd-integer grid spaced 181 ppm; 65–650 structural variants; 4 rounding rules | 1 in 7,200 to 1 in 720 |
| mp/mₑ | −0.19 ppm | 464,100 lattice formulas (prefactors 2ⁱ3ʲ, powers of π, powers of 1843 in sixths, 17 Thomson-cluster factors) | 1 in 380 (global) to 1 in 180 (local) |
| Deuteron moment, refined | +0.33 ppm | 7,680 combinations of his chain states and weights 1–4 | 1 in 290 (global) to 1 in 2 (local) |
| G with 2 mₑ | −34 ppm | 116 cluster and chain variants (the non-cluster ideas of section 7.4, such as the k variants, N = 1842.993 and the composite-rule factor, are not included) | 1 in 130 (global, at 34 ppm); 1 in 30 (global, allowing for the 150 ppm spread between labs); 1 in 6 (local) |

Version 1.2 gave the deuteron "roughly even odds". That used only the local estimate; the consistent treatment shows it can count for much more if the 6/7 fraction is regarded as part of the hit rather than given. The neutron–proton mass difference is left out until its derivation has been checked step by step; it is 18.4 ppm from today's value, closer than G's 34 ppm but far looser than its measurement uncertainty (63σ).

### 11.3 All four at the same time

Three scenarios span the assumptions:

- **Strict:** fewest alternatives and the global estimate throughout.
- **Central:** mid-range variants for α, the local estimate for the proton, the geometric mean of global and local for the deuteron, and G judged against the spread between labs.
- **Generous:** most alternatives, ten target particles tried for the proton, and the local estimate for the deuteron and G.

| Scenario | α | Proton | Deuteron | G | All four at once | Combined significance | If he tried 10 constants | If he tried 30 |
|---|---|---|---|---|---|---|---|---|
| Strict | 1.4×10⁻⁴ | 2.6×10⁻³ | 3.5×10⁻³ | 7.5×10⁻³ | 1 in 100 billion | 1 in 34 million | 1 in 52 million | 1 in 430,000 |
| Central | 4.4×10⁻⁴ | 5.5×10⁻³ | 4.2×10⁻² | 3.3×10⁻² | 1 in 300 million | 1 in 210,000 | 1 in 140,000 | 1 in 1,900 |
| Generous | 1.4×10⁻³ | 5.5×10⁻² | 0.50 | 0.18 | 1 in 150,000 | 1 in 410 | 1 in 250 | 1 in 31 |

What the columns mean:

- **All four at once** multiplies the four chances: the chance that one wrong toolkit hits all four this closely, before any allowance for how these four were chosen.
- **Combined significance** (Fisher's method) is the chance that four unrelated tests give a product that small. It corrects for looking at four results rather than one.
- **If he tried 10 or 30 constants** is the chance that, among that many attempts over his career, at least four come out this well. It corrects for publishing the successes and not the failures, and is computed exactly from the order statistics.

The best single figure is about **1 in 2,000** (central scenario, 30 attempted constants), within a full range of about 1 in 30 to 1 in 430,000. The improved G found no support out of sample (section 7.6). Leaving G out and keeping the other three gives about **1 in 800** on the same central assumptions (1 in 18,000 for 10 attempted constants; `out_of_sample.py`). Counting only the four results we can see, the central figure is about 1 in 200,000. Version 1.2, using two constants and none of the corrections, gave 1 in 16 to 1 in 1,500 for 30 attempts; the improved G and refined deuteron now add real weight.

### 11.4 Interpretation

Taken together, the four agreements are harder to dismiss as coincidence than any one of them. Even allowing for a career's worth of attempts, a toolkit this flexible would match all four this closely about once in two thousand tries under central assumptions. That is suggestive, but the generous end, about 1 in 30, shows it is not decisive: the answer depends on how many alternatives Aspden actually explored, which cannot be recovered from his published work. Three cautions remain:

- Two of the four agreements were improved during this investigation. The G change was found after the target was known; the 116-variant test family accounts for the ideas that were written down, but not for any that were not. Its out-of-sample test (section 7.6) found no support, so G is better left out of the joint figure (about 1 in 800 without it).
- The timeline in section 10 still looks like fitting at 1970s precision.
- The physics behind the α formula is not accurate to anything like its 0.6 ppm agreement. The photon-unit step neglects relativistic speeds and magnetic coupling worth 10–30% (companion paper, U24 and U29). The closeness of α therefore cannot be credited to the precision of the mechanism, which weighs toward coincidence or fitting.
- The probabilities concern coincidence only. They cannot distinguish partial truth from skilled fitting, and they do not rescue the theory as published, which every modern measurement excludes.

The clean way forward is an out-of-sample test: apply the 2 mₑ cluster and the proton-radius refinement, unchanged, to the particle masses in his 1986 *Hadronic Journal* papers, and count how many improve. Those papers are now listed in the restored bibliography (section 14).

---

## 12. What mainstream physics derives from first principles

No accepted theory today derives α, mp/mₑ or G from first principles. The Standard Model requires about 25 dimensionless constants that are measured rather than derived, and gravity adds G (equivalently the Planck mass). What current theory does provide is summarised below.

| Quantity | Status in mainstream physics |
|---|---|
| 1/α | Input. Its running with energy is computed precisely, and QED relates it to the electron's magnetic moment at about 0.1 ppb, which is how α is measured. Its low-energy value is not predicted |
| mp/mₑ | Not predicted. The proton mass comes from QCD: lattice QCD computes hadron masses from three inputs (light and strange quark masses and the coupling); BMW 2008 obtained the nucleon at 0.936(25)(22) GeV versus 0.939 measured. The electron mass is a free Higgs coupling |
| Proton mass versus Planck mass | Partly explained. The strong coupling's logarithmic running sets an exponentially small scale (dimensional transmutation), which is why Gmp²/ħc ≈ 5.9×10⁻³⁹. The underlying coupling value is still an input |
| Neutron–proton mass difference | Computed ab initio from QCD plus QED by BMW (2015) to about 0.3 MeV accuracy, establishing that the neutron is heavier at 5σ, given quark masses and α as inputs. Aspden's value (section 8) is closer, at 18 ppm, but 63σ off as an exact formula |
| G | Input. Why gravity is so weak relative to the other forces (the hierarchy problem) is unexplained |
| Higgs mass | Predicted under assumptions: Shaposhnikov and Wetterich (December 2009) obtained about 126 GeV, within a few GeV, from asymptotic safety of gravity; the 2012 discovery found about 125 GeV |
| Tau lepton mass | Koide's empirical 1981 relation, (mₑ + mμ + mτ) = (2/3)(√mₑ + √mμ + √mτ)², predicts 1776.97 MeV versus 1776.93 ± 0.09 measured. No accepted derivation |

Attempts to derive α directly have the same character as Aspden's:

| Attempt | 1/α | Versus measured |
|---|---|---|
| Eddington (1929) | 136, later 137 | Integer values excluded |
| Wyler (1969–71): α = (9/8π⁴)(π⁵/2⁴5!)^(1/4), from volumes of symmetric domains | 137.0360824 | +0.61 ppm |
| Rosen (1976): α = 4π/(42·41) | 137.0324 | −26 ppm |
| Aspden (1972): 108π(8/1843)^(1/6) | 137.0359148 | −0.62 ppm |

Wyler's group-theory formula and Aspden's aether lattice miss by the same amount in opposite directions, which illustrates how readily simple formulas reach the ppm level. A historical review (arXiv:1411.4673) concludes that none of these is accepted and that the question remains open. Proposals in string theory point to a large "landscape" of possible vacua in which the constants are not unique, and some physicists argue for anthropic selection; neither yields the measured values.

Aspden was asking a legitimate question that current physics has not answered. Where mainstream physics succeeds, it computes relations among constants, or a constant from a few others, with very high precision; it does not reduce the inputs to zero.

### 12.1 Aspden and QED compared: a preliminary statement

*Preliminary, 31 October 2026.* This statement draws on the companion scorecard, *Aspden's Numbers at a Glance* (https://aetherscience.org/aspden-scorecard/). The scorecard scores 48 of Aspden's numbers, and the mainstream predictions for the same quantities, in the same way:
- digits right;
- standard deviations off, against the measurement's uncertainty alone, the test an exact formula must pass;
- standard deviations off again with the theory's own uncertainty added.

It also traces each prediction through the stages that built it, to separate digits that come from the physics from digits that come from numbers put in or choices made with the answer in view. An independent check of that last part (Opus, extra effort) has been applied.

**Where QED and the Standard Model are clearly better.** Where the electromagnetic and weak forces do the work, mainstream theory gets more digits right and lands nearer the measurement every time:

| Quantity | Standard Model digits | Aspden digits |
|---|---|---|
| Hydrogen Lamb shift | 6 | 5 |
| Electron magnetic anomaly | 10 | 8 |
| Muon magnetic anomaly | 7 | 6 |
| W and Z masses | 4 | 1 to 2 |

With its own error bars the Standard Model is within 2.3σ on each, while Aspden's values are 5.7σ to 217σ off. Most of these mainstream digits are calculation, not fitting: for the electron, 8.3 of its 9.5 digits come from QED itself, with α as its measured parameter.

**Where Aspden is strongest: the strong force.** There are seven quantities set mainly by the strong force:
- the proton/electron mass ratio;
- the neutron–proton mass difference;
- the neutral-pion mass;
- the Λ and Ω⁻ masses;
- the proton and neutron magnetic moments.

Aspden's numbers are nearer the measured values than the mainstream values in all seven. They have more digits right in six (4 to 8 digits, against 1 to 3 from lattice QCD), and tie on the Ω⁻. There are two reasons.

- **The strong force is the part of the Standard Model hardest to calculate.** Quarks are bound so tightly that the step-by-step expansion that serves QED so well breaks down. Proton, neutron and meson properties must instead be computed numerically on a space-time grid (lattice QCD), with supercomputers. For most of these quantities its precision is limited by computing power to about 1 to 4 percent, so it claims fewer than 2 digits, and its values are within about 1σ of its own error bars. That leaves room for a compact model to compete, which it cannot do in QED, where the calculation has been carried to five loops and checked to ten digits.
- **Aspden's model is a model of compact charge structures.** It builds particles from charge spheres in contact, sets their energies by minimising electrostatic energy, and takes its integer counts from the lattice. That is the kind of picture that captures regularities in hadron masses and moments. Two results stand out:
  - **The proton/electron mass ratio.** It follows from lattice constants with no adjustable number, and was nearer today's value in 1975 than the measurement of that year (section 6).
  - **The neutron moment, −44/23.** It is still within 1.6σ of today's value after forty years.

**What limits that strength.**
- **As exact formulas they still fail.** Only the neutron moment is within 2σ today. The upper end of his neutral-pion range is too, but he preferred the lower end.
- **Many of the strong-force digits are not physics.** The scorecard's stage-by-stage audit finds that many come from factors matched to particles already known, such as 2^(1/4) for the Λ. Others come from late revisions, such as three successive versions of the proton moment, or, for the neutral pion, from an integer search that already encodes the answer.
- **Only a few results survive the chance test without late tuning.**
  - The proton/electron ratio keeps 2.3 to 2.6 digits beyond chance.
  - The neutron's 44/23 keeps about 3 digits as a single formula (about 1.5 allowing for the 36 particle numbers tested). But the 46 behind it comes from a four-state model with several free choices, and the same model gives a neutron–proton mass difference 63σ off.
  - The other is his fine-structure constant, 2.9 to 3.9 digits beyond chance. α is electromagnetic, but it is a constant the Standard Model takes as an input and does not attempt to derive. His mechanism neglects effects of 10 to 30%, and its assumptions date from 1972, when α was known to about 1 ppm, so the agreement cannot reflect the calculation's precision.
- **The comparison may move.** Lattice QCD improves every few years, so the gap on the strong-force side may close.

**Preliminary verdict.** On the electromagnetic and weak side, QED and the Standard Model are decisively better. Aspden's comparative strength lies on the strong-force side and in constants the Standard Model takes as given (α, mp/mₑ). Those are where further work on his theory should concentrate:
- a correction programme derived from his own lattice and written down before comparing with data;
- predictions registered in advance for measurements now under way.

---

## 13. Assessment: what in the corpus has merit

- **Sound technique.** His lattice electrostatics, Thomson-cluster arithmetic and algebra are generally correct apart from transcription typos.
- **Comparative strength on the strong force (preliminary).** For the seven quantities set mainly by the strong force, his numbers are nearer the measured values than lattice QCD's in all seven and have more digits right in six. QED and the Standard Model are clearly better wherever the electromagnetic and weak forces do the work (section 12.1).
- **Proton/electron mass ratio.** −0.19 ppm from lattice geometry and the integer 1843, with no new adjustable number; the strongest coincidence result. The remaining residual matches α³/2 to 0.05%, an unexplained numerical lead (section 6.5).
- **Fine-structure constant.** −0.6 ppm, with 1843 selected by his own stated rule. His finite-size term, which the result depends on, is exact for a quon that excludes the background, the same principle his G theory uses.
- **Improved G.** Replacing the 1.875 triplet with a doubled electron (exactly 2 mₑ), a choice supported by four features of his own work, brings G from −320 ppm to −34 ppm (section 7.5). It is a fit, not a confirmed correction: applied out of sample, it makes his muon lifetime worse (section 7.6).
- **Joint agreement.** With the corrections in place, matching α, the proton ratio, the deuteron moment and G all this closely by chance has odds of about 1 in 2,000 under central assumptions, even allowing for a career of attempts (section 11).
- **Zitterbewegung-sized orbit.** His jitter radius equals the amplitude predicted by Dirac's equation. This is a correspondence rather than evidence: the radius is taken from the electron's mass (companion paper, U01).
- **Cavity electron (1983).** His one-line anomaly formula follows exactly from a stated cavity model, and among 21 natural variants of that model only his lands within 30 ppm of the electron anomaly (about a 1-in-29 coincidence). The muon, which then has no free parameter, misses by 25 ppm (3.9σ in 1983, about 200σ today). His Lamb-shift formula matched the 1981 measurement only after two late correction factors, and fails the 2019 measurement and ionised helium (section 9.3).
- **Internal consistency of clusters.** The 1.875 cluster and the deuteron deficits come from the same calculation and obey his charge bookkeeping.
- **Michelson–Morley point.** He is right that the null result alone does not disprove every aether, though the version he proposed is excluded.

---

## 14. Open items and next steps

1. Read the papers now reachable through the restored bibliography (https://aetherscience.org/www-aspden-org/papers/bib/refs.htm): 1972a (*Phys. Lett.* 41A, 423; α), 1975a (*Il Nuovo Cimento* 30A, 235; the proton mass), 1989b (*Physics Essays* 2, 173; "The Theory of the Gravitation Constant"), 1986e and 1986j (*Hadronic Journal* 9, 137 and 153; meson masses, full text in the *Aether Science Papers* PDF appendix) and 1982e (the mirror paper). Lecture 30 and Tutorial Notes 1–4, 11 and 12 still need locating.
2. Apply the proton-radius refinement, unchanged, across all of Aspden's particle-mass derivations; if it improves them, the lead gains weight. The doubled-electron half of this item is done (section 7.6): it found no support.
3. Check Note 14's predicted 6.25% meson-lifetime shortfall near γ = 2 against accelerator data.
4. Check the 1986d neutron–proton derivation step by step (the paper is now readable; the result is compared in section 8).
5. Extend the chance-coincidence test to the full set of particle masses in the 1986 papers.
6. Closed in v1.7: the Rydberg/Einstein passage is "Atomic Spectra and the Moving Atom" (1996), with a 1980 version in *Physics Unified*; both are excluded by fast-ion time-dilation tests (section 9.6). No non-relativistic fine-structure derivation exists in the site's texts.
7. Look for any mechanism in his framework that would produce an α³/2 correction to the proton mass (section 6.5), and test whether the same correction improves his other particle masses.
8. Closed in v1.7: no first-principles g = 9.8 m/s² exists in any of the site's texts; 1983d computes a potential, not g (section 9.5).
9. If the 1969 Mercury mechanism is to be pursued, reverse its sign and look for a lattice-boundary rule, tied to density, core or magnetosphere rather than radius, that fits all six planets (section 9.2). The double pulsar would still require a separate mechanism that scales with the central mass.
10. Closed in v1.6: whether the 4/√3 term and the muon's sign switch are derived or chosen (section 9.3). They are derived from three stated choices, giving a modest coincidence for the electron and a failed prediction for the muon. The 1977–82 cavity papers remain to be read for any further justification of the half-cross-section radius.
11. Part 2 of the bottom-up review: test the particle chain built on the units (dimuon, proton, taon, graviton) out of sample, as in item 2.
12. Compare the visible-light direction dependence that a cubic lattice of Aspden's spacing implies (about 10⁻¹², four-fold under rotation; companion paper U16) with published rotating-cavity analyses.

---

## 15. Companion documents

### 15.1 *Aspden's Aether from the Bottom Up, Part 1: The Smallest Units* (abstract)

Published at https://aetherscience.org/aspden-aether-units/ (Word and Markdown versions in /aspden-analysis-files/).

Aspden's physics rests on a uniform continuum of charge and a simple cubic lattice of "quons", each carrying the electron's charge, the two circling each other at the electron's Compton frequency. Part 1 rebuilds these units from *The Physics of Creation* (2003, chapter 7), traces them through *Physics Unified* (1980) and *Physics without Einstein* (1969), and tests them in 41 numbered steps (U01–U41), including four objections: that no restoring force is needed, that the medium need only flex, that background motion keeps the quons moving, and that the medium is light's reference frame, carried with the Earth as Aspden proposed (U37–U40). A supplement, Part 1A (https://aetherscience.org/aspden-quon-model/), derives the model behind them step by step, with every assumption labelled as Aspden's, derived, or a modelling choice.

- **Internally consistent.** The dimensionless chain holds together to 0.6 ppm, the same gap as his α. Its most consequential assumption is that a quon's inertia is half its Thomson mass, by a buoyancy analogy. With the full mass, 1/α comes out 0.56% low.
- **Real scales.** His orbit radius ħ/2mₑc is the Dirac zitterbewegung amplitude and the range of QED vacuum polarization.
- **The c/2 postulate.** The radius rests on a postulate that the two frames move at c relative to each other, each at c/2, which Aspden calls an assumption from 1960 to 2003. Worked through his own equations, it cancels out of α, N and the lattice spacing, and decides only which odd N is chosen (U41).
- **Fatal for light.** The same scale is fatal to the lattice as a medium for light:
  - Aspden's restoring force on a quon is the field of the displaced lattice itself, as his own derivation says. With Coulomb's and Maxwell's laws, the lattice is then a plasma, and his orbit is its plasma oscillation at exactly 511 keV, a credit to his consistency;
  - the same plasma blocks all light below 511 keV (radio, visible, X-rays), cancels static fields beyond about 10⁻¹⁰ m, and is equivalent to a photon of electron mass, 5 × 10²³ times the measured upper limit;
  - his 1982 picture of a vacuum resonating at the Compton frequency, taken literally with each quon on its own spring, fails too: gamma rays of 662 keV, 847 and 1238 keV and 6 GeV travel normally, and photons from 10 keV to 31 GeV from GRB 090510 arrived together after 7.5 billion years;
  - a lattice of spacing 6.37 × 10⁻¹³ m cannot carry waves shorter than about 1 MeV, while photons are seen at 1.4 PeV;
  - shrinking the lattice would break the tie to the electron that sets every scale in the theory;
  - Aspden's own frame for light, carried with the Earth but not turning with it, is excluded by rotating cavities through the Earth's rotation, by a factor of about 1,500; a frame turning with the Earth is excluded by ring lasers (U40).
- **Smaller results.**
  - The cell energy he calls a virtual muon pair is 0.21% below two muon masses.
  - The aether's energy density is 2.5 × 10³⁵ times the observed dark energy, a cancellation problem shared with mainstream physics.
  - The germanium light-hole mass he cited sits inside a tenfold spread across semiconductors.
- **Earlier versions reproduce.** His 1969 correction (y = 0.000456) and his 2003 constant (k = 8.34) both reproduce from his descriptions.
- **The 0.6 ppm gap.** Every relation among his units is exact, and the only gap is his α, 0.615 ppm low. None of his printed figures is wrong. Closing the gap would need a +0.41 ppm change to the photon-unit relation, right to 1 part in 4,000. The photon-unit step itself leaves out effects 10³–10⁵ times larger, because its outer quons spin at 0.41c and 0.58c. So the agreement cannot reflect the calculation's precision. One improvement was found: his free 2003 constant k can be calculated from his own description (k = 11.7), leaving α unchanged.
- **The endless lattice.** Treated as an endless crystal, the lattice confirms his orbit exactly, but the simple cubic arrangement is electrostatically unstable (18% of its vibration modes). Magnetic coupling between the photon unit's moving quons adds 9–29% to its inertia. A wave description of the same 27 quons has the same 0.48c speeds. Only a wave spread over about 7.5 million quons would be slow enough, and then the 36 in his formula for h has to be put in by hand.

### 15.2 Test register

Every test in this paper (M01, M02, …) and in Part 1 (U01–U41) is listed at https://aetherscience.org/aspden-test-register/ in one format: Aspden's claim and source, each calculation step with its number, the inputs and their sources, the script output, the verdict, and the assumptions made in this analysis that a reader could challenge. The register ends with a list of discrepancies found while compiling it.

### 15.3 *Aspden's Aether from the Bottom Up, Part 2: Quarks, Particles and Predictions* (summary)

Published at https://aetherscience.org/aspden-particles/ (Word and Markdown versions in /aspden-analysis-files/).

Two reading passes catalogued every particle claim in the 719 texts on the site, and the numbers were tested against PDG and CODATA values (tests P01–P35, Q1–Q9).

- **Quons and quarks are different things.** None of Aspden's characteristic energies matches a quark mass, and his time-average picture of fractional charge is excluded by deep-inelastic scattering.
- **Then and now.** Of 27 numbers he set against a measurement, 24 agreed within 2σ at the time and 4 do today; 20 of the 27 sit nearer the value he used than today's.
- **What holds.** The neutron moment −44/23 (1.6σ today), the neutral-pion lifetime, and his 1998 tau mass after two revisions.
- **Advance predictions failed.** A charged lepton at 2.587 GeV, further W- and Z-like states, the 2000 Higgs level list, his in-flight meson lifetimes and massless neutrinos.

### 15.4 *Aspden's Numbers at a Glance* (scorecard)

Published at https://aetherscience.org/aspden-scorecard/ (Word, Markdown and sortable CSV files in /aspden-analysis-files/).

Every number of Aspden's tested in these papers (48 rows) with its digits right, the digits the measurement pins down then and now, and its standard deviations off. QED and the Standard Model are scored the same way, with their earlier predictions too. A stage-by-stage audit, checked by an independent reviewer, shows where each prediction's digits come from. Section 12.1 above summarises the result.

---

## Appendix A. Scripts

Full source code and output for each script are in Appendix C.

| Script | Contents |
|---|---|
| `aspden_G.py` | The G derivation as one closed formula; change the cluster energy or lattice integer to recompute |
| `aspden_G_variants.py` | Charge-model constant k, lattice integer, all lattice clusters, averaging and doubled-electron variants |
| `deuteron.py` | The three deuteron states from touching Thomson charges, with and without a finite proton radius |
| `planck.py` | Photon-unit algebra (symbolic), Aspden's finite lattice sums, exact Ewald value, integer step and sensitivity table |
| `alpha_finite_size.py` | The finite-size term in the α derivation: Aspden's term, the no-void and void treatments, the window of allowed coefficients and the second-order void effect |
| `environment_constants.py` | Proton/electron ratio and Rydberg constant from his formulas, the step changes implied by his energy/temperature claim, tests against white-dwarf, solar and quasar data, the charge-neutrality test, Mercury's J₂ term and the α³/2 lead |
| `coincidence.py` | Chance-coincidence tests for α, the proton, the refined deuteron and G with 2 mₑ, and the joint probability of all four (product, Fisher-combined, and career-wide for 10 and 30 attempts) |
| `cavity_1983.py` | The 1983 cavity-electron papers: electron and muon anomalies against 1979–83 and 2023–25 data, series comparison with QED, the "absolute gravitational potential" by both routes, the galactic and annual-modulation tests, and the Lamb shift for hydrogen and He⁺ |
| `cavity_variants.py` | The cavity-electron formula rebuilt from its stated model; the constants the data require; 21 natural variants ranked; the muon prediction and the footnote alternative |
| `np_mass.py` | The 1986d neutron–proton mass difference compared in Aspden's own units with the 1984 and 2022 measurements |
| `moving_atom.py` | Aspden's 1980 and 1996 Rydberg factors for a moving atom, their series against time dilation, and their predictions for the fast-ion Ives–Stilwell experiments |
| `aether_units.py` | Companion paper Part 1: Aspden's smallest units rebuilt (U01–U26; `lattice_dynamics.py` covers U27–U31): identities among the units, the natural frequency and polarization of the quon lattice, the single-displacement response and its tests (Cs-137, SN 2014J, Alväger 1964, GRB 090510), the lattice cutoff, light holes, the 1969 and 2003 versions, and the 0.6 ppm gap (what a fix needs, the restoring coefficient, the photon unit at relativistic speeds, k from his description) |
| `lattice_dynamics.py` | Companion paper Part 1, U27–U31: the quon lattice as an endless crystal (Ewald dynamical matrix and stability, magnetic coupling in the spinning photon unit, speeds in a wave picture) |
| `out_of_sample.py` | Out-of-sample test of the doubled electron: every other use of the 1.875 cluster (the 1986j upsilon, the 2003 muon lifetime) recomputed with 2; effect on the chance calculation |
| `mercury_aether.py` | The 1969 aether-sphere account of Mercury's perihelion: lattice density from his inputs and today's, orbit integration showing the sign, predictions for six planets, the double pulsar, and the special-relativity-only (Sommerfeld) share |

## Appendix B. Reference values used

| Quantity | Value | Source |
|---|---|---|
| 1/α | 137.035999177(21) | CODATA 2022 (PDG 2026) |
| mp/mₑ | 1836.152673426(32) | CODATA 2022 (PDG 2026) |
| G | 6.67430(15) × 10⁻¹¹ m³ kg⁻¹ s⁻² | CODATA 2018/2022 |
| Deuteron moment μd/μN | 0.8574382311(48) | CODATA 2014 |
| Neutron–proton mass difference | (mₙ − mₚ)/mₑ = 2.53098857(74), i.e. 1.29333251 MeV | CODATA 2022 (mₙ/mₑ − mₚ/mₑ) |
| Tau lepton mass | 1776.93 ± 0.09 MeV | Particle Data Group |
| Electron anomaly aₑ | 0.00115965218059(13) | Fan et al. 2023 |
| Muon anomaly aμ | 0.001165920705(147) | Fermilab Muon g−2, final (2025) |
| 1/α from atom recoil | 137.035999206(11) (Rb, 2020); 137.035999046(27) (Cs, 2018) | Morel et al.; Parker et al. |
| Hydrogen 2S₁/₂–2P₁/₂ Lamb shift | 1057.8298(32) MHz | Bezginov et al. 2019 |
| He⁺ n = 2 Lamb shift | 14041.9(1.5) MHz | van Wijngaarden et al. 1987 |
| Cosmic background temperature | 2.72548 K | COBE/FIRAS (Fixsen 2009) |
| Solar-system acceleration | (2.32 ± 0.16) × 10⁻¹⁰ m/s² toward the galactic centre | Gaia EDR3 (2021) |
| GM⊕ | 3.986004418 × 10¹⁴ m³/s² | IERS/WGS 84 |
| Double-pulsar periastron advance | 16.90 °/yr | Kramer et al. 2006, 2021 |
| Fast-ion time dilation, ε = ν_aν_p/ν₀² − 1 | (1.5 ± 2.3) × 10⁻⁹ at v = 0.338c; α̂ within ±8.4 × 10⁻⁸ at 0.03c and 0.064c | Botermann et al. 2014; Reinhardt et al. 2007 |

## Appendix C. Program listings

Each analysis script below is complete and runs on its own with `python3 <script>.py`. They were run on 30 October 2026 with Python 3.13, mpmath 1.3, NumPy 2.5, SymPy 1.14 and SciPy 1.18; the output printed by each run is reproduced after its listing. The last listing is the Node.js script that generates the Word version of this paper from the Markdown source.

### C.1 aspden_G.py

Aspden's G derivation (Notes 6, 8, 9) as one closed formula. CLUSTER = 15/8 reproduces his published value; setting it to 2 gives the improved form of section 7.5.

```python
"""
Aspden's derivation of G (Tutorial Notes 6, 8, 9), rebuilt as one closed formula.

Chain (all quantities in electron-mass units unless noted):
  1. Gravitational charge = background charge displaced by gravitons:
         sqrt(G) * M = sigma * dV,  sigma = e/d^3,  d = 108*pi*a,  a = 2e^2/(3 me c^2)
     With Thomson spheres (E = 2e^2/3r) this gives
         sqrt(G) = 4*pi*(e/me) * g^-4 / (108*pi)^3,   g = Mg/me
  2. Lattice -> dimuon:   Q = (108 pi)^3 / (4 pi/3) / 1843^(4/3) = 944784 pi^2 / 1843^(4/3)
  3. Dimuon -> proton:    P = Q / (sqrt(3/2) - 1)
  4. Proton -> taon:      T = 2 * P * (sqrt(6) - 3/2) - CLUSTER = 2 Q (3 + sqrt(3/2)) - CLUSTER
                          (two proton-dimuon pairs at minimum energy, minus an ejected charge cluster;
                           Aspden used CLUSTER = 1.875 = energy of a touching +-+ in-line electron triplet)
  5. Taon -> graviton:    g = T / x,  where 3x^4 + x^3 = 1  (graviton + two taons has 3x the
                          volume per unit energy of a graviton alone)
Change CLUSTER or N_LATTICE below to see how G responds.
"""
from mpmath import mp, mpf, pi, sqrt, findroot

mp.dps = 25
CLUSTER = mpf(15) / 8          # Aspden's 1.875 (in-line +-+ triplet); the improved form (paper, section 7.5) uses 2
N_LATTICE = 1843               # integer fixed by his fine-structure-constant formula

e  = mpf('4.80320471257e-10')  # esu (CODATA 2022 converted)
me = mpf('9.1093837139e-28')   # g   (CODATA 2022)

Q = 944784 * pi**2 / mpf(N_LATTICE) ** (mpf(4) / 3)
P = Q / (sqrt(mpf(3) / 2) - 1)
T = 2 * Q * (3 + sqrt(mpf(3) / 2)) - CLUSTER
x = findroot(lambda x: 3 * x**4 + x**3 - 1, 0.69)
g = T / x
G_cgs = (4 * pi * (e / me) / g**4 / (108 * pi) ** 3) ** 2

print(f"dimuon Q   = {mp.nstr(Q, 10)}")
print(f"proton P   = {mp.nstr(P, 12)}   (measured 1836.152673426)")
print(f"taon T     = {mp.nstr(T, 10)}   (measured tau = 3477.37)")
print(f"graviton g = {mp.nstr(g, 10)}   (CODATA G needs 5062.1156)")
print(f"G          = {mp.nstr(G_cgs * 1e8, 7)} x 10^-11 m^3 kg^-1 s^-2   (CODATA 6.67430(15))")
```

Output:

```text
dimuon Q   = 412.6658162
proton P   = 1836.15231648   (measured 1836.152673426)
taon T     = 3484.940581   (measured tau = 3477.37)
graviton g = 5062.31836   (CODATA G needs 5062.1156)
G          = 6.672161 x 10^-11 m^3 kg^-1 s^-2   (CODATA 6.67430(15))
```

### C.2 aspden_G_variants.py

Extrapolations of the G chain: the charge-model constant k, the lattice integer, every charge-conserving lattice cluster, averaging schemes and the doubled-electron variant (sections 7.4, 7.5 and 11).

```python
"""Speculative variants of Aspden's G chain, with the charge-model constant k made explicit.
Energy of a charge e of radius a:  E = k e^2 / a   (Aspden/Thomson k = 2/3; surface k = 1/2; uniform k = 3/5).
Lattice cell d = 72*pi*e^2/(me c^2) is fixed by his alpha relation and jitter radius r = hbar/(2 me c), independent of k.
"""
from mpmath import mp, mpf, pi, sqrt, findroot
from itertools import product
mp.dps = 25
e=mpf('4.80320471257e-10'); me=mpf('9.1093837139e-28'); eme=e/me
MEAS = {"CODATA":(6.67430,0.00015),"HUST-TOS-18":(6.674184,0.000078),"HUST-AAF-18":(6.674484,0.000078),
        "UWash-00":(6.674255,0.000092),"UZur-06":(6.67425,0.00012),"UCI-14":(6.67435,0.00013),
        "BIPM-14":(6.67554,0.00016),"JILA-10":(6.67260,0.00025),"LENS-14":(6.67191,0.00099)}
x = findroot(lambda x: 3*x**4 + x**3 - 1, 0.69)   # composite rule; V ~ E^-3 holds for any k

def chain(k=mpf(2)/3, N=1843, cluster=None):
    k=mpf(k)
    da = 72*pi/k                                  # d/a
    Q  = da**3/(4*pi/3)/mpf(N)**(mpf(4)/3)        # dimuon
    q  = 1/sqrt(k)-1                              # Q/P at energy minimum
    P  = Q/q                                      # proton
    Emin = 2/sqrt(k) - 1/k                        # P:Q pair minimum energy / P
    trip = 3 - 3/(4*k)                            # straight +-+ touching triplet
    c = trip if cluster is None else mpf(cluster)
    T  = 2*P*Emin - c
    g  = T/x
    G  = (4*pi*k**3*eme/g**4/(72*pi)**3)**2*mpf('1e8')
    return dict(Q=Q,P=P,T=T,g=g,G=G,trip=trip)

def verdict(G):
    G=float(G); out=[]
    for n,(v,u) in MEAS.items():
        out.append(f"{n}:{(G-v)/u:+.1f}σ")
    return "  ".join(out[:1]+out[1:6])

print("=== 1. Charge-model constant k (N=1843 held fixed) ===")
for name,k in [("surface shell 1/2",mpf(1)/2),("uniform ball 3/5",mpf(3)/5),("Aspden 1/r 2/3",mpf(2)/3)]:
    r=chain(k)
    print(f"{name:18s} proton={mp.nstr(r['P'],9):>12s} (meas 1836.152673)  taon={mp.nstr(r['T'],7):>9s}  G={mp.nstr(r['G'],6)}")

# k needed to hit the measured proton exactly (everything else Aspden's)
kP = findroot(lambda k: chain(k)['P']-mpf('1836.152673426'), mpf(2)/3)
print("k that reproduces measured proton exactly:", mp.nstr(kP,12), " (2/3 =", mp.nstr(mpf(2)/3,12),")  G there:", mp.nstr(chain(kP)['G'],7))

print("\n=== 2. Lattice integer: 1843 vs value that makes alpha exact ===")
Neff = 8*(108*pi/mpf('137.035999177'))**6
for N in [1843, Neff]:
    r=chain(N=N); print(f"N={mp.nstr(N,10):>12s} proton={mp.nstr(r['P'],10)}  G={mp.nstr(r['G'],7)}")

print("\n=== 3. Every charge-conserving cluster of touching Thomson charges on a simple-cubic lattice ===")
# Rule set fixed BEFORE looking at G: sites one charge-diameter (2a) apart, sign alternates with lattice
# parity (every touching pair attracts), cluster connected, net charge +-1 (so a charged taon is left).
k=mpf(2)/3
nbr=[(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)]
def canon(cells):
    m=[min(c[i] for c in cells) for i in range(3)]
    return tuple(sorted(tuple(c[i]-m[i] for i in range(3)) for c in cells))
shapes={1:{canon([(0,0,0)])}}
for n in range(2,6):
    new=set()
    for s in shapes[n-1]:
        for c in s:
            for d in nbr:
                t=(c[0]+d[0],c[1]+d[1],c[2]+d[2])
                if t not in s: new.add(canon(list(s)+[t]))
    shapes[n]=new
def energy(cells):
    E=mpf(len(cells))
    sg=[(-1)**(sum(c)%2) for c in cells]
    for i in range(len(cells)):
        for j in range(i+1,len(cells)):
            D=2*sqrt(sum((cells[i][t]-cells[j][t])**2 for t in range(3)))  # in units of a
            E+= sg[i]*sg[j]/(k*D)
    return E, abs(sum(sg))
results={}
for n in (1,3,5):
    for s in shapes[n]:
        E,q=energy(s)
        if q==1: results.setdefault(mp.nstr(E,8),(n,E))
lo,hi=6.67191,6.67554   # span of the precise modern measurements (LENS-14 .. BIPM-14)
hits=0
print(f"{'n':>2s} {'cluster E (me)':>15s} {'G':>9s}  in modern range?")
for key,(n,E) in sorted(results.items(), key=lambda kv: kv[1][1]):
    G=chain(cluster=E)['G']; inr = lo<=float(G)<=hi; hits+=inr
    print(f"{n:2d} {mp.nstr(E,6):>15s} {mp.nstr(G,6):>9s}  {'YES  '+verdict(G) if inr else ''}")
print(f"distinct cluster energies: {len(results)}, landing in modern G range: {hits}")

print("\n=== 4. Other mechanisms ===")
straight=mpf(15)/8; L=3-mpf(3)/2+mpf(3)/2/(2*sqrt(2))
# A three-charge chain = a centre site + 2 of its 6 neighbours: C(6,2)=15 ways; 3 straight, 12 L-shaped.
orient = (3*straight+12*L)/15
shape  = (straight+L)/2
moving = 3 - mpf(9)/8*(1-mpf(1)/4)          # straight triplet, interactions reduced by (1-v^2/c^2), v=c/2 jitter
Gs_avg = (3*chain(cluster=straight)['G']+12*chain(cluster=L)['G'])/15
for name,c in [("orientation-weighted triplet (15 ways)",orient),("equal weight per shape",shape),
               ("straight triplet in jitter motion (v=c/2)",moving),("doubled electron (exactly 2 me)",mpf(2))]:
    G=chain(cluster=c)['G']
    print(f"{name:42s} cluster={mp.nstr(c,7):>9s}  G={mp.nstr(G,6)}   {verdict(G)}")
print("orientation-weighted, averaging G instead of energy: G =", mp.nstr(Gs_avg,6))
r=chain(cluster=orient); print("graviton masses: straight", mp.nstr(chain()['g'],9), " L", mp.nstr(chain(cluster=L)['g'],9), " weighted", mp.nstr(r['g'],9))
# composite-rule factor that would be needed with the straight triplet
gneed=(4*pi*(mpf(2)/3)**3*eme/(72*pi)**3/sqrt(mpf('6.67430e-8')))**(mpf(1)/4)
xneed=chain()['T']/gneed; F=(1+2/xneed**3)/(1+2*xneed)
print("with straight triplet, composite factor needed for CODATA:", mp.nstr(F,8), "(Aspden: 3)")
```

Output:

```text
=== 1. Charge-model constant k (N=1843 held fixed) ===
surface shell 1/2  proton=  2361.51327 (meas 1836.152673)  taon= 3911.183  G=0.471772
uniform ball 3/5   proton=  1945.29855 (meas 1836.152673)  taon=   3559.4  G=2.99413
Aspden 1/r 2/3     proton=  1836.15232 (meas 1836.152673)  taon= 3484.941  G=6.67216
k that reproduces measured proton exactly: 0.666666195842  (2/3 = 0.666666666667 )  G there: 6.672133

=== 2. Lattice integer: 1843 vs value that makes alpha exact ===
N=        1843 proton=1836.152316  G=6.672161
N= 1842.993195 proton=1836.161356  G=6.671898

=== 3. Every charge-conserving cluster of touching Thomson charges on a simple-cubic lattice ===
 n  cluster E (me)         G  in modern range?
 1             1.0   6.65877  
 3           1.875   6.67216  YES  CODATA:-14.3σ  HUST-TOS-18:-25.9σ  HUST-AAF-18:-29.8σ  UWash-00:-22.8σ  UZur-06:-17.4σ  UCI-14:-16.8σ
 3         2.03033   6.67454  YES  CODATA:+1.6σ  HUST-TOS-18:+4.6σ  HUST-AAF-18:+0.7σ  UWash-00:+3.1σ  UZur-06:+2.4σ  UCI-14:+1.5σ
 5          2.8125   6.68654  
 5         2.87467   6.68749  
 5         2.88058   6.68758  
 5         2.93209   6.68837  
 5         2.93831   6.68847  
 5         2.97342   6.68901  
 5         3.00201   6.68945  
 5            3.03   6.68988  
 5         3.03115    6.6899  
 5         3.07103   6.69051  
 5         3.09996   6.69095  
 5         3.12875    6.6914  
 5         3.13984   6.69157  
 5         3.18533   6.69227  
 5         3.19757   6.69245  
 5         3.22525   6.69288  
 5         3.25529   6.69334  
 5         3.29517   6.69395  
 5          3.3529   6.69484  
distinct cluster energies: 22, landing in modern G range: 2

=== 4. Other mechanisms ===
orientation-weighted triplet (15 ways)     cluster= 1.999264  G=6.67406   CODATA:-1.6σ  HUST-TOS-18:-1.5σ  HUST-AAF-18:-5.4σ  UWash-00:-2.1σ  UZur-06:-1.5σ  UCI-14:-2.2σ
equal weight per shape                     cluster= 1.952665  G=6.67335   CODATA:-6.3σ  HUST-TOS-18:-10.7σ  HUST-AAF-18:-14.5σ  UWash-00:-9.8σ  UZur-06:-7.5σ  UCI-14:-7.7σ
straight triplet in jitter motion (v=c/2)  cluster=  2.15625  G=6.67647   CODATA:+14.5σ  HUST-TOS-18:+29.3σ  HUST-AAF-18:+25.5σ  UWash-00:+24.1σ  UZur-06:+18.5σ  UCI-14:+16.3σ
doubled electron (exactly 2 me)            cluster=      2.0  G=6.67408   CODATA:-1.5σ  HUST-TOS-18:-1.4σ  HUST-AAF-18:-5.2σ  UWash-00:-1.9σ  UZur-06:-1.4σ  UCI-14:-2.1σ
orientation-weighted, averaging G instead of energy: G = 6.67406
graviton masses: straight 5062.31836  L 5062.09272  weighted 5062.13785
with straight triplet, composite factor needed for CODATA: 2.9996204 (Aspden: 3)
```

### C.3 deuteron.py

The deuteron model rebuilt from touching Thomson charges, with point protons (Aspden) and with a finite proton radius (refinement), section 8.

```python
"""Aspden's deuteron model (Creation: The Physical Truth, 2006; Hadronic J. 9, 129, 1986), rebuilt.
Charges are Thomson spheres (E = 2e^2/3r), touching in a line. Units: lepton radius a = 1, energies in me c^2,
so a touching pair at centre distance D (in a) has interaction -/+ 1.5/D.
State A: e+ p- e+ p- e+      (weight 2)
State B: p  e- e+ p-  (+ satellite e+, not in core)   (weight 1, core neutral)
State C: p  e- p      (+ satellite e-e+ pair)          (weight 4)
Moment (his formula): mu_d/mu_N = (6/7) * 2 / (2 - delta/R),  delta = weighted core mass deficit (me), R = mp/me
"""
from mpmath import mp, mpf
mp.dps = 25
MU_MEAS = mpf('0.8574382311'); MU_U = mpf('0.0000000048')    # CODATA 2014
R_MEAS = mpf('1836.15267389')

def core(chain, rp):
    # chain: list of (sign, kind) with kind 'e' or 'p'; returns (rest-mass excess over 2 protons, interaction)
    rad = {'e': mpf(1), 'p': rp}
    x=[mpf(0)]
    for i in range(1,len(chain)):
        x.append(x[-1] + rad[chain[i-1][1]] + rad[chain[i][1]])
    inter = mpf(0)
    for i in range(len(chain)):
        for j in range(i+1,len(chain)):
            inter += chain[i][0]*chain[j][0]*mpf('1.5')/(x[j]-x[i])
    leptons = sum(1 for s,k in chain if k=='e')
    return -(leptons + inter)   # deficit below 2 proton masses (positive = lighter)

A=[(+1,'e'),(-1,'p'),(+1,'e'),(-1,'p'),(+1,'e')]
B=[(+1,'p'),(-1,'e'),(+1,'e'),(-1,'p')]
C=[(+1,'p'),(-1,'e'),(+1,'p')]
def moment(rp, R, wA=2,wB=1,wC=4):
    dA,dB,dC = core(A,rp),core(B,rp),core(C,rp)
    d = (wA*dA+wB*dB+wC*dC)/(wA+wB+wC)
    return dA,dB,dC,d, (mpf(wA+wC)/(wA+wB+wC))*2/(2-d/R)

for label,rp,R in [("Aspden: point protons, R=1836", mpf(0), mpf(1836)),
                   ("point protons, measured R", mpf(0), R_MEAS),
                   ("finite Thomson proton radius a/R, measured R", 1/R_MEAS, R_MEAS)]:
    dA,dB,dC,d,mu = moment(rp,R)
    print(f"{label:46s} deficits A={mp.nstr(dA,7)} B={mp.nstr(dB,7)} C={mp.nstr(dC,7)}  avg={mp.nstr(d,8)}")
    print(f"{'':46s} mu_d = {mp.nstr(mu,10)}   vs measured {MU_MEAS}:  {mp.nstr((mu/MU_MEAS-1)*1e9,4)} ppb  ({mp.nstr((mu-MU_MEAS)/MU_U,4)} sigma)")
# Check his 7/4 and 9/4 heavy-centred triplets
print("\nheavy-centred triplets used for his 7/4 and 9/4: p e- e+ ->", mp.nstr(-1.5+(-0.75)+0.5,4), "   e+ p- e+ ->", mp.nstr(-1.5-1.5+0.75,4))
```

Output:

```text
Aspden: point protons, R=1836                  deficits A=1.375 B=1.125 C=1.25  avg=1.2678571
                                               mu_d = 0.8574389111   vs measured 0.8574382311:  793.0 ppb  (141.7 sigma)
point protons, measured R                      deficits A=1.375 B=1.125 C=1.25  avg=1.2678571
                                               mu_d = 0.8574388865   vs measured 0.8574382311:  764.3 ppb  (136.5 sigma)
finite Thomson proton radius a/R, measured R   deficits A=1.372619 B=1.123446 C=1.248775  avg=1.266255
                                               mu_d = 0.8574385122   vs measured 0.8574382311:  327.9 ppb  (58.57 sigma)

heavy-centred triplets used for his 7/4 and 9/4: p e- e+ -> -1.75    e+ p- e+ -> -2.25
```

### C.4 planck.py

Planck's constant and the fine-structure constant (section 5): symbolic check of the photon-unit algebra, Aspden's finite lattice sums, the exact Ewald value, the integer step and the sensitivity table.

```python
"""Aspden's derivation of Planck's constant (Tutorial Notes 7 and 8), rebuilt and checked.
Units: e = 1, d = 1 (cell side), energies in e^2/d.  x = r/d (quon orbit radius / cell side).
"""
import numpy as np, sympy as sp
from mpmath import mp, mpf, pi, sqrt, log, findroot
mp.dps = 20

# ---------- Part 1: the photon-unit algebra (Note 8), with the printed force balance corrected ----------
m0,d,r,c,e,w,f = sp.symbols('m0 d r c e omega f', positive=True)
I = 36*m0*d**2                          # 3x3x3 quon cube: 12 quons at d, 12 at sqrt(2) d from spin axis
E = (c/(2*r))*I*w                       # energy = jitter angular frequency (c/2r) x angular momentum
E = E.subs(w, 2*sp.pi*f/4)              # radiation frequency = 4 x spin rate (4-fold symmetry)
h = sp.simplify(E/f)                    # E = h f
m0_sol = sp.solve(sp.Eq(m0*(c/(2*r))**2*r, (4*sp.pi*e**2/d**3)*(2*r)), m0)[0]   # centripetal = restoring force over 2r
h = sp.simplify(h.subs(m0, m0_sol))
print("h =", h, "   =>  h c/(2 pi e^2) =", sp.simplify(h*c/(2*sp.pi*e**2)))

# ---------- Part 2: his lattice energy, his way (finite cube, N shells) ----------
def lattice_M(N):
    """S(N) - C(N): potential at a quon from all other quons in the cube |i|,|j|,|k|<=N
       minus the continuum of the whole cube (side 2N+1), as in his QBASIC program."""
    a = np.arange(0, N+1, dtype=float)
    A,B,C = np.meshgrid(a,a,a, indexing='ij')
    R = np.sqrt(A*A+B*B+C*C); R[0,0,0] = np.inf
    mult = (2.0**((A>0)*1+(B>0)*1+(C>0)*1))          # octant multiplicity
    S = np.sum(mult/R)
    cube_centre = 3*np.log(2+np.sqrt(3)) - np.pi/2  # potential at centre of unit cube (= 24(cosh^-1 2 - pi/6)/8)
    return S - cube_centre*(2*N+1)**2

def solve_x(Mneg, corr_coef=1/(4608*np.pi)):
    # 8 pi x^2 = (-M) - corr_coef * x^-4    (his zero-potential condition)
    return float(findroot(lambda x: 8*pi*x**2 + corr_coef/x**4 - Mneg, 0.303))

print("\nN    his r/d        rebuilt r/d     rebuilt 144*pi*r/d")
his = {5:0.3028976690023924, 10:0.3028807822129387, 30:0.3028746523594567}
for N in [5,10,30,60,120]:
    x = solve_x(-lattice_M(N))
    print(f"{N:<4d} {his.get(N, float('nan')):.10f}   {x:.10f}    {144*np.pi*x:.6f}")

# ---------- Part 3: exact infinite-lattice value ----------
# Ewald potential at a site of a simple-cubic lattice in a neutralising background (mean potential zero)
def ewald_sc(eta=2.0, nmax=6):
    s_real = 0.0; s_rec = 0.0
    from math import erfc, exp
    rng = range(-nmax, nmax+1)
    for i in rng:
        for j in rng:
            for k in rng:
                if i==j==k==0: continue
                rr = (i*i+j*j+k*k)**0.5
                s_real += erfc(eta*rr)/rr
                g2 = 4*np.pi**2*(i*i+j*j+k*k)
                s_rec += 4*np.pi/g2*exp(-g2/(4*eta**2))
    return s_real + s_rec - 2*eta/np.sqrt(np.pi) - np.pi/eta**2
psi = ewald_sc()
print(f"\nEwald site potential (mean-zero convention): {psi:.10f}   (two eta values agree: {ewald_sc(eta=1.5):.10f})")
M_inf = psi + np.pi/6   # whole neutral cubic cells around the quon -> add Bethe (mean-inner-potential) term pi/6
print(f"Infinite cubic aether, his convention: M = {M_inf:.10f}")
x_inf = solve_x(-M_inf)
N_inf = (9/(8*x_inf**2))**3
print(f"r/d = {x_inf:.10f}   144 pi r/d = {144*np.pi*x_inf:.6f}   quon/electron volume ratio N = {N_inf:.3f}")

# ---------- Part 4: the integer step and comparison with measurement ----------
ALPHA_INV = mpf('137.035999177')
for N in [1841, 1843, 1845]:
    ai = 108*pi*(mpf(8)/N)**(mpf(1)/6)
    print(f"N={N}: alpha^-1 = {mp.nstr(ai,10)}  ({mp.nstr((ai/ALPHA_INV-1)*1e6,4)} ppm)")
spacing = float(108*pi*(mpf(8)/1843)**(mpf(1)/6)*(1-(mpf(1843)/1845)**(mpf(1)/6)))
print(f"spacing between neighbouring odd N in alpha^-1: {spacing:.5f}  ({spacing/137.036*1e6:.0f} ppm)")

# ---------- Part 5: sensitivity to modelling choices ----------
print("\nSensitivity of the pure-lattice result:")
for label, Mneg, cc in [("his model", -M_inf, 1/(4608*np.pi)),
                        ("no finite-size correction", -M_inf, 0.0),
                        ("spread quon with no void (1/6; inconsistent with his model)", -M_inf, 1/(6*4608*np.pi)),
                        ("Ewald mean-zero potential (no pi/6 term)", -psi, 1/(4608*np.pi))]:
    x = solve_x(Mneg, cc); Nq = (9/(8*x**2))**3
    Nodd = int(np.floor(Nq)); Nodd -= (Nodd % 2 == 0)
    ai = float(108*pi*(mpf(8)/Nodd)**(mpf(1)/6))
    print(f"  {label:58s} lattice alpha^-1 = {144*np.pi*x:9.4f}  N = {Nq:8.2f} -> {Nodd}  alpha^-1 = {ai:.4f}")
```

Output:

```text
h = 288*pi**2*e**2*r/(c*d)    =>  h c/(2 pi e^2) = 144*pi*r/d

N    his r/d        rebuilt r/d     rebuilt 144*pi*r/d
5    0.3028976690   0.3028877950    137.023210
10   0.3028807822   0.3028776183    137.018607
30   0.3028746524   0.3028742254    137.017072
60   nan   0.3028738852    137.016918
120  nan   0.3028737985    137.016878

Ewald site potential (mean-zero convention): -2.8372974795   (two eta values agree: -2.8372974795)
Infinite cubic aether, his convention: M = -2.3136987039
r/d = 0.3028737692   144 pi r/d = 137.016865   quon/electron volume ratio N = 1844.538
N=1841: alpha^-1 = 137.0607155  (180.4 ppm)
N=1843: alpha^-1 = 137.0359148  (-0.6154 ppm)
N=1845: alpha^-1 = 137.0111456  (-181.4 ppm)
spacing between neighbouring odd N in alpha^-1: 0.02477  (181 ppm)

Sensitivity of the pure-lattice result:
  his model                                                  lattice alpha^-1 =  137.0169  N =  1844.54 -> 1843  alpha^-1 = 137.0359
  no finite-size correction                                  lattice alpha^-1 =  137.2606  N =  1824.97 -> 1823  alpha^-1 = 137.2853
  spread quon with no void (1/6; inconsistent with his model) lattice alpha^-1 =  137.2202  N =  1828.20 -> 1827  alpha^-1 = 137.2352
  Ewald mean-zero potential (no pi/6 term)                   lattice alpha^-1 =  151.8546  N =   995.32 -> 995  alpha^-1 = 151.8628
```

### C.5 alpha_finite_size.py

The finite-size term in the α derivation (section 5.3): Aspden's term as the potential at the centre of the quon's void, the no-void and void treatments, the window of coefficients that keeps 1843, and the size of the second-order void effect.

```python
"""The finite-size correction in Aspden's fine-structure-constant derivation, examined in detail.

Setting (Tutorial Notes 7 and 8): a quon of charge e and radius b sits in a uniform background of
opposite charge, density sigma = e/d^3. Aspden adds  integral_0^b 4 pi sigma e x dx = 2 pi sigma e b^2
to the quon's energy. Each shell of background at radius x (charge 4 pi x^2 sigma dx) gives potential
4 pi sigma x dx at the centre, so his term is exactly  e x (potential at the centre of a spherical void
of radius b cut out of the background):  a point quon sitting in its own void.
Units below: e = 1, d = 1, energies in e^2/d.
"""
from mpmath import mp, mpf, pi, quad, findroot
mp.dps = 25

# ---------- 1. Three ways to model the quon's finite size (all relative to a point quon, no void) ----------
# Quon charge distribution: Aspden's Thomson model, charge inside radius r = e (r/b)^2  ->  dq = 2 r/b^2 dr
# Background potential inside a large background sphere of radius Rb (density -sigma):
#   no void:  phi(r) = -2 pi sigma (Rb^2 - r^2/3)            (curvature from the background itself)
#   void b:   phi(r) = -2 pi sigma (Rb^2 - b^2)  for r < b     (constant: no charge inside the cavity)
b, sigma, Rb = mpf(1), mpf(1), mpf(50)
dq = lambda r: 2*r/b**2
phi_novoid = lambda r: -2*pi*sigma*(Rb**2 - r**2/3)
phi_void   = lambda r: -2*pi*sigma*(Rb**2 - b**2)
ref = phi_novoid(0)                                            # point quon, no void
cases = {
  "point quon in its void (Aspden)":            phi_void(0) - ref,
  "spread quon, no void (our earlier 1/6)":     quad(lambda r: dq(r)*phi_novoid(r), [0, b]) - ref,
  "spread quon in its void (consistent)":       quad(lambda r: dq(r)*phi_void(r), [0, b]) - ref,
}
print("Finite-size correction in units of 2 pi sigma e b^2 (Aspden's term = 1):")
for k, v in cases.items():
    print(f"  {k:42s} {mp.nstr(v/(2*pi*sigma*b**2), 8)}")
print("  -> inside a spherical cavity the outside charge gives a constant potential, so any spherical")
print("     quon charge distribution has exactly the energy of a point quon at the centre.")

# ---------- 2. How tightly the coefficient F is pinned (F = 1 is Aspden's term) ----------
Mneg = mpf('2.8372974794806') - pi/6                         # exact lattice term, Aspden's cell convention
def lattice(F):
    x = findroot(lambda x: 8*pi*x**2 + F/(4608*pi)/x**4 - Mneg, mpf('0.303'))
    return x, 144*pi*x, (mpf(9)/(8*x**2))**3                 # r/d, pure-lattice 1/alpha, size ratio N
def odd_below(Nq):
    n = int(Nq); return n if n % 2 else n - 1
A_MEAS = mpf('137.035999177')
print("\nCoefficient F -> lattice 1/alpha, size ratio N, odd integer, final 1/alpha:")
for F in [mpf(1)/6, mpf('0.5'), mpf('0.9'), mpf('0.95'), mpf(1), mpf('1.05'), mpf('1.1'), mpf(2)]:
    x, a_lat, Nq = lattice(F); n = odd_below(Nq)
    a = 108*pi*(mpf(8)/n)**(mpf(1)/6)
    print(f"  F={mp.nstr(F,4):>6s}  lattice 1/alpha={mp.nstr(a_lat,9):>11s}  N={mp.nstr(Nq,7):>9s} -> {n}  1/alpha={mp.nstr(a,9)}  ({mp.nstr((a/A_MEAS-1)*1e6,4)} ppm)")
F_lo = findroot(lambda F: lattice(F)[2] - 1843, mpf('0.92'))   # N reaches 1843 exactly
F_hi = findroot(lambda F: lattice(F)[2] - 1845, mpf('1.02'))   # N reaches 1845
print(f"His rule selects 1843 (N in [1843, 1845)) for F from {mp.nstr(F_lo,5)} to {mp.nstr(F_hi,5)},"
      f" i.e. the term must be right to within {mp.nstr((F_lo-1)*100,3)}% / +{mp.nstr((F_hi-1)*100,3)}%")

# ---------- 3. Second-order effect: the voids in every cell ----------
# With voids, each site carries the quon plus its void (net site charge e/(1-v)), and the background
# density rises by the same factor to keep neutrality. Every term in the quon's energy (lattice,
# displacement, own void) is then the bare charge e times a potential proportional to the dressed site
# charge, so the zero-energy condition keeps its form. The void volume fraction v bounds any residual change:
x0, _, _ = lattice(mpf(1)); d_over_b = 96*pi*x0**2
v = 4*pi/3/d_over_b**3
print(f"\nvoid volume fraction per cell v = {mp.nstr(v,4)} (d/b = {mp.nstr(d_over_b,6)}); "
      f"if it entered the finite-size term alone, F would change by about {mp.nstr(2*v,3)}")
```

Output:

```text
Finite-size correction in units of 2 pi sigma e b^2 (Aspden's term = 1):
  point quon in its void (Aspden)            1.0
  spread quon, no void (our earlier 1/6)     0.16666667
  spread quon in its void (consistent)       1.0
  -> inside a spherical cavity the outside charge gives a constant potential, so any spherical
     quon charge distribution has exactly the energy of a point quon at the centre.

Coefficient F -> lattice 1/alpha, size ratio N, odd integer, final 1/alpha:
  F=0.1667  lattice 1/alpha= 137.220233  N= 1828.196 -> 1827  1/alpha=137.235205  (1454.0 ppm)
  F=   0.5  lattice 1/alpha= 137.139212  N= 1834.686 -> 1833  1/alpha=137.160233  (906.6 ppm)
  F=   0.9  lattice 1/alpha= 137.041414  N= 1842.556 -> 1841  1/alpha=137.060715  (180.4 ppm)
  F=  0.95  lattice 1/alpha= 137.029144  N= 1843.546 -> 1843  1/alpha=137.035915  (-0.6154 ppm)
  F=   1.0  lattice 1/alpha= 137.016865  N= 1844.538 -> 1843  1/alpha=137.035915  (-0.6154 ppm)
  F=  1.05  lattice 1/alpha= 137.004576  N= 1845.531 -> 1845  1/alpha=137.011146  (-181.4 ppm)
  F=   1.1  lattice 1/alpha= 136.992277  N= 1846.525 -> 1845  1/alpha=137.011146  (-181.4 ppm)
  F=   2.0  lattice 1/alpha= 136.769164  N= 1864.673 -> 1863  1/alpha=136.789622  (-1798.0 ppm)
His rule selects 1843 (N in [1843, 1845)) for F from 0.92241 to 1.0233, i.e. the term must be right to within -7.76% / +2.33%

void volume fraction per cell v = 0.0001978 (d/b = 27.6659); if it entered the finite-size term alone, F would change by about 0.000396
```

### C.6 coincidence.py

The chance-coincidence tests of section 11: each constant on its own under one null model (global and local estimates), and the joint probability of all four at once, Fisher-combined and career-wide for 10 and 30 attempts.

```python
"""How often would Aspden's own toolkit hit these constants by chance? (paper section 11, version 1.3)

Null model, applied the same way to every constant: the measured value is unrelated to the toolkit.
For each constant we build every formula of the kind Aspden used and ask how many would land within
his accuracy of the target.
  * global estimate: target placed at random within the range the toolkit's formulas span
        expected chance hits = (distinct formula values) x 2 eps / (log-range spanned)
  * local estimate:  uses the density of formula values right at the target (conservative: it treats
        the fact that the target sits where formulas pile up as given, not as part of the hit)
Corrections from the paper are in place: alpha with his finite-size term (exact in his model),
G with the 2 m_e ejected charge (section 7.5), deuteron with protons given their Thomson radius (section 8).
"""
import itertools, math
import numpy as np
from scipy.optimize import brentq

R  = 1836.15267343            # mp/me (CODATA 2022)
MU = 0.8574382311             # deuteron moment mu_d/mu_N (CODATA 2014)
N  = 1843                     # lattice integer, already fixed by alpha
s15 = math.sqrt(1.5)
def p_from(expected):         # chance of at least one hit, Poisson
    return 1 - math.exp(-expected)
def global_expect(values, target, eps):
    lv = np.unique(np.round(np.log(np.asarray(values)), 12))
    return len(lv)*2*eps/(lv.max() - lv.min())
def local_expect(values, target, eps, window):
    lv = np.log(np.asarray(values)); n = np.sum(np.abs(lv - math.log(target)) < window)
    return n*eps/window

results = {}

# ---------------- Test 1: proton/electron ratio from lattice-count formulas ----------------
C = sorted({2**i * 3**j for i in range(22) for j in range(14) if 2**i * 3**j <= 2e6})
A = [1, s15, s15 - 1, 1/(s15 - 1), math.sqrt(6) - 1.5, 1/(math.sqrt(6) - 1.5), 3 + s15,
     2**(1/3), 3**(1/4), 3**(1/3), 3**(7/12), 2/3, 1.5, 15/8, 8/15, 9/8, 8/9]
vals = np.exp(np.array([math.log(c) + a*math.log(math.pi) + (b/6)*math.log(N) + math.log(f)
               for c in C for a in range(-3, 4) for b in range(-12, 13) for f in A]))
eps = abs(944784*math.pi**2/N**(4/3)/(s15 - 1)/R - 1)
eg, el = global_expect(vals, R, eps), local_expect(vals, R, eps, 1e-2)
results['proton'] = (eps, p_from(eg), p_from(el))
print(f"[1] proton/electron ratio: {len(vals):,} formulas, Aspden error {eps*1e6:.3f} ppm")
print(f"    expected chance hits: global {eg:.4f}, local {el:.4f}")

# ---------------- Test 2: deuteron moment, refined (protons with Thomson radius 1/R) ----------------
def chain_deficit(pattern, start_sign, rp):
    rad = {'H': rp, 'L': 1.0}; x = [0.0]
    for i in range(1, len(pattern)):
        x.append(x[-1] + rad[pattern[i-1]] + rad[pattern[i]])
    s = [start_sign * (-1)**i for i in range(len(pattern))]
    inter = sum(s[i]*s[j]*1.5/(x[j] - x[i]) for i in range(len(pattern)) for j in range(i + 1, len(pattern)))
    return -(pattern.count('L') + inter), abs(sum(s))
def deuteron_family(rp):
    charged, neutral = set(), set()
    for n in range(2, 7):
        for pat in set(itertools.permutations('HH' + 'L'*(n - 2))):
            pat = ''.join(pat)
            if 'HH' in pat: continue
            d, q = chain_deficit(pat, 1, rp)
            (charged if q == 1 else neutral if q == 0 else set()).add(round(d, 9))
    out = []
    for dA, dC in itertools.combinations_with_replacement(sorted(charged), 2):
        for dB in sorted(neutral):
            for wA, wB, wC in itertools.product(range(1, 5), repeat=3):
                W = wA + wB + wC
                out.append((wA + wC)/W * 2/(2 - (wA*dA + wB*dB + wC*dC)/W/R))
    return np.array(out)
mus = deuteron_family(1/R)
eps = np.min(np.abs(mus/MU - 1))
eg, el = global_expect(mus, MU, eps), local_expect(mus, MU, eps, 1e-4)
results['deuteron'] = (eps, p_from(eg), p_from(el))
print(f"\n[2] deuteron moment (refined): {len(mus):,} combinations, best error {eps*1e6:.3f} ppm")
print(f"    expected chance hits: global {eg:.4f}, local {el:.4f}")

# ---------------- Test 3: alpha from the integer step ----------------
p_int = 2*0.615/181.0          # odd-integer grid of 108 pi (8/N)^(1/6) is spaced 181 ppm
p_lo = p_int*4*min(1, 65*181e-6/math.log(10))     # 65 structural variants, 4 rounding rules
p_hi = p_int*4*min(1, 650*181e-6/math.log(10))    # 650 structural variants
results['alpha'] = (0.615e-6, p_lo, p_hi)
print(f"\n[3] alpha: grid hit {p_int:.4f}; p(alpha) = {p_lo:.2e} (65 variants) to {p_hi:.2e} (650 variants)")

# ---------------- Test 4: G with the 2 m_e ejected charge ----------------
e_cgs, me = 4.80320471257e-10, 9.1093837139e-28
eme, G_codata = e_cgs/me, 6.67430
Q = 944784*math.pi**2/N**(4/3); P = Q/(s15 - 1); k = math.sqrt(6) - 1.5
def G_of(g): return (4*math.pi*eme/g**4/(108*math.pi)**3)**2*1e8
lattice_clusters = [1.0, 1.875, 2.0303300858899, 2.8125, 2.87467, 2.88058, 2.93209, 2.93831, 2.97342,
                    3.00201, 3.03, 3.03115, 3.07103, 3.09996, 3.12875, 3.13984, 3.18533, 3.19757,
                    3.22525, 3.25529, 3.29517, 3.3529]
post_hoc = [1.999264, 1.952665, 2.15625, 2.0, 4.0]   # every further cluster idea tried (sections 7.4-7.5)
taons = [3**(7/12)*P, 2*P*k] + [2*P*k - c for c in lattice_clusters + post_hoc]
Gs = []
for n in (1, 2, 3, 4):
    xs = brentq(lambda x: (1 + n/x**3) - 3*(1 + n*x), 0.3, 1.0)
    Gs += [G_of(T/xs) for T in taons]
Gs = np.array(Gs)
eps = abs(G_of((2*P*k - 2.0)/brentq(lambda x: 3*x**4 + x**3 - 1, 0.3, 1.0))/G_codata - 1)
eg34, eg150 = global_expect(Gs, G_codata, eps), global_expect(Gs, G_codata, 150e-6)
el = local_expect(Gs, G_codata, eps, 5e-3)
results['G'] = (eps, p_from(eg34), p_from(eg150), p_from(el))
print(f"\n[4] G with 2 m_e: {len(Gs)} chain variants (all ideas tried), error {eps*1e6:.1f} ppm")
print(f"    expected chance hits: global {eg34:.4f} (34 ppm); global {eg150:.4f} (150 ppm lab spread); local {el:.3f}")

# ---------------- Joint chance of all four at once ----------------
def fisher(x, k):             # probability that k independent uniform p-values multiply to <= x
    return x*sum((-math.log(x))**j/math.factorial(j) for j in range(k))
def career(thresholds, M):    # P(among M attempts, the 4 smallest p-values beat the 4 thresholds)
    t = sorted(thresholds); edges = [0.0] + t
    probs = [edges[i+1] - edges[i] for i in range(4)]; rest = 1 - t[-1]
    total = 0.0
    for n1 in range(M+1):
        for n2 in range(M+1-n1):
            for n3 in range(M+1-n1-n2):
                for n4 in range(M+1-n1-n2-n3):
                    c1, c2, c3, c4 = n1, n1+n2, n1+n2+n3, n1+n2+n3+n4
                    if c1 < 1 or c2 < 2 or c3 < 3 or c4 < 4: continue
                    r = M - c4
                    lp = (math.lgamma(M+1) - sum(math.lgamma(n+1) for n in (n1, n2, n3, n4, r))
                          + sum(n*math.log(p) for n, p in zip((n1, n2, n3, n4), probs) if n)
                          + (r*math.log(rest) if r else 0.0))
                    total += math.exp(lp)
    return total
pa, pp, pd, pg = results['alpha'], results['proton'], results['deuteron'], results['G']
scenarios = {
  "strict":   [pa[1], pp[1], pd[1], pg[1]],                                  # fewest alternatives, global null
  "central":  [math.sqrt(pa[1]*pa[2]), pp[2], math.sqrt(pd[1]*pd[2]), pg[2]],  # mid alternatives, G at lab spread
  "generous": [pa[2], min(1, 10*pp[2]), pd[2], pg[3]],                       # most alternatives, 10 target particles
}
print("\nScenario   alpha     proton    deuteron  G         | joint (all at once)  Fisher-combined  career M=10   M=30")
for name, ps in scenarios.items():
    x = math.prod(ps)
    print(f"{name:9s}  {ps[0]:.2e}  {ps[1]:.2e}  {ps[2]:.2e}  {ps[3]:.2e}  | {x:.2e}             {fisher(x,4):.2e}         "
          f"{career(ps,10):.2e}     {career(ps,30):.2e}")
```

Output:

```text
[1] proton/electron ratio: 464,100 formulas, Aspden error 0.194 ppm
    expected chance hits: global 0.0026, local 0.0055

[2] deuteron moment (refined): 7,680 combinations, best error 0.328 ppm
    expected chance hits: global 0.0035, local 0.6885

[3] alpha: grid hit 0.0068; p(alpha) = 1.39e-04 (65 variants) to 1.39e-03 (650 variants)

[4] G with 2 m_e: 116 chain variants (all ideas tried), error 33.5 ppm
    expected chance hits: global 0.0076 (34 ppm); global 0.0338 (150 ppm lab spread); local 0.195

Scenario   alpha     proton    deuteron  G         | joint (all at once)  Fisher-combined  career M=10   M=30
strict     1.39e-04  2.65e-03  3.47e-03  7.54e-03  | 9.61e-12             2.95e-08         1.94e-08     2.30e-06
central    4.39e-04  5.49e-03  4.16e-02  3.33e-02  | 3.33e-09             4.83e-06         7.04e-06     5.34e-04
generous   1.39e-03  5.49e-02  4.98e-01  1.77e-01  | 6.71e-06             2.45e-03         3.95e-03     3.24e-02
```

### C.7 environment_constants.py

The proton/electron ratio and Rydberg constant from Aspden's formulas, the step changes implied by his claim that N falls with energy or temperature, tests against white-dwarf, solar and quasar measurements, the charge-neutrality test of his 1983 explanation, the J₂ contribution to Mercury's perihelion, and the α³/2 lead (sections 6 and 9).

```python
"""Proton/electron mass ratio and Rydberg constant in Aspden's lattice theory, and his claim that the
lattice integer N falls in integer steps as energy or thermal activity rises ("The Fifth Question:
What is a Neutrino?"). Every constant then shifts in discrete steps; we compare one step with
measurements made in hot or distant environments.
Aspden's formulas (Phys. Lett. 41A, 423, 1972; Il Nuovo Cimento 30A, 235, 1975):
    1/alpha = 108 pi (8/N)^(1/6)
    mp/me   = (3/4) 108^3 pi^2 N^(-4/3) / (sqrt(3/2) - 1)
    Rydberg energy  hcR = (alpha^2/2) me c^2        (standard relation; follows from his alpha)
Spectral-line frequency scaling claimed by Aspden: f ~ N^(4/9) (Tutorial Note 10, optical, ~72 km/s per
unit N) and f ~ N^(1/9) (revised radio analysis in the Q&A, ~18 km/s per unit N).
"""
from mpmath import mp, mpf, pi, sqrt
mp.dps = 25
C_KMS = mpf('299792.458')
ALPHA_INV, MU, RY_EV, ME_EV = mpf('137.035999177'), mpf('1836.152673426'), mpf('13.605693122990'), mpf('510998.95069')
ALPHA_U, MU_U, RY_U = mpf('0.000000021'), mpf('0.000000032'), mpf('0.000000000015')

ainv = lambda N: 108*pi*(mpf(8)/N)**(mpf(1)/6)
mu   = lambda N: mpf(3)/4*108**3*pi**2*mpf(N)**(-mpf(4)/3)/(sqrt(mpf(3)/2) - 1)
ry   = lambda N: ME_EV/(2*ainv(N)**2)

N0 = 1843
print("1. Aspden's values (N = 1843) versus CODATA 2022")
for name, val, meas, u in [("1/alpha", ainv(N0), ALPHA_INV, ALPHA_U),
                           ("mp/me", mu(N0), MU, MU_U),
                           ("Rydberg energy hcR (eV)", ry(N0), RY_EV, RY_U)]:
    print(f"   {name:24s} {mp.nstr(val,13):>18s}  measured {mp.nstr(meas,13):>18s}  "
          f"{mp.nstr((val/meas-1)*1e6,4):>8s} ppm  ({mp.nstr((val-meas)/u,3)} sigma)")

print("\n2. Shift per step if N falls with energy or temperature (relative change)")
steps = {}
for dN in (1, 2):
    N1 = N0 - dN
    d_alpha = ainv(N0)/ainv(N1) - 1          # alpha = 1/ainv
    d_mu    = mu(N1)/mu(N0) - 1
    d_ry    = ry(N1)/ry(N0) - 1
    f49     = (mpf(N1)/N0)**(mpf(4)/9) - 1
    f19     = (mpf(N1)/N0)**(mpf(1)/9) - 1
    steps[dN] = (d_alpha, d_mu, d_ry, f49, f19)
    print(f"   N {N0} -> {N1}: d(alpha)/alpha = {mp.nstr(d_alpha*1e6,4)} ppm, d(mu)/mu = {mp.nstr(d_mu*1e6,4)} ppm, "
          f"d(R)/R = {mp.nstr(d_ry*1e6,4)} ppm, line shift {mp.nstr(-f49*C_KMS,4)} km/s (N^4/9) or {mp.nstr(-f19*C_KMS,4)} km/s (N^1/9)")

print("\n3. One step (N 1843 -> 1842) against measurements in hot or distant environments")
d_alpha, d_mu, d_ry, f49, f19 = steps[1]
tests = [
  ("White dwarf GD133, H2 at 11,800 K, mu", d_mu, mpf('-2.7e-5'), mpf('4.7e-5')),
  ("White dwarf G29-38, H2 at 14,500 K, mu", d_mu, mpf('-5.8e-5'), mpf('3.8e-5')),
  ("White dwarf G191-B2B, Fe V, alpha", d_alpha, mpf('4.2e-5'), mpf('1.6e-5')),
  ("White dwarf G191-B2B, Ni V, alpha", d_alpha, mpf('-6.1e-5'), mpf('5.8e-5')),
  ("Quasar absorber z = 0.89 (methanol), mu", d_mu, mpf('-1.0e-7'), sqrt(mpf('0.8e-7')**2 + mpf('1.0e-7')**2)),
  ("Quasar absorber z = 1.15 (ESPRESSO), alpha", d_alpha, mpf('1.3e-6'), sqrt(mpf('1.3e-6')**2 + mpf('0.4e-6')**2)),
]
for name, pred, meas, u in tests:
    print(f"   {name:44s} predicted {mp.nstr(pred*1e6,4):>8s} ppm   measured {mp.nstr(meas*1e6,3):>6s} +/- {mp.nstr(u*1e6,2):>4s} ppm   "
          f"-> {mp.nstr(abs(pred-meas)/u,3)} sigma")
# Sun: line positions vs lab, after the gravitational redshift (measured 638 +/- 6 m/s, GR 633.1 m/s)
resid, u = mpf('638') - mpf('633.1'), mpf('6')
for label, f in (("N^4/9", f49), ("N^1/9", f19)):
    shift = -f*C_KMS*1000
    print(f"   Sun, 5,800 K photosphere, line shift ({label}): predicted {mp.nstr(shift,5)} m/s, "
          f"residual measured {mp.nstr(resid,2)} +/- {u} m/s -> {mp.nstr(abs(shift-resid)/u,4)} sigma")

print("\n4. Aspden's 1983 explanation of the mp/me residual: proton and electron charges differ by 1.07e-7")
print("   Measured neutrality of matter: |q_p + q_e|/e = (-0.1 +/- 1.1) x 10^-21  ->  excluded by a factor of about 10^14")

print("\n5. Mercury: perihelion advance from the Sun's measured oblateness, J2 = (2.4 +/- 0.2) x 10^-7")
J2, R_sun, a, e, P_days = mpf('2.4e-7'), mpf('6.957e8'), mpf('5.7909e10'), mpf('0.205630'), mpf('87.9691')
p = a*(1 - e**2)
per_century = 3*pi*J2*(R_sun/p)**2 * (mpf('36525')/P_days) * 206264.806
print(f"   J2 contribution = {mp.nstr(per_century,3)} arcsec/century, against the 42.98 arcsec/century relativistic term")

print("\n6. A numerical lead: simple alpha-power corrections to the mp/me residual (not motivated by the theory)")
a = 1/ALPHA_INV
need = MU/mu(N0) - 1
coefs = {'1': 1, '1/2': mpf(1)/2, '2': 2, '3/2': mpf(3)/2, '2/3': mpf(2)/3, '1/3': mpf(1)/3, '3': 3, '1/4': mpf(1)/4,
         '4': 4, 'pi': pi, '1/pi': 1/pi, '1/(2pi)': 1/(2*pi), '2pi': 2*pi, 'pi/2': pi/2, '1/(4pi)': 1/(4*pi)}
cands = sorted((abs(c*a**k/need - 1), f"{cn} x alpha^{k}", c*a**k) for k in range(1, 5) for cn, c in coefs.items())
err, name, v = cands[0]
corrected = mu(N0)*(1 + v)
import math
logs = [math.log(float(x[2])) for x in cands]
print(f"   needed correction {mp.nstr(need,6)}; best of {len(cands)} candidates: {name} = {mp.nstr(v,6)} "
      f"({mp.nstr(err*100,3)}% off)")
print(f"   mp/me x (1 + {name}) = {mp.nstr(corrected,13)} vs {MU}: {mp.nstr((corrected/MU-1)*1e9,3)} ppb ({mp.nstr((corrected-MU)/MU_U,3)} sigma)")
print(f"   chance that the best of {len(cands)} such candidates lands this close: "
      f"{len(cands)*2*float(err)/(max(logs)-min(logs)):.4f}")
```

Output:

```text
1. Aspden's values (N = 1843) versus CODATA 2022
   1/alpha                      137.0359148472  measured      137.035999177   -0.6154 ppm  (-4.02e+3 sigma)
   mp/me                        1836.152316484  measured     1836.152673426   -0.1944 ppm  (-1.12e+4 sigma)
   Rydberg energy hcR (eV)      13.60570986838  measured     13.60569312299     1.231 ppm  (1.12e+6 sigma)

2. Shift per step if N falls with energy or temperature (relative change)
   N 1843 -> 1842: d(alpha)/alpha = -90.45 ppm, d(mu)/mu = 723.9 ppm, d(R)/R = -180.9 ppm, line shift 72.31 km/s (N^4/9) or 18.08 km/s (N^1/9)
   N 1843 -> 1841: d(alpha)/alpha = -180.9 ppm, d(mu)/mu = 1449.0 ppm, d(R)/R = -361.9 ppm, line shift 144.6 km/s (N^4/9) or 36.17 km/s (N^1/9)

3. One step (N 1843 -> 1842) against measurements in hot or distant environments
   White dwarf GD133, H2 at 11,800 K, mu        predicted    723.9 ppm   measured  -27.0 +/- 47.0 ppm   -> 16.0 sigma
   White dwarf G29-38, H2 at 14,500 K, mu       predicted    723.9 ppm   measured  -58.0 +/- 38.0 ppm   -> 20.6 sigma
   White dwarf G191-B2B, Fe V, alpha            predicted   -90.45 ppm   measured   42.0 +/- 16.0 ppm   -> 8.28 sigma
   White dwarf G191-B2B, Ni V, alpha            predicted   -90.45 ppm   measured  -61.0 +/- 58.0 ppm   -> 0.508 sigma
   Quasar absorber z = 0.89 (methanol), mu      predicted    723.9 ppm   measured   -0.1 +/- 0.13 ppm   -> 5.65e+3 sigma
   Quasar absorber z = 1.15 (ESPRESSO), alpha   predicted   -90.45 ppm   measured    1.3 +/-  1.4 ppm   -> 67.5 sigma
   Sun, 5,800 K photosphere, line shift (N^4/9): predicted 72307.0 m/s, residual measured 4.9 +/- 6.0 m/s -> 1.205e+4 sigma
   Sun, 5,800 K photosphere, line shift (N^1/9): predicted 18078.0 m/s, residual measured 4.9 +/- 6.0 m/s -> 3012.0 sigma

4. Aspden's 1983 explanation of the mp/me residual: proton and electron charges differ by 1.07e-7
   Measured neutrality of matter: |q_p + q_e|/e = (-0.1 +/- 1.1) x 10^-21  ->  excluded by a factor of about 10^14

5. Mercury: perihelion advance from the Sun's measured oblateness, J2 = (2.4 +/- 0.2) x 10^-7
   J2 contribution = 0.0305 arcsec/century, against the 42.98 arcsec/century relativistic term

6. A numerical lead: simple alpha-power corrections to the mp/me residual (not motivated by the theory)
   needed correction 1.94397e-7; best of 60 candidates: 1/2 x alpha^3 = 1.94297e-7 (0.0514% off)
   mp/me x (1 + 1/2 x alpha^3) = 1836.152673243 vs 1836.152673426: -0.0999 ppb (-5.73 sigma)
   chance that the best of 60 such candidates lands this close: 0.0032
```

### C.8 cavity_1983.py

Aspden's 1983 cavity-resonant electron papers (sections 9.3–9.5): the electron and muon anomaly formula against 1979–83 and 2023–25 data, its series against QED, the "absolute gravitational potential" by the g-factor and 3 K routes, the galactic, Gaia and annual-modulation tests, and the Lamb-shift formula for hydrogen and He⁺.

```python
"""Aspden's 1983 cavity-resonant electron papers, checked against current data.

  1983c  Lett. Nuovo Cimento 36, 364: anomalous g-factor and the hydrogen 2S-2P Lamb shift
         a = 1/(hc/e^2 - 1 +/- 4/sqrt3)       (+ electron, - muon; hc/e^2 = 2 pi / alpha)
         dv = (4 pi/15) alpha^3 R c (1 + 2 alpha/(sqrt3 pi)) / (1 + 2 alpha) * (1 - m/M)       eq. (18)
  1983d  Lett. Nuovo Cimento 37, 169: "absolute gravitational potential" phi at the Earth's surface
         g/2 = (1 + phi/(2c^2)) (1 + a)       eq. (3)
         phi m* = k T  (3 K background, m* = 0.04 m_e)    eq. (5)
CGS units for phi (cm^2/s^2), as in the paper.
"""
from mpmath import mp, mpf, pi, sqrt
mp.dps = 30

ALPHA_INV = {  # alpha^-1 from sources independent of the electron g-factor (except CODATA, which mixes)
    "Williams-Olsen 1979 (Aspden's input)": mpf('137.035963'),
    "Rb atom recoil 2020":                  mpf('137.035999206'),
    "Cs atom recoil 2018":                  mpf('137.035999046'),
    "CODATA 2022":                          mpf('137.035999177'),
    "Aspden's own lattice value":           mpf('137.0359148'),
}
AE_1979, AE_2023, AE_2023_U = mpf('0.001159652200'), mpf('0.00115965218059'), mpf('0.00000000000013')
AMU_1979, AMU_2025, AMU_2025_U = mpf('0.001165924'), mpf('0.001165920705'), mpf('0.000000000147')
C = mpf('2.99792458e10')

def a_aspden(ainv, sign=+1):
    return 1/(2*pi*ainv - 1 + sign*4/sqrt(3))

print("1. Anomalous moments from 1/(2pi/alpha - 1 +/- 4/sqrt3)")
for label, ainv in ALPHA_INV.items():
    ae, am = a_aspden(ainv, +1), a_aspden(ainv, -1)
    print(f"   {label:38s} a_e = {mp.nstr(ae,12)} ({mp.nstr((ae/AE_2023-1)*1e6,3):>6s} ppm vs 2023)   "
          f"a_mu = {mp.nstr(am,10)} ({mp.nstr((am/AMU_2025-1)*1e6,3)} ppm, {mp.nstr((am-AMU_2025)/AMU_2025_U,3)} sigma vs Fermilab 2025)")
print(f"   1979-83 data: a_e {AE_1979}, a_mu {AMU_1979};  2023-25 data: a_e {AE_2023}({AE_2023_U}), a_mu {AMU_2025}({AMU_2025_U})")
am83 = a_aspden(mpf('137.035963'), -1)
print(f"   muon in 1983: Aspden {mp.nstr(am83,9)} vs CERN 1979 0.001165924(8.5e-9): {mp.nstr((am83-AMU_1979)/mpf('8.5e-9'),3)} sigma")
ainv = ALPHA_INV["CODATA 2022"]
print(f"   muon minus electron: Aspden {mp.nstr((a_aspden(ainv,-1)-a_aspden(ainv,+1))*1e6,5)} x 10^-6, "
      f"measured {mp.nstr((AMU_2025-AE_2023)*1e6,5)} x 10^-6")

# Series in (alpha/pi): Aspden's closed form versus QED's mass-independent coefficients
x = mpf(1)/2   # a = x/(1 + k x) with x = alpha/(2 pi)  ->  coefficients of (alpha/pi)^n
k = 4/sqrt(3) - 1
asp = [x*(-k*x)**n for n in range(4)]
qed = [mpf('0.5'), mpf('-0.328478965579'), mpf('1.181241456587'), mpf('-1.912245764926')]
print("   series coefficients of (alpha/pi)^n, n = 1..4:  Aspden", [mp.nstr(c,6) for c in asp], " QED", [mp.nstr(c,7) for c in qed])

# QED prediction with alpha(Rb): universal terms + mass-dependent, hadronic and weak (approx 4.47e-12)
apr = 1/(ALPHA_INV["Rb atom recoil 2020"]*pi)
a_qed = sum(c*apr**(n+1) for n, c in enumerate(qed)) + mpf('6.7')*apr**5 + mpf('4.47e-12')
print(f"   QED with alpha(Rb): a_e = {mp.nstr(a_qed,13)}, minus measured = {mp.nstr((a_qed-AE_2023)*1e12,3)} x 10^-12")
print(f"   Aspden with alpha(Rb): minus measured = {mp.nstr((a_aspden(ALPHA_INV['Rb atom recoil 2020'])-AE_2023)*1e12,4)} x 10^-12")

print("\n2. 'Absolute gravitational potential' phi from eq. (3): phi = 2c^2 [(1+a_meas)/(1+a_Aspden) - 1]")
phi_vals = {}
for (lab_a, ae) in (("1979 g-factor", AE_1979), ("2023 g-factor", AE_2023)):
    for lab, ainv in ALPHA_INV.items():
        if lab == "CODATA 2022": continue
        phi = 2*C**2*((1 + ae)/(1 + a_aspden(ainv)) - 1)
        phi_vals[(lab_a, lab)] = phi
        print(f"   {lab_a}, alpha {lab:38s} phi = {mp.nstr(phi/1e12,4):>7s} x 10^12 cm^2/s^2")
GM_SUN, AU, GM_E, R_E = mpf('1.32712440018e26'), mpf('1.495978707e13'), mpf('3.986004418e20'), mpf('6.371e8')
phi_ss = GM_SUN/AU + GM_E/R_E
print(f"   solar-system potential at the Earth's surface: {mp.nstr(phi_ss/1e12,4)} x 10^12 (Aspden: 9.49)")
KB, ME = mpf('1.380649e-16'), mpf('9.1093837139e-28')
for T, ms, lab in ((mpf('2.7'), mpf('0.04'), "Aspden 1983: T = 2.7 K, m* = 0.04 m_e"),
                   (mpf('2.72548'), mpf('0.04'), "T = 2.72548 K (COBE/FIRAS), m* = 0.04 m_e"),
                   (mpf('2.72548'), 1/mpf('24.52'), "T = 2.72548 K, m* = m_e/24.52 (his lattice particle)")):
    print(f"   3 K route, {lab:52s} phi = {mp.nstr(KB*T/(ms*ME)/1e12,4)} x 10^12")
v_c = mpf('2.30e7')
print(f"   Milky Way: Sun orbits at ~230 km/s, so |phi_galaxy| > v_c^2 = {mp.nstr(v_c**2/1e12,3)} x 10^12 "
      f"= {mp.nstr(v_c**2/phi_ss,3)} x the solar-system value")
acc_expected = (mpf('2.30e5'))**2/(mpf('8.2')*mpf('3.0857e19'))
print(f"   expected pull toward the galactic centre v^2/R0 = {mp.nstr(acc_expected*1e10,3)} x 10^-10 m/s^2; "
      f"Gaia EDR3 measured 2.32 +/- 0.16 x 10^-10 m/s^2 toward the galactic centre")
dphi = GM_SUN/AU*mpf('0.0167')
print(f"   annual change of phi from Earth's eccentricity: +/- {mp.nstr(dphi/1e12,3)} x 10^12 -> g/2 changes "
      f"+/- {mp.nstr(dphi/(2*C**2),3)}, versus the 2023 uncertainty 1.3e-13 ({mp.nstr(dphi/(2*C**2)/mpf('1.3e-13'),3)} x)")
print(f"   QED leaves no room: |a_QED - a_meas| ~ 1e-12 -> phi/(2c^2) < ~1e-12 -> phi < {mp.nstr(2*C**2*mpf('1e-12')/1e12,2)} x 10^12")

print("\n3. Lamb shift, hydrogen 2S1/2-2P1/2, eq. (18)")
def lamb(ainv, Rinf_cm, c, mM, full=True):
    a = 1/ainv
    base = 4*pi/15*a**3*Rinf_cm*c
    return base*(1 + 2*a/(sqrt(3)*pi))/(1 + 2*a)*(1 - mM) if full else base
for lab, ainv, R, c, mM in (("Aspden's inputs (1983)", mpf('137.036'), mpf('109737'), mpf('2.99793e10'), 1/mpf(1836)),
                            ("CODATA 2022 inputs", mpf('137.035999177'), mpf('109737.31568157'), C, 1/mpf('1836.152673426'))):
    print(f"   {lab:24s} eq.(17) {mp.nstr(lamb(ainv,R,c,mM,False)/1e6,7)} MHz;  eq.(18) {mp.nstr(lamb(ainv,R,c,mM)/1e6,8)} MHz")
L_new = lamb(mpf('137.035999177'), mpf('109737.31568157'), C, 1/mpf('1836.152673426'))/1e6
for lab, v, u in (("Lundeen & Pipkin 1981", mpf('1057.845'), mpf('0.009')), ("Bezginov et al. 2019", mpf('1057.8298'), mpf('0.0032'))):
    print(f"   vs {lab:22s} {v} +/- {u} MHz: difference {mp.nstr((L_new-v)*1000,4)} kHz = {mp.nstr((L_new-v)/u,3)} sigma")
print(f"   the two correction factors move eq.(17) by {mp.nstr((lamb(mpf('137.036'),mpf('109737'),mpf('2.99793e10'),1/mpf(1836))/lamb(mpf('137.036'),mpf('109737'),mpf('2.99793e10'),1/mpf(1836),False)-1)*100,3)} %")
print(f"   step (13) uses dE = 2 hcR dn0 / n0^3 with n0 = 1; Bohr-Sommerfeld gives 2 hcR dn / n^3 with n = 2 "
      f"-> 8x smaller: {mp.nstr(L_new/8,5)} MHz")
# He+ (Z = 2): the orbital angular velocity w scales Z^2 and the Rydberg term Z^2 -> Z^4
a = 1/mpf('137.035999177')
heplus = 16*4*pi/15*a**3*mpf('109737.31568157')*C*(1 + 2*a/(sqrt(3)*pi))*(1 - 1/mpf('7294.29954'))/1e6
print(f"   He+ (Z = 2), same formula scaled Z^4: {mp.nstr(heplus/(1+2*a),6)} MHz (with 1+2a) or "
      f"{mp.nstr(heplus/(1+4*a),6)} MHz (with 1+2Za); measured 14041.9 +/- 1.5 MHz")
```

Output:

```text
1. Anomalous moments from 1/(2pi/alpha - 1 +/- 4/sqrt3)
   Williams-Olsen 1979 (Aspden's input)   a_e = 0.00115964650448 ( -4.89 ppm vs 2023)   a_mu = 0.001165891225 (-25.3 ppm, -201.0 sigma vs Fermilab 2025)
   Rb atom recoil 2020                    a_e = 0.00115964619856 ( -5.16 ppm vs 2023)   a_mu = 0.001165890916 (-25.5 ppm, -203.0 sigma vs Fermilab 2025)
   Cs atom recoil 2018                    a_e = 0.00115964619991 ( -5.16 ppm vs 2023)   a_mu = 0.001165890917 (-25.5 ppm, -203.0 sigma vs Fermilab 2025)
   CODATA 2022                            a_e = 0.0011596461988 ( -5.16 ppm vs 2023)   a_mu = 0.001165890916 (-25.5 ppm, -203.0 sigma vs Fermilab 2025)
   Aspden's own lattice value             a_e = 0.00115964691175 ( -4.54 ppm vs 2023)   a_mu = 0.001165891637 (-24.9 ppm, -198.0 sigma vs Fermilab 2025)
   1979-83 data: a_e 0.0011596522, a_mu 0.001165924;  2023-25 data: a_e 0.00115965218059(1.3e-13), a_mu 0.001165920705(1.47e-10)
   muon in 1983: Aspden 0.00116589123 vs CERN 1979 0.001165924(8.5e-9): -3.86 sigma
   muon minus electron: Aspden 6.2447 x 10^-6, measured 6.2685 x 10^-6
   series coefficients of (alpha/pi)^n, n = 1..4:  Aspden ['0.5', '-0.32735', '0.214316', '-0.140313']  QED ['0.5', '-0.328479', '1.181241', '-1.912246']
   QED with alpha(Rb): a_e = 0.001159652180251, minus measured = -0.339 x 10^-12
   Aspden with alpha(Rb): minus measured = -5982.0 x 10^-12

2. 'Absolute gravitational potential' phi from eq. (3): phi = 2c^2 [(1+a_meas)/(1+a_Aspden) - 1]
   1979 g-factor, alpha Williams-Olsen 1979 (Aspden's input)   phi =   10.23 x 10^12 cm^2/s^2
   1979 g-factor, alpha Rb atom recoil 2020                    phi =   10.78 x 10^12 cm^2/s^2
   1979 g-factor, alpha Cs atom recoil 2018                    phi =   10.77 x 10^12 cm^2/s^2
   1979 g-factor, alpha Aspden's own lattice value             phi =   9.495 x 10^12 cm^2/s^2
   2023 g-factor, alpha Williams-Olsen 1979 (Aspden's input)   phi =   10.19 x 10^12 cm^2/s^2
   2023 g-factor, alpha Rb atom recoil 2020                    phi =   10.74 x 10^12 cm^2/s^2
   2023 g-factor, alpha Cs atom recoil 2018                    phi =   10.74 x 10^12 cm^2/s^2
   2023 g-factor, alpha Aspden's own lattice value             phi =    9.46 x 10^12 cm^2/s^2
   solar-system potential at the Earth's surface: 9.497 x 10^12 (Aspden: 9.49)
   3 K route, Aspden 1983: T = 2.7 K, m* = 0.04 m_e                phi = 10.23 x 10^12
   3 K route, T = 2.72548 K (COBE/FIRAS), m* = 0.04 m_e            phi = 10.33 x 10^12
   3 K route, T = 2.72548 K, m* = m_e/24.52 (his lattice particle) phi = 10.13 x 10^12
   Milky Way: Sun orbits at ~230 km/s, so |phi_galaxy| > v_c^2 = 529.0 x 10^12 = 55.7 x the solar-system value
   expected pull toward the galactic centre v^2/R0 = 2.09 x 10^-10 m/s^2; Gaia EDR3 measured 2.32 +/- 0.16 x 10^-10 m/s^2 toward the galactic centre
   annual change of phi from Earth's eccentricity: +/- 0.148 x 10^12 -> g/2 changes +/- 8.24e-11, versus the 2023 uncertainty 1.3e-13 (634.0 x)
   QED leaves no room: |a_QED - a_meas| ~ 1e-12 -> phi/(2c^2) < ~1e-12 -> phi < 0.0018 x 10^12

3. Lamb shift, hydrogen 2S1/2-2P1/2, eq. (18)
   Aspden's inputs (1983)   eq.(17) 1070.999 MHz;  eq.(18) 1057.8479 MHz
   CODATA 2022 inputs       eq.(17) 1071.0 MHz;  eq.(18) 1057.8491 MHz
   vs Lundeen & Pipkin 1981  1057.845 +/- 0.009 MHz: difference 4.138 kHz = 0.46 sigma
   vs Bezginov et al. 2019   1057.8298 +/- 0.0032 MHz: difference 19.34 kHz = 6.04 sigma
   the two correction factors move eq.(17) by -1.23 %
   step (13) uses dE = 2 hcR dn0 / n0^3 with n0 = 1; Bohr-Sommerfeld gives 2 hcR dn / n^3 with n = 2 -> 8x smaller: 132.23 MHz
   He+ (Z = 2), same formula scaled Z^4: 16932.5 MHz (with 1+2a) or 16692.4 MHz (with 1+2Za); measured 14041.9 +/- 1.5 MHz
```

### C.9 mercury_aether.py

The 1969 aether-sphere account of Mercury's perihelion (section 9.2): the lattice density from his inputs and today's, an orbit integration that fixes the sign of the effect, predictions for six planets with the ephemeris limits, the double pulsar, and the share of the advance that special relativity alone supplies.

```python
"""Aspden's aether explanation of Mercury's perihelion (Physics Without Einstein, 1969, ch. 5, pp. 84-86).

Each planet carries a sphere of 'space-time lattice' (radius R, mass M). Moving with the planet, the lattice sheds
substance that streams backward, so the lattice+substance pair carries net angular momentum -(2/5) M R^2 w
about the Sun (w = orbital angular velocity). He conserves H - dH for the planet (per unit planet mass P):
    (r^2 - k) dtheta/dt = const,   k = (2/5)(M/P) R^2                       (his 5.7 and the text after 5.8)
and states the perihelion advance per revolution as  (8 pi/5)(M/P)(R/X)^2       (5.9)
He fits Mercury with R = 1.1 x planet radius and a 38"/century anomaly, getting a lattice density of ~150 g/cc;
chapter 6 then derives 144 g/cc from the lattice spacing.
"""
import math
import numpy as np
from scipy.integrate import solve_ivp

ARCSEC = math.pi/(180*3600)
def density_needed(anom_arcsec_cy, P_g, R_cm, X_cm, period_d, boundary=1.1):
    per_rev = anom_arcsec_cy*ARCSEC/(36525/period_d)
    M_over_P = per_rev*5/(8*math.pi)*(X_cm/(boundary*R_cm))**2
    return M_over_P*P_g/(4/3*math.pi*(boundary*R_cm)**3)

print("1. Mercury: lattice density implied by (5.9)")
print(f"   Aspden's inputs (38\"/cy, P 3.27e26 g, X 5.7e12 cm, R 2.495e8 cm, 88 d): "
      f"{density_needed(38, 3.27e26, 2.495e8, 5.7e12, 88):.1f} g/cc (he wrote 'about 150'; ch. 6 lattice gives 144)")
print(f"   today's inputs (42.98\"/cy, P 3.3011e26 g, a 5.7909e12 cm, R 2.4397e8 cm, 87.969 d): "
      f"{density_needed(42.98, 3.3011e26, 2.4397e8, 5.7909e12, 87.969):.1f} g/cc")
# boundary needed to keep 144 g/cc with today's anomaly: density ~ boundary^-5
b = 1.1*(density_needed(42.98, 3.3011e26, 2.4397e8, 5.7909e12, 87.969)/144)**0.2
print(f"   to keep 144 g/cc the lattice boundary must sit at {b:.4f} x Mercury's radius")
print("   the 38\"/cy rested on Dicke's 1967 solar oblateness; helioseismology gives J2 = 2.2e-7, worth only 0.03\"/cy")

print("\n2. Sign check: integrate (r^2 - k) dtheta/dt = L with Newtonian radial force")
def precession(k, e=0.2, GM=1.0, a=1.0, n_orbits=3):
    rp = a*(1 - e); vp = math.sqrt(GM*(1 + e)/rp)
    L = (rp**2 - k)*vp/rp
    def f(t, y):
        r, rd, th = y
        thd = L/(r**2 - k)
        return [rd, r*thd**2 - GM/r**2, thd]
    def peri(t, y): return y[1]
    peri.direction = 1          # radial velocity crosses zero going up = perihelion
    T = 2*math.pi*math.sqrt(a**3/GM)
    sol = solve_ivp(f, [0, n_orbits*T*1.05], [rp, 0.0, 0.0], events=peri, rtol=1e-12, atol=1e-14)
    th = sol.y_events[0][:, 2]
    return (th[1] - th[0]) - 2*math.pi
for k in (1e-4, 1e-3):
    d = precession(k)
    print(f"   k/a^2 = {k:g}: perihelion moves {d:+.3e} rad per orbit; (5.9) magnitude 4 pi k/a^2 = {4*math.pi*k:.3e}"
          f"  -> {'ADVANCE' if d > 0 else 'REGRESSION (backward)'}")

print("\n3. Same mechanism, same 144 g/cc, applied to the other planets (lattice boundary 1.1 x radius)")
GM_SUN, C = 1.32712440018e20, 299792458.0
planets = {  # mass g, radius cm, semi-major axis cm, eccentricity, period d
    "Mercury": (3.3011e26, 2.4397e8, 5.7909e12, 0.2056, 87.969),
    "Venus":   (4.8675e27, 6.0518e8, 1.08209e13, 0.0068, 224.701),
    "Earth":   (5.9722e27, 6.371e8, 1.495979e13, 0.0167, 365.256),
    "Mars":    (6.4171e26, 3.3895e8, 2.27939e13, 0.0934, 686.980),
    "Jupiter": (1.89813e30, 6.9911e9, 7.78570e13, 0.0489, 4332.59),
    "Saturn":  (5.6834e29, 5.8232e9, 1.433530e14, 0.0565, 10759.22),
}
sigma_epm = {"Mercury": 0.008, "Venus": 0.315, "Earth": 0.033, "Mars": 0.003, "Jupiter": 33.9, "Saturn": 0.067}  # mas/cy, x10-50 realistic
print(f"   {'planet':8s} {'GR \"/cy':>9s} {'Aspden \"/cy':>13s} {'ratio':>9s}   boundary needed for GR value")
for name, (P, R, a, e, Pd) in planets.items():
    revs = 36525/Pd
    gr = 6*math.pi*GM_SUN/(C**2*a/100*(1 - e**2))*revs/ARCSEC
    M = 144*4/3*math.pi*(1.1*R)**3
    asp = 8*math.pi/5*(M/P)*(1.1*R/a)**2*revs/ARCSEC
    need = 1.1*(gr/asp)**0.2
    print(f"   {name:8s} {gr:9.3f} {asp:13.4g} {asp/gr:9.3g}   {need:.4f} x radius")
print("   ephemeris (EPM2017) formal limits on any extra perihelion motion: "
      + ", ".join(f"{k} {v} mas/cy" for k, v in sigma_epm.items()) + " (realistic: x10-50)")

print("\n4. Double pulsar J0737-3039A/B: neutron stars, radius ~12 km, mean density ~4e14 g/cc")
P, R = 1.338*1.989e33, 1.2e6
M = 144*4/3*math.pi*(1.1*R)**3
a_orb = 8.79e10   # cm, relative orbit
Pb_d = 0.10225
per_rev = 8*math.pi/5*(M/P)*(1.1*R/a_orb)**2
print(f"   M_lattice/P = {M/P:.2e}; predicted periastron advance {per_rev*(365.25/Pb_d)*180/math.pi:.2e} deg/yr; measured 16.899 deg/yr")

print("\n5. Special relativity alone (Sommerfeld 1916, same calculation as hydrogen fine structure)")
print(f"   Mercury: GR 6 pi GM/(c^2 p) per orbit; relativistic mass alone gives pi GM/(c^2 p) -> {42.98/6:.2f}\"/cy of the 42.98\"/cy")
```

Output:

```text
1. Mercury: lattice density implied by (5.9)
   Aspden's inputs (38"/cy, P 3.27e26 g, X 5.7e12 cm, R 2.495e8 cm, 88 d): 143.8 g/cc (he wrote 'about 150'; ch. 6 lattice gives 144)
   today's inputs (42.98"/cy, P 3.3011e26 g, a 5.7909e12 cm, R 2.4397e8 cm, 87.969 d): 189.6 g/cc
   to keep 144 g/cc the lattice boundary must sit at 1.1622 x Mercury's radius
   the 38"/cy rested on Dicke's 1967 solar oblateness; helioseismology gives J2 = 2.2e-7, worth only 0.03"/cy

2. Sign check: integrate (r^2 - k) dtheta/dt = L with Newtonian radial force
   k/a^2 = 0.0001: perihelion moves -1.370e-03 rad per orbit; (5.9) magnitude 4 pi k/a^2 = 1.257e-03  -> REGRESSION (backward)
   k/a^2 = 0.001: perihelion moves -1.370e-02 rad per orbit; (5.9) magnitude 4 pi k/a^2 = 1.257e-02  -> REGRESSION (backward)

3. Same mechanism, same 144 g/cc, applied to the other planets (lattice boundary 1.1 x radius)
   planet     GR "/cy   Aspden "/cy     ratio   boundary needed for GR value
   Mercury     42.980         32.65      0.76   1.1622 x radius
   Venus        8.625         23.32       2.7   0.9016 x radius
   Earth        3.839          7.91      2.06   0.9519 x radius
   Mars         1.351        0.7186     0.532   1.2480 x radius
   Jupiter      0.062         12.32       198   0.3821 x radius
   Saturn       0.014          1.96       144   0.4073 x radius
   ephemeris (EPM2017) formal limits on any extra perihelion motion: Mercury 0.008 mas/cy, Venus 0.315 mas/cy, Earth 0.033 mas/cy, Mars 0.003 mas/cy, Jupiter 33.9 mas/cy, Saturn 0.067 mas/cy (realistic: x10-50)

4. Double pulsar J0737-3039A/B: neutron stars, radius ~12 km, mean density ~4e14 g/cc
   M_lattice/P = 5.21e-13; predicted periastron advance 1.21e-16 deg/yr; measured 16.899 deg/yr

5. Special relativity alone (Sommerfeld 1916, same calculation as hydrogen fine structure)
   Mercury: GR 6 pi GM/(c^2 p) per orbit; relativistic mass alone gives pi GM/(c^2 p) -> 7.16"/cy of the 42.98"/cy
```

### C.10 cavity_variants.py

Whether Aspden's 4/√3 is derived or chosen (section 9.3): his chain of equations rebuilt, the constants the electron and muon data require, 21 natural variants of the model ranked, and his alternative muon formula.

```python
"""Is Aspden's 4/sqrt3 derived or chosen?  (1983c eqs 1-8, rebuilt; paper section 9.3)

Model: radial standing wave between inner radius r and outer radius R at the Compton frequency v0 = mc^2/h.
  half-wave condition  2(R - r) v0 = c          ->  R = h/2mc + r      (electron; muon: R = h/2mc - r)
  inner radius         pi r^2 = (1/2) sigma_T   ->  r = (2/sqrt3) e^2/mc^2
  anomaly              a = mc^2/(mc^2 - e^2/2R) - 1   (spin mass excludes field energy outside R)
Writing x = alpha/2pi:  e^2/2R = mc^2 x/(1 + k x)  with k = 2 r/(e^2/mc^2),  so
  a = 1/(2pi/alpha + j + k)   with j = -1 (spin-mass form), k = 4/sqrt3.
Alternatives: other natural inner radii (k) and other mass forms (j). The half-wave condition is forced:
a full or quarter wave changes the leading term away from Schwinger's alpha/2pi.
"""
from mpmath import mp, mpf, pi, sqrt, log
mp.dps = 30
AINV = mpf('137.035999206')            # Rb atom recoil 2020
AE, AMU = mpf('0.00115965218059'), mpf('0.001165920705')
X = 1/(2*pi*AINV)

# 1. Derivation check: symbolic chain reproduces eq. (8) exactly
k_asp = 4/sqrt(3)
R_over = 1 + k_asp*X                    # R / (h/2mc)
e_out = X/R_over                        # e^2/2R in units of mc^2
a_chain = 1/(1 - e_out) - 1
print(f"1. chain (1)-(7) gives a = {mp.nstr(a_chain,15)}; closed form (8) = {mp.nstr(1/(2*pi*AINV - 1 + k_asp),15)}")

# 2. What constants would the data need?
c_e = 1/AE - 2*pi*AINV                  # = j + k needed for the electron
c_mu = 1/AMU - 2*pi*AINV                # = j - k needed for the muon
print(f"2. data need j+k = {mp.nstr(c_e,6)} (electron) and j-k = {mp.nstr(c_mu,6)} (muon)")
print(f"   with j = -1: k_e = {mp.nstr(c_e+1,6)}, k_mu = {mp.nstr(-(c_mu+1),6)}  (Aspden 4/sqrt3 = {mp.nstr(k_asp,6)}); "
      f"asymmetry {mp.nstr(((-(c_mu+1))/(c_e+1)-1)*100,3)} %")
print(f"   sum k_e + k_mu = {mp.nstr(c_e - c_mu,6)} vs Aspden 8/sqrt3 = {mp.nstr(2*k_asp,6)} "
      f"({mp.nstr(((2*k_asp)/(c_e-c_mu)-1)*100,3)} %): this sum is what sets the muon-electron difference")

# 3. Enumerate natural alternatives
radii = {  # inner radius r in units of the classical radius e^2/mc^2  ->  k = 2 r
    "zero (point reflector)": mpf(0),
    "half classical radius": mpf(1)/2,
    "Thomson-sphere radius 2/3": mpf(2)/3,
    "quarter Thomson cross-section": sqrt(mpf(2)/3),
    "classical radius": mpf(1),
    "half Thomson cross-section (Aspden)": 2/sqrt(3),
    "full Thomson cross-section": sqrt(mpf(8)/3),
}
forms = {"a = E_out/mc^2 (j=0)": 0, "spin mass excludes E_out (j=-1, Aspden)": -1, "a = E_out/(mc^2+E_out) (j=+1)": 1}
rows = []
for rn, r in radii.items():
    for fn, j in forms.items():
        k = 2*r
        ae = 1/(2*pi*AINV + j + k)
        am = 1/(2*pi*AINV + j - k)
        rows.append((abs(ae/AE - 1), rn, fn, ae, am, j + k))
rows.sort()
print(f"\n3. {len(rows)} variants (7 inner radii x 3 mass forms), ranked by electron error:")
for err, rn, fn, ae, am, c in rows[:8]:
    print(f"   {rn:36s} {fn:42s} a_e {mp.nstr((ae/AE-1)*1e6,4):>8s} ppm   a_mu {mp.nstr((am/AMU-1)*1e6,4):>8s} ppm")
cs = [r[5] for r in rows]
span = max(cs) - min(cs)
window = 2*abs(rows[0][5] - c_e)
print(f"   constants j+k span {mp.nstr(span,3)}; Aspden's lands {mp.nstr(abs(rows[0][5]-c_e),3)} from the target, "
      f"next best {mp.nstr(min(abs(r[5]-c_e) for r in rows[1:]),3)}")
print(f"   chance that one of {len(rows)} such constants lands this close to a random target in that span: "
      f"{mp.nstr(len(rows)*window/span,2)}")

# 4. QED comparison of the second-order term and of the muon-electron difference
print(f"\n4. second-order coefficient of (alpha/pi)^2: Aspden -(4/sqrt3 - 1)/4 = {mp.nstr(-(k_asp-1)/4,6)}, QED -0.328479")
apl = 1/(pi*AINV)
qed_diff = apl**2*(log(mpf('206.7682830'))/3 - mpf(25)/36)
print(f"   muon-electron difference / (alpha/pi)^2: measured {mp.nstr((AMU-AE)/apl**2,6)}; Aspden {mp.nstr((1/(2*pi*AINV-1-k_asp)-1/(2*pi*AINV-1+k_asp))/apl**2,6)} "
      f"(2/sqrt3 = {mp.nstr(2/sqrt(3),6)} at leading order); QED leading term (1/3)ln(m_mu/m_e) - 25/36 = {mp.nstr(qed_diff/apl**2,6)}")
meas = (AMU - AE)/apl**2
print("   simple numbers near the measured value: " + ", ".join(
    f"{n} = {mp.nstr(v,5)} ({mp.nstr((v/meas-1)*100,2)}%)" for n, v in (("2/sqrt3", 2/sqrt(3)), ("7/6", mpf(7)/6), ("pi/e", pi/mp.e))))

# 5. His footnote alternative for a muon "created by charge pair annihilation" (1983d, eq. 4; printed 4 sqrt3, read as 4/sqrt3)
D = 2*pi*AINV - 1
for lab, kk in (("4/sqrt3", 4/sqrt(3)), ("4 sqrt3 (as printed)", 4*sqrt(3))):
    am4 = 2/D - 1/(D + kk)
    print(f"5. muon, footnote form with {lab:22s}: a_mu = {mp.nstr(am4,10)} ({mp.nstr((am4/AMU-1)*1e6,4)} ppm)")
```

Output:

```text
1. chain (1)-(7) gives a = 0.00115964619855784; closed form (8) = 0.00115964619855784
2. data need j+k = 1.30495 (electron) and j-k = -3.33132 (muon)
   with j = -1: k_e = 2.30495, k_mu = 2.33132  (Aspden 4/sqrt3 = 2.3094); asymmetry 1.14 %
   sum k_e + k_mu = 4.63627 vs Aspden 8/sqrt3 = 4.6188 (-0.377 %): this sum is what sets the muon-electron difference

3. 21 variants (7 inner radii x 3 mass forms), ranked by electron error:
   half Thomson cross-section (Aspden)  spin mass excludes E_out (j=-1, Aspden)    a_e   -5.158 ppm   a_mu   -25.55 ppm
   Thomson-sphere radius 2/3            a = E_out/mc^2 (j=0)                       a_e   -32.91 ppm   a_mu  -2324.0 ppm
   classical radius                     spin mass excludes E_out (j=-1, Aspden)    a_e    353.8 ppm   a_mu   -386.1 ppm
   half classical radius                a = E_out/mc^2 (j=0)                       a_e    353.8 ppm   a_mu  -2711.0 ppm
   zero (point reflector)               a = E_out/(mc^2+E_out) (j=+1)              a_e    353.8 ppm   a_mu  -5025.0 ppm
   quarter Thomson cross-section        a = E_out/mc^2 (j=0)                       a_e   -380.3 ppm   a_mu  -1976.0 ppm
   quarter Thomson cross-section        spin mass excludes E_out (j=-1, Aspden)    a_e    779.8 ppm   a_mu   -813.5 ppm
   classical radius                     a = E_out/mc^2 (j=0)                       a_e   -805.4 ppm   a_mu  -1550.0 ppm
   constants j+k span 5.27; Aspden's lands 0.00445 from the target, next best 0.0284
   chance that one of 21 such constants lands this close to a random target in that span: 0.035

4. second-order coefficient of (alpha/pi)^2: Aspden -(4/sqrt3 - 1)/4 = -0.32735, QED -0.328479
   muon-electron difference / (alpha/pi)^2: measured 1.16181; Aspden 1.1574 (2/sqrt3 = 1.1547 at leading order); QED leading term (1/3)ln(m_mu/m_e) - 25/36 = 1.08276
   simple numbers near the measured value: 2/sqrt3 = 1.1547 (-0.61%), 7/6 = 1.1667 (0.42%), pi/e = 1.1557 (-0.52%)
5. muon, footnote form with 4/sqrt3               : a_mu = 0.001165874147 (-39.93 ppm)
5. muon, footnote form with 4 sqrt3 (as printed)  : a_mu = 0.001172052325 (5259.0 ppm)
```

### C.11 moving_atom.py

Aspden's two Rydberg factors for a moving atom (section 9.6): their agreement with time dilation to order (v/c)², and their predictions for the Heidelberg and GSI fast-ion experiments.

```python
"""Aspden's Rydberg-constant argument against time dilation (paper section 9.6).

Physics Unified (1980), ch. 3, eq. (56): only the kinetic part of the Bohr energy gains mass with speed, so
    R(v)/R(0) = 2 - gamma                         gamma = 1/sqrt(1 - v^2/c^2)
Aether Science Papers (1996), pp. 41-47, "Atomic Spectra and the Moving Atom": the electrodynamic force offsets the
Coulomb force by beta^2, the mass rises as 1/beta, and the quantised quantity is v r (charge-velocity moment), so
    R(v)/R(0) = (2 - beta^2) beta^3               beta = sqrt(1 - v^2/c^2)
Special relativity (and Lorentz's own aether theory): emitted frequency scales as beta exactly.
Test: fast-ion Ives-Stilwell experiments measure eps = nu_a nu_p / nu_0^2 - 1, where nu_a, nu_p are the lines seen
parallel and antiparallel to the beam. With the lab at rest in the aether, a source clock factor F gives
    nu_a nu_p = nu_0^2 F^2 / (1 - v^2/c^2)  ->  eps = (F gamma)^2 - 1     (zero for F = beta).
"""
from mpmath import mp, mpf, sqrt
mp.dps = 20

def factors(v):
    b = sqrt(1 - v**2); g = 1/b
    return {"special relativity": b, "Aspden 1980 (2 - gamma)": 2 - g, "Aspden 1996 ((2 - beta^2) beta^3)": (2 - b**2)*b**3}, g

print("1. Series check: all three agree to order (v/c)^2")
x = mpf('0.01')
for name, F in factors(sqrt(x))[0].items():
    print(f"   {name:36s} F = {mp.nstr(F, 15)}   (1 - x/2 = {mp.nstr(1 - x/2, 15)})")
print("   exact: Aspden 1996 F/beta = 1 - (v/c)^4;  Aspden 1980 F/beta = 1 - (v/c)^4/4 + ...")

tests = [  # (experiment, v/c, measured eps, 1-sigma or bound)
    ("Heidelberg TSR, Li+ (Saathoff 2003; Reinhardt 2007)", mpf('0.064'), mpf(0), mpf('8.4e-8')*mpf('0.064')**2),
    ("GSI ESR, Li+ (Botermann et al. 2014)", mpf('0.338'), mpf('1.5e-9'), mpf('2.3e-9')),
]
print("\n2. Fast-ion Ives-Stilwell tests: eps = nu_a nu_p / nu0^2 - 1")
for name, v, meas, u in tests:
    F, g = factors(v)
    print(f"   {name}  (v = {v} c), measured {mp.nstr(meas,2)} +/- {mp.nstr(u,2)}")
    for model, f in F.items():
        eps = (f*g)**2 - 1
        print(f"      {model:36s} predicts eps = {mp.nstr(eps, 4):>12s}  -> {mp.nstr(abs(eps-meas)/u, 3)} sigma")

print("\n3. In 1996 terms: the 1990s Ives-Stilwell-type data were at v/c ~ 0.005-0.03, where (v/c)^4 <= 1e-6;")
for v in (mpf('0.005'), mpf('0.03'), mpf('0.064'), mpf('0.338')):
    print(f"   v/c = {v}: (v/c)^4 = {mp.nstr(v**4, 3)}")
```

Output:

```text
1. Series check: all three agree to order (v/c)^2
   special relativity                   F = 0.99498743710662   (1 - x/2 = 0.995)
   Aspden 1980 (2 - gamma)              F = 0.994962184740788   (1 - x/2 = 0.995)
   Aspden 1996 ((2 - beta^2) beta^3)    F = 0.994887938362909   (1 - x/2 = 0.995)
   exact: Aspden 1996 F/beta = 1 - (v/c)^4;  Aspden 1980 F/beta = 1 - (v/c)^4/4 + ...

2. Fast-ion Ives-Stilwell tests: eps = nu_a nu_p / nu0^2 - 1
   Heidelberg TSR, Li+ (Saathoff 2003; Reinhardt 2007)  (v = 0.064 c), measured 0.0 +/- 3.4e-10
      special relativity                   predicts eps =          0.0  -> 0.0 sigma
      Aspden 1980 (2 - gamma)              predicts eps =     -8.44e-6  -> 2.45e+4 sigma
      Aspden 1996 ((2 - beta^2) beta^3)    predicts eps =    -3.355e-5  -> 9.75e+4 sigma
   GSI ESR, Li+ (Botermann et al. 2014)  (v = 0.338 c), measured 1.5e-9 +/- 2.3e-9
      special relativity                   predicts eps =          0.0  -> 0.652 sigma
      Aspden 1980 (2 - gamma)              predicts eps =    -0.007806  -> 3.39e+6 sigma
      Aspden 1996 ((2 - beta^2) beta^3)    predicts eps =     -0.02593  -> 1.13e+7 sigma

3. In 1996 terms: the 1990s Ives-Stilwell-type data were at v/c ~ 0.005-0.03, where (v/c)^4 <= 1e-6;
   v/c = 0.005: (v/c)^4 = 6.25e-10
   v/c = 0.03: (v/c)^4 = 8.1e-7
   v/c = 0.064: (v/c)^4 = 1.68e-5
   v/c = 0.338: (v/c)^4 = 0.0131
```

### C.12 np_mass.py

The neutron–proton mass difference from 1986d, compared in Aspden's own units (section 8).

```python
"""Neutron-proton mass difference (Hadronic Journal 9, 129, 1986 = 1986d), compared in Aspden's own units.
His Thomson-charge model gives (m_n - m_p)/m_e = 2.5309419; he converted with m_e c^2 = 0.511004 MeV (1984) to 1.2933214 MeV.
The theory predicts the dimensionless ratio, so the fair test is against the measured ratio, not against MeV."""
from mpmath import mp, mpf
mp.dps = 20
asp = mpf('2.5309419')
cases = [
    ("PDG 1984 (his comparison)", mpf('1.293323'), mpf('0.000016'), mpf('0.5110034')),
    ("CODATA 2022", None, None, None),
]
# 1984: ratio from MeV values; 2022: from the mass ratios directly
r84, u84 = mpf('1.293323')/mpf('0.5110034'), mpf('0.000016')/mpf('0.5110034')
mn, mp_ = mpf('1838.68366200'), mpf('1836.152673426')
r22, u22 = mn - mp_, mpf('0.00000074')
for name, r, u in (("1984 measurement", r84, u84), ("CODATA 2022", r22, u22)):
    print(f"{name:18s} (m_n-m_p)/m_e = {mp.nstr(r,10)} +/- {mp.nstr(u,2)};  Aspden {asp}: "
          f"{mp.nstr((asp/r-1)*1e6,3)} ppm, {mp.nstr((asp-r)/u,3)} sigma")
me22 = mpf('0.51099895069')
print(f"In MeV with today's electron mass: Aspden {mp.nstr(asp*me22,9)} MeV vs measured {mp.nstr(r22*me22,9)} MeV")
print(f"His printed 1.2933214 MeV used the 1984 m_e; against today's 1.29333251 MeV that mixes units and gives "
      f"{mp.nstr((mpf('1.2933214')/(r22*me22)-1)*1e6,3)} ppm")
```

Output:

```text
1984 measurement   (m_n-m_p)/m_e = 2.530947935 +/- 3.1e-5;  Aspden 2.5309419: -2.38 ppm, -0.193 sigma
CODATA 2022        (m_n-m_p)/m_e = 2.530988574 +/- 7.4e-7;  Aspden 2.5309419: -18.4 ppm, -63.1 sigma
In MeV with today's electron mass: Aspden 1.29330866 MeV vs measured 1.29333251 MeV
His printed 1.2933214 MeV used the 1984 m_e; against today's 1.29333251 MeV that mixes units and gives -8.59 ppm
```

### C.13 build_docx.js

Generates the .docx from the Markdown source so both versions carry identical content. Run with `node build_docx.js paper.md paper.docx "running header"` (requires the `docx` npm package).

```javascript
// Build the .docx from the Markdown source so both files carry identical content.
const fs = require('fs');
const path = require('path');
const {
  Document, Packer, Paragraph, TextRun, HeadingLevel, Table, TableRow, TableCell,
  WidthType, ShadingType, BorderStyle, AlignmentType, LevelFormat, ExternalHyperlink,
  Footer, Header, PageNumber, TabStopType, LineRuleType, ImageRun,
} = require('docx');
const FIG_DIR = path.join(path.dirname(path.resolve(process.argv[2])), 'figures'); // figures referenced by URL are read from here by file name

const SRC = process.argv[2];
const OUT = process.argv[3];
const HEADER = process.argv[4] || 'Aspden investigation · working paper'; // running header text
const md = fs.readFileSync(SRC, 'utf8').replace(/\r/g, '').split('\n');

const CONTENT_W = 9360; // US Letter, 1" margins
const FONT = 'Calibri', MONO = 'Consolas';
const ACCENT = '1F3864';

// ---------- inline formatting ----------
function inline(text, base = {}) {
  const out = [];
  const re = /(\*\*[^*]+\*\*|\*[^*\s][^*]*\*|`[^`]+`|\[[^\]]+\]\([^)]+\)|https?:\/\/[^\s)]+)/g;
  let last = 0, m;
  while ((m = re.exec(text)) !== null) {
    if (m.index > last) out.push(new TextRun({ text: text.slice(last, m.index), ...base }));
    const t = m[0];
    if (t.startsWith('**')) out.push(new TextRun({ text: t.slice(2, -2), bold: true, ...base }));
    else if (t.startsWith('`')) out.push(new TextRun({ text: t.slice(1, -1), font: MONO, ...base, size: base.size ? base.size - 2 : 20 }));
    else if (t.startsWith('[')) {
      const mm = t.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
      out.push(new ExternalHyperlink({ link: mm[2], children: [new TextRun({ text: mm[1], style: 'Hyperlink', ...base })] }));
    } else if (t.startsWith('http')) {
      out.push(new ExternalHyperlink({ link: t, children: [new TextRun({ text: t, style: 'Hyperlink', ...base })] }));
    } else out.push(new TextRun({ text: t.slice(1, -1), italics: true, ...base }));
    last = m.index + t.length;
  }
  if (last < text.length) out.push(new TextRun({ text: text.slice(last), ...base }));
  return out;
}

// ---------- tables ----------
const cellBorder = { style: BorderStyle.SINGLE, size: 4, color: 'BFBFBF' };
const borders = { top: cellBorder, bottom: cellBorder, left: cellBorder, right: cellBorder };
function plain(s) { return s.replace(/\*\*|`/g, '').replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); }
function buildTable(rows) {
  const ncol = rows[0].length;
  // column widths proportional to content length (sqrt-damped), with a floor
  const weights = [];
  for (let c = 0; c < ncol; c++) {
    let mx = 4;
    for (const r of rows) mx = Math.max(mx, plain(r[c] || '').length);
    weights.push(Math.sqrt(Math.min(mx, 90)));
  }
  const tot = weights.reduce((a, b) => a + b, 0);
  let widths = weights.map(w => Math.max(1000, Math.round(CONTENT_W * w / tot)));
  const scale = CONTENT_W / widths.reduce((a, b) => a + b, 0);
  widths = widths.map(w => Math.floor(w * scale));
  widths[widths.length - 1] += CONTENT_W - widths.reduce((a, b) => a + b, 0);
  const trs = rows.map((r, i) => new TableRow({
    tableHeader: i === 0,
    children: r.map((txt, c) => new TableCell({
      borders, width: { size: widths[c], type: WidthType.DXA },
      shading: i === 0 ? { fill: 'DCE3EF', type: ShadingType.CLEAR, color: 'auto' } : undefined,
      margins: { top: 60, bottom: 60, left: 100, right: 100 },
      children: [new Paragraph({ spacing: { before: 0, after: 0 },
        children: inline(txt, i === 0 ? { bold: true, size: 18, font: FONT } : { size: 18, font: FONT }) })],
    })),
  }));
  return new Table({ width: { size: CONTENT_W, type: WidthType.DXA }, columnWidths: widths, rows: trs });
}
function splitRow(line) {
  return line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|').map(s => s.trim());
}

// ---------- block parse ----------
const children = [];
const numberingConfigs = [{
  reference: 'bullets',
  levels: [0, 1, 2].map(l => ({ level: l, format: LevelFormat.BULLET, text: ['•', '–', '·'][l], alignment: AlignmentType.LEFT,
    style: { paragraph: { indent: { left: 540 + 360 * l, hanging: 270 } } } })),
}];
let numCount = 0, inNum = false, subCount = 0, inSub = false, title = null, i = 0, sawTitle = false;

while (i < md.length) {
  const line = md[i];
  if (!line.trim()) { inNum = false; if (i + 1 < md.length && !/^\s/.test(md[i + 1])) inSub = false; i++; continue; }
  if (line.startsWith('```')) {           // code block: equations (no tag) or program listings (tagged)
    const listing = line.slice(3).trim().length > 0;
    i++;
    while (i < md.length && !md[i].startsWith('```')) {
      children.push(new Paragraph({ shading: { fill: 'F2F2F2', type: ShadingType.CLEAR, color: 'auto' },
        indent: { left: listing ? 0 : 360 }, spacing: { before: 0, after: 0, line: listing ? 220 : 276 },
        children: [new TextRun({ text: md[i] || ' ', font: MONO, size: listing ? 14 : 19 })] }));
      i++;
    }
    children.push(new Paragraph({ spacing: { after: 120 }, children: [] }));
    i++; continue;
  }
  if (/^\s*\|/.test(line)) {             // table (may be indented under a list item)
    const rows = [];
    while (i < md.length && /^\s*\|/.test(md[i])) {
      if (!/^\s*\|\s*:?-{3,}/.test(md[i])) rows.push(splitRow(md[i]));
      i++;
    }
    children.push(buildTable(rows));
    children.push(new Paragraph({ spacing: { after: 120 }, children: [] }));
    continue;
  }
  if (/^---\s*$/.test(line)) {            // rule
    children.push(new Paragraph({ border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: 'BFBFBF', space: 1 } }, spacing: { after: 200 }, children: [] }));
    i++; continue;
  }
  let m;
  if ((m = line.match(/^(#{1,4})\s+(.*)$/))) {
    const lvl = m[1].length, txt = m[2];
    if (lvl === 1 && !sawTitle) {
      sawTitle = true; title = txt;
      children.push(new Paragraph({ alignment: AlignmentType.LEFT, spacing: { after: 120, line: 264, lineRule: LineRuleType.AUTO },
        children: [new TextRun({ text: txt, bold: true, size: 40, color: ACCENT, font: FONT })] }));
    } else {
      const heading = [HeadingLevel.HEADING_1, HeadingLevel.HEADING_1, HeadingLevel.HEADING_2, HeadingLevel.HEADING_3][lvl - 1];
      children.push(new Paragraph({ heading, children: inline(txt) }));
    }
    i++; continue;
  }
  if ((m = line.match(/^(\s*)-\s+(.*)$/))) {
    const ind = m[1].length;                 // CommonMark nesting: 2 spaces under '-', 3 under '1.'
    const level = ind === 0 ? 0 : ind < 5 ? 1 : 2;
    if (level === 0) inSub = false;
    children.push(new Paragraph({ numbering: { reference: 'bullets', level }, spacing: { after: 60 }, children: inline(m[2]) }));
    i++; continue;
  }
  if ((m = line.match(/^(\s+)\d+\.\s+(.*)$/))) {   // numbered list nested under a list item
    if (!inSub) {
      subCount++; inSub = true;
      numberingConfigs.push({ reference: `sub${subCount}`, levels: [{ level: 0, format: LevelFormat.DECIMAL, text: '%1.',
        alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 1080, hanging: 360 } } } }] });
    }
    children.push(new Paragraph({ numbering: { reference: `sub${subCount}`, level: 0 }, spacing: { after: 60 }, children: inline(m[2]) }));
    i++; continue;
  }
  if ((m = line.match(/^\d+\.\s+(.*)$/))) {
    inSub = false;
    if (!inNum) {
      numCount++; inNum = true;
      numberingConfigs.push({ reference: `num${numCount}`, levels: [{ level: 0, format: LevelFormat.DECIMAL, text: '%1.',
        alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 540, hanging: 360 } } } }] });
    }
    children.push(new Paragraph({ numbering: { reference: `num${numCount}`, level: 0 }, spacing: { after: 60 }, children: inline(m[1]) }));
    i++; continue;
  }
  if ((m = line.match(/^!\[([^\]]*)\]\(([^)\s]+)\)\s*$/))) {   // figure on its own line: embed the local copy
    const file = path.join(FIG_DIR, path.basename(m[2]));
    const data = fs.readFileSync(file);
    const pw = data.readUInt32BE(16), ph = data.readUInt32BE(20);   // PNG header width and height
    const w = 624, h = Math.round(w * ph / pw);                      // full text width (6.5 in at 96 px/in)
    children.push(new Paragraph({ alignment: AlignmentType.CENTER, spacing: { before: 120, after: 60 }, keepNext: true,
      children: [new ImageRun({ type: 'png', data, transformation: { width: w, height: h },
        altText: { title: m[1], description: m[1], name: path.basename(file) } })] }));
    i++; continue;
  }
  // paragraph: join consecutive plain lines
  let buf = line.trim(); i++;
  while (i < md.length && md[i].trim() && !/^\s*(#|\||```|-\s|\d+\.\s|---)/.test(md[i])) { buf += ' ' + md[i].trim(); i++; }
  const isSubtitle = children.length === 1 && /^\*\*.*\*\*$/.test(buf);
  const isCaption = /^\*\*Figure \d+\.\*\*/.test(buf);
  children.push(new Paragraph({ spacing: { after: isCaption ? 220 : 140 },
    children: isSubtitle ? [new TextRun({ text: buf.slice(2, -2), size: 26, color: '404040', font: FONT })]
      : isCaption ? inline(buf, { size: 19, color: '404040' }) : inline(buf) }));
}

const doc = new Document({
  creator: 'Doug Westmoreland with Claude (Anthropic)',
  title: title || 'Working paper',
  styles: {
    default: { document: { run: { font: FONT, size: 22 }, paragraph: { spacing: { line: 276 } } } },
    paragraphStyles: [
      { id: 'Heading1', name: 'Heading 1', basedOn: 'Normal', next: 'Normal', quickFormat: true,
        run: { size: 30, bold: true, color: ACCENT, font: FONT }, paragraph: { spacing: { before: 320, after: 140 }, outlineLevel: 0, keepNext: true, keepLines: true } },
      { id: 'Heading2', name: 'Heading 2', basedOn: 'Normal', next: 'Normal', quickFormat: true,
        run: { size: 25, bold: true, color: ACCENT, font: FONT }, paragraph: { spacing: { before: 240, after: 100 }, outlineLevel: 1, keepNext: true, keepLines: true } },
      { id: 'Heading3', name: 'Heading 3', basedOn: 'Normal', next: 'Normal', quickFormat: true,
        run: { size: 22, bold: true, font: FONT }, paragraph: { spacing: { before: 200, after: 80 }, outlineLevel: 2, keepNext: true, keepLines: true } },
    ],
  },
  numbering: { config: numberingConfigs },
  sections: [{
    properties: { page: { size: { width: 12240, height: 15840 }, margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } },
    headers: { default: new Header({ children: [new Paragraph({ alignment: AlignmentType.RIGHT,
      children: [new TextRun({ text: HEADER, size: 16, color: '808080' })] })] }) },
    footers: { default: new Footer({ children: [new Paragraph({ alignment: AlignmentType.CENTER,
      children: [
        new TextRun({ text: 'Page ', size: 16, color: '808080' }),
        new TextRun({ children: [PageNumber.CURRENT], size: 16, color: '808080' }),
        new TextRun({ text: ' of ', size: 16, color: '808080' }),
        new TextRun({ children: [PageNumber.TOTAL_PAGES], size: 16, color: '808080' }),
      ] })] }) },
    children,
  }],
});

Packer.toBuffer(doc).then(buf => { fs.writeFileSync(OUT, buf); console.log('wrote', OUT, buf.length, 'bytes'); });
```

### C.15 out_of_sample.py

```python
"""out_of_sample.py - the out-of-sample test of the "doubled electron" (working paper section 7.5, test O1-O4).

THE RULE (written in the working paper, section 7.5, before this test was run):
  "Wherever Aspden's other derivations eject or subtract a 1.875 cluster ..., the same replacement must be made,
   and those results must improve, or at least not worsen."
Applied here literally: every place Aspden uses the in-line three-charge energy factor 1.875 = 3 - 3/4 - 3/4 + 3/8
is given the value 2 instead. Nothing else is changed, and each result is compared with the measurement Aspden
himself compared it with.

CENSUS (done before any replacement was computed): all 719 texts of aetherscience.org (posts, pages, the static
archive and 98 OCR'd scans) were searched for 1.875 / 1-875 / 1·875 / 15/8. Five texts matched:
  - Tutorial Note 9: the ejected +-+ electron cluster in the G chain        -> the in-sample case (where 2 was chosen)
  - Aether Science Papers 1986j (Hadronic J. 9, 153), p. 154: (g*:g*:g*) = 1.875 x 3259 MeV for the 1976 "upsilon"
  - The Physics of Creation (2003), ch. 3 (two copies): the muon-lifetime derivation, 3 - 0.75 - 0.75 + 0.375
  - Physics Unified (1980) ch. 3 and books/Asp/3640.htm: 15/8 as a binomial-series coefficient (unrelated)
The 1986e paper uses in-line three-charge systems with unequal energies (its general formula), never the
equal-charge value 1.875, so it is outside the rule.
"""
from mpmath import mp, mpf, pi, sqrt, cbrt, findroot, ceil, floor
mp.dps = 25

def show(tag, text, val=""):
    print(f"  {tag:4s} {text:<86s} {val}")

print("O1  In-sample reference: the G chain (Tutorial Note 9)")
e, me = mpf('4.80320471257e-10'), mpf('9.1093837139e-28')
Q = 944784 * pi**2 / mpf(1843) ** (mpf(4) / 3)
x = findroot(lambda x: 3 * x**4 + x**3 - 1, 0.69)
def G_of(cluster):
    g = (2 * Q * (3 + sqrt(mpf(3) / 2)) - cluster) / x
    return (4 * pi * (e / me) / g**4 / (108 * pi) ** 3) ** 2 * 1e8
for c_ in (mpf(15) / 8, mpf(2)):
    Gv = G_of(c_)
    show("1", f"cluster {mp.nstr(c_,4)}: G (x 1e-11), ppm vs CODATA 6.67430(15)", f"{mp.nstr(Gv,7)}   {mp.nstr((Gv/mpf('6.67430')-1)*1e6,4)} ppm")
show("2", "(2 was chosen here with the measured G known; this case cannot count as a test)")

print("\nO2  1986j (Hadronic J. 9, 153, p. 154): the triple group (g*:g*:g*) for the 1976 'upsilon'")
gstar = mpf(3259)                                   # MeV, his g* = 2^(1/3) g(2587)
show("1", "his g* (MeV) and 2^(1/3) x 2587", f"{gstar}   {mp.nstr(cbrt(2)*2587,6)}")
show("2", "with 1.875 (his): energy (MeV)", mp.nstr(mpf('1.875') * gstar, 6))
show("3", "with 2 (replacement): energy (MeV)", mp.nstr(2 * gstar, 6))
show("4", "his target: the 'upsilon of mass energy 6.1 GeV' announced in 1976", "E288, Hom et al. PRL 36, 1236 (1976), about 6.0 GeV")
show("5", "status of that target", "not confirmed by E288's own 1977 data; withdrawn ('Oops-Leon')")
show("6", "the real upsilon, found by E288 in 1977: Upsilon(1S) (MeV, PDG)", "9460.40")
show("7", "result", "no test possible: the particle both values are compared with does not exist")

print("\nO3  The Physics of Creation (2003) ch. 3: the muon lifetime")
h_over_mec2 = mpf('6.62607015e-34') / (mpf('9.1093837139e-31') * mpf('299792458') ** 2)
base = (mpf(3) / (4 * pi)) ** 2 * (108 * pi) ** 6 * h_over_mec2    # his formula without the 25/8 factor
tau_meas = mpf('2.1969811e-6')                                       # PDG, +/- 0.0000022e-6
def muon(f):
    """His argument with the in-line triplet factor f (his f = 1.875), step by step:
    a) three charges, each with energy x cbrt(3) (charge volume shared three ways), in line: E3 = f cbrt3 muon units;
    b) the threshold multiple n: the first integer n for which n*E3 is within 1 part in 1000 of an integer;
    c) each triplet formed sheds s = 3 - E3; a triplet is raised to the separated form (Fig. 3.3),
       E_sep = (3 - 3/4) cbrt3, by k shed quanta, the least k with k*s >= s + (E_sep - 3);
    d) the k donors remain as triplets, so n triplets yield floor(n/k) separated forms;
    e) only separated forms decay: chance m/(n+m), lifetime = ((n+m)/m) x (3/4pi)^2 (108 pi)^6 h/(m_e c^2)."""
    c3 = cbrt(3)
    E3 = f * c3
    n = next(i for i in range(1, 500) if abs(i*E3 - mp.nint(i*E3)) / (i*E3) < mpf('0.001'))
    s = 3 - E3
    Esep = (3 - mpf('0.75')) * c3
    k = int(ceil((s + (Esep - 3)) / s)) if s > 0 else None
    m = int(floor(mpf(n) / k)) if k else 0
    tau = (n + m) / mpf(m) * base if m else None
    return E3, n, s, Esep, k, m, tau
for f, lab in ((mpf('1.875'), "1.875 (his)"), (mpf(2), "2 (replacement)")):
    E3, n, s, Esep, k, m, tau = muon(f)
    show("1", f"{lab}: triplet energy E3 = f cbrt3 (muon units)", mp.nstr(E3, 6))
    show("2", f"{lab}: first n with n E3 within 1/1000 of an integer; n E3", f"{n}   {mp.nstr(n*E3, 6)}")
    show("3", f"{lab}: energy shed per triplet s = 3 - E3; separated form E_sep", f"{mp.nstr(s, 5)}   {mp.nstr(Esep, 6)}")
    show("4", f"{lab}: quanta needed to raise one triplet, k = ceil((s + E_sep - 3)/s)", f"{k}   (his text: 2(0.2958) > 0.2958 + 0.2451)" if f == mpf('1.875') else str(k))
    show("5", f"{lab}: separated forms m = floor(n/k); ratio n:m (his text: 17:8)", f"{m}   {n}:{m}")
    show("6", f"{lab}: lifetime ((n+m)/m) x base (microseconds); vs PDG 2.1969811", f"{mp.nstr(tau*1e6, 6)}   {mp.nstr((tau/tau_meas-1)*100, 4)} %")
show("7", "his printed lifetime: '2.199 microseconds ... within one part per thousand'", "")

print("\nO4  Score")
show("1", "out-of-sample uses of the 1.875 factor found", "2 (1986j upsilon; 2003 muon lifetime)")
show("2", "improved", "0")
show("3", "worse", "1 (muon lifetime: +0.09% becomes +68%)")
show("4", "not testable", "1 (the 1976 upsilon does not exist)")

print("\nO5  What this does to the chance calculation (working paper section 11)")
import math
def career(thresholds, M):
    """P(among M independent uniform p-values, the k smallest beat the k sorted thresholds) - same method as
    coincidence.py, for any k."""
    t = sorted(thresholds); k = len(t); edges = [0.0] + t
    probs = [edges[i+1] - edges[i] for i in range(k)]; rest = 1 - t[-1]
    def rec(i, used, lp):
        if i == k:
            r = M - used
            return math.exp(lp + math.lgamma(M+1) - math.lgamma(r+1) + (r*math.log(rest) if r else 0.0))
        tot = 0.0
        for n in range(0, M - used + 1):
            if used + n < i + 1:
                continue
            tot += rec(i+1, used+n, lp - math.lgamma(n+1) + (n*math.log(probs[i]) if n else 0.0))
        return tot
    return rec(0, 0, 0.0)
central = {"alpha": 4.39e-04, "proton": 5.49e-03, "deuteron": 4.16e-02, "G": 3.33e-02}   # coincidence.py, central row
four = list(central.values()); three = [central[k] for k in ("alpha", "proton", "deuteron")]
show("1", "central scenario, all four (as published in section 11): career M = 30", f"1 in {1/career(four, 30):,.0f}")
show("2", "central scenario, G left out (treated as unsupported): career M = 30", f"1 in {1/career(three, 30):,.0f}")
show("3", "central scenario, G left out: career M = 10", f"1 in {1/career(three, 10):,.0f}")
```

Output:

```output
O1  In-sample reference: the G chain (Tutorial Note 9)
  1    cluster 1.875: G (x 1e-11), ppm vs CODATA 6.67430(15)                                  6.672161   -320.5 ppm
  1    cluster 2.0: G (x 1e-11), ppm vs CODATA 6.67430(15)                                    6.674076   -33.55 ppm
  2    (2 was chosen here with the measured G known; this case cannot count as a test)        

O2  1986j (Hadronic J. 9, 153, p. 154): the triple group (g*:g*:g*) for the 1976 'upsilon'
  1    his g* (MeV) and 2^(1/3) x 2587                                                        3259.0   3259.42
  2    with 1.875 (his): energy (MeV)                                                         6110.63
  3    with 2 (replacement): energy (MeV)                                                     6518.0
  4    his target: the 'upsilon of mass energy 6.1 GeV' announced in 1976                     E288, Hom et al. PRL 36, 1236 (1976), about 6.0 GeV
  5    status of that target                                                                  not confirmed by E288's own 1977 data; withdrawn ('Oops-Leon')
  6    the real upsilon, found by E288 in 1977: Upsilon(1S) (MeV, PDG)                        9460.40
  7    result                                                                                 no test possible: the particle both values are compared with does not exist

O3  The Physics of Creation (2003) ch. 3: the muon lifetime
  1    1.875 (his): triplet energy E3 = f cbrt3 (muon units)                                  2.70422
  2    1.875 (his): first n with n E3 within 1/1000 of an integer; n E3                       17   45.9717
  3    1.875 (his): energy shed per triplet s = 3 - E3; separated form E_sep                  0.29578   3.24506
  4    1.875 (his): quanta needed to raise one triplet, k = ceil((s + E_sep - 3)/s)           2   (his text: 2(0.2958) > 0.2958 + 0.2451)
  5    1.875 (his): separated forms m = floor(n/k); ratio n:m (his text: 17:8)                8   17:8
  6    1.875 (his): lifetime ((n+m)/m) x base (microseconds); vs PDG 2.1969811                2.19908   0.09534 %
  1    2 (replacement): triplet energy E3 = f cbrt3 (muon units)                              2.8845
  2    2 (replacement): first n with n E3 within 1/1000 of an integer; n E3                   17   49.0365
  3    2 (replacement): energy shed per triplet s = 3 - E3; separated form E_sep              0.1155   3.24506
  4    2 (replacement): quanta needed to raise one triplet, k = ceil((s + E_sep - 3)/s)       4
  5    2 (replacement): separated forms m = floor(n/k); ratio n:m (his text: 17:8)            4   17:4
  6    2 (replacement): lifetime ((n+m)/m) x base (microseconds); vs PDG 2.1969811            3.69445   68.16 %
  7    his printed lifetime: '2.199 microseconds ... within one part per thousand'            

O4  Score
  1    out-of-sample uses of the 1.875 factor found                                           2 (1986j upsilon; 2003 muon lifetime)
  2    improved                                                                               0
  3    worse                                                                                  1 (muon lifetime: +0.09% becomes +68%)
  4    not testable                                                                           1 (the 1976 upsilon does not exist)

O5  What this does to the chance calculation (working paper section 11)
  1    central scenario, all four (as published in section 11): career M = 30                 1 in 1,869
  2    central scenario, G left out (treated as unsupported): career M = 30                   1 in 802
  3    central scenario, G left out: career M = 10                                            1 in 18,078
```

### C.14 aether_units.py

Listed in full, with its output, in the appendix of the companion paper (section 15.1), and included in analysis-scripts.zip.

---

## References

1. H. Aspden, Tutorial Notes 1–20, Aether Science. https://aetherscience.org/category/tutorial-notes/
2. H. Aspden, commentary on *Creation: The Physical Truth* (2007). https://aspden.org/
3. H. Aspden, "Laser interferometry experiments on light speed anisotropy," *Phys. Lett. A* 85, 411 (1981). https://research.ibm.com/publications/laser-interferometry-experiments-on-light-speed-anisotropy
4. R. D. Klauber, "Analysis of the anomalous Brillet and Hall experimental result," *Found. Phys. Lett.* (2004). https://ar5iv.labs.arxiv.org/html/gr-qc/0210106
5. S. Herrmann et al., "Rotating optical cavity experiment testing Lorentz invariance at the 10⁻¹⁷ level," *Phys. Rev. D* 80, 105011 (2009). https://arxiv.org/pdf/1002.1284
6. M. Nagel et al., "Direct terrestrial test of Lorentz symmetry in electrodynamics to 10⁻¹⁸," *Nat. Commun.* 6, 8174 (2015). https://pmc.ncbi.nlm.nih.gov/articles/PMC4569797
7. A. A. Michelson and E. W. Morley, "On the relative motion of the Earth and the luminiferous ether" (1887). https://gutenberg.org/cache/epub/70888/pg70888-images.html
8. C. W. F. Everitt et al., "Gravity Probe B: final results," *Phys. Rev. Lett.* 106, 221101 (2011). https://web3.arxiv.org/pdf/1105.3456
9. LARES-2 frame-dragging measurement, *Nature* (2026), as reported. https://thedebrief.org/?p=49788
10. Wettzell ring laser, *Physics World*. https://physicsworld.com/a/optical-gyroscope-detects-earths-rotation-with-the-highest-precision-yet/
11. R. M. T. White et al., "Slow supernovae show cosmological time dilation out to z ∼ 1," *MNRAS* 533, 3365 (2024). https://lss.fnal.gov/archive/2024/pub/fermilab-pub-24-0293-ppd.pdf
12. G. Luzzi et al., CMB temperature evolution from Planck SZ data, *JCAP* 09, 011 (2015). https://iac.es/en/science-and-technology/publications/constraining-evolution-cmb-temperature-sz-measurements-planck-data
13. L. M. Lubin and A. Sandage, "The Tolman surface brightness test for the reality of the expansion IV" (2001). https://arxiv.org/abs/astro-ph/0106566
14. M. T. Murphy et al., ESPRESSO limit on α variation, *A&A* (2022). https://www.aanda.org/articles/aa/full_html/2022/02/aa42257-21/aa42257-21.html
15. Redshift quantization overview. https://en.wikipedia.org/wiki/Redshift_quantization
16. Review of rotating-superconductor gravitomagnetic experiments (Tajmar; Graham et al.). https://arxiv.org/pdf/2206.07574
17. Table of G measurements, arXiv:1905.09551. https://arxiv.org/pdf/1905.09551
18. Q. Li et al., "Measurements of the gravitational constant using two independent methods," *Nature* 560, 582 (2018). https://ideas.repec.org/a/nat/nature/v560y2018i7720d10.1038_s41586-018-0431-5.html
19. NIST redetermination of G, *Metrologia* 63, 025012 (2026). https://www.nist.gov/news-events/news/2026/04/nist-weighs-mystery-gravitational-constant
20. Particle Data Group, Physical Constants (2026). https://pdgweb.lbl.gov/2026/reviews/rpp2026-rev-phys-constants.pdf
21. CODATA 2014 recommended values. https://arxiv.org/pdf/1507.07956
22. CODATA 1973 recommended values. https://wiki.potsdam.edu/wikichem/index.php/CODATA_Recommended_Values_of_the_Fundamental_Physical_Constants/1973
23. 1986 CODATA values. https://s20.xray.aps.anl.gov/Physical_constants_1986.html
24. S. Dürr et al. (BMW), "Ab initio determination of light hadron masses." https://ar5iv.labs.arxiv.org/html/0906.3599
25. S. Borsanyi et al. (BMW), "Ab initio calculation of the neutron-proton mass difference," *Science* 347, 1452 (2015). https://pure.psu.edu/en/publications/ab-initio-calculation-of-the-neutron-proton-mass-difference/
26. M. Shaposhnikov and C. Wetterich, "Asymptotic safety of gravity and the Higgs boson mass" (2009). https://arxiv.org/abs/0912.0208
27. Koide relation and the tau mass. https://arxiv.org/pdf/0812.1875
28. Attempts at a determination of the fine-structure constant from first principles: a brief historical overview, arXiv:1411.4673. https://arxiv.org/pdf/1411.4673
29. Dimensionless physical constants. https://en.wikipedia.org/wiki/Dimensionless_physical_constant
30. H. Aspden and D. M. Eagles, "Calculation of the proton mass in a lattice model for the aether," *Il Nuovo Cimento* 30A, 235 (1975). https://aetherscience.org/www-aspden-org/papers/bib/1975a.htm
31. H. Aspden, "The assessment of a theory for the proton-electron mass ratio," *Lett. Nuovo Cimento* 38, 423 (1983). https://aetherscience.org/www-aspden-org/papers/bib/1983i.htm
32. H. Aspden, "The Fifth Question: What is a Neutrino?" (Energy Science Q&A). https://aetherscience.org/www-energyscience-org-uk-question-es0105/
33. H. Aspden, Lecture No. 2, "Why Einstein Was Wrong: Part I" (1997), and appendix. https://aetherscience.org/category/lectures/le02.htm and https://aetherscience.org/www-energyscience-org-uk-le-le02app/
34. J. Bagdonaite et al., "Limits on a gravitational field dependence of the proton–electron mass ratio from H₂ in white dwarf stars," *Phys. Rev. Lett.* (2014). https://arxiv.org/pdf/1409.1000
35. J. C. Berengut et al., "Limits on the dependence of the fine-structure constant on gravitational potential from white-dwarf spectra," *Phys. Rev. Lett.* 111, 010801 (2013). https://arxiv.org/abs/1305.1337
36. J. Bagdonaite et al., "Robust constraint on a drifting proton-to-electron mass ratio at z = 0.89 from methanol observation at three radio telescopes," *Phys. Rev. Lett.* 111, 231101 (2013). https://research.chalmers.se/en/publication/188714
37. G. Bressi et al., "Testing the neutrality of matter by acoustic means in a spherical resonator" (2011). https://arxiv.org/pdf/1102.2766
38. J. I. González Hernández et al., "The solar gravitational redshift from HARPS-LFC Moon spectra," *A&A* (2020). https://iac.es/en/science-and-technology/publications/solar-gravitational-redshift-harps-lfc-moon-spectra-test-general-theory-relativity
39. C. M. Will, "New general relativistic contribution to Mercury's perihelion advance," *Phys. Rev. Lett.* 120, 191101 (2018). https://link.aps.org/accepted/10.1103/PhysRevLett.120.191101
40. H. Aspden, *Physics without Einstein* (Sabberton, 1969), chapters 4–7. https://aetherscience.org/category/books/Pwech5.pdf (and Pwech4, Pwech6, Pwech7)
41. H. Aspden, "Power from Space: Inertia and Gravitation," Energy Science Report No. 6. https://aetherscience.org/www-aspden-org/reports/Es6/esr6.pdf
42. H. Aspden, "The Lamb shift for a cavity-resonant electron," *Lett. Nuovo Cimento* 36, 364 (1983). https://aetherscience.org/www-aspden-org/papers/bib/1983c.pdf
43. H. Aspden, "The determination of absolute gravitational potential," *Lett. Nuovo Cimento* 37, 169 (1983). https://aetherscience.org/www-aspden-org/papers/bib/1983d.pdf
44. X. Fan, T. G. Myers, B. A. D. Sukra and G. Gabrielse, "Measurement of the electron magnetic moment," *Phys. Rev. Lett.* 130, 071801 (2023). https://cfp.physics.northwestern.edu/documents/2023MeasurementElectronMangeticMoment.pdf
45. Muon g−2 Collaboration, final Fermilab result (2025), as reported in *CERN Courier*. https://cerncourier.com/fermilabs-final-word-on-muon-g-2/
46. N. Bezginov et al., "A measurement of the atomic hydrogen Lamb shift and the proton charge radius," *Science* 365, 1007 (2019). https://inspirehep.net/literature/1752910
47. A. van Wijngaarden et al., "Improved anisotropy measurement of the Lamb shift in He⁺" (1987). https://scholar.uwindsor.ca/physicspub/138/
48. Gaia Collaboration (S. A. Klioner et al.), "Gaia Early Data Release 3: Acceleration of the solar system from Gaia astrometry," *A&A* 649, A9 (2021). https://openaccess.inaf.it/handle/20.500.12386/29942
49. L. Iorio, "Calculation of the uncertainties in the planetary precessions with the recent EPM2017 ephemerides and their use in fundamental physics and beyond" (2019). https://arxiv.org/abs/1810.13415
50. M. Kramer et al., "Tests of general relativity from timing the double pulsar," *Science* 314, 97 (2006). https://arxiv.org/abs/astro-ph/0609417
51. M. Kramer et al., "Strong-field gravity tests with the double pulsar," *Phys. Rev. X* 11, 041050 (2021). https://arxiv.org/abs/2112.06795
52. H. Aspden, "Atomic Spectra and the Moving Atom," *Aether Science Papers* (Sabberton, 1996), pp. 41–47. https://aetherscience.org/www-aspden-org/books/Asp/4147.htm
53. H. Aspden, *Physics Unified* (Sabberton, 1980), chapters 2 and 3. https://aetherscience.org/book-physics-unified/
54. B. Botermann et al., "Test of time dilation using stored Li⁺ ions as clocks at relativistic speed," *Phys. Rev. Lett.* 113, 120405 (2014). https://arxiv.org/abs/1409.7951
55. S. Reinhardt et al., "Test of relativistic time dilation with fast optical atomic clocks at different velocities," *Nature Physics* 3, 861 (2007), as cited in ref. 54.
56. H. Aspden, "An empirical approach to meson energy correlation," *Hadronic J.* 9, 153 (1986) (1986j). https://aetherscience.org/book-aether-science-papers/aether-science-paper-1986j/
57. D. C. Hom et al., "Observation of high-mass dilepton pairs in hadron collisions at 400 GeV," *Phys. Rev. Lett.* 36, 1236 (1976); its withdrawal: "Oops-Leon", https://en.wikipedia.org/wiki/Oops-Leon
58. H. Aspden, *The Physics of Creation*, 2nd ed. (2003), ch. 3, "The Ubiquitous Muon". https://aetherscience.org/2edpocch3/
59. Particle Data Group, muon mean life τ = 2.1969811(22) × 10⁻⁶ s. https://pdglive.lbl.gov/view/S004T ; Υ(1S) mass 9460.40 MeV (PDG).
