"""Draw an ideal Poiseuille profile, not measured data. Run from _media: MPLCONFIGDIR=/tmp/codex-wiki-matplotlib python ../laminar-pipe-velocity-profile.py Tested with Python 3.14.4, matplotlib 3.10.7, numpy 2.3.5. The matching PNG basename is written to the current working directory. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np def main(): radius_mm = 5.0 mean_speed = 0.10 fig, (sketch, profile) = plt.subplots(1, 2, figsize=(10, 5.3)) fig.patch.set_facecolor("white") fig.suptitle("Ideal laminar pipe flow", fontsize=19, weight="bold", y=0.97) fig.text(0.5, 0.905, "Fully developed Poiseuille solution • illustrative parameters, not measured data", ha="center", fontsize=11) blue = "#1765a8" orange = "#bc5e0a" sketch.set_title("Axial velocities (arrows ∝ speed)", fontsize=12, pad=12) sketch.set_xlim(-0.35, 3.5) sketch.set_ylim(-6, 6) sketch.axhline(radius_mm, color="#344454", linewidth=4) sketch.axhline(-radius_mm, color="#344454", linewidth=4) sketch.axhline(0, color="#bac5d0", linestyle=":", linewidth=1) ys = np.linspace(-4.5, 4.5, 11) for y in ys: speed = 2 * mean_speed * (1 - (y / radius_mm) ** 2) sketch.annotate("", (0.1 + 2.4 * speed / (2 * mean_speed), y), (0.1, y), arrowprops={"arrowstyle": "-|>", "color": blue, "lw": 2, "mutation_scale": 12}) sketch.text(2.8, 5.35, "fixed wall", ha="right", fontsize=10) sketch.text(2.8, -5.65, "fixed wall", ha="right", fontsize=10) sketch.set_ylabel("Signed distance from axis (mm)", fontsize=11) sketch.set_yticks([-5, -2.5, 0, 2.5, 5]) sketch.set_xticks([]) for spine in sketch.spines.values(): spine.set_visible(False) y = np.linspace(-radius_mm, radius_mm, 401) speed = 2 * mean_speed * (1 - (y / radius_mm) ** 2) profile.set_title("Quantitative profile", fontsize=12, pad=12) profile.plot(speed, y, color=blue, linewidth=2.8) profile.axvline(mean_speed, color=orange, linestyle="--", linewidth=1.8) profile.scatter([0, 0, 2 * mean_speed], [-5, 5, 0], color=blue, s=28, zorder=4) profile.annotate("centre: 0.20 m/s", (0.20, 0), (0.035, 1.4), fontsize=11, arrowprops={"arrowstyle": "->", "color": blue}, color=blue) profile.text(0.106, -1.8, "area mean\n0.10 m/s", color=orange, fontsize=11) profile.set_xlim(-0.006, 0.225) profile.set_ylim(-6, 6) profile.set_xticks([0, 0.05, 0.10, 0.15, 0.20]) profile.set_yticks([-5, -2.5, 0, 2.5, 5]) profile.set_xlabel("Axial velocity u (m/s)", fontsize=11) profile.grid(alpha=0.22) profile.spines[["top", "right"]].set_visible(False) fig.text(0.5, 0.045, r"$u(r)=2U[1-(r/R)^2]$ $R=5$ mm $U=0.10$ m/s", ha="center", fontsize=13) fig.subplots_adjust(left=0.09, right=0.965, bottom=0.20, top=0.79, wspace=0.27) fig.savefig(Path(__file__).with_suffix(".png").name, dpi=110, facecolor="white", transparent=False) plt.close(fig) if __name__ == "__main__": main()