This notebook demonstrates some capabilities of SageMath in computations regarding the Poincaré horizon of the 4-dimensional anti-de Sitter spacetime. It also provides computations and figures for Example 17 of Chap. 3 of the lecture notes Geometry and physics of black holes.
The corresponding tools have been developed within the SageManifolds project.
version()
'SageMath version 9.5.beta1, Release Date: 2021-09-13'
First we set up the notebook to display mathematical objects using LaTeX rendering and we ask for running tensor computations in parallel on 8 threads:
%display latex
Parallelism().set(nproc=8)
We declare the anti-de Sitter spacetime as a 4-dimensional Lorentzian manifold:
M = Manifold(4, 'M', latex_name=r'\mathscr{M}', structure='Lorentzian')
print(M)
M
4-dimensional Lorentzian manifold M
and endow it with the conformal coordinates $(\tau, \chi, \theta,\phi)$ (cf. the generic anti-de Sitter notebook):
X_conf.<ta,ch,th,ph> = M.chart(r'ta:\tau ch:(0,pi/2):\chi th:(0,pi):\theta ph:(0,2*pi):periodic:\phi')
print(X_conf)
X_conf
Chart (M, (ta, ch, th, ph))
X_conf.coord_range()
First of all, we declare the AdS length scale $\ell$ as a symbolic variable:
var('l', latex_name=r'\ell', domain='real')
assume(l>0)
Then we define the metric tensor $g$ by providing its nonzero components:
g = M.metric()
g[0,0] = -l^2/cos(ch)^2
g[1,1] = l^2/cos(ch)^2
g[2,2] = l^2/cos(ch)^2*sin(ch)^2
g[3,3] = l^2/cos(ch)^2*sin(ch)^2*sin(th)^2
g.display()
Let us check that $g$ is a solution of the vaccum Einstein equation with the cosmological constant $\Lambda = - 3 /\ell^2$:
Ric = g.ricci()
R = g.ricci_scalar()
Lambda = -3/l^2
Ric - 1/2*R*g + Lambda*g == 0
The Poincaré patch is the open subset $\mathscr{M}_{\rm P}$ of $\mathscr{M}$ defined by $$ \cos\tau - \sin\chi \sin\theta \cos\phi > 0 \quad\mbox{and}\quad -\pi < \tau < \pi.$$ Hence we declare it as
MP = M.open_subset('MP', latex_name=r'\mathscr{M}_{\rm P}',
coord_def={X_conf: [cos(ta) - sin(ch)*sin(th)*cos(ph)>0, ta>-pi, ta<pi]})
print(MP)
MP
Open subset MP of the 4-dimensional Lorentzian manifold M
We introduce the Poincaré coordinates $(t,x,y,u)$ on $\mathscr{M}_{\rm P}$ as
X_Poinc.<t,x,y,u> = MP.chart('t x y u:(0,+oo)')
X_Poinc
X_Poinc.coord_range()
The Poincaré coordinates are defined by their link to the conformal coordinates, which we declare via the method transition_map
on the restriction of the conformal coordinates to $\mathscr{M}_{\rm P}$, X_conf.restrict(MP)
:
conf_to_Poinc = X_conf.restrict(MP).transition_map(X_Poinc,
[l*sin(ta)/(cos(ta) - sin(ch)*sin(th)*cos(ph)),
l*sin(ch)*sin(th)*sin(ph)/(cos(ta) - sin(ch)*sin(th)*cos(ph)),
l*sin(ch)*cos(th)/(cos(ta) - sin(ch)*sin(th)*cos(ph)),
l*(cos(ta) - sin(ch)*sin(th)*cos(ph))/cos(ch)])
conf_to_Poinc.display()
In order to help SageMath with simplifications, we explicitly set some assumptions:
assume(sin(ch)>0, sin(th)>0)
assume(cos(ta) - sin(ch)*sin(th)*cos(ph)>0)
We provide the inverse of the coordinate change $(\tau,\chi,\theta,\phi) \mapsto (t,x,y,u)$ by means of the method set_inverse
:
conf_to_Poinc.set_inverse(atan2(2*l*t, x^2+y^2-t^2+l^2*(1+l^2/u^2)),
acos(2*l^3/u/sqrt((x^2+y^2-t^2+l^2*(1+l^2/u^2))^2 + 4*l^2*t^2)),
acos(2*l*y/sqrt((x^2+y^2-t^2+l^2*(1+l^2/u^2))^2
+ 4*l^2*(t^2-l^4/u^2))),
atan2(2*l*x, x^2+y^2-t^2-l^2*(1-l^2/u^2)))
Check of the inverse coordinate transformation: ta == -arctan2(2*l^2*sin(ta)/(cos(ph)*sin(ch)*sin(th) - cos(ta)), -2*l^2*cos(ta)/(cos(ph)*sin(ch)*sin(th) - cos(ta))) **failed** ch == ch *passed* th == th *passed* ph == -arctan2(2*l^2*sin(ch)*sin(ph)*sin(th)/(cos(ph)*sin(ch)*sin(th) - cos(ta)), -2*l^2*cos(ph)*sin(ch)*sin(th)/(cos(ph)*sin(ch)*sin(th) - cos(ta))) **failed** t == t *passed* x == x *passed* y == y *passed* u == u *passed* NB: a failed report can reflect a mere lack of simplification.
conf_to_Poinc.inverse().display()
We note that the Jacobian of the coordinate change is quite involved:
conf_to_Poinc.jacobian()
For plotting purposes, we introduce the 2-dimensional plane $\mathbb{R}^2$, spanned by Cartesian coordinates $(\tau, x_\chi)$:
R2 = Manifold(2, 'R^2', latex_name=r'\mathbb{R}^2')
X2.<ta, x_ch> = R2.chart(r'ta:\tau x_ch:x_\chi')
X2
and define the following map from AdS spacetime to $\mathbb{R}^2$:
Phi = M.diff_map(R2, {(X_conf, X2): [ta, ch*cos(ph)]})
Phi.display()
Let us the grid of coordinates $(t,u)$ for $(x,y)=(0,0)$ in terms of the coordinates $(\tau,\chi)$. This is achieved by using the method plot
on the chart X_Poinc
:
graph1 = X_Poinc.plot(X2, ambient_coords=(x_ch, ta), mapping=Phi.restrict(MP),
fixed_coords={x: 0, y: 0},
ranges={t: (-15, 15), u: (0.01, 12)}, parameters={l: 1},
color={t: 'red', u: 'grey'}, number_values={t: 33, u: 25},
plot_points=200)
We superpose the plot of the Poincaré horizon and a few labels:
graph = polygon([(-pi/2, -pi), (pi/2, 0), (-pi/2, pi)], color='cornsilk')
graph += graph1
graph_hor = plot(pi/2 - ch, (ch, -pi/2, pi/2), color='green',
thickness=3) \
+ plot(ch - pi/2, (ch, -pi/2, pi/2), color='green',
thickness=3) \
+ text(r'$\mathscr{H}$', (-0.9, 2.85), fontsize=18, color='green')
graph += graph_hor
region_labels = text(r'$\mathscr{M}$', (1, 2.5), fontsize=18, color='black') \
+ text(r'$\mathscr{M}_{\rm P}$', (-0.4, 0.5), fontsize=18,
color='black')
graph += region_labels
show(graph, frame=True, gridlines=True, figsize=8)
graph.save('neh_AdS_Poincare_patch.pdf', frame=True,
gridlines=True, figsize=8)
The computation of the metric components with respect to Poincaré coordinates is triggered by the method display
when it receives the Poincaré chart X_Poinc
as an argument:
g.display(X_Poinc)
Since the above components of $g$ do not depend of $t$, the coordinate vector $\displaystyle\frac{\partial}{\partial t}$ is clearly a Killing vector of $(\mathscr{M}_{\rm P}, g)$. Its expression in terms the conformal coordinates is
vt = X_Poinc.frame()[0]
vt.display()
Let us check that $\xi$ is indeed a Killing vector of $(\mathcal{M}_{\rm P}, g)$:
g.restrict(MP).lie_derivative(vt).display()
We note that the components of $\partial/\partial t$ with respect to conformal coordinates are smooth functions of $(\tau,\chi,\theta,\phi)$ that can be extended beyond $\mathscr{M}_{\rm P}$. We may therefore extend $\partial/\partial t$ to a vector field $\xi$ defined on the entire AdS spacetime $\mathscr{M}$:
xi = M.vector_field([vt[i].expr() for i in M.irange()],
name='xi', latex_name=r'\xi')
xi.display()
Let us check that the restriction of $\xi$ to $\mathscr{M}_{\rm P}$ coincides with $\partial/\partial t$:
xi.restrict(MP).display(X_Poinc)
$\xi$ is a global Killing vector:
g.lie_derivative(xi).display()
Another view of the same property by forming the Killing equation $\nabla_a \xi_b + \nabla_b \xi_a = 0$:
nabla = g.connection()
nabla(xi.down(g)).symmetrize().display()
graph = polygon([(-pi/2, -pi), (pi/2, 0), (-pi/2, pi)], color='cornsilk')
graph += xi.plot(X2, ambient_coords=(x_ch, ta), mapping=Phi,
fixed_coords={th: pi/2}, parameters={l: 1},
ranges={ta: (-pi, pi)}, number_values={ta: 11, ch: 7, ph: 3},
color='red', scale=0.3, arrowsize=2)
graph += graph_hor
show(graph, frame=True, gridlines=True, figsize=8, aspect_ratio=1)
graph.save("neh_AdS_Killing_vec.pdf", frame=True, gridlines=True,
figsize=8, aspect_ratio=1)
The expression of the Poincaré coordinate $u$ in terms of the conformal coordinates $(\tau,\chi,\theta,\phi)$
is read as the last component (index 3
) of the coordinate transformation conf_to_Poinc
, which
implements $(\tau,\chi,\theta,\phi)\mapsto (t,x,y,u)$:
conf_to_Poinc(ta, ch, th, ph)
conf_to_Poinc(ta, ch, th, ph)[3]
This expression being regular in all $\mathscr{M}$, we may extend $u$ to a scalar field defined on $\mathscr{M}$ by
U = M.scalar_field(conf_to_Poinc(ta, ch, th, ph)[3], name='u')
U.display()
The Poincaré horizon
is the hypersurface $\mathscr{H}$ bounding the Poincaré patch $\mathscr{M}_{\rm P}$ in
$\mathscr{M}$. It follows that $\mathscr{H}$ is the level set $u=0$ within the region $-\pi<\tau<\pi$.
$\mathscr{H}$ has actually two connected components: one for $-\pi < \tau < 0$ and the other one
for $0 < \tau <\pi$. In what follows, we focus on the connected component that has $0 < \tau <\pi$; we define
it as a submanifold of $\mathscr{M}$, by means of the keyword ambient
in the function Manifold
:
H = Manifold(3, 'H', ambient=M, latex_name=r'\mathscr{H}')
print(H)
3-dimensional differentiable submanifold H immersed in the 4-dimensional Lorentzian manifold M
We consider that $\mathscr{H}$ is spanned by the coordinates $(\chi,\theta,\phi)$, so that we declare the following chart:
XH.<ch,th,ph> = H.chart(r'ch:(0,pi/2):\chi th:(0,pi):\theta ph:(0,2*pi):periodic:\phi')
XH
The embedding $F$ of $\mathscr{H}$ into $\mathscr{M}$ is easily defined in the pair of charts
(XH, X_conf)
by noticing that, for $0 < \tau <\pi$, $u=0 \iff \tau = \arccos(\sin\chi\sin\theta\cos\phi)$:
F = H.diff_map(M, {(XH, X_conf): (acos(sin(ch)*sin(th)*cos(ph)), ch, th, ph)},
name='F')
F.display()
We declare that $F$ is the embedding of $\mathscr{H}$ into $\mathscr{M}$, thereby ending the definition of $\mathscr{H}$:
H.set_embedding(F)
print(H)
3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M
We may check that the scalar field $u$ is zero on $\mathscr{H}$ by considering the pullback of $u$ by $F$:
FU = F.pullback(U)
print(FU)
Scalar field F^*(u) on the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M
FU.display()
The metric induced by $g$ on $\mathscr{H}$ is obtained as the pullback of $g$ by the embedding $F$:
Fg = F.pullback(g)
print(Fg)
Field of symmetric bilinear forms F^*(g) on the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M
Fg.display()
We declare a metric $h$ on $\mathscr{H}$ and initialize it with the pullback $F^* g$:
h = H.metric('h')
h.set(Fg)
h.display()
This is a degenerate metric:
h.determinant().display()
Hence the Poincaré horizon $\mathscr{H}$ is a null hypersurface.
Since $\mathscr{H}$ is the isosurface $u=0$, its normal $k$ is defined as the gradient of $u$:
dU = diff(U)
dU.display()
dU
is a 1-form; we turn it into a vector field by raising its index with the metric $g$, via the method up
:
k = dU.up(g)
k.set_name('k')
k.display()
Plot of $k$:
graph = k.plot(X2, ambient_coords=(x_ch, ta), mapping=Phi,
fixed_coords={th: pi/2}, parameters={l: 1},
ranges={ta: (-pi, pi)}, number_values={ta: 11, ch: 7, ph: 3},
color='orange', scale=0.3, arrowsize=2)
graph += graph_hor
graph += line([(-pi/2, -pi), (-pi/2, pi)], color='black')
graph += line([(pi/2, -pi), (pi/2, pi)], color='black')
show(graph, frame=True, gridlines=True, figsize=8, aspect_ratio=1)
We note that, graphically, $k$ appears tangent to $\mathscr{H}$, in agreement with $\mathscr{H}$ being a null hypersurface (the only kind of hypersurface for which the normal is also tangent to the hypersurface).
The spacetime metric $g$ restricted to $\mathscr{H}$ is evaluated by means of the method along
:
g_H = H.lorentzian_metric('g_H', latex_name=r'\left.g\right|_{\mathscr{H}}',
dest_map=F)
g_H.set(g.along(F))
print(g_H)
Lorentzian metric g_H along the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M with values on the 4-dimensional Lorentzian manifold M
g_H.display()
The vector field $k$ restricted to $\mathscr{H}$:
k_H = k.along(F)
k_H.set_name('k_H', latex_name=r'\left.k\right|_{\mathscr{H}}')
print(k_H)
Vector field k_H along the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M with values on the 4-dimensional Lorentzian manifold M
k_H.display()
Check that $\left.k\right|_{\mathscr{H}}$ is a null vector field:
g_H(k_H, k_H).expr()
Since $\left.k\right|_{\mathscr{H}}$ is normal to $\mathscr{H}$, we recover the fact that $\mathscr{H}$ is a null hypersurface.
The Killing vector field $\xi$ restricted to $\mathscr{H}$:
xi_H = xi.along(F)
xi_H.set_name('xi_H', latex_name=r'\left.\xi\right|_{\mathscr{H}}')
print(xi_H)
Vector field xi_H along the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M with values on the 4-dimensional Lorentzian manifold M
xi_H.display()
Value of $\tau$ on $\mathscr{H}$:
ta_H = F.expr()[0]
ta_H
We check that $ \xi \stackrel{\mathscr{H}}{=} \frac{\sin\tau}{\cos\chi} \, k $:
xi_H == sin(ta_H)/cos(ch)*k_H
Hence, on $\mathscr{H}$, the Killing vector $\xi$ is normal to $\mathscr{H}$. $\mathscr{H}$ being a null hypersurface, this implies that $\mathscr{H}$ is a Killing horizon.
As a consequence, $\xi$ must be a null vector on $\mathscr{H}$. We can check this property by computing the scalar square of $\xi$ in all $\mathscr{M}$:
xi2 = g(xi, xi)
xi2.display()
and notice that it is equal to $-u^2/\ell^2$:
xi2 == - U^2/l^2
so that $\xi$ is null on $\mathscr{H}$ as a direct consequence of the vanishing of $u$ on $\mathscr{H}$. Incidentally, the above formula implies that the Killing vector $\xi$ is timelike everywhere on the AdS spacetime, except on the Poincaré horizon, where it is null.
The non-affinity coefficient $\kappa$ of $\xi$ on $\mathscr{H}$ is defined by $\nabla_\xi \xi \stackrel{\mathscr{H}}{=} \kappa \xi$. To compute $\kappa$, we first compute the "acceleration" vector $\nabla_\xi \xi$:
acc = nabla(xi).contract(xi)
acc.display()
and subsquently evaluate it on $\mathscr{H}$:
acc.along(F).display()
Hence we get $\kappa = 0$, so that the Poincaré horizon $\mathscr{H}$ is a degenerate Killing horizon.
Note that $\kappa = 0$ can also be obtained via the formula $$\mathrm{d}(\xi\cdot\xi) \stackrel{\mathscr{H}}{=} -2 \kappa \underline{\xi} . $$ which holds for any Killing horizon. The left hand side is computed as
dxi2 = diff(xi2)
dxi2.display()
The restriction of this 1-form to $\mathscr{H}$ is computed by means of the method along
:
dxi2_H = dxi2.along(F)
print(dxi2_H)
1-form dg(xi,xi) along the 3-dimensional differentiable submanifold H embedded in the 4-dimensional Lorentzian manifold M with values on the 4-dimensional Lorentzian manifold M
dxi2_H.display()
Hence $\mathrm{d}(\xi\cdot\xi) \stackrel{\mathscr{H}}{=} 0$ and we recover $\kappa=0$.