codexcoriolis-earth-latitude-and-eastward-acceleration.py
coriolis-earth-latitude-and-eastward-acceleration.py
"""Show local Earth rotation geometry and a northward-velocity example.
Run from the desired output directory. Tested with Python 3.14,
Matplotlib 3.10.7 and NumPy 2.3.5; dependencies are in pyproject.toml.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Arc, Circle
import numpy as np
def arrow(ax, start, end, color, label=None, text=None):
ax.annotate("", xy=end, xytext=start,
arrowprops={"arrowstyle": "-|>", "color": color, "lw": 2, "mutation_scale": 15})
if label:
ax.text(*text, label, fontsize=11, color=color)
def main():
omega, speed, phi = 7.292115e-5, 20.0, np.pi / 4
acceleration = 2 * omega * speed * np.sin(phi)
fig, (left, right) = plt.subplots(1, 2, figsize=(10, 5.7), facecolor="white")
fig.subplots_adjust(left=0.035, right=0.98, top=0.79, bottom=0.25, wspace=0.15)
for ax in (left, right):
ax.set_aspect("equal")
ax.set_facecolor("white")
ax.axis("off")
left.set_xlim(-1.25, 1.65)
left.set_ylim(-1.1, 1.5)
left.add_patch(Circle((0, 0), 0.88, facecolor="#eef6fa", edgecolor="#507080", lw=1.4))
left.plot([-1.1, 1.1], [0, 0], color="#999999", lw=1)
left.text(-1.14, -0.16, "equatorial plane", fontsize=10)
arrow(left, (0, -1.0), (0, 1.37), "#555555", r"$\boldsymbol{\Omega}$", (0.08, 1.22))
p = 0.88 * np.array([np.cos(phi), np.sin(phi)])
left.plot([0, p[0]], [0, p[1]], color="#888888", ls="--")
left.add_patch(Arc((0, 0), 0.70, 0.70, theta1=0, theta2=45, color="#555555"))
left.text(0.37, 0.13, r"$\varphi=45^\circ$", fontsize=11)
left.plot(*p, "o", color="#222222", ms=5)
arrow(left, p, p + 0.52 * np.array([np.cos(phi), np.sin(phi)]),
"#009e73", "up", (1.04, 1.02))
arrow(left, p, p + 0.56 * np.array([-np.sin(phi), np.cos(phi)]),
"#0072b2", "north", (0.11, 1.10))
left.text(0, -1.05, "Meridian section (spherical Earth)", ha="center", fontsize=10)
left.set_title("Latitude sets the vertical rotation component", fontsize=12, pad=16)
right.set_xlim(-0.65, 1.65)
right.set_ylim(-0.3, 1.7)
arrow(right, (0, 0), (1.4, 0), "#777777", "east", (1.22, -0.17))
arrow(right, (0, 0), (0, 1.35), "#777777", "north", (-0.18, 1.46))
arrow(right, (0, 0), (0, 1.06), "#0072b2")
right.text(0.08, 1.0, r"$\mathbf{v}=20\,\mathbf{e}_N\ {\rm m\,s^{-1}}$", fontsize=11, color="#0072b2")
arrow(right, (0, 0.59), (1.12, 0.59), "#d55e00")
right.text(0.20, 0.74, r"$\mathbf{a}_{\rm cor}=f u\,\mathbf{e}_E$", fontsize=12, color="#d55e00")
right.text(0.35, 0.37, "eastward acceleration", fontsize=10, color="#d55e00")
right.text(-0.49, 0.57, r"$\odot$", fontsize=24, color="#009e73", ha="center")
right.text(-0.60, 0.24, "up\n(out of page)", fontsize=9, color="#009e73")
right.text(0.55, -0.29, "Arrows show directions; lengths are schematic.", ha="center", fontsize=9)
right.set_title("Local horizontal view at 45° north", fontsize=12, pad=16)
fig.suptitle("Why a northward velocity has an eastward Coriolis acceleration", fontsize=15, y=0.98)
fig.text(0.5, 0.875, r"$\boldsymbol{\Omega}=\Omega\cos\varphi\,\mathbf{e}_N+\Omega\sin\varphi\,\mathbf{e}_U,\qquad f=2\Omega\sin\varphi$",
fontsize=13, ha="center")
fig.text(0.5, 0.15, rf"$\Omega=7.292115\times10^{{-5}}\ {{\rm s^{{-1}}}},\qquad a_E={acceleration:.7f}\ {{\rm m\,s^{{-2}}}}$",
fontsize=13, ha="center")
fig.text(0.5, 0.085, r"At 10 s: $\Delta x_E\simeq\frac{1}{2} a_E t^2=0.1031$ m (local, short-time estimate).",
fontsize=11, ha="center")
fig.text(0.5, 0.025, "Initial northward motion, no other horizontal force; this is not a prediction of a wind trajectory.",
fontsize=10, ha="center")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=110, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()