codexgravitational-tidal-field.py
gravitational-tidal-field.py
"""Generate gravitational-tidal-field.png in cwd (Python 3.14).
Dependencies: numpy and matplotlib. Newtonian, short-time exterior approximation
near a spherical Earth: GM=g R^2. Arrows show relative, not total, acceleration.
"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
G_LOCAL = 9.81 # m/s^2
EARTH_RADIUS = 6.371e6 # m
def main():
coefficient = G_LOCAL / EARTH_RADIUS
angle = np.arange(8) * np.pi / 4
x, y = np.cos(angle), np.sin(angle)
# Local radial direction is vertical; the horizontal direction is transverse.
relative_ax = -coefficient * x
relative_ay = 2 * coefficient * y
seconds = np.linspace(0, 10, 201)
radial_change_mm = 0.5 * 2 * coefficient * seconds**2 * 1000
transverse_change_mm = -0.5 * coefficient * seconds**2 * 1000
plt.rcParams.update({"font.size": 10, "axes.spines.top": False,
"axes.spines.right": False})
fig, (left, right) = plt.subplots(1, 2, figsize=(10, 4.5), layout="constrained")
fig.patch.set_facecolor("white")
circle = np.linspace(0, 2 * np.pi, 241)
left.plot(np.cos(circle), np.sin(circle), color="#bbb", ls=":")
left.scatter(x, y, color="#1565a8", zorder=3)
left.scatter([0], [0], color="#333", zorder=3)
arrows = left.quiver(x, y, relative_ax * 1e6, relative_ay * 1e6,
color="#1565a8", angles="xy", scale_units="xy", scale=5,
width=0.008)
left.quiverkey(arrows, 0.10, 0.12, 1, r"$1\ \mu\mathrm{m}/\mathrm{s}^2$",
labelpos="E", coordinates="axes")
left.text(0, 1.8, "Radial stretching", ha="center", color="#1565a8")
left.text(0, -1.9, "Earth's centre is far below", ha="center", fontsize=9)
left.set(xlabel="Transverse separation (m)", ylabel="Radial separation (m)",
title="Relative acceleration in free fall", xlim=(-2, 2), ylim=(-2.05, 2.05))
left.set_aspect("equal")
left.set_xticks([-1, 0, 1])
left.set_yticks([-1, 0, 1])
right.plot(seconds, radial_change_mm, color="#1565a8", lw=2.5,
label="Radial pair: stretches")
right.plot(seconds, transverse_change_mm, color="#d26c16", lw=2.5,
label="Transverse pair: compresses")
right.axhline(0, color="#888", lw=0.7)
right.text(0.04, 0.94, "Initially 1 m apart, zero relative velocity\n" +
r"Short time: $\Delta\xi\simeq\frac{1}{2}\ddot\xi(0)t^2$",
transform=right.transAxes, va="top", fontsize=9)
right.set(xlabel="Elapsed free-fall time (s)", ylabel="Change in separation (mm)",
title="A small effect accumulates", xlim=(0, 10), ylim=(-0.11, 0.205))
right.legend(loc="lower left", frameon=False, fontsize=9)
right.grid(alpha=0.2)
fig.savefig("gravitational-tidal-field.png", dpi=120,
facecolor="white", transparent=False)
plt.close(fig)
print(f"Radial relative acceleration per metre = {2 * coefficient:.12e} s^-2")
print(f"Transverse relative acceleration per metre = {-coefficient:.12e} s^-2")
print(f"1 s, 1 m initial separation: radial change = {coefficient * 1e6:.9f} um")
print(f"1 s, 1 m initial separation: transverse change = {-0.5 * coefficient * 1e6:.9f} um")
if __name__ == "__main__":
main()