codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2012iiipaper-60-collapse.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2012/iii/paper-60-collapse.py
"""Python 3.14; numpy 2.3.5, matplotlib 3.10.7. Writes only the PNG basename to cwd.
The caller supplies MPLCONFIGDIR; no environment variable is changed here.
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
th=np.linspace(0,2*np.pi,1200);t=(th-np.sin(th))/np.pi;r=(1-np.cos(th))/2
fig,ax=plt.subplots(figsize=(10,5),dpi=100,facecolor='white')
ax.plot(t,r,'--',color='#8b929a',lw=2,label='Ideal pressureless top-hat (formal collapse)')
mask=th<=1.5*np.pi
ax.plot(t[mask],r[mask],color='#2166ac',lw=3,label='Expansion and infall before relaxation')
ax.plot([t[mask][-1],2.45],[.5,.5],color='#2166ac',lw=3,label='Schematic virialized size')
ax.scatter([1,2],[1,0],s=40,color=['#2166ac','#8b929a'])
ax.axhline(.5,color='#b35806',ls=':',lw=1.5);ax.axvline(1,color='#aaa',ls=':',lw=1);ax.axvline(2,color='#aaa',ls=':',lw=1)
ax.annotate('Turnaround',xy=(1,1),xytext=(1.18,1.1),arrowprops={'arrowstyle':'->'})
ax.text(2.02,.55,r'$R_{\rm vir}=R_{\rm ta}/2$',color='#2166ac');ax.text(1.92,.09,'Formal collapse',ha='right',color='#65696e')
ax.set(xlim=(0,2.45),ylim=(0,1.23),xlabel=r'$t/t_{\rm ta}$',ylabel=r'$R/R_{\rm ta}$',title='Spherical collapse and energy-conserving virialization')
ax.legend(loc='lower left',fontsize=9,framealpha=1);ax.grid(alpha=.15);fig.tight_layout();fig.savefig('paper-60-collapse.png',dpi=100,facecolor='white',transparent=False);plt.close(fig)