codex/past-exam-of-the-advanced-fluid-dynamics-course-of-the-university-of-oxford/2017-force-free-arcade-projections.py

past-exam-of-the-advanced-fluid-dynamics-course-of-the-university-of-oxford/2017-force-free-arcade-projections.py
"""Original linear force-free arcade projections; Python 3.14, numpy, matplotlib."""
from pathlib import Path
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

plt.rcParams.update({'font.size': 12, 'axes.spines.top': False, 'axes.spines.right': False})
k = np.pi
lam = .6*k
q = .8*k
fig, axes = plt.subplots(1, 2, figsize=(10.8, 4.4), constrained_layout=True, facecolor='white')
colors = ['#1864ab', '#d9480f', '#2b8a3e', '#862e9c']
for j, (s, color) in enumerate(zip([.18, .34, .52, .72], colors)):
    xm = np.arcsin(s)/k
    xp = 1-xm
    x = np.linspace(xm, xp, 501)
    z = np.log(np.sin(k*x)/s)/q
    y = .15*j + (lam/q)*(x-xm)
    for ax, ordinate in zip(axes, [z, y]):
        ax.plot(x, ordinate, color=color, lw=2.1, label=f's = {s:.2f}')
        ix = 155
        ax.annotate('', xy=(x[ix+15], ordinate[ix+15]), xytext=(x[ix], ordinate[ix]), arrowprops={'arrowstyle': '-|>', 'color': color, 'lw': 1.8})
        ax.plot([xm, xp], [ordinate[0], ordinate[-1]], 'o', color=color, ms=4)
for ax in axes:
    ax.axvline(0, color='.6', lw=1, ls=':')
    ax.axvline(1, color='.6', lw=1, ls=':')
    ax.set_xlim(-.03, 1.03)
    ax.set_xlabel(r'$x/a$')
    ax.grid(alpha=.18)
axes[0].axhline(0, color='.3', lw=1)
axes[0].set_ylim(-.035, .76)
axes[0].set_ylabel(r'$z/a$')
axes[0].set_title('Vertical projection: flux-function contours')
axes[0].text(.02, .72, r'$\lambda/k=0.6,\quad q/k=0.8$', fontsize=11)
axes[0].text(.13, .035, r'$B_z>0$', fontsize=11)
axes[0].text(.69, .035, r'$B_z<0$', fontsize=11)
axes[0].legend(loc='upper right', frameon=False, fontsize=10)
axes[1].set_ylim(-.04, 1.05)
axes[1].set_ylabel(r'$y/a$')
axes[1].set_title('Horizontal projection: sheared connections')
axes[1].text(.07, .95, r'$dy/dx=\lambda/q=0.75$', fontsize=11)
fig.savefig(Path.cwd()/Path(__file__).with_suffix('.png').name, dpi=130, facecolor='white', transparent=False)
plt.close(fig)