# Anti-de Sitter spacetime¶

This notebook demonstrates a few capabilities of SageMath in computations regarding the 4-dimensional anti-de Sitter spacetime. The corresponding tools have been developed within the SageManifolds project.

NB: a version of SageMath at least equal to 8.2 is required to run this notebook:

In [1]:
version()

Out[1]:
'SageMath version 9.0.beta3, Release Date: 2019-10-26'

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

In [2]:
%display latex


We also define a viewer for 3D plots (use 'threejs' or 'jmol' for interactive 3D graphics and initialize a time counter for benchmarking:

In [3]:
viewer3D = 'threejs' # must be 'threejs', 'jmol', 'tachyon' or None (default)
import time
comput_time0 = time.perf_counter()


## Spacetime manifold¶

We declare the anti-de Sitter spacetime as a 4-dimensional Lorentzian manifold:

In [4]:
M = Manifold(4, 'M', r'\mathcal{M}', structure='Lorentzian')
print(M); M

4-dimensional Lorentzian manifold M

Out[4]:

We consider hyperbolic coordinates $(\tau,\rho,\theta,\phi)$ on $\mathcal{M}$. Allowing for the standard coordinate singularities at $\rho=0$, $\theta=0$ or $\theta=\pi$, these coordinates cover the entire spacetime manifold (which is topologically $\mathbb{R}^4$). If we restrict ourselves to regular coordinates (i.e. to considering only mathematically well defined charts), the hyperbolic coordinates cover only an open part of $\mathcal{M}$, which we call $\mathcal{M}_0$, on which $\rho$ spans the open interval $(0,+\infty)$, $\theta$ the open interval $(0,\pi)$ and $\phi$ the open interval $(0,2\pi)$. Therefore, we declare:

In [5]:
M0 = M.open_subset('M_0', r'\mathcal{M}_0' )
X_hyp.<ta,rh,th,ph> = M0.chart(r'ta:\tau rh:(0,+oo):\rho th:(0,pi):\theta ph:(0,2*pi):\phi')
print(X_hyp); X_hyp

Chart (M_0, (ta, rh, th, ph))

Out[5]:
In [6]:
X_hyp.coord_range()

Out[6]:

## $\mathbb{R}^{2,3}$ as an ambient space¶

The AdS metric can be defined as that induced by the immersion of $\mathcal{M}$ in $\mathbb{R}^{2,3}$, the latter being nothing but $\mathbb{R}^5$ equipped with a flat pseudo-Riemannian metric of signature $(-,-,+,+,+)$. Let us construct $\mathbb{R}^{2,3}$ as a 5-dimensional manifold covered by canonical coordinates:

In [7]:
R23 = Manifold(5, 'R23', r'\mathbb{R}^{2,3}', structure='pseudo-Riemannian', signature=1,
metric_name='h')
X23.<U,V,X,Y,Z> = R23.chart()
print(X23); X23

Chart (R23, (U, V, X, Y, Z))

Out[7]:

We define the pseudo-Riemannian metric of $\mathbb{R}^{2,3}$:

In [8]:
h = R23.metric()
h[0,0], h[1,1], h[2,2], h[3,3], h[4,4] = -1, -1, 1, 1, 1
h.display()

Out[8]:

The AdS immersion into $\mathbb{R}^{2,3}$ is defined as a differential map $\Phi$ from $\mathcal{M}$ to $\mathbb{R}^{2,3}$, by providing its expression in terms of $\mathcal{M}$'s default chart (which is X_hyp = $(\mathcal{M}_0,(\tau,\rho,\theta,\phi))$ ) and $\mathbb{R}^{2,3}$'s default chart (which is X23 = $(\mathbb{R}^{2,3},(U,V,X,Y,Z))$ ):

In [9]:
var('l', latex_name=r'\ell', domain='real')
assume(l>0)
Phi = M.diff_map(R23, [l*cosh(rh)*cos(ta/l),
l*cosh(rh)*sin(ta/l),
l*sinh(rh)*sin(th)*cos(ph),
l*sinh(rh)*sin(th)*sin(ph),
l*sinh(rh)*cos(th)],
name='Phi', latex_name=r'\Phi')
print(Phi); Phi.display()

Differentiable map Phi from the 4-dimensional Lorentzian manifold M to the 5-dimensional pseudo-Riemannian manifold R23

Out[9]:

The constant $\ell$ is the AdS length parameter. Considering AdS metric as a solution of vacuum Einstein equation with negative cosmological constant $\Lambda$, one has $\ell = \sqrt{-3/\Lambda}$.

Let us evaluate the image of a point via the map $\Phi$:

In [10]:
p = M((ta, rh, th, ph), name='p'); print(p)

Point p on the 4-dimensional Lorentzian manifold M


The coordinates of $p$ in the chart X_hyp:

In [11]:
X_hyp(p)

Out[11]:
In [12]:
q = Phi(p); print(q)

Point Phi(p) on the 5-dimensional pseudo-Riemannian manifold R23

In [13]:
X23(q)

Out[13]:

The image of $\mathcal{M}$ by the immersion $\Phi$ is a hyperboloid of one sheet, of equation $$-U^2-V^2+X^2+Y^2+Z^2=-\ell^2.$$ Indeed:

In [14]:
(Uq,Vq,Xq,Yq,Zq) = X23(q)
s = - Uq^2 - Vq^2 + Xq^2 + Yq^2 + Zq^2
s.simplify_full()

Out[14]:

We may use the immersion $\Phi$ to draw the coordinate grid $(\tau,\rho)$ in terms of the coordinates $(U,V,X)$ for $\theta=\pi/2$ and $\phi=0$ ($X\geq 0$ part) or $\phi=\pi$ ($X\leq 0$ part). The red (rep. grey) curves are those for which $\rho={\rm const}$ (resp. $\tau={\rm const}$):

In [15]:
graph_hyp = X_hyp.plot(X23, mapping=Phi, ambient_coords=(V,X,U), fixed_coords={th:pi/2, ph:0},
ranges={ta:(0,2*pi), rh:(0,2)}, number_values=9,
color={ta:'red', rh:'grey'}, thickness=2, parameters={l:1},
label_axes=False)  # phi = 0 => X > 0 part
graph_hyp += X_hyp.plot(X23, mapping=Phi, ambient_coords=(V,X,U), fixed_coords={th:pi/2, ph:pi},
ranges={ta:(0,2*pi), rh:(0,2)}, number_values=9,
color={ta:'red', rh:'grey'}, thickness=2, parameters={l:1},
label_axes=False)  # phi = pi => X < 0 part
show(graph_hyp, aspect_ratio=1, viewer=viewer3D,
axes_labels=['V','X','U'])


To have a nicer picture, we add the plot of the hyperboloid obtained by parametric_plot with $(\tau,\rho)$ as parameters and the expressions of $(U,V,X)$ in terms of $(\tau,\rho)$ deduced from the coordinate representation of $\Phi$:

In [16]:
Phi.coord_functions() # the default pair of charts (X_hyp, X23) is assumed

Out[16]:
In [17]:
Ug = Phi.coord_functions()[0](ta,rh,pi/2,0).subs({l:1})  # l=1 substituted to have numerical values
Vg = Phi.coord_functions()[1](ta,rh,pi/2,0).subs({l:1})
Xg = Phi.coord_functions()[2](ta,rh,pi/2,0).subs({l:1})
Ug, Vg, Xg

Out[17]:
In [18]:
hyperboloid = parametric_plot3d([Vg, Xg, Ug], (ta,0,2*pi), (rh,-2,2), color=(1.,1.,0.9))
graph_hyp += hyperboloid
show(graph_hyp, aspect_ratio=1, viewer=viewer3D,
axes_labels=['V','X','U'])


## Spacetime metric¶

As mentionned above, the AdS metric $g$ on $\mathcal{M}$ is that induced by the flat metric $h$ on $\mathbb{R}^{2,3}$, i.e.$g$ is the pullback of $h$ by the differentiable map $\Phi$:

In [19]:
g = M.metric()
g.set( Phi.pullback(h) )


The expression of $g$ in terms of $\mathcal{M}$'s default frame is found to be

In [20]:
g.display()

Out[20]:
In [21]:
g[:]

Out[21]:

## Curvature

The Riemann tensor of $g$ is

In [22]:
Riem = g.riemann()
print(Riem)

Tensor field Riem(g) of type (1,3) on the 4-dimensional Lorentzian manifold M

In [23]:
Riem.display_comp(only_nonredundant=True)

Out[23]:

The Ricci tensor:

In [24]:
Ric = g.ricci()
print(Ric)
Ric.display()

Field of symmetric bilinear forms Ric(g) on the 4-dimensional Lorentzian manifold M

Out[24]:
In [25]:
Ric[:]

Out[25]:

The Ricci scalar:

In [26]:
R = g.ricci_scalar()
print(R)
R.display()

Scalar field r(g) on the 4-dimensional Lorentzian manifold M

Out[26]:

We recover the fact that AdS spacetime has a constant curvature. It is indeed a maximally symmetric space. In particular, the Riemann tensor is expressible as $$R^i_{\ \, jlk} = \frac{R}{n(n-1)} \left( \delta^i_{\ \, k} g_{jl} - \delta^i_{\ \, l} g_{jk} \right),$$ where $n$ is the dimension of $\mathcal{M}$: $n=4$ in the present case. Let us check this formula here, under the form $R^i_{\ \, jlk} = -\frac{R}{6} g_{j[k} \delta^i_{\ \, l]}$:

In [27]:
delta = M.tangent_identity_field()
Riem == - (R/6)*(g*delta).antisymmetrize(2,3)  # 2,3 = last positions of the
#       type-(1,3) tensor g*delta

Out[27]:

We may also check that AdS metric is a solution of the vacuum Einstein equation with (negative) cosmological constant $\Lambda = - 3/\ell^2$:

In [28]:
Lambda = -3/l^2
Ric - 1/2*R*g + Lambda*g == 0

Out[28]:

Null geodesics that are radial with respect to coordinates $(\tau,\rho,\theta,\phi)$ obey $$\tau = \pm 2 \ell \left( \mathrm{atan} \left(\mathrm{e}^\rho\right) - \frac{\pi}{4} \right) + \tau_0,$$ where $\tau_0$ is a constant (the value of $\tau$ at $\rho=0$). Note that, due to the homogeneity of AdS spacetime, any null geodesic is a "radial" geodesic with respect to some coordinate system $(\tau',\rho',\theta',\phi')$, as in Minkowski spacetime, any null geodesic is a straight line and one can always find a Minkowskian coordinate system $(t',x',y',z')$ with respect to which the null geodesic is radial.

Let us consider two finite families of radial null geodesics having $\theta=\pi/2$ and $\phi=0$ or $\pi$:

• null_geod1 has $\phi=\pi$ when $\tau< 0$ and $\phi=0$ when $\tau>0$
• null_geod2 has $\phi=0$ when $\tau<0$ and $\phi=\pi$ when $\tau>0$
In [29]:
lamb = var('lamb', latex_name=r'\lambda')
null_geod1 = [M.curve({X_hyp: [2*sgn(lamb)*l*(atan(exp(abs(lamb))) - pi/4) + 2*pi*(i-4)/8,
abs(lamb), pi/2, pi*unit_step(-lamb)]},
(lamb, -oo, +oo)) for i in range(9)]
null_geod2 = [M.curve({X_hyp: [2*sgn(lamb)*l*(atan(exp(abs(lamb))) - pi/4) + 2*pi*(i-4)/8,
abs(lamb), pi/2, pi*unit_step(lamb)]},
(lamb, -oo, +oo)) for i in range(9)]
null_geods = null_geod1 + null_geod2

In [30]:
print(null_geods[0])

Curve in the 4-dimensional Lorentzian manifold M

In [31]:
null_geods[0].display()

Out[31]:
In [32]:
null_geods[9].display()

Out[32]:

To graphically display these geodesics, we introduce a Cartesian-like coordinate system $(\tau,x_\rho,y_\rho,z_\rho)$ linked to $(\tau,\rho,\theta,\phi)$ by the standard formulas:

In [33]:
X_hyp_graph.<ta,x_rho,y_rho,z_rho> = M0.chart(r'ta:\tau x_rho:x_\rho y_rho:y_\rho z_rho:z_\rho')
hyp_to_hyp_graph = X_hyp.transition_map(X_hyp_graph, [ta, rh*sin(th)*cos(ph),
rh*sin(th)*sin(ph), rh*cos(th)])
hyp_to_hyp_graph.display()

Out[33]:

Let us plot the null geodesics in terms of the coordinates $(\tau,x_\rho)$:

In [34]:
graph_2d = Graphics()
for geod in null_geods:
geod.expr(geod.domain().canonical_chart(), X_hyp_graph)
graph_2d += geod.plot(X_hyp_graph, ambient_coords=(x_rho,ta), prange=(-4,4),
parameters={l:1}, color='green', thickness=1.5)
graph_2d += X_hyp_graph.plot(X_hyp_graph, ambient_coords=(x_rho,ta),
fixed_coords={th:0, ph:pi},
ranges={ta:(-pi,pi), x_rho:(-4,4)},
number_values={ta: 9, x_rho: 9},
color={ta:'red', x_rho:'grey'}, parameters={l:1})
show(graph_2d, aspect_ratio=1, ymin=-pi, ymax=pi)


We can also get a 3D view of the radial null geodesics via the isometric immersion $\Phi$:

In [35]:
graph_3d = Graphics()
for geod in null_geods:
graph_3d += geod.plot(X23, mapping=Phi, ambient_coords=(V,X,U), prange=(-2,2),
parameters={l:1}, color='green', thickness=2,
plot_points=20, label_axes=False)
show(graph_3d+graph_hyp, aspect_ratio=1, viewer=viewer3D,
axes_labels=['V','X','U'])