codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2010iiipaper-54-vaidya-penrose.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2010/iii/paper-54-vaidya-penrose.py
"""Schematic double-null Penrose diagram. Python 3.14, numpy 2.3.5,
matplotlib 3.10.7. Write an opaque PNG basename to caller CWD.
MPLCONFIGDIR is owned by the caller and is not changed here.
"""
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
def point(p, q):
return ((q-p)/2, (q+p)/2)
def main():
fig, ax = plt.subplots(figsize=(9, 6), facecolor="white")
vertices=[point(-1,0),point(-1,1),point(0,1),point(1,0)]
ax.add_patch(Polygon(vertices,closed=True,facecolor="#f3f7fb",edgecolor="none"))
# p labels outgoing null rays, q labels ingoing null rays; both increase
# to the future. The spacelike singularity is schematic p+q=1.
q0, q1 = .30, .56
band=[point(-1,q0),point(-1,q1),point(1-q1,q1),point(1-q0,q0)]
ax.add_patch(Polygon(band,closed=True,facecolor="#deedce",edgecolor="none"))
for qa in (q0,q1):
p=np.linspace(-1,1-qa,160); x,y=point(p,qa+0*p)
ax.plot(x,y,color="#498c3f",lw=1.3)
# Past boundary of the ingoing chart. It is not a regular axis.
x,y=point(np.linspace(-1,1,200),0);ax.plot(x,y,color="#606975",ls=":",lw=1.3)
p=-np.ones(200);q=np.linspace(0,1,200);x,y=point(p,q)
ax.plot(x,y,color="black",lw=1.8)
p=np.linspace(-1,0,200);x,y=point(p,np.ones(200));ax.plot(x,y,color="black",lw=1.8)
xx=np.linspace(-.5,.5,221); yy=.5+.009*np.sin(np.linspace(0,38*np.pi,len(xx)))
ax.plot(xx,yy,color="black",lw=1.7)
# Event horizon p=0; apparent horizon p>0 before final stationarity.
q=np.linspace(0,1,400);x,y=point(0*q,q);ax.plot(x,y,color="#b3292d",lw=3)
h=np.clip((q-q0)/(q1-q0),0,1);papp=.18*(1-3*h*h+2*h*h*h)
x,y=point(papp,q);ax.plot(x,y,color="#2268ac",lw=2,ls="--")
for pp,qa,qb in [(-.30,.60,1),(.20,.62,.80)]:
x0,y0=point(pp,qa);x1,y1=point(pp,qb)
ax.annotate("",(x1,y1),(x0,y0),arrowprops={"arrowstyle":"->","lw":1.7,"color":"#7356a7"})
xa,ya=point(-.65,.43);xb,yb=point(-.18,.43)
ax.annotate("",(xb,yb),(xa,ya),arrowprops={"arrowstyle":"->","lw":1.8,"color":"#376b30"})
ax.text(.04,.565,"Future spacelike singularity r = 0",ha="center",fontsize=12)
ax.text(.90,.24,r"$\mathscr{I}^{+}$",fontsize=23)
ax.text(.77,-.31,r"$\mathscr{I}^{-}$",fontsize=23)
ax.text(1.03,0,r"$i^{0}$",fontsize=15)
ax.text(.53,.51,r"$i^{+}$",fontsize=15)
ax.annotate("Event horizon",point(0,.79),(.06,.36),fontsize=11,color="#a12427",
arrowprops={"arrowstyle":"-","color":"#a12427"})
ax.annotate("Apparent horizon\n(finally coincident)",point(.18,.17),(-.45,-.13),fontsize=10,color="#2268ac",
arrowprops={"arrowstyle":"-","color":"#2268ac"})
ax.text(.36,.04,"Accretion",fontsize=11,color="#376b30",rotation=-45)
ax.text(.58,-.13,r"Initially $m=M_0$",fontsize=11,rotation=-45)
ax.text(.67,.39,r"Finally $m=M_1$",fontsize=11,rotation=-45)
ax.text(-.30,.23,"Black-hole interior",fontsize=11)
ax.text(.49,-.48,"Future",fontsize=10)
ax.annotate("",(.49,-.37),(.49,-.45),arrowprops={"arrowstyle":"->","color":"black"})
ax.set_title("Accretion onto a pre-existing black hole",fontsize=15,pad=18)
ax.text(.24,-.59,"Schematic: ingoing and outgoing null directions have slopes −1 and +1.\nOne exterior and the future interior; no regular centre is depicted.",
ha="center",va="top",fontsize=10)
ax.set_xlim(-.61,1.16);ax.set_ylim(-.68,.63);ax.set_aspect("equal");ax.axis("off")
fig.savefig(Path(__file__).with_suffix(".png").name,dpi=140,facecolor="white",transparent=False,bbox_inches="tight")
plt.close(fig)
if __name__ == "__main__":
main()