codex/past-exam-of-the-differential-equations-2-course-of-the-university-of-oxford/2021-boundary-layer.py

past-exam-of-the-differential-equations-2-course-of-the-university-of-oxford/2021-boundary-layer.py
#!/usr/bin/env python3
"""Oxford A6 2021, Q3(c): leading composite and inner approximations.

Python 3.14.4, NumPy 2.3.5, Matplotlib 3.10.7 (repository dependencies).
These are asymptotic profiles, not numerical or exact BVP solutions.
Run in the output directory; writes 2021-boundary-layer.png there.
"""
from pathlib import Path

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


def main():
    x = np.linspace(1, 2, 2401)
    fig, ax = plt.subplots(figsize=(8.2, 4.2), layout="constrained")
    fig.patch.set_facecolor("white")
    outer = np.exp(x - 1)
    for eps, color in [(0.04, "#176aa5"), (0.08, "#b45224")]:
        composite = outer - np.e * np.exp(-2 * (2 - x) / eps)
        ax.plot(x, composite, color=color, lw=2,
                label=rf"composite, $\epsilon={eps}$")
    ax.plot(x, outer, color="#555555", lw=1.6, ls="--", label="outer")
    ax.scatter([1, 2], [1, 0], color="#222222", s=24, zorder=5)
    ax.annotate("right boundary layer", (1.985, 0.85), xytext=(1.60, 0.50),
                fontsize=10, arrowprops={"arrowstyle": "->"})
    ax.set(xlim=(1, 2), ylim=(-0.05, 2.95), xlabel="$x$", ylabel="leading approximation")
    ax.grid(alpha=0.16)
    ax.legend(loc="upper left", fontsize=9)
    ax.spines[["top", "right"]].set_visible(False)
    inset = ax.inset_axes([0.17, 0.15, 0.35, 0.24])
    X = np.linspace(0, 3.5, 501)
    inset.plot(X, np.e * (1 - np.exp(-2 * X)), color="#3a7d44", lw=1.7)
    inset.axhline(np.e, color="#555555", ls="--", lw=0.9)
    inset.set(xlim=(0, 3.5), ylim=(0, 2.95), xlabel=r"$X=(2-x)/\epsilon$",
              title=r"Inner: $e(1-e^{-2X})$")
    inset.set_yticks([0, np.e], ["0", "$e$"])
    inset.tick_params(labelsize=8)
    inset.xaxis.label.set_fontsize(9)
    inset.title.set_fontsize(9)
    inset.grid(alpha=0.12)
    fig.savefig(Path("2021-boundary-layer.png"), dpi=115,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()