codex/past-exam-of-the-physics-course-of-the-year-1-of-the-natural-sciences-course-of-the-university-of-cambridge/2015/paper-1-meter-response.py

past-exam-of-the-physics-course-of-the-year-1-of-the-natural-sciences-course-of-the-university-of-cambridge/2015/paper-1-meter-response.py
"""Original normalized meter response plots; Python 3.14, numpy, matplotlib."""

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np


fig, axes = plt.subplots(1, 3, figsize=(12, 3.8), constrained_layout=True,
                         facecolor="white")
t = np.linspace(0, 14, 700)
for zeta, label, color in [(0.3, "Underdamped (0.3)", "#c55412"),
                           (1, "Critical (1)", "#1764a0"),
                           (2, "Overdamped (2)", "#197c54")]:
    if zeta < 1:
        wd = np.sqrt(1-zeta*zeta)
        y = 1-np.exp(-zeta*t)*(np.cos(wd*t)+zeta/wd*np.sin(wd*t))
    elif zeta == 1:
        y = 1-(1+t)*np.exp(-t)
    else:
        r1, r2 = -zeta+np.sqrt(zeta*zeta-1), -zeta-np.sqrt(zeta*zeta-1)
        y = 1+(r2*np.exp(r1*t)-r1*np.exp(r2*t))/(r1-r2)
    axes[0].plot(t, y, color=color, label=label, lw=2)
axes[0].axhline(1, color="0.55", ls="--", lw=0.8)
axes[0].set(xlabel=r"Normalized time $\omega_0t$",
            ylabel=r"Deflection $\theta/\theta_\infty$", title="Step from rest")
axes[0].legend(title=r"Illustrative $\gamma/\omega_0$", fontsize=8, title_fontsize=9)
x = np.geomspace(0.01, 100, 600)
axes[1].loglog(x, 1/(1+x*x), color="#1764a0", lw=2)
axes[1].set(xlabel=r"Frequency ratio $\omega/\omega_0$",
            ylabel=r"Amplitude / DC amplitude", title="Critical amplitude response")
axes[2].semilogx(x, -2*np.degrees(np.arctan(x)), color="#1764a0", lw=2)
axes[2].set(xlabel=r"Frequency ratio $\omega/\omega_0$",
            ylabel="Phase relative to drive (degrees)", title="Critical phase response",
            yticks=[0, -45, -90, -135, -180])
for ax in axes:
    ax.grid(alpha=0.22)
    ax.spines[["top", "right"]].set_visible(False)
fig.savefig("paper-1-meter-response.png", dpi=160, facecolor="white")
plt.close(fig)