codex/singular-perturbation-inner-rescaling-balance.py

singular-perturbation-inner-rescaling-balance.py
"""Explain inner rescaling and signed derivative balance with two panels.

Python 3.14, NumPy 2.3, Matplotlib 3.10. Run from _media to emit the PNG there.
"""

from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
                         "axes.spines.right": False, "figure.facecolor": "white",
                         "axes.facecolor": "white"})
    fig, (left, right) = plt.subplots(1, 2, figsize=(10.5, 4.8), layout="constrained")
    colors = ("#0072B2", "#D55E00", "#009E73")
    for epsilon, color, style in zip((0.2, 0.05, 0.01), colors, ("-", "--", ":")):
        # The epsilon=0.2 domain ends at X=5, rather than extending past x=1.
        X = np.linspace(0, min(6, 1 / epsilon), 601)
        Y = np.expm1(-X) / np.expm1(-1 / epsilon)
        left.plot(X, Y, style, color=color, linewidth=2.6,
                  label=rf"Exact, $\epsilon={epsilon:g}$")
    mark_X = np.arange(0, 6.01, 0.6)
    left.plot(mark_X, -np.expm1(-mark_X), "o", color="black", fillstyle="none",
              markersize=5, label=r"Inner limit $1-e^{-X}$")
    left.text(0.45, 0.22, "Profiles nearly collapse after rescaling.\n"
              r"Finite-$\epsilon$ normalization still matters.", fontsize=10)
    left.set(xlim=(0, 6), ylim=(-0.025, 1.06), xlabel=r"Inner coordinate $X=x/\epsilon$",
             ylabel=r"$Y_\epsilon(X)=y_\epsilon(\epsilon X)$", title="The layer has a fixed inner shape")
    left.legend(loc="center right", frameon=False, fontsize=9.5)
    X = np.linspace(0, 6, 601)
    epsilon = 0.05
    magnitude = np.exp(-X) / (-np.expm1(-1 / epsilon))
    right.plot(X, magnitude, color="#0072B2", linewidth=2.6,
               label=r"$\epsilon y_\epsilon'=Y_\epsilon'$ ")
    right.plot(X, -magnitude, color="#D55E00", linewidth=2.6,
               label=r"$\epsilon^2y_\epsilon''=Y_\epsilon''$")
    right.axhline(0, color="#333333", linestyle="--", linewidth=1.2)
    right.text(1.6, -0.72, r"$Y_\epsilon''+Y_\epsilon'=0$" + "\n"
               + "Equal magnitudes, opposite signs.", fontsize=11)
    right.set(xlim=(0, 6), ylim=(-1.1, 1.1), xlabel=r"Inner coordinate $X=x/\epsilon$",
              ylabel="Signed equation terms, multiplied by ε",
              title=r"Both derivative terms survive ($\epsilon=0.05$)")
    right.legend(loc="upper right", frameon=False, fontsize=10)
    for ax in (left, right):
        ax.grid(alpha=0.18)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()