codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2003ibpaper-4-cylinder-potentials.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2003/ib/paper-4-cylinder-potentials.py
#!/usr/bin/env python3
"""Cylinder equipotentials; Python3.14/NumPy2.3.5/Matplotlib3.10.7.
Write an opaque PNG to caller CWD; honor caller MPLCONFIGDIR.
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
def main():
x=np.linspace(-3.6,3.6,801)
y=np.linspace(-2.8,2.8,621)
X,Y=np.meshgrid(x,y)
R2=X*X+Y*Y
phi=np.ma.masked_where(R2<=1,X*(1+1/np.maximum(R2,1e-20)))
fig,ax=plt.subplots(figsize=(7.0,5.4),layout='constrained',facecolor='white')
curves=ax.contour(X,Y,phi,levels=np.arange(-3.5,3.51,.5),colors='#225f96',linewidths=.9)
ax.clabel(curves,levels=[-3,-2,-1,0,1,2,3],inline=True,fontsize=8)
ax.add_patch(Circle((0,0),1,facecolor='#eeeeee',edgecolor='black',linewidth=1.3,zorder=3))
ax.text(0,0,'Cylinder',ha='center',va='center',fontsize=10,zorder=4)
ax.scatter([-1,1],[0,0],s=20,color='#b04d18',zorder=5)
ax.annotate('Uniform flow',xy=(3.2,2.45),xytext=(1.7,2.45),va='center',arrowprops={'arrowstyle':'->','lw':1.3})
ax.set(xlabel='x/a',ylabel='y/a',title=r'Equipotentials: $\phi/(Ua)=(r/a+a/r)\cos\theta$')
ax.set_aspect('equal');ax.set_facecolor('white')
fig.savefig('paper-4-cylinder-potentials.png',dpi=120,facecolor='white',transparent=False)
plt.close(fig)
if __name__=='__main__':main()