# Aspden's Aether from the Bottom Up, Part 1A: The Quon–Continuum Model, Derived Step by Step

**The model behind Part 1: every assumption labelled, every equation derived, every number reproducible by hand**

By Doug Westmoreland (project lead: direction and review) and Claude, Anthropic (research and analysis) · Version 1.2, 31 October 2026 (1.1 adds section 13, objections considered; 1.2 adds Aspden's own words on the c/2 orbital speed and on the Earth's own aether (sections 1.2–1.3), corrects section 13.4 to test the frame Aspden actually proposed, works through Tutorial Note 18 (section 13.5), and adds three figures) · Supplement to *Aspden's Aether from the Bottom Up, Part 1: The Smallest Units* (v1.5)

---

## Why this document exists

Part 1 tested Aspden's quons and charge continuum. It reported conclusions, but it did not show enough of the model behind them, or the reasons for each modelling choice, for a reader to check the work. This document fills that gap. Every statement is labelled:

- **[A]** Aspden states it (source given);
- **[D]** derived here from [A] statements and standard physics (Coulomb's law, Newton's laws, Maxwell's equations);
- **[M]** a modelling choice made in this analysis, with the reason for it and what would change if it were made differently.

Every number is printed, line by line, by the script `quon_model.py`. Its output labels (W1–W8) are quoted at each step, and each line can be checked on a calculator.

**A correction found by writing this out.** Part 1 version 1.2 (tests U11–U14) treated Aspden's restoring force on a quon as a spring that holds each quon independently. Working through the forces in full (section 4 below) shows that the restoring force is the field of the displaced lattice itself, as Aspden's own derivation of it says. A lattice held only by its own field responds to light like a plasma, not like a set of springs. The consequence is stronger than before:

- a vacuum made of this lattice would block all light below 511 keV, including radio, visible light and X-rays;
- it would cancel static electric fields beyond about 10⁻¹⁰ m;
- equivalently, it would give the photon a mass equal to the electron's, 5 × 10²³ times the measured upper limit.

Part 1 has been revised (version 1.3): U11–U15 are relabelled as Aspden's own resonance picture, and the self-consistent model is added as tests U32–U36.

**A second correction (version 1.2).** Version 1.1 of section 13.4 placed the lattice at rest in the frame of the cosmic background radiation. That was this analysis's choice, not Aspden's. In his picture the Earth carries its own aether, whose electromagnetic frame travels with the Earth but does not turn with it (section 1.3). Section 13.4 now tests that frame. The 370 km/s problem disappears, but the laboratory still moves through the frame at the Earth's surface speed as the planet turns, about 283 m/s at Berlin, and rotating-cavity experiments exclude that by a factor of about 1,500.

---

## 1. What Aspden says

### 1.1 The units and the forces

| Statement | Source |
|---|---|
| The aether is "a uniform continuum of electric charge density σ which is populated by a uniform cubic-structured array of aether lattice particles of unitary charge, here denoted q, and of charge polarity opposite to that of the continuum" | *The Physics of Creation* (POC), ch. 6 |
| An applied field "will displace those charges q through a distance D relative to the continuum charge σ … Since the relative spacing between those charges q will be unchanged by this collective displacement there will be no change in the Coulomb force on any particle due to the action of its neighbours" | POC ch. 6 |
| "By Gauss' theorem a planar slice of charge density σ and thickness D has a total normal electric field density of 4πσD … The restoring force on q is therefore 4πσqD (6.1). This is equal to Vq" | POC ch. 6, eq. 6.1 |
| The stored energy density is then V²/8π (6.4). "Here then is the basis for the displacement currents we associate with Maxwell's theory … one should really think instead in terms of the kinetic energy associated with oscillations of the quon lattice system represented by those waves" | POC ch. 6, eqs. 6.2–6.4 |
| "The continuum and q charge systems, the G and E frames, respectively, are displaced 2r one from the other owing to their relative motion at speed c in circular orbits of radius r given by r = h/4πmc" | POC ch. 7, eq. 7.1 |
| The orbit is held by the same force: 4πσq(2r) = m₀Ω²r | POC ch. 6, eq. 6.5; ch. 7, eq. 7.5 |
| The quon's effective mass is half its Thomson mass: m₀ = q²/3bc² | POC ch. 7, eq. 7.4 |
| The quon's inertial mass is known "from its natural rhythmic motion at the Compton electron frequency and the Maxwell displacement field theory governing that motion" | "The Fifth Question" (2001) |
| "The theory assumes the continuum proper has zero energy"; "I must admit that I have no idea how to explain or justify the existence of the continuum" | POC ch. 7, p. 113 |
| The vacuum has a natural frequency at the Compton electron frequency; a "dual displacement" makes it non-dispersive below the pair-creation frequency | *Wireless World*, 1982 (Lecture 24) |

### 1.2 Why each frame moves at c/2

Every size in the model starts from the orbit radius r = ħ/2mₑc (POC 7.1). Aspden obtains it from two statements:

- the two frames orbit at the electron's Compton frequency, ħΩ = mₑc² [A, POC 6.14];
- they move at the speed of light relative to each other [A, POC 6.6]. Because they circle a common centre on opposite sides, with equal radii (Figure 1), each then moves at c/2, and Ω·2r = c gives r = c/2Ω = ħ/2mₑc [A, POC 6.13–6.15].

The second statement is a postulate, and Aspden says so. His texts, in order:

| Work | What he says |
|---|---|
| *The Theory of Gravitation* (1959 manuscript, published 1960; web reprint with 1998 notes) | From his balance equations (5)–(8), v = u and r = R: "The relative velocity between the particles and the continuum is therefore 2v. When the aether is disturbed and the disturbance is propagated relative to the aether particle system or the continuum this velocity 2v will equal the propagation velocity c. Hence v is equal to c/2." His 1998 note: "The essential point is that the relative velocity between the system of aether particles and the medium constituting the background continuum is assumed to be the speed of light. The consequences of this assumption are the test of this, but one can appeal to logic … given that its components have a relative motion that has a universal value, it seems logical to take that as the speed of light." |
| *Physics without Einstein* (1969), ch. 4, 6 and 7 | Adding energy to space enlarges both orbits and raises the orbital speed v; because the mass-energy density 2ρc² is conserved, "it also follows that c has increased in proportion to v … Later, it will be proved that c is the relative velocity of the E and G frames, making v=½c" (the site's scanned text reads "3c"). Ch. 7: "the relative velocity of the space-time frames can vary slightly, adjusting the speed of light". The promised proof was not found. Ch. 6, eq. 6.7, uses the relation as a condition: "if the relative velocity between the two systems … is c exactly". |
| *Physics Unified* (1980), ch. 5 | "a model of the aether which carries matter universally in synchronous circular orbital oscillations in balance with something in space in synchronous countermotion at the relative speed of light, the frequency being mₑc²/h"; "a relative velocity of light applies for relative motion of the q charges and σ"; at eqs. 86–93, "As their relative velocity is c, they move at a speed ½c in orbit … Thus: r = h/4πmₑc (93)". |
| *Physics Unified* (1980), ch. 2 (a different half-speed) | From the retardation of the Coulomb interaction he obtains ½c as "the displacement speed of charge in the propagation direction", which "is not to be confused with the propagation of electromagnetic waves or electric field disturbance". Later: "a general propagation speed c/k, where k is a constant believed by the author to be 2". |
| *The Physics of Creation* (2003), ch. 6 | "If we now ask how the aether determines a characteristic speed c it is fairly evident that a likely candidate is the relative velocity between the E-frame and the G-frame, meaning the quantity Ω(2r) and so we derive the relationship: r = h/4πmₑc (6.6)". At 6.13–6.15: "The E frame and the G frame describe orbits of equal radius r. As their relative velocity is c, they move at speed c/2 in orbit." |
| *The Physics of Creation* (2003), ch. 5 | The aether's kinetic energy density (2ρ)(c/2)²/2 (5.16), from p. 82 of *Physics without Einstein*, "on the assumption that it has two systems, each of mass-density ρ, moving at speed c/2, but having a relative velocity c". Newtonian mechanics applies at that speed, he says, because the motion "is strictly harmonious, having a fixed frequency". |
| Tutorial Notes 18 (1999) and 20 | Note 18: the quons move in orbit "at a speed c/2 so as to move at a speed c relative to the gravitons", and quons that leave the lattice to balance its momentum "travel at the speed c/2" (section 13.5). Note 20: "c being speed relative to the E-frame, whereas c/2 is the speed relative to the I-frame, the inertial frame". |

![Figure 1. Aspden's two frames and the c/2 postulate](https://aetherscience.org/aspden-analysis-files/fig-two-frames.png)

**Figure 1.** (a) One cell of Aspden's aether. The quon (E frame) and the continuum (G frame) circle a common centre at the same angular speed Ω, on opposite sides and on equal radii r, so their relative speed is Ω·2r. Aspden's postulate sets that to c, so each moves at c/2. (b) The force balance fixes Ω, the electron's Compton frequency, whatever the radius. The relative speed grows with the radius, and the postulate picks the radius at which it equals c: r = ħ/2mₑc.

What follows from the postulate:

- **Nothing in the force balance picks the radius.** The orbit is the plasma oscillation of section 5, Ω² = 8πnq²/m₀, and r does not appear in it: every radius has the same frequency (Figure 1b). Aspden notes this property in *Physics without Einstein* ch. 4: his two frames form a system "capable of disturbance without change of the periodic time parameter". So the radius is set by the postulate alone. [D, agrees with A]
- **In his own chain it reaches less than it seems.** Redoing POC 7.19–7.26 with a relative speed s·c in place of c gives ħc/q² = 144π(r/d)/s, m₀/mₑ = (4/9)(r/d)²/s² and N = (9/8)³s⁶(d/r)⁶. For a given N, s cancels: 1/α = 108π(8/N)^(1/6), and d, m₀, b and E₀ are unchanged. Only r and r/d scale with s. The postulate reaches α only through the zero-energy condition (POC 7.18), which picks N = 1843 for any s from 138 ppm below 1 to 41 ppm above it (W14). It cannot be the source of the 0.6 ppm gap (Part 1, U41). [D]
- **There is no steady stream for light to ride on.** The relative velocity of the two frames turns with the orbit, sweeping through every direction in the orbital plane 1.24 × 10²⁰ times a second. In the model, light's speed comes from the field equations of section 6, not from the orbital speed. [D]
- **The radius is a real scale.** ħ/2mₑc is the amplitude of the electron's trembling motion (zitterbewegung) in Dirac's theory, which Aspden cites (POC ch. 6). Dirac's trembling has twice Aspden's frequency, and speed c rather than c/2 (Part 1, U01–U02).

### 1.3 The Earth's own aether

Near the Earth, Aspden does not put the aether at rest in one universal frame. His picture:

| Work | What he says |
|---|---|
| *The Theory of Gravitation* (1960) | "The negative result provided definite proof that the earth has an aether of its own, a medium which moves with the earth through some surrounding medium." |
| *Physics Unified* (1980), ch. 9 | "The optical experiments in Chapter 3 were reconciled by introducing the idea of a moving electromagnetic reference frame. This is a non-rotating frame of reference which moves linearly with the space lattice and which is formed by the rotation of a whole region of the lattice." Lattice particles freed at the leading surface travel through the region to the rear: "Their momentum will balance the forward momentum of the whole region." |
| Tutorial Note 18 (1999) | The aether, "when disturbed by being dragged along by body Earth reacts to keep its net linear momentum zero"; the backflow moves at c/2 (section 13.5). |
| Lecture 8 | "Michelson found he could detect the Earth's rotation relative to that non-rotating ether by his light wave interference experiments jointly with Gale in 1925." |
| Reply to Allyn Shell (Feedback Note 4) | "a sphere of aether lattice such as is coextensive with body Earth and rotates with body Earth", inside an enveloping space domain with its own spin axis. |
| 1983b | "If the West-East speed of a laboratory, owing to its rotation about the Earth's axis (some 350 m/s at 40oN), shows up in speed-of-light anisotropy measurements confined within the laboratory, then it is submitted that this would clearly refute Einstein's theory." |

So the lattice sphere inside the Earth turns with it, but the frame that light travels in moves with the Earth and does not turn. Section 13.4 tests that frame (Figure 2), and section 13.5 works through Note 18's backflow (Figure 3).

---

## 2. The model, piece by piece

| Element | Value used | Label | Reason | If chosen differently |
|---|---|---|---|---|
| Units | Gaussian formulas, as Aspden writes them; SI numbers with q² → e²/4πε₀ | [M] | Keeps his equations recognisable | No effect |
| Quons | Point charges q = e on a simple cubic lattice, spacing d | [A] | His description | A finite size b changes local forces by about (b/d)³ = 5 × 10⁻⁵ of a cell; neglected for the response to fields |
| Continuum | Uniform charge density −σ, σ = nq, n = 1/d³ (one quon's charge per cell) | [A] | Neutrality (POC 7.7) | — |
| Continuum's motion | Moves only as a rigid frame (the G frame); does not compress locally | [M] | Aspden describes it as a frame. He raises compression as one alternative (POC p. 113), and his third question favours a continuum that "resists compression" | A compressible continuum would add a longitudinal sound-like response; the transverse (light) results below do not depend on it |
| Inertia of the continuum | M per cell = m₀ | [D] | Both frames orbit with the same radius r about a common centre, so their momenta balance only if their inertias are equal | With M ≫ m₀ the orbital frequency would be ħω_p = 361 keV instead of 511 keV; no conclusion changes |
| Forces | Electromagnetic only: Coulomb's law between all charges, and Maxwell's equations for fields that change | [M] | Aspden names no other force. His own derivation of 6.1 uses Gauss's theorem, which is Coulomb's law | Section 6.7 discusses what a different force law would have to do |
| Dynamics | Newton's laws for small displacements about the steady orbit; the orbital speed c/2 is absorbed into m₀, as Aspden does | [A] + [M] | Small disturbances of a steady motion are linear | Relativistic corrections at c/2 are about 25%; they would shift numbers but not the sign of any effect below |
| Wavelengths | Long compared with d (kd ≪ 1) for the response to light, except section 8 | [M] | Visible light is 8 × 10⁵ lattice spacings long | Short wavelengths are treated by the full lattice sums (section 10) |

---

## 3. The numbers, one formula per line

Each line is printed by `quon_model.py` (W2).

1. r = ħ/(2mₑc) = 1.9308 × 10⁻¹³ m. [A] eq. 7.1, which is h/4πmₑc. It combines the Compton frequency with the postulate that the two frames move at c relative to each other (section 1.2).
2. Ω = (c/2)/r = 7.76344 × 10²⁰ rad/s. [A] speed c/2 on radius r. So ħΩ = 510.999 keV = mₑc².
3. r/d = (3/4)(8/1843)^(1/6) = 0.302916. [A] eqs. 7.24–7.26.
4. d = r ÷ (r/d) = 6.37403 × 10⁻¹³ m.
5. n = 1/d³ = 3.86151 × 10³⁶ quons per m³.
6. σ = ne = 6.18681 × 10¹⁷ C/m³.
7. The restoring force per metre of displacement, Aspden's 4πσq, is in SI k = σe/ε₀ = 1.11951 × 10¹⁰ N/m.
8. The orbit balance m₀Ω²r = k(2r) [A, 7.5] gives m₀ = 2k/Ω² = 0.0407813 mₑ, so m₀c² = 20.8392 keV.
9. The quon radius from m₀ = q²/3bc² [A, 7.4] is b = q²/(3m₀c²) = 2.30329 × 10⁻¹⁴ m.
10. The electron's Thomson radius is a = 2q²/(3mₑc²) = 1.87863 × 10⁻¹⁵ m.
11. N = (b/a)³ = 1843.0, recovering his integer. This shows the chain is closed.

Steps 8 to 11 are the algebra of POC 7.5–7.26. They need no assumption beyond Aspden's own.

---

## 4. The force on a quon when the lattice shifts

This is the step that decides how the lattice responds to light, so it is set out in full.

Suppose every quon moves by the same small vector u relative to the continuum. This is Aspden's "collective displacement". The force on one quon has three parts.

**4.1 Its own cell's continuum.** Take the continuum belonging to that quon's cell as a uniformly charged sphere. By Gauss's law, the field at distance u from the centre of a uniformly charged sphere of density σ is (4π/3)σu, directed back toward the centre (opposite charges attract). So this part of the force is −(4π/3)σq u. [D]

**4.2 All the other quons and their cells.** Each other cell is now a quon displaced by u from its own patch of continuum: a neutral cell carrying a dipole moment qu. Together they form a uniformly polarized medium with polarization P = nqu = σu, from which our cell has been cut out. The field at the centre of a spherical hole in a uniformly polarized medium is the medium's average (macroscopic) field E plus (4π/3)P. This is the standard Lorentz cavity field. In a cubic lattice, the dipoles near the hole contribute nothing further, by symmetry. [D]

**4.3 The sum.** The force on the quon is q[E + (4π/3)σu − (4π/3)σu] = qE.

The two local terms cancel exactly. A quon has no spring of its own; it feels only the average field of the whole system. Aspden says the same in words: "there will be no change in the Coulomb force on any particle due to the action of its neighbours." [D, agrees with A]

**4.4 Check by exact lattice sums.** The Ewald method (section 10) computes the forces in the endless lattice without the sphere approximation. Its results:

- for a lattice wave of very long wavelength moving along its direction of travel, the restoring force corresponds exactly to the plasma frequency (W3 line 5: `1.000000`);
- for one moving across its direction of travel, it is zero (line 6: `-1.31e-10`);
- for a single quon moved while all others stay put, the force constant is one-third of the plasma value (line 7: `0.33333`), which is the sphere result of 4.1.

So 4.1–4.3 are confirmed.

**4.5 What the average field E is.** It is produced by the displacement itself. A displaced slab of quons uncovers a layer of continuum charge on each face, which is the planar slice Aspden describes. Its field, by Gauss's law, is E = −4πσu = −4πP. That is exactly his 6.1, and it holds:

- for motion along the direction in which the displacement varies (Gauss's law);
- for uniform motion in an endless medium in any direction (Maxwell's displacement current, see 6.2 with k → 0).

So **Aspden's restoring force 4πσqD is the field of the displaced lattice acting back on the quons, not a separate spring.** [D] That is the whole difference between Part 1 version 1.2 and this document.

---

## 5. The orbit

Write u_E for the displacement of the quon frame and u_G for that of the continuum frame. Per cell, Newton's law gives:

```
m₀ ü_E = q E          M ü_G = −q E          E = −4π P,   P = nq (u_E − u_G)
```

Subtracting the second from the first and multiplying by nq:

```
P̈ = −4π n q² (1/m₀ + 1/M) P = −Ω_pl² P
```

With M = m₀, Ω_pl² = 8πnq²/m₀. Every quon and every piece of continuum oscillates at Ω_pl, and a circular orbit is two such oscillations a quarter-cycle apart.

- **Same as Aspden's.** His 7.5, m₀Ω²r = 4πσq(2r), says Ω² = 8πσq/m₀ = 8πnq²/m₀. That is the same equation (W4 line 3: Ω_pl/Ω = `1.0`).
- **Numbers.** With the quons alone moving (continuum held still), ħω_p = 361.331 keV. With both frames moving, ħΩ_pl = 510.999 keV (W4).

**Conclusion of this step.** Aspden's orbit is the uniform plasma oscillation of the two frames: two charge systems swinging through each other, held by the field their separation creates. This is a credit to Aspden. The orbit is consistent with Coulomb's law and Newton's laws, and its frequency comes out at exactly the electron's Compton frequency once his m₀ is used.

---

## 6. How the lattice responds to light

**6.1 Driven motion.** A light wave brings an electric field E that varies as e^(−iωt). By section 4, each quon feels qE and each piece of continuum −qE, with no other local force. So:

```
P̈ = n q² (1/m₀ + 1/M) E = (Ω²/4π) E     →     P(ω) = −(Ω² / 4πω²) E
```

This is the response of a plasma. [D]

**6.2 Maxwell's equations with this response.** For a wave varying as e^(i(kx−ωt)), Maxwell's equations give

```
k² c² E = ω² (E + 4πP) = ω² (1 − Ω²/ω²) E     →     c² k² = ω² − Ω²
```

- **Uniform motion.** For k = 0 this returns ω = Ω, the orbit of section 5. The uniform field is then E = −4πP, as stated in 4.5.
- **Light below Ω.** For ω < Ω, k² is negative, so no wave travels. The field dies away over a length c/√(Ω² − ω²), which for visible light is 3.86 × 10⁻¹³ m. That is the orbit diameter 2r (W5 lines 1–2).

**6.3 What this predicts.** Printed by W5:

| Photon | ε = 1 − Ω²/ω² | Travels? | Group speed / c |
|---|---|---|---|
| Radio, 100 MHz | −1.5 × 10²⁴ | no | — |
| Visible, 500 nm | −4.2 × 10¹⁰ | no | — |
| X-ray, 10 keV | −2,610 | no | — |
| Gamma, 100 keV | −25 | no | — |
| Cs-137 gamma, 661.7 keV | 0.40 | yes | 0.635 |
| 1 MeV | 0.74 | yes | 0.860 |
| 35 MeV | 0.9998 | yes | 0.99989 |
| 6 GeV | 1.0 | yes | 1 − 3.6 × 10⁻⁹ |

Radio, light and X-rays could not cross even a millionth of a millimetre of such a vacuum. Above 511 keV, light would travel, but slowly and with strong dispersion. Between the 35 MeV and 31 GeV photons of the burst GRB 090510, the speed difference would be 1.1 × 10⁻⁴ of c, 3 × 10¹³ times the observed limit (W5 line 3). The 6 GeV laboratory speed measurement (Alväger 1964, ±1.3 × 10⁻⁴) cannot tell this model apart from c. Everything below 511 keV can, and it rules the model out.

**6.4 The same thing as a photon mass.** The relation c²k² = ω² − Ω² is the wave equation of a photon with rest energy ħΩ. So Aspden's vacuum, treated with Coulomb's and Maxwell's laws, gives light a rest mass equal to the electron's, 511 keV (W6). The measured upper limits are:

- 1 × 10⁻¹⁸ eV (Particle Data Group, from the solar wind's magnetic field, Ryutov 2007), 5 × 10²³ times smaller;
- 1 × 10⁻¹⁷ eV in the laboratory (Lakes 1998);
- 1 × 10⁻¹⁴ eV from a direct test of Coulomb's law (Williams, Faller and Hill 1971).

**6.5 Static fields.** The same physics applies to a steady field. Using the exact lattice sums (section 10), an applied field that varies over a distance λ is reduced to the fraction 1 − ω_p²/ω_L(k)² of itself, where ω_L is the longitudinal lattice frequency at k = 2π/λ (W7):

| Field variation | Fraction of the applied field left |
|---|---|
| Over 200 lattice spacings (1.3 × 10⁻¹⁰ m) | 0.003% |
| Over 20 spacings | 0.26% |
| Over 4 spacings | 5% |
| Over 2 spacings | 9% |

So the field of a charge would be cancelled beyond about 10⁻¹⁰ m. Coulomb's law has been verified from atomic scales to laboratory scales and beyond, so a vacuum of this kind is excluded by the plain existence of electrostatics.

Aspden's own 6.1 says the same thing in other words. The quon stops moving when the restoring force 4πσqD equals the applied force Vq. In Coulomb's law that is the point at which the total field at the quon is zero, and any other charge placed there would feel the same zero field.

**6.6 If there is no separate vacuum term.** Aspden says the displacement current is the quon displacement. Taken literally, Maxwell's equations then lose their own vacuum term, and the wave equation becomes c²k² = −Ω². In that case nothing propagates at any frequency.

**6.7 The dilemma, and what Aspden's text would need.**

- **If the quons respond to fields,** as they must if they carry the displacement current, then by sections 4–6 the vacuum is a plasma. It blocks light below 511 keV and screens charges.
- **If the quons do not respond,** they carry no displacement current, and the claim of POC ch. 6 fails.

The only way between the two is a force law in which the field of the displaced lattice acts on the quons but not on ordinary matter. Aspden's ch. 6 computes how the quons move under an applied field V, and identifies their displacement with the field's energy. It does not say what an ordinary charge then feels. Reading it as "matter still feels V" requires exactly that unstated rule, and the rule would break Coulomb's law, because the uncovered continuum charge is ordinary charge. Reading it with Coulomb's law gives section 6.5. His 1982 "dual displacement" idea, a second structure moving to cancel the first, would make the net polarization zero. But then the quons again carry no displacement current. Neither version is given in equations, so neither can be tested.

**6.8 Aspden's 1982 resonance picture, for comparison.** In 1982 Aspden described the vacuum as having a natural frequency at the Compton frequency. Part 1 version 1.2 modelled that literally: each quon held by its own spring of frequency Ω. That gives ε = 1 + Ω²/(Ω² − ω²) (reading A) or Ω²/(Ω² − ω²) (reading B), with transparency below 511 keV and a stop band or cutoff above it (Part 1, U12). Section 4 shows that the lattice he describes has no such spring: the local forces cancel. So readings A and B describe his words in 1982, not his model. Both are excluded anyway (Part 1, U13–U14), and so is the self-consistent plasma model. Every version of a vacuum built from charges with his inertia and spacing fails with light; they differ only in which energies they get wrong.

---

## 7. What changed in Part 1

| Test in Part 1 | Problem | Change |
|---|---|---|
| U11 (v1.2), static polarization equals the vacuum's (credited) | The restoring force used is the lattice's own field, so "P = ε₀E" means the applied field is cancelled inside: complete screening, not a vacuum | Withdrawn as a credit; replaced by U36 (screening) |
| U12 (v1.2), single-displacement response (readings A and B) | Assumed a spring independent of the field (Aspden's 1982 words), which section 4 shows his lattice lacks | Kept, relabelled "Aspden's resonance picture"; the self-consistent response is U34 |
| U13, U14 (v1.2) (Cs-137, SN 2014J, Alväger, GRB 090510) | Tested the resonance picture | Kept for that picture; U34–U35 test the self-consistent model, which fails more severely |
| U15 (v1.2), scale needed to pass GRB 090510 | Oscillator form | Kept; the plasma model needs ħΩ below 10⁻¹⁸ eV (U35), which would need r larger than 10¹¹ m |
| U10 (v1.2), natural frequency | Unchanged | The plasma frequency of the two frames is Ω (U33) |
| U40 (v1.4), the lattice as a fixed reference frame | Tested the cosmic background's frame, which Aspden did not propose | Version 1.5 tests his Earth-carried frame as well: excluded by a factor of about 1,500 through the Earth's rotation, against 7.6 × 10¹⁰ for the background's frame |
| None (new in v1.5) | The c/2 postulate was folded into input I1 | I1 split into I1a (Compton frequency) and I1b (relative speed c); U41 shows I1b cancels out of α, N and d |

The conclusion that the lattice cannot carry light is unchanged. It now rests on a model whose every step is shown, and it is stronger: the self-consistent model fails for all light below 511 keV, not only at gamma-ray energies.

---

## 8. The lattice cutoff (Part 1, U16)

A wave on a discrete lattice is carried from site to site. Take the simplest case: a wave equation with spacing d, where each site couples to its neighbours. The displacement at site j obeys ü_j = (c²/d²)(u_{j+1} − 2u_j + u_{j−1}). Trying u_j = e^(i(kjd − ωt)) gives ω² = (4c²/d²)sin²(kd/2), so ω = (2c/d) sin(kd/2). [D]

- **The cutoff.** Waves exist only up to ω = 2c/d, an energy of ħ·2c/d = 0.62 MeV, and wavelengths shorter than 2d (0.97 MeV) repeat longer ones.
- **The slowing.** For small kd, sin x ≈ x − x³/6 gives a speed deficit of (kd)²/24.
- **Direction.** In three dimensions the same sum runs over the three lattice directions, so the deficit depends on direction, with a [100]–[111] difference of (kd)²/36.
- **Comparison.** Photons of 1.4 PeV are observed, with wavelengths 1.4 × 10⁹ times shorter than 2d.

*Choice made.* [M] Nearest-neighbour coupling. Long-range Coulomb coupling changes the coefficient of the slowing, but not the existence of a cutoff, which follows from the spacing alone.

---

## 9. The photon unit (Part 1, U24, U30, U31)

**Counting.** The 3×3×3 block spins about the lattice axis through its centre. Its 27 quons sit at (x, y, z) with each coordinate −d, 0 or +d. The distance from the axis is ρ = √(x² + y²):

- three quons have ρ = 0;
- twelve have ρ = d, with (x, y) = (±d, 0) or (0, ±d), three z values each;
- twelve have ρ = √2 d.

So I = Σm₀ρ² = 12m₀d² + 12 × 2m₀d² = 36m₀d², Aspden's value. [A, checked]

**Spin rate.** Aspden says the unit radiates at four times its spin rate and that its energy is Ω times its angular momentum. So it spins at Ω/4 = c/8r. [A]

**Speeds.** v = ρΩ/4. With d/r = 1/0.30292 this gives 0.413c at ρ = d and 0.584c at ρ = √2 d. [D]

**The energy theorem.** For any particle moving in a circle of radius ρ at angular rate ω:

- its angular momentum is mρ²ω;
- its kinetic energy is ½mρ²ω², which is ½ω × (angular momentum).

Summing over particles, the kinetic energy is ½ωL for any collection of circular motions at the same ω, rigid or wave-like. With L = ħ and ω = Ω/4, KE = ħΩ/8 = 63.9 keV. The 27 quons' rest energy is 27 × 20.84 = 562.7 keV, so the kinetic energy is 11.4% of it, and the rms speed is √(2 × 0.1135) c = 0.476c. [D]

**The relativistic correction.** Aspden relied on the formula for increase of mass with speed (*Physics Unified* ch. 4). Weighting each quon's mass by 1/√(1 − v²/c²) raises the angular momentum by 18.7%. [D]

**Spreading the motion.** If the same angular momentum is shared by N quons with the same total Σρ², each moves at 1/√N of the speed. The mass correction then falls below 0.41 ppm only when N exceeds 7.5 million. But then the sum Σρ² is set by requiring the angular momentum to be ħ, not by the 3×3×3 geometry, so Aspden's 36 would have to be put in by hand (U31). [D]

---

## 10. The endless-lattice sums (Part 1, U27–U28)

**What is computed.** For a wave of displacement with wavevector k, each quon is pulled by the Coulomb forces of every other quon and of the continuum. The coefficients of those pulls form a 3×3 matrix D(k), the dynamical matrix. Its eigenvalues are the squared frequencies ω² of the three lattice waves at that k. A negative eigenvalue means that displacement grows instead of oscillating: the lattice is unstable to it.

**Why the Ewald method.** The sums of 1/r³ forces over an endless lattice converge only conditionally: the answer depends on the order of summation, which physically means the shape of the sample. The Ewald method splits each Coulomb term into a short-range part, summed directly, and a smooth long-range part, summed over the reciprocal lattice. This gives the unique answer for an endless medium. The formula used is D(k) = (4π/3)·1 − S(k), with S(k) = Σ_{R≠0} ∂_a∂_b(1/R) e^(ik·R) evaluated by Ewald summation (`lattice_dynamics.py`).

**Checks that the code is right:**

1. The trace of D(k) equals the plasma frequency squared at every k. This is required for Coulomb forces, whose three squared frequencies always add up to the plasma frequency squared: `1.000000` at five random k.
2. The results do not depend on the Ewald splitting parameter: identical eigenvalues for three values.
3. A single quon moved alone has one-third of the plasma value (section 4.4).
4. A body-centred cubic lattice computed the same way is stable everywhere.

**Result.** For the simple cubic lattice, 18.4% of all modes over the Brillouin zone have ω² < 0. The worst is a shear wave at k = (π/d, π/d, 0), with ω² = −0.093 ω_p².

*Choices.* [M] Electric forces only, with a rigid continuum. Magnetic forces between quons moving at c/2 are about 25% of the electric ones and could change this. That would need a relativistic calculation not attempted here.

---

## 11. Magnetic coupling in the photon unit (Part 1, U29)

**The interaction.** Two charges moving at speeds well below c interact, beyond Coulomb's law, through the Darwin term L = (q²/2c²r)[v_i·v_j + (v_i·n)(v_j·n)], where n is the unit vector between them. This is the first correction to Coulomb's law from the finite speed of the field (it follows from the Liénard–Wiechert potentials expanded to order v²/c²). For charges moving in parallel the term is positive and acts like extra kinetic energy.

**Added inertia.** For the block spinning at rate ω, every vᵢ is ω times a fixed vector. So L_D = (q²ω²d/2c²)S, where S = 97.44 is the sum over the 351 pairs (lattice units). The angular momentum gains ∂L_D/∂ω = 2L_D/ω, which is an added moment of inertia I_D = (q²d/c²)S. Since q²/c² = 3bm₀ (eq. 7.4), I_D/I = (3b/d)S/36 = 29.3%.

**Screening.** The rest of the lattice responds to this magnetic field. A plasma excludes fields that change more slowly than its plasma frequency over the skin depth c/ω_p (from 6.2: such fields decay as e^(−x√(Ω²−ω²)/c)). With the continuum held, c/ω_p = 0.857d. Multiplying each pair by e^(−r/0.857d) gives I_D/I = 9.1%.

*Choices.* [M] The Darwin term is leading order only, and the screening is modelled as a simple exponential. Both are approximations; at 0.4–0.6c the next order is not small. The conclusion needs only the size: tens of percent, against the 0.000041% that would close the α gap.

---

## 12. Which conclusions depend on which choices

| Conclusion | Depends on | If that choice changed |
|---|---|---|
| The orbit is the plasma oscillation at exactly Ω (credit) | Aspden's m₀ and 7.5; Coulomb's law; M = m₀ | With M ≫ m₀, ħω = 361 keV instead of 511 keV; still a plasma oscillation |
| Quons feel only the average field (no local spring) | Coulomb's law; cubic symmetry | Only a non-cubic lattice, or a non-Coulomb force acting on quons alone, gives a local spring |
| Light below 511 keV cannot travel; photon mass mₑ | The above, plus Maxwell's equations | Needs a force law that makes the lattice's field act on quons but not on matter (6.7), which Aspden does not state |
| Static charges screened beyond about 10⁻¹⁰ m | The same | The same |
| Simple cubic lattice unstable | Electric forces only; rigid continuum | Magnetic forces at c/2 might stabilise it; untested |
| Photon unit inertia off by 10–30% | Aspden's spin rate Ω/4 and 27 quons; his mass–speed formula; Darwin term | A spread-out wave lowers the speeds but removes the geometric 36 |

---

## 13. Objections considered

Doug Westmoreland raised five objections to sections 4–6 and 13.4.

- **Restoring forces.** There need not be any restoring force on the quons.
- **The medium flexes.** The aether's purpose is to give electromagnetic waves a medium to travel against, a reference frame. Normally it has zero net force and motion, but it must flex to carry waves.
- **Background motion.** The quons may be in some periodic motion, driven for example by the cosmic background radiation.
- **The reference frame.** Implicit in the second point: the medium itself defines the frame against which light travels.
- **The Earth's own aether** (raised after version 1.1 of 13.4). The aether moves with the planet, in rotating disks, and this is where Aspden's c/2 comes in.

Each is taken in turn. The numbers are printed by `quon_model.py`, blocks W9–W13.

### 13.1 No restoring force

This agrees with section 4, which found exactly that: in equilibrium, and under any uniform shift, the local forces on a quon cancel, so it has no spring of its own. The plasma result does not come from a restoring force. It comes from charged particles with mass responding to the wave's own electric field. The plasma frequency, ω_p² = nq²/ε₀m, contains only the density, the charge and the mass. No spring constant appears (W9 line 1).

The Earth's ionosphere shows this. It contains about 10¹² free electrons per cubic metre, with nothing holding them in place, and it reflects radio waves below about 9 MHz (W9). That is why shortwave radio can skip around the world. Aspden's quons are the same kind of medium with a far higher density of charge per unit mass, so the same formula puts their cutoff at 361 keV, or 511 keV with the continuum moving too. Removing restoring forces makes the lattice more plasma-like, not less. [D]

### 13.2 The medium flexes

A lattice of charges in a continuum can flex in two ways, and both were computed.

- **Polarization: quons shift together relative to the continuum.** This is the displacement Aspden uses for the displacement current (POC ch. 6). It is the plasma response of sections 5–6, which blocks light below 511 keV.
- **Shear: neighbouring quons shift relative to one another.** This is a crystal's elastic flexing, and it carries shear waves whose speed is set by the stiffness and the mass density. The stiffness comes from the quons' Coulomb repulsion, and the exact lattice sums give it directly (W10):

| Direction of travel | Shear-wave speeds |
|---|---|
| [111] (body diagonal) | 0.215c, 0.215c |
| [110] (face diagonal) | 0.279c, and one unstable (0.134c × i) |
| [100] (cube axis) | both unstable (0.134c × i) |

For light to be a shear wave of this lattice, three things would have to change:

- the lattice would need to be 13–22 times stiffer;
- it would need to be stable along the cube axes;
- its wave speed would need to be the same in every direction to 1 part in 10¹⁷ (main paper, section 3).

The mass to be moved is 143 g/cm³ (W10 line 4). The stiffness that gives c is not the stiffness of the lattice Aspden describes. [D]

### 13.3 Background motion

Aspden already gives every quon a large periodic motion: the orbit at c/2, 149,896 km/s, at the Compton frequency.

- **The background's share is tiny by comparison.** At 2.725 K, kT is 2.3 × 10⁻⁴ eV. A free quon would move at 55 km/s. Within the lattice its thermal amplitude is 5.8 × 10⁻¹⁷ m, or 0.0001 of the spacing (W11).
- **The crystal is nowhere near melting.** Its coupling parameter q²/(a kT) is 1.6 × 10⁷, against about 175 at melting.
- **No motion of this kind changes the response.** The response to a new wave is linear, so it adds to whatever motion is already present and is unaffected by it. This holds as long as the motions are small enough that the forces stay proportional to the displacements, which these are by a wide margin.

So background-driven motion, or any steady periodic motion, does not change sections 5–6. [D]

Aspden himself linked the 2.7 K background to a particle of about his quon's mass. His 1983 "absolute gravitational potential" took kT = φm* with m* = 0.04 mₑ (main paper, section 9.4).

### 13.4 The medium as light's reference frame

Version 1.1 of this section put the lattice at rest in the cosmic background's frame. That was this analysis's choice. Aspden's own frame is carried with the Earth (section 1.3). Figure 2 compares the three possibilities, and W12 prints the numbers.

- **(a) At rest in the background's frame.** The Earth moves through it at 369.8 km/s (Planck 2018). Without length contraction, light's speed in the laboratory would depend on direction by about ½(v/c)² = 7.6 × 10⁻⁷, changing as the Earth turns. Rotating optical and microwave cavities see nothing at about 10⁻¹⁷ to 10⁻¹⁸ (Herrmann et al. 2009; Nagel et al. 2015), 7.6 × 10¹⁰ times below. This is not Aspden's frame; it is kept for comparison.
- **(b) Aspden's: carried with the Earth, not turning with it.** The 370 km/s disappears, because the frame travels with the Earth, and ring lasers sense the Earth's rotation against it, as he intended. But a laboratory on the turning Earth moves through the frame at the surface speed: 283 m/s at Berlin, 356 m/s at 40°N (his 1983 "some 350 m/s"). He wrote that if this speed showed up in light-speed measurements confined to the laboratory, "this would clearly refute Einstein's theory". The rotating cavities in Berlin looked for exactly that signal, fixed in the laboratory at twice the turntable rate. Without length contraction it should be ½(v/c)² = 4.4 × 10⁻¹³; it is below 3 × 10⁻¹⁶, a factor of about 1,500 (W12 lines 5–9; main paper section 3.1). The largest steady flow of the frame past the laboratory that this allows is about 7 m/s.
- **(c) Turning with the Earth: a co-rotating disk or sphere of aether.** Nothing flows past the laboratory, so the cavities see nothing. But a ring laser fixed to the ground would then sense no rotation, because light's frame would turn with the instrument. The Wettzell ring laser senses the Earth's full rotation to 48 parts per billion (main paper section 3.3).
- **In between.** If ring lasers sense the full rotation, Stokes's theorem fixes the average flow of the frame past the ground, round Berlin's latitude circle, at 283 m/s: 38 times the cavity limit (W12 lines 13–14). No mixture of (b) and (c) passes both experiments.
- **The one escape** is an aether in which moving rulers and clocks contract and slow exactly as relativity says (Lorentz's aether). That aether makes every prediction relativity makes and cannot be detected (main paper, section 3.3).

![Figure 2. Three choices for the frame light travels in near the Earth](https://aetherscience.org/aspden-analysis-files/fig-earth-frames.png)

**Figure 2.** Three choices for the frame light travels in near the Earth, seen from above the North Pole. Blue dots: the aether lattice. Dotted circle: Berlin's latitude. Black square: a laboratory. (a) The lattice at rest in the cosmic background's frame (version 1.1 of this section; not Aspden's). (b) Aspden's frame, carried with the Earth but not turning: the laboratory crosses it at 283 m/s. (c) A disk of aether turning with the Earth. Each fails one experiment (W12).

### 13.5 Tutorial Note 18: the backflow at c/2

This is where Aspden's c/2 meets the Earth's moving aether. Note 18 (1999) quotes *Physics Unified* (p. 67) and argues in four steps (Figure 3; numbers in W13):

1. **Light's speed depends on the lattice's density.** c₁ = √(P/ρ) (59), where ρ is the lattice's mass density, and n = c/c₁ (60). A thinner lattice carries light faster.
2. **The moving lattice sheds a backflow.** When the Earth's region of lattice moves at v, "some of the lattice substance will be shed to establish the counterflow at velocity u", so that the aether's total momentum stays zero: uk + v(1 − k) = 0 (61), where k is the shed fraction. The faster the backflow, the smaller the fraction needed.
3. **The region is thinner, so light is faster.** n² = 1 − k (62). To first order, c/n = c(1 + k/2) = c − vc/2u, so light gains v × c/2|u|.
4. **The backflow moves at c/2.** Quons that leave the lattice keep the speed they had in orbit, "meaning that u has the value c/2". Only this value makes the gain exactly v. Light then moves at c + v in the direction of the Earth's motion, which is c relative to the Earth. A backflow at c would give a gain of v/2, and one at c/4 a gain of 2v (Figure 3b).

So c/2 enters at step 4. The quons' orbital speed, which comes from the postulate of section 1.2, is what makes the drag complete rather than partial. For the Earth's orbital speed of 29.8 km/s the shed fraction is 0.0002 (W13).

**The catch** is in the next step of the note. The thinning is a change of density, so it speeds light up by the same amount in every direction. Relative to the Earth, light then goes at c ahead, c + 2v behind and c + v across (Figure 3c; W13 line 7), and the Michelson–Morley signal is the full ½(v/c)² of a stationary aether (W13 line 8). Note 18 reaches c relative to the Earth in every direction by stating that the result is "a vector expression and not a scalar quantity". That is the step that would remove the signal, and it is asserted, not derived (main paper section 3.1; register M01). Even granting it, the result is frame (b) of section 13.4, which the cavity experiments exclude through the Earth's rotation. Note 18 also gives no reason why the drag should follow the Earth's travel and not its turning. If it followed both, the result would be frame (c).

![Figure 3. Tutorial Note 18: the backflow at c/2](https://aetherscience.org/aspden-analysis-files/fig-note18.png)

**Figure 3.** Tutorial Note 18. (a) The Earth's region of lattice moves at v. A fraction k of its quons flows back at u = c/2, so the aether's momentum stays zero and the region is thinner by k. (b) Light's gain in speed is v × c/2|u|; only u = c/2 makes it exactly v. (c) A change of density acts the same way in every direction, so relative to the Earth light goes at c ahead but at c + 2v behind (W13).

### 13.6 What would answer these objections

Each objection describes a property the medium should have, such as carrying waves at c, without strain, in every direction, as a reference frame. None gives the equation by which the quons and continuum actually move when a wave passes. Whatever that equation is, the wave speed, and how it varies with frequency and direction, must come out of the model's own charges, masses and spacing, as they do in sections 5–6 and 13.2. With Aspden's numbers, every way of letting the lattice flex that was tried fails:

- **as a plasma:** blocked below 511 keV;
- **as an elastic solid:** 0.2–0.3c, direction-dependent, unstable along the cube axes;
- **as a frame carried with the Earth:** excluded through the Earth's own rotation, by a factor of about 1,500.

A medium that works would need a different set of numbers or a different force law, and that would also change the α, h and G results built on these units.

---

## 14. Checking it yourself

- **Every number above.** `quon_model.py` prints each one in order, with its formula (W1–W14). It needs Python 3 with mpmath and numpy. It imports the lattice sums from `lattice_dynamics.py` in the same folder.
- **The figures.** `figures.py` draws Figures 1–3 with matplotlib. Every number in them is printed by `quon_model.py` (W2, W12–W14).
- **By hand.** Sections 3, 5, 6.2, 8 and 9 need only a calculator: the constants in W1 and the formulas as written.
- **Where to challenge.** The labels [A], [D] and [M] show where to push. [A] can be checked against Aspden's text. [D] can be checked line by line. [M] items are judgment calls, each with its reason and its consequence stated.

---

## References

1. H. Aspden, *The Physics of Creation*, 2nd ed. (2003), ch. 6, eqs. 6.1–6.8. https://aetherscience.org/2edpocch6/ ; ch. 7. https://aetherscience.org/2edpocch7/
2. H. Aspden, "The Fifth Question: What is a Neutrino?" (2001). https://aetherscience.org/www-energyscience-org-uk-question-es0105/
3. H. Aspden, "The Ether – An Assessment," *Wireless World* 88, 37 (1982); Lecture 24. https://aetherscience.org/www-energyscience-org-uk-le-le24/
4. H. Aspden, *Physics Unified* (1980), ch. 4. https://aetherscience.org/book-physics-unified/
5. H. A. Lorentz, *The Theory of Electrons* (1909): the cavity (local) field; any text on dielectrics, e.g. C. Kittel, *Introduction to Solid State Physics*, ch. 16.
6. P. P. Ewald, *Ann. Phys.* 64, 253 (1921); M. Born and K. Huang, *Dynamical Theory of Crystal Lattices* (1954): lattice sums and the dynamical matrix.
7. C. G. Darwin, *Phil. Mag.* 39, 537 (1920); J. D. Jackson, *Classical Electrodynamics*, 3rd ed., §12.6: the Darwin Lagrangian.
8. Particle Data Group, photon mass limit m < 1 × 10⁻¹⁸ eV (Ryutov 2007); Lakes 1998, < 1 × 10⁻¹⁷ eV; Williams, Faller and Hill 1971, < 1 × 10⁻¹⁴ eV. https://pdg.lbl.gov/2021/listings/rpp2021-list-photon.pdf
9. A. A. Abdo et al., *Nature* 462, 331 (2009) (GRB 090510); Part 1, U14.
10. Ionospheric plasma frequency f_p ≈ 8.98 √n_e Hz and shortwave propagation: K. Davies, *Ionospheric Radio* (Peregrinus, 1990).
11. Planck Collaboration, "Planck 2018 results. I. Overview", *A&A* 641, A1 (2020): solar dipole 369.82 ± 0.11 km/s.
12. S. Herrmann et al., *Phys. Rev. D* 80, 105011 (2009); M. Nagel et al., *Nat. Commun.* 6, 8174 (2015): rotating-cavity tests of light-speed isotropy.
13. D. J. Fixsen, *ApJ* 707, 916 (2009): CMB temperature 2.72548 K.
14. H. Aspden, *The Theory of Gravitation* (1960), web reprint with 1998 notes. https://aetherscience.org/www-energyscience-org-uk-tg-pr1/
15. H. Aspden, *Physics without Einstein* (1969), ch. 4, https://aetherscience.org/book-physics-without-einstein/book-physics-without-einstein-pwech4/ ; ch. 6, https://aetherscience.org/book-physics-without-einstein/book-physics-without-einstein-pwech6/ ; ch. 7, https://aetherscience.org/book-physics-without-einstein/book-physics-without-einstein-pwech7/
16. H. Aspden, *Physics Unified* (1980), ch. 2, https://aetherscience.org/book-physics-unified/book-physics-unified-puchapter2/ ; ch. 5, https://aetherscience.org/book-physics-unified/book-physics-unified-puchapter5/ ; ch. 9, https://aetherscience.org/book-physics-unified/book-physics-unified-puchapter9/
17. H. Aspden, *The Physics of Creation*, 2nd ed. (2003), ch. 5. https://aetherscience.org/2edpocch5/
18. H. Aspden, Tutorial Note 18, "Michelson–Morley Revisited" (1999), https://aetherscience.org/www-energyscience-org-uk-tu-tu18/ ; Tutorial Note 20, https://aetherscience.org/www-energyscience-org-uk-tu-tu20/
19. H. Aspden, Lecture No. 8. https://aetherscience.org/www-energyscience-org-uk-le-le08/
20. H. Aspden, "Aether Structure: Feedback from Allyn M. Shell" (Feedback Note 4). https://aetherscience.org/www-energyscience-org-uk-feedback-fn04/
21. H. Aspden, 1983b: optical sensing of a laboratory's West–East speed. https://aetherscience.org/www-energyscience-org-uk-papers-bib-1983b/
22. Wettzell ring laser: "Optical gyroscope detects Earth's rotation with the highest precision yet", *Physics World*. https://physicsworld.com/a/optical-gyroscope-detects-earths-rotation-with-the-highest-precision-yet/

---

## Appendix. Program listings and output

`quon_model.py`, `figures.py` and `lattice_dynamics.py` are in the analysis-scripts download.

### Listing: quon_model.py

```python
"""quon_model.py - the quon-continuum model built step by step (Part 1A; tests U32-U41 of Part 1).

Every number in Part 1A, "The quon-continuum model, derived step by step", is printed here in the order of the
derivation, with the formula next to it, so each line can be checked by hand or on a calculator.

Model (each choice is explained in Part 1A, section 2):
  - Gaussian units in the formulas (Aspden's), SI for the numbers: q^2 (Gaussian) = e^2/(4 pi eps0).
  - Quons: point charges +q = e on a simple cubic lattice, spacing d, mass m0 (Aspden 7.4/7.25).
  - Continuum: uniform charge density -sigma = -n q, n = 1/d^3, moving as a rigid frame with inertia M per cell.
  - Both frames orbit with radius r (Aspden 7.1), so M = m0 (equal and opposite momenta).
  - All charges interact only electromagnetically (Coulomb + Maxwell); Newtonian equations of motion for small
    displacements about the orbit, with the orbital speed c/2 absorbed into m0 as Aspden does.
"""
import io, contextlib, os, runpy, math
from mpmath import mp, mpf, pi, sqrt
mp.dps = 25
HERE = os.path.dirname(os.path.abspath(__file__))

def show(tag, formula, val, unit=""):
    print(f"  {tag:4s} {formula:<70s} = {val} {unit}")
def n6(x): return mp.nstr(x, 6)

# ---------------- W1 constants ----------------
print("W1  Constants (CODATA 2022) and Aspden's inputs")
e, me, c, hbar = mpf('1.602176634e-19'), mpf('9.1093837139e-31'), mpf('299792458'), mpf('1.054571817e-34')
eps0 = mpf('8.8541878188e-12'); keV = mpf('1.602176634e-16'); eV = keV / 1000
q2 = e**2 / (4*pi*eps0)
show("1", "e (C), m_e (kg), c (m/s), hbar (J s)", f"{e}, {me}, {c}, {hbar}")
show("2", "q^2 = e^2/(4 pi eps0) (J m), the Gaussian e^2 in SI", n6(q2))
N = 1843; rd = mpf(3)/4*(mpf(8)/N)**(mpf(1)/6)
show("3", "Aspden: N = 1843, r/d = (3/4)(8/N)^(1/6)", n6(rd))

# ---------------- W2 hand-check worksheet ----------------
print("\nW2  The units, one formula per line")
r = hbar/(2*me*c);                    show("1", "r = hbar/(2 m_e c)", n6(r), "m")
Om = (c/2)/r;                         show("2", "Omega = (c/2)/r", n6(Om), "rad/s")
show("3", "hbar Omega", n6(hbar*Om/keV), "keV")
d = r/rd;                             show("4", "d = r/(r/d)", n6(d), "m")
n = 1/d**3;                           show("5", "n = 1/d^3 (quons per m^3)", n6(n), "m^-3")
sigma = n*e;                          show("6", "sigma = n e (continuum charge density)", n6(sigma), "C/m^3")
kS = sigma*e/eps0;                    show("7", "k = sigma e / eps0 (Gaussian 4 pi sigma q), force per metre", n6(kS), "N/m")
m0 = 2*kS/Om**2;                      show("8", "m0 = 2k/Omega^2 (from m0 Omega^2 r = k (2r), Aspden 7.5)", n6(m0/me), "m_e")
show("9", "m0 c^2", n6(m0*c**2/keV), "keV")
b = q2/(3*m0*c**2);                   show("10", "b = q^2/(3 m0 c^2) (Aspden 7.4)", n6(b), "m")
a = 2*q2/(3*me*c**2);                 show("11", "a = 2 q^2/(3 m_e c^2) (electron Thomson radius)", n6(a), "m")
show("12", "N = (b/a)^3", n6((b/a)**3))

# ---------------- W3 the force on a quon when the lattice shifts ----------------
print("\nW3  Force on one quon when every quon shifts by u relative to the continuum (Gaussian units, per q u)")
show("1", "own cell's continuum, taken as a sphere: -(4 pi/3) sigma", "-4.18879 sigma")
show("2", "all other quons and their cells: Lorentz cavity field +(4 pi/3) P, P = sigma u", "+4.18879 sigma")
show("3", "sum of the local terms", "0")
show("4", "what remains is q times the macroscopic field E of the displaced lattice", "")
with contextlib.redirect_stdout(io.StringIO()):
    L = runpy.run_path(os.path.join(HERE, "lattice_dynamics.py"))
dyn, wp2 = L["dyn"], L["wp2"]
import numpy as np, itertools
Dk = dyn([1e-4, 0, 0]) / wp2
show("5", "Ewald check, k -> 0: longitudinal / w_p^2 (macroscopic field only)", f"{Dk[0,0]:.6f}")
show("6", "Ewald check, k -> 0: transverse / w_p^2 (no local restoring force)", f"{Dk[1,1]:.2e}")
g = np.linspace(-np.pi, np.pi, 13)[:-1] + np.pi/12
avg = sum(dyn([x, y, z]) for x, y, z in itertools.product(g, g, g)) / len(g)**3 / wp2
show("7", "Ewald check: one quon moved alone (average of D over the zone) / w_p^2, expect 1/3", f"{avg[0,0]:.5f}")

# ---------------- W4 equations of motion and the orbit ----------------
print("\nW4  Equations of motion: m0 u_E'' = q E,  M u_G'' = -q E,  E = -4 pi P (uniform motion), P = n q (u_E - u_G)")
wp = sqrt(4*pi*q2*n/m0) if False else sqrt(kS/m0)         # 4 pi n q^2/m0 in SI is n e^2/(eps0 m0) = k/m0
show("1", "w_p^2 = 4 pi n q^2/m0 (quons alone, continuum held)", n6(hbar*wp/keV), "keV (hbar w_p)")
M = m0
Wtot = sqrt(kS*(1/m0 + 1/M))
show("2", "Omega_pl^2 = 4 pi n q^2 (1/m0 + 1/M), M = m0", n6(hbar*Wtot/keV), "keV (hbar Omega_pl)")
show("3", "Omega_pl / Omega (Aspden's orbital frequency)", mp.nstr(Wtot/Om, 12))
show("4", "so the orbit is the uniform plasma oscillation of the two frames", "")

# ---------------- W5 response to light ----------------
print("\nW5  Response to a wave of frequency w: P = -(Omega^2/(4 pi w^2)) E, eps(w) = 1 - Omega^2/w^2,")
print("    Maxwell for transverse waves: c^2 k^2 = eps w^2 = w^2 - Omega^2")
E_O = hbar*Om/eV
rows = [("radio, 100 MHz", mpf('4.1357e-7')), ("visible, 500 nm", mpf('2.4797')), ("X-ray, 10 keV", mpf(1e4)),
        ("gamma, 100 keV", mpf(1e5)), ("Cs-137, 661.7 keV", mpf('661657')), ("1 MeV", mpf(1e6)),
        ("35 MeV", mpf(35e6)), ("6 GeV", mpf(6e9)), ("31 GeV", mpf(31e9))]
print(f"       {'photon':22s} {'eps':>14s} {'propagates?':>12s} {'v_group/c':>14s} {'1 - v_group/c':>14s}")
for lab, E in rows:
    ep = 1 - (E_O/E)**2
    if ep > 0:
        vg = sqrt(ep)
        print(f"       {lab:22s} {mp.nstr(ep,6):>14s} {'yes':>12s} {mp.nstr(vg,8):>14s} {mp.nstr(1-vg,4):>14s}")
    else:
        print(f"       {lab:22s} {mp.nstr(ep,6):>14s} {'no':>12s} {'-':>14s} {'-':>14s}")
show("1", "decay length of a blocked wave, c/sqrt(Omega^2 - w^2), visible light", n6(c/sqrt(Om**2 - (mpf('2.4797')*eV/hbar)**2)), "m")
show("2", "  (equal to 2r, the orbit diameter)", n6(2*r), "m")
t_grb = mpf('0.859') / (mpf('7.535') * mpf('3.15576e16'))
dv = (1 - sqrt(1 - (E_O/mpf(35e6))**2)) - (1 - sqrt(1 - (E_O/mpf(31e9))**2))
show("3", "GRB 090510: speed difference 35 MeV vs 31 GeV, and the limit (Part 1, U14)", f"{mp.nstr(dv,3)}  vs  {mp.nstr(t_grb,2)}  (x {mp.nstr(dv/t_grb,2)})")

# ---------------- W6 photon mass ----------------
print("\nW6  The same dispersion as a photon with rest energy hbar Omega")
show("1", "photon rest energy implied, hbar Omega", n6(E_O), "eV")
for lab, lim in (("PDG limit (Ryutov 2007, solar wind)", mpf('1e-18')), ("laboratory, Lakes 1998", mpf('1e-17')),
                 ("Coulomb's law, Williams, Faller and Hill 1971", mpf('1e-14'))):
    show("2", f"{lab}: limit (eV) and ratio", f"{mp.nstr(lim,2)}   x {mp.nstr(E_O/lim,2)}")

# ---------------- W7 static fields ----------------
print("\nW7  Static fields: a slowly varying applied field E_ext is screened by the factor 1 - w_p^2/w_L(k)^2")
for lab, kv in (("k = 0.01 pi/d", [0.01*np.pi, 0, 0]), ("k = 0.1 pi/d", [0.1*np.pi, 0, 0]),
                ("k = 0.5 pi/d", [0.5*np.pi, 0, 0]), ("k = pi/d (X)", [np.pi, 0, 0])):
    wL2 = max(np.linalg.eigvalsh(dyn(kv))) / wp2
    print(f"       {lab:16s} w_L^2/w_p^2 = {wL2:.5f}   field left = {1 - 1/wL2:+.5f} of the applied field")
show("1", "wavelength 2d/0.01 in metres (fields smoother than this are cancelled to < 0.01%)", n6(2*d/0.01), "m")

# ---------------- W8 Aspden's resonance picture, for comparison ----------------
print("\nW8  Aspden's 1982 resonance picture: each quon held by its own spring of frequency Omega")
show("1", "eps_A(w) = 1 + Omega^2/(Omega^2 - w^2)   (spring plus bare vacuum; Part 1 reading A)", "")
show("2", "eps_B(w) = Omega^2/(Omega^2 - w^2)        (spring, quons carry all displacement; reading B)", "")
show("3", "a spring independent of the macroscopic field would need a local force that W3 shows is absent", "")

# ---------------- W9-W12: objections considered (Part 1A section 13; Part 1 tests U37-U40) ----------------
# ---------------- W13: Tutorial Note 18 (Part 1A section 13.5); W14: the c/2 postulate (Part 1A 1.2; Part 1 U41) ----
print("\nW9  Free charges with no restoring force at all: the plasma frequency needs only charge, mass and density")
show("1", "w_p = sqrt(n q^2/(eps0 m)) (SI); no spring constant appears", "")
for lab, nn, mm in (("ionosphere F layer, electrons n = 1e12 m^-3", mpf('1e12'), me),
                    ("Aspden's quons against a still continuum, n = 1/d^3, m = m0", n, m0)):
    w = sqrt(nn*e**2/(eps0*mm))
    show("2", f"{lab}: f_p", f"{n6(w/(2*pi))} Hz  (hbar w = {n6(hbar*w/eV)} eV)")
show("3", "radio below about 9 MHz is reflected by the ionosphere (shortwave 'skip'); same physics, same formula", "")

print("\nW10 The lattice flexing: its own elastic (shear) waves, from the exact lattice sums at long wavelength")
wpd_c = sqrt(kS/m0) * d / c                                   # w_p d / c
show("1", "w_p d / c (converts lattice units to fractions of c)", n6(wpd_c))
for name, dirv in (("[100] cube axis", [1, 0, 0]), ("[110] face diagonal", [1, 1, 0]), ("[111] body diagonal", [1, 1, 1])):
    u = np.array(dirv, float); u /= np.linalg.norm(u)
    kv = 0.05*np.pi*u
    w2, vec = np.linalg.eigh(dyn(kv)/wp2)
    sp = []
    for j in range(3):
        if abs(vec[:, j] @ u) > 0.9:
            continue                                          # longitudinal: gapped at w_p, not a sound wave
        s_ = math.sqrt(abs(w2[j]))/np.linalg.norm(kv)*float(wpd_c)
        sp.append(f"{s_:.3f}c" if w2[j] > 0 else f"{s_:.3f}c x i (unstable)")
    show("2", f"shear-wave speeds along {name}", ", ".join(sp))
show("3", "stiffness increase needed for c along [111] and [110]: (c/s)^2", f"{(1/0.2146)**2:.1f} and {(1/0.2793)**2:.1f}")
show("4", "mass density the waves must move, m0/d^3", n6(m0/d**3/1000), "g/cm^3")

print("\nW11 Periodic motion driven by the cosmic background (T = 2.72548 K)")
kB = mpf('1.380649e-23'); T = mpf('2.72548')
show("1", "kT", n6(kB*T/eV), "eV")
show("2", "rms speed if a quon were free, sqrt(3kT/m0)", n6(sqrt(3*kB*T/m0)/1000), "km/s")
show("3", "orbital speed Aspden already gives every quon", n6(c/2/1000), "km/s")
aws = (3/(4*pi*n))**(mpf(1)/3)
show("4", "crystal coupling q^2/(a kT), a = (3/4 pi n)^(1/3) (a Coulomb crystal melts near 175)", n6(q2/(aws*kB*T)))
show("5", "thermal amplitude in the lattice, sqrt(kT/(m0 w_p^2)), and as a fraction of d", f"{n6(sqrt(kB*T/kS))} m   {n6(sqrt(kB*T/kS)/d)}")
show("6", "the response to a wave is linear, so it adds to any existing motion and is unchanged by it", "")

print("\nW12 The lattice as light's reference frame: three choices")
print("    (a) at rest in the cosmic background's frame (this analysis's first choice, Part 1A v1.1; not Aspden's)")
vE = mpf('369820')                                            # m/s, Planck 2018 dipole
show("1", "Earth's speed through the background's rest frame (Planck 2018)", n6(vE/1000), "km/s")
show("2", "light-speed anisotropy for an ether without length contraction, (1/2)(v/c)^2", n6((vE/c)**2/2))
show("3", "rotating-cavity limit (Herrmann et al. 2009; Nagel et al. 2015)", "about 1e-17 to 1e-18")
show("4", "ratio", mp.nstr((vE/c)**2/2/mpf('1e-17'), 2))
print("    (b) Aspden's: carried along with the Earth, not turning with it (PU ch. 9; Lecture 8; 1983b)")
wE, RE = mpf('7.2921150e-5'), mpf('6.371e6')                  # rad/s (sidereal), m (mean radius)
deg = pi/180
vB = wE*RE*mp.cos(mpf('52.52')*deg)
show("5", "lab's speed through that frame, Omega_E R cos(latitude), Berlin 52.52 N", n6(vB), "m/s")
show("6", "  the same at 40 N (Aspden 1983: 'some 350 m/s at 40oN')", n6(wE*RE*mp.cos(40*deg)), "m/s")
sigB = vB**2/c**2/2; limB = mpf('3e-16')
show("7", "expected lab-fixed signal at twice the turntable rate, (1/2)(v/c)^2, Berlin", n6(sigB))
show("8", "measured: lab-fixed signals at twice the rotation rate (Herrmann et al. 2009, Berlin)", "below 3e-16")
show("9", "ratio", n6(sigB/limB))
vmax = c*sqrt(2*limB)
show("10", "largest steady flow of the frame past the Berlin lab that this allows, c sqrt(2 x 3e-16)", n6(vmax), "m/s")
print("    (c) turning with the Earth (a co-rotating disk or sphere of aether)")
show("11", "rotation a ring laser fixed to the ground would then sense", "0 (no Sagnac effect)")
show("12", "measured: the Wettzell ring laser senses the Earth's full rotation (main paper 3.3)", "to 48 parts per billion")
show("13", "in between, Stokes's theorem: mean flow past the ground round Berlin's latitude circle", n6(vB), "m/s")
show("14", "  as a multiple of the cavity limit in line 10", n6(vB/vmax))

print("\nW13 Tutorial Note 18 (from PU p. 67): how a backflow at u = c/2 gives light the speed c relative to the moving Earth")
show("1", "momentum balance (61): (1-k) v + k u = 0, so k = v/(v - u); Aspden's u = -c/2 gives k = v/(v + c/2) ~ 2v/c", "")
show("2", "the lattice is thinner by the fraction k, so (62) n^2 = 1 - k and light's speed is c1 = c/n = c/sqrt(1 - k)", "")
show("3", "to first order c1 = c(1 + k/2) = c - v c/(2u): light gains v times c/(2|u|)", "")
for lab, uu in (("|u| = c/4", c/4), ("|u| = c/2 (Aspden: the quons' orbital speed)", c/2), ("|u| = c", c)):
    show("4", f"  gain in light's speed per unit of v, c/(2|u|), {lab}", n6(c/(2*uu)))
for lab, v in (("Earth's orbital speed, 29.78 km/s", mpf('29780')), ("Earth through the background, 369.82 km/s", vE)):
    k = v/(v + c/2); c1 = c/sqrt(1 - k)
    print(f"    {lab}")
    show("5", "  fraction of the lattice in the backflow, k", n6(k))
    show("6", "  c1 - c, the gain in light's speed (first order: v)", n6(c1 - c), "m/s")
    show("7", "  light's speed relative to the Earth minus c: ahead, behind, across", f"{n6(c1 - v - c)}, {n6(c1 + v - c)}, {n6(sqrt(c1**2 - v**2) - c)} m/s")
    show("8", "  Michelson-Morley signal t_along/t_across - 1 with this scalar c1, and (1/2)(v/c)^2", f"{n6(c1/sqrt(c1**2 - v**2) - 1)}  {n6(v**2/c**2/2)}")
show("9", "a density change speeds light equally in every direction, so it leaves the Michelson-Morley signal intact;", "")
show("  ", "the null result needs light to move at c relative to the Earth in every direction, which Note 18 asserts", "")

print("\nW14 The postulate that the two frames move at c relative to each other (Part 1A section 1.2; Part 1 U41)")
show("1", "Aspden: Omega (2r) = c (TG 1960 'assumed'; POC 6.6 'a likely candidate'). Write Omega (2r) = s c", "")
show("2", "the force balance m0 Omega^2 = 8 pi q^2/d^3 contains no r: the frequency is fixed, the orbit's size is free", "")
show("3", "POC 7.19-7.26 redone with s: hbar c/q^2 = 144 pi (r/d)/s,  m0/m_e = (4/9)(r/d)^2/s^2,  N = (9/8)^3 s^6 (d/r)^6", "")
show("4", "so for a given N: 1/alpha = 108 pi (8/N)^(1/6) and d, m0, b, E0 do not depend on s; only r and r/d scale with s", "")
Lsum = mpf('2.3136987')
def chain_s(s_):
    x0 = mp.findroot(lambda x: 8*pi*x**2 - Lsum + s_**4/(4608*pi*x**4), mpf('0.3'))   # zero-energy lattice, b/d = s^2/(96 pi x^2)
    N0 = (mpf(9)/8)**3 * s_**6 / x0**6
    No = int(N0) if int(N0) % 2 == 1 else int(N0) - 1
    xN = (mpf(9)/8)**(mpf(1)/2) * s_ * mpf(No)**(-mpf(1)/6)
    rr = s_*hbar/(2*me*c)
    return x0, N0, No, xN, 144*pi*xN/s_, rr/xN, (mpf(4)/9)*xN**2/s_**2
for s_ in (mpf('0.9999'), mpf(1), mpf('1.00004')):
    x0, N0, No, xN, ai, dd, mm = chain_s(s_)
    show("5", f"s = {mp.nstr(s_, 7)}: zero-energy N, odd N, r/d, 1/alpha, d (m), m0/m_e",
         f"{mp.nstr(N0, 7)}  {No}  {mp.nstr(xN, 7)}  {mp.nstr(ai, 10)}  {mp.nstr(dd, 6)}  {mp.nstr(mm, 6)}")
sl = mp.findroot(lambda s_: chain_s(s_)[1] - 1843, mpf('0.9999'))
sh = mp.findroot(lambda s_: chain_s(s_)[1] - 1845, mpf('1.00003'))
show("6", "range of s that keeps N = 1843 (the zero-energy N between 1843 and 1845)", f"{mp.nstr(sl, 8)} to {mp.nstr(sh, 8)}")
show("7", "  in parts per million", f"{mp.nstr((sl - 1)*10**6, 4)} to +{mp.nstr((sh - 1)*10**6, 4)} ppm")
show("8", "outside it N becomes 1841 or 1845 and 1/alpha jumps by (1/6)(2/1843)", n6(mpf(2)/1843/6*10**6), "ppm")
show("9", "so the postulate cannot move the 0.6 ppm gap: within the range 1/alpha is unchanged, outside it jumps", "")
```

### Output: quon_model.py

```output
W1  Constants (CODATA 2022) and Aspden's inputs
  1    e (C), m_e (kg), c (m/s), hbar (J s)                                   = 1.602176634e-19, 9.1093837139e-31, 299792458.0, 1.054571817e-34 
  2    q^2 = e^2/(4 pi eps0) (J m), the Gaussian e^2 in SI                    = 2.30708e-28 
  3    Aspden: N = 1843, r/d = (3/4)(8/N)^(1/6)                               = 0.302916 

W2  The units, one formula per line
  1    r = hbar/(2 m_e c)                                                     = 1.9308e-13 m
  2    Omega = (c/2)/r                                                        = 7.76344e+20 rad/s
  3    hbar Omega                                                             = 510.999 keV
  4    d = r/(r/d)                                                            = 6.37403e-13 m
  5    n = 1/d^3 (quons per m^3)                                              = 3.86151e+36 m^-3
  6    sigma = n e (continuum charge density)                                 = 6.18681e+17 C/m^3
  7    k = sigma e / eps0 (Gaussian 4 pi sigma q), force per metre            = 1.11951e+10 N/m
  8    m0 = 2k/Omega^2 (from m0 Omega^2 r = k (2r), Aspden 7.5)               = 0.0407813 m_e
  9    m0 c^2                                                                 = 20.8392 keV
  10   b = q^2/(3 m0 c^2) (Aspden 7.4)                                        = 2.30329e-14 m
  11   a = 2 q^2/(3 m_e c^2) (electron Thomson radius)                        = 1.87863e-15 m
  12   N = (b/a)^3                                                            = 1843.0 

W3  Force on one quon when every quon shifts by u relative to the continuum (Gaussian units, per q u)
  1    own cell's continuum, taken as a sphere: -(4 pi/3) sigma               = -4.18879 sigma 
  2    all other quons and their cells: Lorentz cavity field +(4 pi/3) P, P = sigma u = +4.18879 sigma 
  3    sum of the local terms                                                 = 0 
  4    what remains is q times the macroscopic field E of the displaced lattice =  
  5    Ewald check, k -> 0: longitudinal / w_p^2 (macroscopic field only)     = 1.000000 
  6    Ewald check, k -> 0: transverse / w_p^2 (no local restoring force)     = -1.31e-10 
  7    Ewald check: one quon moved alone (average of D over the zone) / w_p^2, expect 1/3 = 0.33333 

W4  Equations of motion: m0 u_E'' = q E,  M u_G'' = -q E,  E = -4 pi P (uniform motion), P = n q (u_E - u_G)
  1    w_p^2 = 4 pi n q^2/m0 (quons alone, continuum held)                    = 361.331 keV (hbar w_p)
  2    Omega_pl^2 = 4 pi n q^2 (1/m0 + 1/M), M = m0                           = 510.999 keV (hbar Omega_pl)
  3    Omega_pl / Omega (Aspden's orbital frequency)                          = 1.0 
  4    so the orbit is the uniform plasma oscillation of the two frames       =  

W5  Response to a wave of frequency w: P = -(Omega^2/(4 pi w^2)) E, eps(w) = 1 - Omega^2/w^2,
    Maxwell for transverse waves: c^2 k^2 = eps w^2 = w^2 - Omega^2
       photon                            eps  propagates?      v_group/c  1 - v_group/c
       radio, 100 MHz           -1.52666e+24           no              -              -
       visible, 500 nm           -4.2466e+10           no              -              -
       X-ray, 10 keV                 -2610.2           no              -              -
       gamma, 100 keV                -25.112           no              -              -
       Cs-137, 661.7 keV             0.40355          yes     0.63525569         0.3647
       1 MeV                         0.73888          yes     0.85958134         0.1404
       35 MeV                       0.999787          yes     0.99989341      0.0001066
       6 GeV                             1.0          yes            1.0       3.627e-9
       31 GeV                            1.0          yes            1.0      1.359e-10
  1    decay length of a blocked wave, c/sqrt(Omega^2 - w^2), visible light   = 3.86159e-13 m
  2      (equal to 2r, the orbit diameter)                                    = 3.86159e-13 m
  3    GRB 090510: speed difference 35 MeV vs 31 GeV, and the limit (Part 1, U14) = 0.000107  vs  3.6e-18  (x 3.0e+13) 

W6  The same dispersion as a photon with rest energy hbar Omega
  1    photon rest energy implied, hbar Omega                                 = 510999.0 eV
  2    PDG limit (Ryutov 2007, solar wind): limit (eV) and ratio              = 1.0e-18   x 5.1e+23 
  2    laboratory, Lakes 1998: limit (eV) and ratio                           = 1.0e-17   x 5.1e+22 
  2    Coulomb's law, Williams, Faller and Hill 1971: limit (eV) and ratio    = 1.0e-14   x 5.1e+19 

W7  Static fields: a slowly varying applied field E_ext is screened by the factor 1 - w_p^2/w_L(k)^2
       k = 0.01 pi/d    w_L^2/w_p^2 = 1.00003   field left = +0.00003 of the applied field
       k = 0.1 pi/d     w_L^2/w_p^2 = 1.00257   field left = +0.00256 of the applied field
       k = 0.5 pi/d     w_L^2/w_p^2 = 1.05229   field left = +0.04970 of the applied field
       k = pi/d (X)     w_L^2/w_p^2 = 1.10424   field left = +0.09440 of the applied field
  1    wavelength 2d/0.01 in metres (fields smoother than this are cancelled to < 0.01%) = 1.27481e-10 m

W8  Aspden's 1982 resonance picture: each quon held by its own spring of frequency Omega
  1    eps_A(w) = 1 + Omega^2/(Omega^2 - w^2)   (spring plus bare vacuum; Part 1 reading A) =  
  2    eps_B(w) = Omega^2/(Omega^2 - w^2)        (spring, quons carry all displacement; reading B) =  
  3    a spring independent of the macroscopic field would need a local force that W3 shows is absent =  

W9  Free charges with no restoring force at all: the plasma frequency needs only charge, mass and density
  1    w_p = sqrt(n q^2/(eps0 m)) (SI); no spring constant appears            =  
  2    ionosphere F layer, electrons n = 1e12 m^-3: f_p                       = 8.97866e+6 Hz  (hbar w = 3.71328e-8 eV) 
  2    Aspden's quons against a still continuum, n = 1/d^3, m = m0: f_p       = 8.73694e+19 Hz  (hbar w = 361331.0 eV) 
  3    radio below about 9 MHz is reflected by the ionosphere (shortwave 'skip'); same physics, same formula =  

W10 The lattice flexing: its own elastic (shear) waves, from the exact lattice sums at long wavelength
  1    w_p d / c (converts lattice units to fractions of c)                   = 1.16717 
  2    shear-wave speeds along [100] cube axis                                = 0.134c x i (unstable), 0.134c x i (unstable) 
  2    shear-wave speeds along [110] face diagonal                            = 0.134c x i (unstable), 0.279c 
  2    shear-wave speeds along [111] body diagonal                            = 0.215c, 0.215c 
  3    stiffness increase needed for c along [111] and [110]: (c/s)^2         = 21.7 and 12.8 
  4    mass density the waves must move, m0/d^3                               = 143.452 g/cm^3

W11 Periodic motion driven by the cosmic background (T = 2.72548 K)
  1    kT                                                                     = 0.000234864 eV
  2    rms speed if a quon were free, sqrt(3kT/m0)                            = 55.125 km/s
  3    orbital speed Aspden already gives every quon                          = 149896.0 km/s
  4    crystal coupling q^2/(a kT), a = (3/4 pi n)^(1/3) (a Coulomb crystal melts near 175) = 1.55054e+7 
  5    thermal amplitude in the lattice, sqrt(kT/(m0 w_p^2)), and as a fraction of d = 5.79761e-17 m   9.09566e-5 
  6    the response to a wave is linear, so it adds to any existing motion and is unchanged by it =  

W12 The lattice as light's reference frame: three choices
    (a) at rest in the cosmic background's frame (this analysis's first choice, Part 1A v1.1; not Aspden's)
  1    Earth's speed through the background's rest frame (Planck 2018)        = 369.82 km/s
  2    light-speed anisotropy for an ether without length contraction, (1/2)(v/c)^2 = 7.60868e-7 
  3    rotating-cavity limit (Herrmann et al. 2009; Nagel et al. 2015)        = about 1e-17 to 1e-18 
  4    ratio                                                                  = 7.6e+10 
    (b) Aspden's: carried along with the Earth, not turning with it (PU ch. 9; Lecture 8; 1983b)
  5    lab's speed through that frame, Omega_E R cos(latitude), Berlin 52.52 N = 282.69 m/s
  6      the same at 40 N (Aspden 1983: 'some 350 m/s at 40oN')               = 355.889 m/s
  7    expected lab-fixed signal at twice the turntable rate, (1/2)(v/c)^2, Berlin = 4.4458e-13 
  8    measured: lab-fixed signals at twice the rotation rate (Herrmann et al. 2009, Berlin) = below 3e-16 
  9    ratio                                                                  = 1481.93 
  10   largest steady flow of the frame past the Berlin lab that this allows, c sqrt(2 x 3e-16) = 7.34339 m/s
    (c) turning with the Earth (a co-rotating disk or sphere of aether)
  11   rotation a ring laser fixed to the ground would then sense             = 0 (no Sagnac effect) 
  12   measured: the Wettzell ring laser senses the Earth's full rotation (main paper 3.3) = to 48 parts per billion 
  13   in between, Stokes's theorem: mean flow past the ground round Berlin's latitude circle = 282.69 m/s
  14     as a multiple of the cavity limit in line 10                         = 38.4959 

W13 Tutorial Note 18 (from PU p. 67): how a backflow at u = c/2 gives light the speed c relative to the moving Earth
  1    momentum balance (61): (1-k) v + k u = 0, so k = v/(v - u); Aspden's u = -c/2 gives k = v/(v + c/2) ~ 2v/c =  
  2    the lattice is thinner by the fraction k, so (62) n^2 = 1 - k and light's speed is c1 = c/n = c/sqrt(1 - k) =  
  3    to first order c1 = c(1 + k/2) = c - v c/(2u): light gains v times c/(2|u|) =  
  4      gain in light's speed per unit of v, c/(2|u|), |u| = c/4             = 2.0 
  4      gain in light's speed per unit of v, c/(2|u|), |u| = c/2 (Aspden: the quons' orbital speed) = 1.0 
  4      gain in light's speed per unit of v, c/(2|u|), |u| = c               = 0.5 
    Earth's orbital speed, 29.78 km/s
  5      fraction of the lattice in the backflow, k                           = 0.000198631 
  6      c1 - c, the gain in light's speed (first order: v)                   = 29778.5 m/s
  7      light's speed relative to the Earth minus c: ahead, behind, across   = -1.47896, 59558.5, 29777.0 m/s 
  8      Michelson-Morley signal t_along/t_across - 1 with this scalar c1, and (1/2)(v/c)^2 = 4.93278e-9  4.93376e-9 
    Earth through the background, 369.82 km/s
  5      fraction of the lattice in the backflow, k                           = 0.0024611 
  6      c1 - c, the gain in light's speed (first order: v)                   = 369592.0 m/s
  7      light's speed relative to the Earth minus c: ahead, behind, across   = -227.822, 739412.0, 369364.0 m/s 
  8      Michelson-Morley signal t_along/t_across - 1 with this scalar c1, and (1/2)(v/c)^2 = 7.58996e-7  7.60868e-7 
  9    a density change speeds light equally in every direction, so it leaves the Michelson-Morley signal intact; =  
       the null result needs light to move at c relative to the Earth in every direction, which Note 18 asserts =  

W14 The postulate that the two frames move at c relative to each other (Part 1A section 1.2; Part 1 U41)
  1    Aspden: Omega (2r) = c (TG 1960 'assumed'; POC 6.6 'a likely candidate'). Write Omega (2r) = s c =  
  2    the force balance m0 Omega^2 = 8 pi q^2/d^3 contains no r: the frequency is fixed, the orbit's size is free =  
  3    POC 7.19-7.26 redone with s: hbar c/q^2 = 144 pi (r/d)/s,  m0/m_e = (4/9)(r/d)^2/s^2,  N = (9/8)^3 s^6 (d/r)^6 =  
  4    so for a given N: 1/alpha = 108 pi (8/N)^(1/6) and d, m0, b, E0 do not depend on s; only r and r/d scale with s =  
  5    s = 0.9999: zero-energy N, odd N, r/d, 1/alpha, d (m), m0/m_e          = 1843.424  1843  0.3028856  137.0359148  6.37403e-13  0.0407813 
  5    s = 1.0: zero-energy N, odd N, r/d, 1/alpha, d (m), m0/m_e             = 1844.538  1843  0.3029159  137.0359148  6.37403e-13  0.0407813 
  5    s = 1.00004: zero-energy N, odd N, r/d, 1/alpha, d (m), m0/m_e         = 1844.984  1843  0.302928  137.0359148  6.37403e-13  0.0407813 
  6    range of s that keeps N = 1843 (the zero-energy N between 1843 and 1845) = 0.99986198 to 1.0000414 
  7      in parts per million                                                 = -138.0 to +41.45 ppm 
  8    outside it N becomes 1841 or 1845 and 1/alpha jumps by (1/6)(2/1843)   = 180.865 ppm
  9    so the postulate cannot move the 0.6 ppm gap: within the range 1/alpha is unchanged, outside it jumps =  
```


### Listing: figures.py

```python
"""figures.py - the three figures in Part 1A (sections 1.2, 13.4 and 13.5). Writes PNG files to the folder given
as the first argument (default: ./figures). Every number drawn is printed by quon_model.py (W2, W12-W14)."""
import os, sys, math
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, Circle, Rectangle, Arc
import numpy as np

OUT = sys.argv[1] if len(sys.argv) > 1 else "figures"
os.makedirs(OUT, exist_ok=True)
plt.rcParams.update({"font.size": 9.5, "font.family": "DejaVu Sans", "axes.linewidth": 0.8,
                     "mathtext.fontset": "dejavusans", "savefig.dpi": 200})
BLUE, ORANGE, PURPLE, RED, GREEN, GREY, INK = "#2F6DB5", "#D9822B", "#6A3D9A", "#C0392B", "#2E8B57", "#8A8A8A", "#222222"

def arrow(ax, p, q, color, lw=1.6, ms=11, style="-|>", z=3, ls="-"):
    ax.add_patch(FancyArrowPatch(p, q, arrowstyle=style, mutation_scale=ms, color=color, lw=lw, zorder=z, linestyle=ls,
                                 shrinkA=0, shrinkB=0))

def save(fig, name):
    p = os.path.join(OUT, name)
    fig.savefig(p, bbox_inches="tight", pad_inches=0.06, facecolor="white")
    plt.close(fig)
    print("wrote", p)

# ---------------------------------------------------------------------------------------------------------------------
# Figure 1: the two frames and the c/2 postulate
# ---------------------------------------------------------------------------------------------------------------------
fig = plt.figure(figsize=(6.8, 3.25))
ax = fig.add_axes([0.0, 0.0, 0.47, 0.93]); ax.set_aspect("equal"); ax.axis("off")
ax.set_xlim(-1.75, 1.95); ax.set_ylim(-1.9, 1.45)
ax.set_title("(a) One cell: two frames orbiting a common centre", fontsize=9.5, loc="left", pad=2)
ax.add_patch(Circle((0, 0), 1, fill=False, ls=(0, (3, 3)), lw=0.9, color=GREY))
th = math.radians(25)
qx, qy = math.cos(th), math.sin(th)
ax.plot([-qx, qx], [-qy, qy], color=GREY, lw=0.9, zorder=1)
ax.plot([0], [0], marker="+", ms=9, mew=1.4, color=INK, zorder=4)
ax.text(0.05, -0.16, "centre\n(I frame)", fontsize=8, color=INK, ha="left", va="top")
ax.add_patch(Circle((qx, qy), 0.09, color=BLUE, zorder=5))
ax.add_patch(Circle((-qx, -qy), 0.10, facecolor="white", edgecolor=ORANGE, lw=2, zorder=5))
t = np.array([-math.sin(th), math.cos(th)])          # direction of motion (both turn anticlockwise)
arrow(ax, (qx, qy), (qx + 0.72*t[0], qy + 0.72*t[1]), BLUE, lw=2)
arrow(ax, (-qx, -qy), (-qx - 0.72*t[0], -qy - 0.72*t[1]), ORANGE, lw=2)
ax.text(qx + 0.72*t[0] + 0.09, qy + 0.72*t[1], "c/2", color=BLUE, fontsize=10, ha="left", va="center", fontweight="bold")
ax.text(-qx - 0.72*t[0] - 0.09, -qy - 0.72*t[1], "c/2", color=ORANGE, fontsize=10, ha="right", va="center", fontweight="bold")
ax.text(qx + 0.14, qy - 0.1, "quon\n(E frame)", color=BLUE, fontsize=8.5, ha="left", va="top")
ax.text(-qx - 0.14, -qy + 0.1, "continuum\n(G frame)", color=ORANGE, fontsize=8.5, ha="right", va="bottom")
ax.text(0.45*qx - 0.02, 0.45*qy + 0.06, "r", fontsize=9.5, color=INK, ha="right", va="bottom", style="italic")
ax.text(-0.5*qx - 0.02, -0.5*qy + 0.06, "r", fontsize=9.5, color=INK, ha="right", va="bottom", style="italic")
ax.add_patch(Arc((0, 0), 2.6, 2.6, theta1=-58, theta2=-14, color=INK, lw=1))
a1, a2 = math.radians(-17), math.radians(-12)
arrow(ax, (1.3*math.cos(a1), 1.3*math.sin(a1)), (1.3*math.cos(a2), 1.3*math.sin(a2)), INK, lw=1, ms=8)
ax.text(1.36, -0.72, "both turn\nat Ω", fontsize=8.5, ha="left", va="center")
ax.text(0.1, -1.58, "speed of one relative to the other: Ω·2r", fontsize=8.5, ha="center")
ax.text(0.1, -1.85, "Aspden's postulate: Ω·2r = c", fontsize=9.5, ha="center", fontweight="bold", color=PURPLE)

bx = fig.add_axes([0.6, 0.15, 0.39, 0.7])
rr = np.linspace(0, 4.2, 50)                          # units of 1e-13 m
Om = 7.76344e20
bx.plot(rr, 2*Om*rr*1e-13/2.99792458e8, color=INK, lw=1.6)
bx.axhline(1, color=PURPLE, ls=(0, (4, 3)), lw=1.3)
r0 = 1.9308
bx.plot([r0], [1], "o", color=PURPLE, ms=6, zorder=5)
bx.plot([r0, r0], [0, 1], color=PURPLE, lw=0.8, ls=":")
bx.text(0.15, 1.06, "postulate: relative speed = c", color=PURPLE, fontsize=8.5, va="bottom")
bx.annotate("r = ħ/2m$_e$c\n= 1.93 × 10$^{-13}$ m", xy=(r0, 1), xytext=(2.35, 0.42), fontsize=8.5,
            arrowprops=dict(arrowstyle="-", color=PURPLE, lw=0.8), color=PURPLE)
bx.set_xlim(0, 4.2); bx.set_ylim(0, 2.15)
bx.set_xlabel("orbit radius r (10$^{-13}$ m)")
bx.set_ylabel("relative speed Ω·2r  (units of c)")
bx.spines[["top", "right"]].set_visible(False)
bx.set_title("(b) Ω is the same for every radius", fontsize=9.5, loc="left", pad=6)
save(fig, "fig-two-frames.png")

# ---------------------------------------------------------------------------------------------------------------------
# Figure 2: three choices for the frame light travels in, near the Earth (view from above the North Pole)
# ---------------------------------------------------------------------------------------------------------------------
fig, axs = plt.subplots(1, 3, figsize=(6.9, 3.65))
fig.subplots_adjust(left=0.01, right=0.99, top=0.86, bottom=0.30, wspace=0.06)
titles = ["(a) At rest in the\nbackground's frame", "(b) Aspden's: carried with\nthe Earth, not turning",
          "(c) Turning with the Earth\n(a co-rotating disk)"]
verdicts = [
    [("Earth crosses it at 370 km/s", INK), ("cavities: expect 7.6 × 10$^{-7}$", INK), ("measured < 10$^{-17}$", INK),
     ("✗ excluded, ~10$^{11}$ ×", RED)],
    [("ring lasers see Earth turn  ✓", GREEN), ("lab crosses it at 283 m/s", INK),
     ("cavities: expect 4.4 × 10$^{-13}$", INK), ("measured < 3 × 10$^{-16}$", INK), ("✗ excluded, ~1,500 ×", RED)],
    [("cavities see no flow  ✓", GREEN), ("ring laser would see", INK), ("no rotation; Wettzell sees", INK),
     ("the full rotation (48 ppb)", INK), ("✗ excluded", RED)],
]
lat_r = 0.62                                            # radius of Berlin's latitude circle in the drawing
for j, ax in enumerate(axs):
    ax.set_aspect("equal"); ax.axis("off"); ax.set_xlim(-1.5, 1.5); ax.set_ylim(-1.45, 1.45)
    ax.set_title(titles[j], fontsize=9, pad=3)
    g = np.arange(-1.4, 1.41, 0.2)
    X, Y = np.meshgrid(g, g)
    if j == 0:
        m = np.ones_like(X, bool)
    else:
        m = X**2 + Y**2 < 1.32**2
    if j == 2:
        a = math.radians(14); Xr, Yr = X*math.cos(a) - Y*math.sin(a), X*math.sin(a) + Y*math.cos(a); X, Y = Xr, Yr
    ax.plot(X[m], Y[m], ".", ms=2.2, color=BLUE, alpha=0.55, zorder=1)
    if j > 0:
        ax.add_patch(Circle((0, 0), 1.32, fill=False, color=BLUE, lw=0.8, ls=(0, (2, 2)), alpha=0.8))
    ax.add_patch(Circle((0, 0), 0.9, facecolor="#E8EEF5", edgecolor=INK, lw=1, zorder=2, alpha=0.9))
    ax.add_patch(Circle((0, 0), lat_r, fill=False, color=GREY, lw=0.8, ls=":", zorder=3))
    ax.plot([0], [0], marker="+", color=INK, ms=6, zorder=4)
    ax.add_patch(Arc((0, 0), 0.5, 0.5, theta1=200, theta2=340, color=INK, lw=1, zorder=4))
    arrow(ax, (0.235, -0.085), (0.25, -0.03), INK, lw=1, ms=7, z=4)
    lx, ly = 0, -lat_r
    ax.add_patch(Rectangle((lx - 0.07, ly - 0.07), 0.14, 0.14, color=INK, zorder=6))
    ax.text(lx, ly - 0.14, "lab", fontsize=7.5, ha="center", va="top", zorder=6)
    if j == 0:
        arrow(ax, (-1.35, 1.2), (-0.35, 1.2), RED, lw=2.2, ms=12)
        ax.text(-0.3, 1.2, "Earth\n370 km/s", fontsize=7.5, color=RED, va="center", bbox=dict(facecolor="white", edgecolor="none", pad=1))
    if j == 1:
        arrow(ax, (lx, ly), (lx + 0.62, ly), RED, lw=2, ms=11, z=7)
        ax.text(lx + 0.66, ly + 0.02, "283 m/s", fontsize=7.5, color=RED, va="center", bbox=dict(facecolor="white", edgecolor="none", pad=1), zorder=7)
    if j == 2:
        ax.add_patch(Arc((0, 0), 2.45, 2.45, theta1=20, theta2=70, color=BLUE, lw=1.3))
        arrow(ax, (math.cos(math.radians(68))*1.225, math.sin(math.radians(68))*1.225),
              (math.cos(math.radians(75))*1.225, math.sin(math.radians(75))*1.225), BLUE, lw=1.3, ms=9)
        ax.text(1.0, 1.15, "aether turns\nwith the Earth", fontsize=7, color=BLUE, ha="left", va="bottom")
    y = -1.62
    for txt, col in verdicts[j]:
        ax.text(0, y, txt, fontsize=7.8, color=col, ha="center", va="top", fontweight="bold" if col in (RED,) else None)
        y -= 0.27
fig.text(0.5, 0.005, "View from above the North Pole; dotted circle: Berlin's latitude (52.5° N). Blue dots: the aether lattice.",
         ha="center", fontsize=7.5, color=GREY)
save(fig, "fig-earth-frames.png")

# ---------------------------------------------------------------------------------------------------------------------
# Figure 3: Tutorial Note 18, the backflow at c/2 and what it does to light's speed
# ---------------------------------------------------------------------------------------------------------------------
fig = plt.figure(figsize=(6.8, 5.0))
ax = fig.add_axes([0.0, 0.53, 1.0, 0.45]); ax.axis("off"); ax.set_xlim(0, 10); ax.set_ylim(-0.15, 3.7)
ax.set_title("(a) The Earth's aether moves at v; a small fraction k flows back at c/2 so the total momentum stays zero",
             fontsize=9, loc="left", pad=2)
ax.add_patch(Rectangle((0.3, 0.7), 5.4, 2.9, facecolor="#EEF3FA", edgecolor=BLUE, lw=1))
ax.text(0.45, 3.45, "Earth's region of aether lattice", fontsize=8, color=BLUE, va="top")
rng = np.random.default_rng(3)
for yy in (1.2, 1.75, 2.3, 2.85):
    for xx in np.arange(0.6, 5.2, 0.62):
        arrow(ax, (xx, yy), (xx + 0.32, yy), BLUE, lw=1.1, ms=6)
for yy, xx in ((1.47, 4.9), (2.58, 4.3)):
    arrow(ax, (xx, yy), (xx - 3.6, yy), ORANGE, lw=1.8, ms=10)
ax.text(5.85, 2.9, "most of the lattice (1 − k)\nmoves forward at v", color=BLUE, fontsize=8, va="center")
ax.text(5.85, 1.75, "a fraction k of the quons\nflows back at u = c/2", color=ORANGE, fontsize=8, va="center")
ax.text(5.85, 0.95, "(Aspden: their orbital speed)", color=ORANGE, fontsize=7.5, va="center")
ax.text(0.3, 0.32, "momentum:  (1 − k)·v = k·(c/2)   so   k ≈ 2v/c        "
        "lattice thinner by k   so   light faster by (k/2)·c = v", fontsize=8.5, color=INK, va="center")
ax.text(0.3, 0.0, "e.g. v = 30 km/s (Earth's orbit): k = 0.0002, light gains 29,779 m/s", fontsize=7.8, color=GREY,
        va="center")

bx = fig.add_axes([0.08, 0.07, 0.36, 0.33])
uu = np.linspace(0.2, 1.3, 200)
bx.plot(uu, 1/(2*uu), color=INK, lw=1.6)
bx.plot([0.5], [1], "o", color=ORANGE, ms=6, zorder=5)
bx.axhline(1, color=PURPLE, ls=(0, (4, 3)), lw=1)
bx.annotate("u = c/2: gain = v exactly,\nso light moves at c\nrelative to the Earth", xy=(0.5, 1), xytext=(0.62, 1.55),
            fontsize=7.8, color=ORANGE, arrowprops=dict(arrowstyle="-", color=ORANGE, lw=0.8))
bx.text(1.0, 0.56, "u = c: gain v/2", fontsize=7.8, color=INK)
bx.set_xlim(0.2, 1.3); bx.set_ylim(0, 2.6)
bx.set_xlabel("backflow speed u (units of c)")
bx.set_ylabel("light's gain in speed ÷ v")
bx.spines[["top", "right"]].set_visible(False)
bx.set_title("(b) Why it has to be c/2", fontsize=9, loc="left", pad=4)

cx = fig.add_axes([0.52, 0.02, 0.47, 0.42]); cx.set_aspect("equal"); cx.axis("off")
cx.set_xlim(-2.6, 2.6); cx.set_ylim(-1.55, 1.75)
cx.set_title("(c) The catch: thinning speeds light the same way in every direction", fontsize=8.6, loc="left", pad=2)
cx.add_patch(Circle((0, 0), 0.32, facecolor="#E8EEF5", edgecolor=INK, lw=1))
cx.text(0, 0, "Earth", fontsize=7, ha="center", va="center")
arrow(cx, (0, -0.42), (0.55, -0.42), RED, lw=1.4, ms=8)
cx.text(0.6, -0.42, "v", fontsize=8, color=RED, va="center")
arrow(cx, (0.38, 0), (1.55, 0), PURPLE, lw=1.6, ms=9); cx.text(1.6, 0.12, "ahead:\nc", fontsize=8, color=PURPLE, va="bottom")
arrow(cx, (-0.38, 0), (-2.0, 0), PURPLE, lw=1.6, ms=9); cx.text(-2.1, 0.12, "behind:\nc + 2v", fontsize=8, color=PURPLE, va="bottom")
arrow(cx, (0, 0.38), (0, 1.3), PURPLE, lw=1.6, ms=9); cx.text(0.1, 1.2, "across: c + v", fontsize=8, color=PURPLE, va="center")
cx.text(0, -0.9, "light's speed relative to the Earth if the change is only a density effect", fontsize=7.4,
        ha="center", color=INK)
cx.text(0, -1.2, "Michelson–Morley signal stays ½(v/c)²; Note 18 gets c in every", fontsize=7.4, ha="center", color=RED)
cx.text(0, -1.45, "direction only by calling the result a vector (asserted, not derived)", fontsize=7.4, ha="center",
        color=RED)
save(fig, "fig-note18.png")
```
