| Hosted by CoCalc | Download
Kernel: SageMath 7.2.rc1

Kruskal-Szekeres coordinates and Carter-Penrose diagram of Schwarzschild spacetime

This Jupyter/SageMath worksheet is relative to the lectures Geometry and physics of black holes

These computations are based on SageManifolds (v0.9)

Click here to download the worksheet file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, with the command sage -n jupyter

First we set up the notebook to display mathematical objects using LaTeX formatting:

%display latex

Spacetime

We declare the spacetime manifold MM:

M = Manifold(4, 'M') print(M)
4-dimensional differentiable manifold M

The ingoing Eddington-Finkelstein domain

The domain of ingoing Eddington-Finkelstein coordinates (t~,r,θ,ϕ)(\tilde t, r, \theta, \phi):

M_EF = M.open_subset('M_EF', latex_name=r'M_{\rm EF}')

The Schwarzschild-Droste domain

The domain of Schwarzschild-Droste coordinates is MSD=MIMIIM_{\rm SD} = M_{\rm I} \cup M_{\rm II}:

M_SD = M_EF.open_subset('M_SD', latex_name=r'M_{\rm SD}') M_I = M_SD.open_subset('M_I', latex_name=r'M_{\rm I}') M_II = M_SD.open_subset('M_II', latex_name=r'M_{\rm II}') M_SD.declare_union(M_I, M_II)

The Schwarzschild-Droste coordinates (t,r,θ,ϕ)(t,r,\theta,\phi):

X_SD.<t,r,th,ph> = M_SD.chart(r't r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') m = var('m') ; assume(m>=0) X_SD.add_restrictions(r!=2*m) X_SD
X_SD_I = X_SD.restrict(M_I, r>2*m) ; X_SD_I
X_SD_II = X_SD.restrict(M_II, r<2*m) ; X_SD_II
M.default_chart()

Eddington-Finkelstein coordinates

The ingoing Eddington-Finkelstein chart:

X_EF.<te,r,th,ph> = M_EF.chart(r'te:\tilde{t} r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') X_EF
SD_to_EF = X_SD.transition_map(X_EF, [t+2*m*ln(abs(r/(2*m)-1)), r, th, ph]) SD_to_EF.display()
SD_to_EF.inverse().display()
X_EF_I = X_EF.restrict(M_I, r>2*m) ; X_EF_I
X_EF_II = X_EF.restrict(M_II, r<2*m) ; X_EF_II
M.atlas()

Kruskal-Szekeres coordinates

X_KS.<T,X,th,ph> = M.chart(r'T X th:(0,pi):\theta ph:(0,2*pi):\phi') X_KS.add_restrictions(T^2 < 1 + X^2) X_KS
X_KS_I = X_KS.restrict(M_I, [X>0, T<X, T>-X]) ; X_KS_I
X_KS_II = X_KS.restrict(M_II, [T>0, T>abs(X)]) ; X_KS_II
X_KS_EF = X_KS.restrict(M_EF, X+T>0) ; X_KS_EF
SD_I_to_KS = X_SD_I.transition_map(X_KS_I, [sqrt(r/(2*m)-1)*exp(r/(4*m))*sinh(t/(4*m)), sqrt(r/(2*m)-1)*exp(r/(4*m))*cosh(t/(4*m)), th, ph]) SD_I_to_KS.display()
SD_II_to_KS = X_SD_II.transition_map(X_KS_II, [sqrt(1-r/(2*m))*exp(r/(4*m))*cosh(t/(4*m)), sqrt(1-r/(2*m))*exp(r/(4*m))*sinh(t/(4*m)), th, ph]) SD_II_to_KS.display()
EF_to_KS = X_EF.transition_map(X_KS_EF, [exp(r/(4*m))*(cosh(te/(4*m))-r/(4*m)*exp(-te/(4*m))), exp(r/(4*m))*(sinh(te/(4*m))+r/(4*m)*exp(-te/(4*m))), th, ph]) EF_to_KS.display()

Plot of the IEF grid in terms of KS coordinates:

graph = X_EF.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={te:(-16,6), r:(1e-6,5)}, steps={te:1, r:0.5}, style={te:'--', r:'-'}, parameters={m:1})
graph += text(r'$\tilde{t}=0$', (2.65, 0.25), fontsize=16, color='red', rotation=-24) graph += text(r'$\tilde{t}=2m$', (2.8, 1.6), fontsize=16, color='red') graph += text(r'$\tilde{t}=-2m$', (2.68, -0.9), fontsize=16, color='red', rotation=-35) show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook

Adding the Schwarzschild horizon to the plot:

hor = line([(0,0), (4,4)], color='black', thickness=2) \ + text(r'$\mathscr{H}$', (3, 2.7), fontsize=20, color='black') graph += hor

Adding the curvature singularity r=0r=0 to the plot:

sing = X_SD_II.plot(X_KS, fixed_coords={r:0, th:pi/2, ph:pi}, ambient_coords=(X,T), color='brown', thickness=4, style='--', parameters={m:1}) \ + text(r'$r=0$', (2.5, 3), rotation=45, fontsize=16, color='brown') graph += sing show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook
graph.save("sch_IEF_KS.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)

Plot of Schwarzschild-Droste grid on MIM_{\rm I} in terms of KS coordinates

graph = X_SD_I.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(2.001,5)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='blue', parameters={m:1})
hor2 = line([(0,0), (4,4)], color='black', thickness=2) \ + text(r'$\mathscr{H}$', (2.95, 3.2), fontsize=20, color='black') region_labels = text(r'$\mathscr{M}_{\rm I}$', (2.4, 0.4), fontsize=20, color='blue') graph2 = graph + hor2 + region_labels show(graph2, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook
graph2.save("sch_SD_I_KS.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)
graph += X_SD_II.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(0.001,1.999)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='blue', parameters={m:1}) region_labels = text(r'$\mathscr{M}_{\rm I}$', (2.4, 0.4), fontsize=20, color='blue') + \ text(r'$\mathscr{M}_{\rm II}$', (0, 0.5), fontsize=20, color='blue') graph += hor + sing + region_labels show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook
graph.save("sch_SD_KS.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)

Radial null geodesics

The outgoing family:

var('u') outgeod = M.curve({X_EF: [r + 4*m*ln(abs(r/(2*m)-1)) + u, r, pi/2, pi]}, (r, 0, +oo)) outgeod.display()

The ingoing family:

var('v') ingeod = M.curve({X_EF: [-r + v, r, pi/2, pi]}, (r, 0, +oo)) ingeod.display()
graph = Graphics() for u0 in range(-10, 10, 2): graph += outgeod.plot(chart=X_KS, ambient_coords=(X,T), prange=(0.01, 1.99), parameters={m: 1, u: u0}, color='green', style='-') graph += outgeod.plot(chart=X_KS, ambient_coords=(X,T), prange=(2.01, 5), parameters={m: 1, u: u0}, color='green', style='-') graph += ingeod.plot(chart=X_KS, ambient_coords=(X,T), prange=(0.01, 5), parameters={m: 1, v: u0}, color='green', style='--') graph += hor graph += sing show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook
graph.save("sch_rad_null_geod_KS.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)

Extension to MIIIM_{\rm III} and MIVM_{\rm IV}

M_III = M.open_subset('M_III', latex_name=r'M_{\rm III}', coord_def={X_KS: [X<0, X<T, T<-X]}) X_KS_III = X_KS.restrict(M_III) ; X_KS_III
M_IV = M.open_subset('M_IV', latex_name=r'M_{\rm IV}', coord_def={X_KS: [T<0, T<-abs(X)]}) X_KS_IV = X_KS.restrict(M_IV) ; X_KS_IV

Schwarzschild-Droste coordinates in MIIIM_{\rm III} and MIVM_{\rm IV}:

X_SD_III.<t,r,th,ph> = M_III.chart(r't r:(2*m,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') X_SD_III
SD_III_to_KS = X_SD_III.transition_map(X_KS_III, [-sqrt(r/(2*m)-1)*exp(r/(4*m))*sinh(t/(4*m)), - sqrt(r/(2*m)-1)*exp(r/(4*m))*cosh(t/(4*m)), th, ph]) SD_III_to_KS.display()
X_SD_IV.<t,r,th,ph> = M_IV.chart(r't r:(0,2*m) th:(0,pi):\theta ph:(0,2*pi):\phi') X_SD_IV
SD_IV_to_KS = X_SD_IV.transition_map(X_KS_IV, [-sqrt(1-r/(2*m))*exp(r/(4*m))*cosh(t/(4*m)), -sqrt(1-r/(2*m))*exp(r/(4*m))*sinh(t/(4*m)), th, ph]) SD_IV_to_KS.display()

Plot of the maximal extension

graph = X_SD_I.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(2.001,5)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='blue', parameters={m:1}) graph += X_SD_II.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(0.001,1.999)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='steelblue', parameters={m:1}) graph += X_SD_III.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(2.001,5)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='chocolate', parameters={m:1}) graph += X_SD_IV.plot(X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, ranges={t:(-10,10), r:(0.001,1.999)}, steps={t:1, r:0.5}, style={t:'--', r:'-'}, color='gold', parameters={m:1})
bifhor = line([(-4,-4), (4,4)], color='black', thickness=3) + \ line([(-4,4), (4,-4)], color='black', thickness=3) + \ text(r'$\mathscr{H}$', (3, 2.7), fontsize=20, color='black') sing2 = X_SD_IV.plot(X_KS, fixed_coords={r:0, th:pi/2, ph:pi}, ambient_coords=(X,T), color='brown', thickness=4, style='--', parameters={m:1}) \ + text(r"$r'=0$", (2.5, -3), rotation=-45, fontsize=16, color='brown') region_labels = text(r'$\mathscr{M}_{\rm I}$', (2.4, 0.4), fontsize=20, color='blue') + \ text(r'$\mathscr{M}_{\rm II}$', (0, 0.5), fontsize=20, color='steelblue') + \ text(r'$\mathscr{M}_{\rm III}$', (-2.4, 0.4), fontsize=20, color='chocolate') + \ text(r'$\mathscr{M}_{\rm IV}$', (0, -0.5), fontsize=20, color='gold') graph += bifhor + sing + sing2 + region_labels show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3)
Image in a Jupyter notebook
graph.save("sch_kruskal_diag.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)
xi = M.vector_field(name='xi', latex_name=r'\xi') xi[X_KS.frame(), 0, X_KS] = X/(4*m) xi[X_KS.frame(), 1, X_KS] = T/(4*m) xi.display(X_KS.frame(), X_KS)
xi.display(X_KS_I.frame(), X_SD_I)
xi.display(X_SD_I.frame())
#graph_xi = xi.plot(X_KS, chart_domain=X_KS, ambient_coords=(X,T), fixed_coords={th:pi/2,ph:pi}, # max_range=4, nb_values=19, color='red', parameters={m:1}) #graph = graph_xi + bifhor + sing + sing2 #show(graph, xmin=-3, xmax=3, ymin=-3, ymax=3) # graph.save("sch_xi_extend.pdf", xmin=-3, xmax=3, ymin=-3, ymax=3)

Carter-Penrose diagram

The coordinates (T~,X~,θ,φ)(\tilde T, \tilde X, \theta, \varphi) associated with the conformal compactification of the Schwarzschild spacetime are

X_C.<T1,X1,th,ph> = M.chart(r'T1:(-pi/2,pi/2):\tilde{T} X1:(-pi,pi):\tilde{X} th:(0,pi):\theta ph:(0,2*pi):\varphi') X_C.add_restrictions([-pi+abs(X1)<T1, T1<pi-abs(X1)]) X_C

The chart of compactified coordinates plotted in terms of itself:

X_C.plot(X_C, ambient_coords=(X1,T1), nb_values=25)
Image in a Jupyter notebook

The transition map from Kruskal-Szekeres coordinates to the compactified ones:

KS_to_C = X_KS.transition_map(X_C, [atan(T+X)+atan(T-X), atan(T+X)-atan(T-X), th, ph]) print(KS_to_C) KS_to_C.display()
Change of coordinates from Chart (M, (T, X, th, ph)) to Chart (M, (T1, X1, th, ph))

The Kruskal-Szekeres chart plotted in terms of the compactified coordinates:

graph = X_KS.plot(X_C, ambient_coords=(X1,T1), fixed_coords={th:pi/2,ph:0}, ranges={T:(-15,15), X:(-8,8)}, nb_values=33, plot_points=150, style={T:'--', X:'-'}) show(graph)
Image in a Jupyter notebook

Transition map between the Schwarzschild-Droste chart and the chart of compactified coordinates

The transition map is obtained by composition of previously defined ones:

SD_I_to_C = KS_to_C.restrict(M_I) * SD_I_to_KS print(SD_I_to_C) SD_I_to_C.display()
Change of coordinates from Chart (M_I, (t, r, th, ph)) to Chart (M_I, (T1, X1, th, ph))
SD_II_to_C = KS_to_C.restrict(M_II) * SD_II_to_KS print(SD_II_to_C) SD_II_to_C.display()
Change of coordinates from Chart (M_II, (t, r, th, ph)) to Chart (M_II, (T1, X1, th, ph))
SD_III_to_C = KS_to_C.restrict(M_III) * SD_III_to_KS print(SD_III_to_C) SD_III_to_C.display()
Change of coordinates from Chart (M_III, (t, r, th, ph)) to Chart (M_III, (T1, X1, th, ph))
SD_IV_to_C = KS_to_C.restrict(M_IV) * SD_IV_to_KS print(SD_IV_to_C) SD_IV_to_C.display()
Change of coordinates from Chart (M_IV, (t, r, th, ph)) to Chart (M_IV, (T1, X1, th, ph))

Carter-Penrose diagram

The diagram is obtained by plotting the Schwarzschild-Droste charts with respect to the compactified chart:

graph = X_SD_I.plot(X_C, ranges={t:(-16,16), r:(2.001,12)}, fixed_coords={th:pi/2,ph:0}, ambient_coords=(X1,T1), nb_values=25, style={t:'--', r:'-'}, color='blue', parameters={m:1}) graph += X_SD_II.plot(X_C, ranges={t:(-16,16), r:(0.001,1.999)}, fixed_coords={th:pi/2,ph:0}, ambient_coords=(X1,T1), nb_values=25, style={t:'--', r:'-'}, color='steelblue', parameters={m:1}) graph += X_SD_III.plot(X_C, ranges={t:(-16,16), r:(2.001,12)}, fixed_coords={th:pi/2,ph:0}, ambient_coords=(X1,T1), nb_values=25, style={t:'--', r:'-'}, color='chocolate', parameters={m:1}) graph += X_SD_IV.plot(X_C, ranges={t:(-16,16), r:(0.001,1.999)}, fixed_coords={th:pi/2,ph:0}, ambient_coords=(X1,T1), nb_values=25, style={t:'--', r:'-'}, color='gold', parameters={m:1})
sing = X_SD_II.plot(X_C, fixed_coords={r:0, th:pi/2, ph:pi}, ambient_coords=(X1,T1), max_range=20, color='brown', thickness=4, style='--', parameters={m:1}) + text(r'$r=0$', (0.4, 1.7), fontsize=16, color='brown') sing2 = X_SD_IV.plot(X_C, fixed_coords={r:0, th:pi/2, ph:pi}, ambient_coords=(X1,T1), max_range=20, color='brown', thickness=4, style='--', parameters={m:1}) + text(r"$r'=0$", (0.4, -1.7), fontsize=16, color='brown') bifhor = line([(-pi/2,-pi/2), (pi/2,pi/2)], color='black', thickness=3) + \ line([(-pi/2,pi/2), (pi/2,-pi/2)], color='black', thickness=3) + \ text(r'$\mathscr{H}$', (1, 1.2), fontsize=20, color='black') region_labels = text(r'$\mathscr{M}_{\rm I}$', (2, 0.4), fontsize=20, color='blue', background_color='white') + \ text(r'$\mathscr{M}_{\rm II}$', (0.4, 1), fontsize=20, color='steelblue', background_color='white') + \ text(r'$\mathscr{M}_{\rm III}$', (-2, 0.4), fontsize=20, color='chocolate', background_color='white') + \ text(r'$\mathscr{M}_{\rm IV}$', (0.4, -1), fontsize=20, color='gold', background_color='white') graph += sing+sing2+bifhor+region_labels show(graph)
Image in a Jupyter notebook
graph.save('sch_carter-penrose.pdf')