This notebook demonstrates a few capabilities of SageMath in computations regarding embedded submanifolds on the specific example of the 3+1 slicing of Kerr spacetime. The corresponding tools have been developed within the SageManifolds project (version 1.3, as included in SageMath 8.3).
Click here to download the notebook file (ipynb format). To run it, you must start SageMath within the Jupyter notebook, via the command sage -n jupyter
NB: a version of SageMath at least equal to 8.3 is required to run this notebook:
version()
'SageMath version 8.3, Release Date: 2018-08-03'
The first cell defines some notebook options. Parallelism is usefull to speedup calculation of the connection.
%display latex
Parallelism().set(nproc=8)
Next cells are used to define the manifolds. In our case, $M$ will be the Kerr spacetime, of which $N$ is a single spacelike submanifold of dimension 3 (hypersurface).
M = Manifold(4, 'M', structure="Lorentzian")
print(M)
4-dimensional Lorentzian manifold M
N = Manifold(3, 'N', ambient=M, structure="Riemannian")
print(N)
3-dimensional pseudo-Riemannian submanifold N embedded in 4-dimensional differentiable manifold M
Note the ambient=M
, used to declare $N$ as a submanifold of $M$.
We will use a single chart, corresponding to the so-called Kerr coordinates (NB: they differ from the standard Boyer-Lindquist coordinates):
C.<t,r,th,ph> = M.chart(r't:(-oo,+oo) r:(0,+oo) th:(0,pi):\theta ph:(-pi,pi):\phi')
The metric depends on two quantities: the mass of the black-hole and its angular momentum. These are declared as symbolic variables. $\rho$ is a shortcut notation.
m = var('m') # mass
a = var('a') # ratio J/m
rho = sqrt(r^2+a^2*cos(th)^2)
We set the metric components in the Kerr coordinates introduced above:
g = M.metric()
g[0,0], g[1,1], g[2,2] = -(1-2*m*r/rho^2), 1+2*m*r/rho^2, rho^2
g[3,3] = (r^2+a^2+2*a^2*m*r*sin(th)**2/rho^2)*sin(th)^2
g[0,1] = 2*m*r/rho^2
g[0,3] = -2*a*m*r/rho^2*sin(th)^2
g[1,3] = -a*sin(th)^2*(1+2*m*r/rho^2)
g[:]
Let's compute the Levi-Civita connection:
nab = g.connection()
List of Christoffel symbols:
nab.display(only_nonredundant=True)
Ricci tensor:
nab.ricci()[:]
This proves that the metric given in cell [8] is indeed solution of the vacuum Einstein equation, as expected of a Kerr metric.
It's now time to foliate it along the $t$ axis.
To compute 3+1 quantities, we must first declare an embedding from $N$ to $M$. because we want our foliation to encompass the whole manifold, the embedding must depend on a parameter $\tau$.
tau = var(r'tau') # foliation parameter
Let's also declare a chart on $N$.
CN.<r0,th0,ph0> = N.chart(r'r0:(0,+oo) th0:(0,pi):\theta_0 ph0:(-pi,pi):\phi_0')
The embedding used is a very simple one, it simply sets $t = \tau$.
phi = N.diff_map(M, {(CN,C):[tau,r0,th0,ph0]})
phi.display()
The two partial inverses are also quite simple:
phi_inv = M.diff_map(N, {(C,CN):[r,th,ph]})
phi_inv.display()
phi_inv_tau = M.scalar_field({C:t})
phi_inv_tau.display()
The following line registers the embedding, as well as the inverses. This cannot be done during the creation of the manifolds because the embedding phi
needs exisiting domain and codomain to be created.
N.set_embedding(phi, inverse=phi_inv, var=tau, t_inverse={tau: phi_inv_tau})
Computing the adapted chart is needed for computing the shift and extrinsic curvature. This create another chart, which in our case is identical to CN
because of the form of the embedding.
T = N.adapted_chart()
T
The induced metric on $N$ (or first fundamental form) is then given by:
N.induced_metric()[:]
And its inverse:
N.induced_metric().inverse()[:]
The normal vector is given by
N.normal().display()
Let's check that it is correcly normalized:
g(N.normal(), N.normal()).display()
The lapse and shift are also easily computed:
N.lapse().display()
N.shift().display()
The extrinsic curvature (or second fundamental form) is long to compute because of failed simplifications (see the last component).
N.second_fundamental_form()[:]
It is also possible to project any tensor on $M$ orhogonaly on the submnifold or on the normal vector. This can be useful for example to decompose an energy-impulsion tensor.
Let's construct a fourth-order tensor from a simple vector field.
v = M.vector_field()
v.add_comp()[:] = [1,1,1,1]
The fourth-order tensor $v\otimes v\otimes v\otimes v$ is then projected twice on the submanifold (on the indices 1 and 3) and twice along the normal vector (indicies 0 and 2). The result is the following second-order tensor on $M$:
N.mixed_projection(v*v*v*v, [0,2]).display()