codexangstrom-periodic-heating-rod-geometry.py
angstrom-periodic-heating-rod-geometry.py
"""Original periodic-heating geometry; Python 3.14, matplotlib 3.10.7.
Run from _media: MPLBACKEND=Agg python ../angstrom-periodic-heating-rod-geometry.py
The dimensions are illustrative, not a reconstruction of a particular apparatus.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, Rectangle
import numpy as np
def main():
plt.rcParams.update({"font.size": 11, "figure.facecolor": "white"})
fig, ax = plt.subplots(figsize=(10, 5.8), dpi=120)
ax.set(xlim=(-0.08, 1.05), ylim=(-0.55, 0.78))
ax.axis("off")
ax.set_title("Ångström method: one periodic input, two local thermometers", pad=14)
ax.add_patch(Rectangle((0.04, 0.16), 0.87, 0.18, facecolor="#e6c58d", edgecolor="#6c4e1c", lw=1.6))
ax.add_patch(Rectangle((-0.015, 0.10), 0.075, 0.30, facecolor="#e99b8f", edgecolor="#a53927"))
ax.text(0.02, 0.50, "Heater / cooler\nat x = 0", ha="center", color="#a53927")
ax.text(0.49, 0.25, "Uniform rod: conductivity k, diffusivity α = k/(ρcₚ)", ha="center")
ax.text(0.94, 0.27, "Far end\nx = L", ha="left", va="center")
for x, lab, col in [(0.27, "1", "#146c94"), (0.57, "2", "#7c3f96")]:
ax.plot(x, 0.34, "o", color=col, ms=8)
level = 0.68 if lab == "1" else 0.60
ax.plot([x, x, 0.69], [0.34, level, level], color=col, lw=1.5)
ax.text(x, 0.42, f"x{lab}", ha="center", color=col)
ax.add_patch(Rectangle((0.69, 0.56), 0.26, 0.16, facecolor="#f2f5f7", edgecolor="#4c5863"))
ax.text(0.82, 0.64, "Synchronized\nrecorder", ha="center", va="center")
ax.annotate("", xy=(0.57, 0.06), xytext=(0.27, 0.06), arrowprops={"arrowstyle": "<->", "color": "#333333"})
ax.text(0.42, -0.015, "Measured spacing Δx", ha="center")
for x in [0.16, 0.43, 0.71, 0.85]:
ax.add_patch(FancyArrowPatch((x, 0.16), (x, -0.13), arrowstyle="->", mutation_scale=12, color="#8b6c42"))
ax.text(0.51, -0.20, "Possible side losses to surroundings at T∞", ha="center", color="#72532b")
ax.text(0.51, -0.29, "Insulate; keep the cross-section nearly isothermal; test far-end influence", ha="center", fontsize=10)
t = np.linspace(0, 2*np.pi, 200)
ax.plot(-0.05 + 0.10*t/(2*np.pi), -0.18 + 0.045*np.cos(t), color="#a53927", lw=2)
ax.text(0, -0.34, "Periodic drive", ha="center", color="#a53927", fontsize=10)
ax.text(0.49, -0.44, "Fit the same frequency at both sensors: amplitude ratio A₁/A₂ and phase lag Δφ", ha="center", fontsize=11)
fig.tight_layout()
fig.savefig(Path(__file__).stem + ".png", facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()