"""Generate an original schematic; write the PNG basename in the current directory. Tested with Python 3.14, NumPy 2.3.5 and Matplotlib 3.10.7. MPLCONFIGDIR supplied by the caller is respected. """ import os from pathlib import Path os.environ.setdefault('MPLCONFIGDIR',str(Path.cwd()/'.paper-65-mplconfig')) import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import Circle,Polygon,FancyArrowPatch Q=.4 OM=np.sqrt(1+Q) XC=Q/(1+Q) def potential(x,y): return -1/np.hypot(x,y)-Q/np.hypot(x-1,y)-.5*(1+Q)*((x-XC)**2+y*y) def gradient(x,y): r=np.hypot(x,y);s=np.hypot(x-1,y) return np.array([x/r**3+Q*(x-1)/s**3-(1+Q)*(x-XC),y/r**3+Q*y/s**3-(1+Q)*y]) def l1(): lo,hi=.001,.999 for _ in range(80): mid=(lo+hi)/2 if gradient(mid,0)[0]>0:lo=mid else:hi=mid return (lo+hi)/2 def donor_boundary(): point=l1();crit=potential(point,0);points=[] for theta in np.linspace(-np.pi,np.pi,1001): d=np.array([np.cos(theta),np.sin(theta)]) if abs(abs(theta)-np.pi)<1e-8:r=1-point else: radii=np.linspace(.001,.7,1000);vals=potential(1+radii*d[0],radii*d[1])-crit indices=np.flatnonzero(vals>=0) if not len(indices):raise RuntimeError('No first equipotential crossing') hi=radii[indices[0]];lo=hi-.7/999 for _ in range(45): mid=(lo+hi)/2 if potential(1+mid*d[0],mid*d[1])