"""Compare exact optima of an original dimensionless parabolic-polar model. Run from _media using the repository Python 3.14 / NumPy / Matplotlib setup. The curves are constructed calculations, not measured aircraft performance. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np def drag_ratio(x): x = np.asarray(x, dtype=float) return (x**2 + x**-2) / 2 def power_ratio(x): x = np.asarray(x, dtype=float) return (x**3 + x**-1) / 2 def main(): x_mp = 3**(-0.25) assert np.isclose(drag_ratio(1), 1) assert np.isclose(power_ratio(x_mp), 2 * 3**(-0.75)) assert np.isclose(3 * x_mp**2 - x_mp**-2, 0) x = np.linspace(0.48, 1.75, 601) fig, axes = plt.subplots(1, 2, figsize=(8.4, 4.6), dpi=100, facecolor="white") specs = [(axes[0], drag_ratio, "#245f8e", "Drag required", r"$D/D_{\min}$", 1.0), (axes[1], power_ratio, "#ba5c24", "Propulsive power required", r"$P/(D_{\min}V_{\rm MD})$", x_mp)] for ax, curve, color, title, ylabel, optimum in specs: ax.set_facecolor("white") ax.plot(x, curve(x), color=color, lw=2.5) ax.axvline(x_mp, color="#ba5c24", ls=":", lw=1.2) ax.axvline(1, color="#245f8e", ls="--", lw=1.2) y_min = float(curve(optimum)) ax.scatter([optimum], [y_min], color=color, s=35, zorder=5) ax.annotate("Minimum", (optimum, y_min), xytext=(12, 30), textcoords="offset points", fontsize=10, arrowprops={"arrowstyle": "->", "color": color}) ax.set(xlim=(0.48, 1.75), ylim=(0.65, 3.05), title=title, xlabel=r"Speed ratio $V/V_{\rm MD}$", ylabel=ylabel) ax.grid(alpha=0.17) axes[0].text(0.50, 2.65, r"$D=aV^2+b/V^2$", fontsize=11) axes[1].text(0.50, 2.65, r"$P=DV=aV^3+b/V$", fontsize=11) fig.suptitle("Different speeds minimize drag and required power", fontsize=14, y=0.98) fig.text(0.5, 0.083, r"Dotted: $V_{\rm MP}/V_{\rm MD}=3^{-1/4}\simeq0.760$" " Dashed: drag minimum at 1", ha="center", fontsize=10) fig.text(0.5, 0.027, "Constructed model: steady level flight, fixed weight and density, constant polar coefficients.", ha="center", fontsize=9, color="#444444") fig.tight_layout(rect=(0, 0.12, 1, 0.94)) fig.savefig(Path("minimum-drag-and-power-speeds.png"), facecolor="white", dpi=100) plt.close(fig) if __name__ == "__main__": main()