codexpast-exam-of-the-physics-1-paper-of-the-university-of-oxford2017-resit-orbital-impulses.py
past-exam-of-the-physics-1-paper-of-the-university-of-oxford/2017-resit-orbital-impulses.py
"""Four osculating Kepler ellipses; output only the matching PNG in cwd."""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
fig,axes=plt.subplots(2,2,figsize=(9.2,8),layout='constrained')
theta=np.linspace(0,2*np.pi,1000)
r0=np.array([0.,1.]);vc=np.array([-1.,0.]);kick=.18
cases=[('a: forward tangential',np.array([-kick,0.])),('b: radially outward',np.array([0.,kick])),('c: backward tangential',np.array([kick,0.])),('d: radially inward',np.array([0.,-kick]))]
for ax,(label,dv) in zip(axes.flat,cases):
v=vc+dv;h=np.cross(np.r_[r0,0.],np.r_[v,0.])[2]
e=(np.dot(v,v)-1)*r0-np.dot(r0,v)*v
directions=np.column_stack((np.cos(theta),np.sin(theta)))
rad=h*h/(1+directions@e);xy=rad[:,None]*directions
ax.plot(np.cos(theta),np.sin(theta),'--',color='.65',label='original circle')
ax.plot(xy[:,0],xy[:,1],color='#1f77b4',lw=2,label='new ellipse')
ax.scatter([0],[0],s=85,color='#dfaa2b',zorder=5)
ax.scatter([0],[1],s=35,color='black',zorder=6)
ax.annotate('',xy=r0+1.8*dv,xytext=r0,arrowprops=dict(arrowstyle='->',color='#c33',lw=2.5))
ax.set(title=label,xlim=(-1.7,1.7),ylim=(-2.5,1.5),aspect='equal',xlabel=r'$x/r_0$',ylabel=r'$y/r_0$')
ax.grid(alpha=.15)
axes[0,0].legend(loc='lower left',fontsize=8)
fig.suptitle('Small velocity changes at the top of a counterclockwise orbit',fontsize=14)
fig.savefig(Path.cwd()/Path(__file__).with_suffix('.png').name,dpi=140,facecolor='white')