codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2015iiipaper-79-rossby-dispersion.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2015/iii/paper-79-rossby-dispersion.py
"""Generate an original Rossby dispersion/reflection sketch in the caller's cwd.
Tested with Python 3.14, NumPy 2.3.5 and matplotlib 3.10.7.
MPLCONFIGDIR is supplied by the caller and is never overridden here.
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
def main():
fig, (ax, circle) = plt.subplots(1, 2, figsize=(9, 5), dpi=100, facecolor='white')
k = np.linspace(-5, 5, 1601)
for ell, color in [(0, '#006e9c'), (0.6, '#a53f00'), (1.5, '#42783a')]:
ax.plot(k, -k/(k*k+ell*ell+1), color=color, linewidth=2, label=f'$l/a={ell:g}$')
w, ell = -0.3, 0.6
centre = -1/(2*w)
radius = np.sqrt(1/(4*w*w)-1)
offset = np.sqrt(radius*radius-ell*ell)
ki, kr = centre-offset, centre+offset
ax.axhline(0, color='0.55', linewidth=0.7)
ax.axvline(0, color='0.55', linewidth=0.7)
ax.axhline(w, color='0.55', linestyle=':', linewidth=1)
ax.scatter([ki, kr], [w, w], color='black', s=23, zorder=4)
ax.set(xlabel='$k/a$', ylabel=r'$\omega a/\beta$', title='Frequency at fixed meridional wavenumber')
ax.legend(loc='upper right', fontsize=9)
ax.grid(alpha=0.15)
angle = np.linspace(0, 2*np.pi, 801)
circle.plot(centre+radius*np.cos(angle), radius*np.sin(angle), color='#006e9c', linewidth=2)
circle.axhline(0, color='0.55', linewidth=0.7)
circle.axvline(0, color='0.55', linewidth=0.7)
circle.plot([0, centre+radius+0.3], [ell, ell], ':', color='0.5')
circle.scatter([ki, kr], [ell, ell], color='black', s=25, zorder=4)
circle.scatter([centre], [0], marker='+', color='0.4', s=65)
circle.annotate('Incident\nwestward group', (ki, ell), xytext=(ki-0.1, ell+0.5), ha='center', fontsize=9,
arrowprops={'arrowstyle': '->', 'color': '0.25'})
circle.annotate('Reflected\neastward group', (kr, ell), xytext=(kr+0.05, ell+0.5), ha='center', fontsize=9,
arrowprops={'arrowstyle': '->', 'color': '0.25'})
circle.set(xlabel='$k/a$', ylabel='$l/a$', title=r'Constant frequency: $\omega a/\beta=-0.3$')
circle.set_xlim(-0.1, centre+radius+0.3)
circle.set_ylim(-1.55, 1.55)
circle.set_aspect('equal', adjustable='box')
circle.grid(alpha=0.15)
fig.suptitle('Rossby waves: phase travels west, reflected energy travels east', fontsize=12)
fig.tight_layout(rect=(0, 0, 1, 0.93))
fig.savefig('paper-79-rossby-dispersion.png', dpi=100, facecolor='white', transparent=False)
plt.close(fig)
if __name__ == '__main__':
main()