codexoutgoing-radiation-pulse-spherical-spreading.py
outgoing-radiation-pulse-spherical-spreading.py
"""Draw outgoing-radiation-pulse-spherical-spreading.png in cwd.
Angularly averaged leading far-field pulse model, not a spherically symmetric
vector Maxwell solution or a measurement. Emission is P0*sin²(pi*s/tau)
for 0 <= s <= tau and zero outside that interval; L = c*tau.
Tested with Python 3.14.4, NumPy 2.3.5, Matplotlib 3.10.7.
Run from _media with MPLBACKEND=Agg MPLCONFIGDIR=/tmp/codex-wiki-matplotlib.
"""
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Wedge
import numpy as np
def emission(q):
return np.where((q >= 0) & (q <= 1), np.sin(np.pi * q) ** 2, 0.0)
def main():
plt.rcParams.update({"font.size": 12, "axes.titlesize": 14})
blue, orange, green = "#1766a6", "#bc5710", "#23744a"
fig = plt.figure(figsize=(10.6, 8.0), facecolor="white")
fig.suptitle("An outgoing pulse spreads; its total energy stays the same", fontsize=17, y=0.98)
fig.text(0.5, 0.927, r"Angularly averaged far-field model: $\overline{S}_r=P_{\rm emit}(t-r/c)/(4\pi r^2)$",
ha="center", fontsize=13)
for rectangle, time, color in [((0.10, 0.54, 0.33, 0.32), 3, blue),
((0.59, 0.54, 0.33, 0.32), 5, orange)]:
ax = fig.add_axes(rectangle, facecolor="white")
ax.add_patch(Wedge((0, 0), time, 0, 360, width=1, color=color, alpha=0.16))
for radius in (time - 1, time):
ax.add_patch(Circle((0, 0), radius, fill=False, color=color, lw=1.7))
ax.plot(0, 0, "o", color="#333333", ms=5)
ax.text(0, -0.65, "Source", ha="center", fontsize=10)
ax.annotate("", (time, 0), (0, 0), arrowprops={"arrowstyle": "->", "color": color})
ax.text(time / 2, 0.35, rf"$ct={time}L$", ha="center", color=color)
ax.annotate("", (0, time), (0, time - 1),
arrowprops={"arrowstyle": "<->", "color": "#333333"})
ax.text(0.3, time - 0.5, r"$L$", va="center")
ax.set_title(rf"$t={time}\tau$: shell from ${time-1}L$ to ${time}L$", pad=8)
ax.set(xlim=(-5.5, 5.5), ylim=(-5.5, 5.5), aspect="equal")
ax.axis("off")
fig.text(0.5, 0.52, r"Same length scale in both snapshots. Shell thickness $L=c\tau$; shading marks support only.",
ha="center", fontsize=10.5)
density = fig.add_axes((0.10, 0.14, 0.37, 0.29), facecolor="white")
position = np.linspace(0, 6, 1801)
for time, color in [(3, blue), (5, orange)]:
profile = emission(time - position)
density.plot(position, profile, color=color, lw=2.5, label=rf"$t={time}\tau$")
density.fill_between(position, profile, color=color, alpha=0.12)
density.set(xlim=(0, 6), ylim=(0, 1.18), xlabel=r"Radius $r/L$",
ylabel=r"$(c/P_0)\,dU/dr$")
density.set_title("Energy per radius translates outward", pad=12, fontsize=12)
density.legend(loc="upper left", fontsize=11)
density.grid(alpha=0.2)
density.text(0.5, 0.68, r"Both areas $=1/2$", transform=density.transAxes, ha="center", fontsize=11)
dilution = fig.add_axes((0.61, 0.14, 0.35, 0.29), facecolor="white")
ratio = np.linspace(1, 4, 501)
dilution.plot(ratio, 1 / ratio, color=green, lw=2.5, label=r"Field: $E(r)/E(r_0)=r_0/r$")
dilution.plot(ratio, 1 / ratio ** 2, color=blue, lw=2.5, ls="--",
label=r"Flux: $S_r(r)/S_r(r_0)=(r_0/r)^2$")
dilution.scatter([2, 2], [0.5, 0.25], color=[green, blue], zorder=3)
dilution.annotate("1/2", (2, 0.5), xytext=(2.18, 0.53), color=green, fontsize=11)
dilution.annotate("1/4", (2, 0.25), xytext=(2.18, 0.25), color=blue, fontsize=11)
dilution.set(xlim=(1, 4), ylim=(0, 1.12), xlabel=r"Distance ratio $r/r_0$", ylabel="Ratio to reference value")
dilution.set_title("Compare the same emitted instant", pad=12, fontsize=12)
dilution.legend(loc="upper right", fontsize=9.5)
dilution.grid(alpha=0.2)
fig.text(0.285, 0.062, r"Shell energy $U=P_0\tau/2$ at either time", ha="center", fontsize=11)
fig.text(0.5, 0.018, "Calculated model, not measured data. Fixed-direction ratios use corresponding arrival times in the radiation zone.",
ha="center", fontsize=10.5)
fig.savefig("outgoing-radiation-pulse-spherical-spreading.png", dpi=110,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()