Defining a degenerate metric manifold $M$

This Jupyter notebook illustrates SageMath functionalities regarding smooth manifolds equipped with a degenerate metric. The involved tools have been developed through the SageManifolds project.

Author: Hans Fotsing Tetsing

A version of SageMath at least equal to 9.1 is required to run this notebook

In [1]:
version()
Out[1]:
'SageMath version 9.1, Release Date: 2020-05-20'
In [2]:
%display latex
In [3]:
M = Manifold(3, 'M', structure='degenerate_metric')
print(M)
3-dimensional degenerate_metric manifold M

We call $g$ the metric on $M$

In [4]:
g = M.metric() 
print(g)
degenerate metric g on the 3-dimensional degenerate_metric manifold M
In [5]:
g.parent()
Out[5]:
In [6]:
det(g).display()
Out[6]:

The determinant of any degenerate matric is the zero scalar function. By default (when the components are not yet set) the signature is the triplet (n_-,n_+,n_0) where n_-=0 is the number of negative entries, n_+=dim(M) the number of positive entries and n_0=1 is the number number of zero in the digonal, all that in the writting of the metric in an orthogonal basis.

In [7]:
g.signature()
Out[7]:
In [8]:
U = M.open_subset('U')
print(U)
Open subset U of the 3-dimensional degenerate_metric manifold M
In [9]:
X.<x,y,z> = U.chart(); X
Out[9]:

One can use a field of symmetric bilinear forms to set the components of a degenerate metric.

In [10]:
dx, dy = X.coframe()[0], X.coframe()[1]
In [11]:
b = dx*dx + x^2*dy*dy
b = b.symmetrize()
print(b)
Field of symmetric bilinear forms on the Open subset U of the 3-dimensional degenerate_metric manifold M
In [12]:
g.set(b)
In [13]:
g.display()
Out[13]:
In [14]:
g[:]
Out[14]:

We define another metric and set its nonzero components.

In [15]:
h = g._new_instance()
h.set_name('h')
print(h)
degenerate metric h on the 3-dimensional degenerate_metric manifold M
In [16]:
h[0,0], h[1,1] = 1, x^2
In [17]:
h.display()
Out[17]:

On the only local chart (U,X), h and g have the same components, so there are equal! However, g is the metric of the degenerate metric manifold M but not h.

In [18]:
h == g
Out[18]:
In [19]:
g is M.metric()
Out[19]:
In [20]:
h is M.metric()
Out[20]:

Degenerate hypersurface of a 6-dimensional Lorentzian manifold

In [21]:
M = Manifold(6, 'M', structure='Lorentzian')
print(M)
6-dimensional Lorentzian manifold M
In [22]:
X.<x0,x1,x2,x3,x4,x5> = M.chart(); X
Out[22]:
In [23]:
g = M.metric()
print(g)
Lorentzian metric g on the 6-dimensional Lorentzian manifold M
In [24]:
g[0,0], g[1,1], g[2,2], g[3,3], g[4,4], g[5,5] = -1, 1, exp(2*x0), exp(2*x0), exp(2*x1), exp(2*x1)
In [25]:
g[:]
Out[25]:

We define now on M the degenerate hypersurface x0+x1=0.

In [26]:
H = Manifold(5, 'H', ambient=M, structure='degenerate_metric')
print(H)
degenerate hypersurface H embedded in 6-dimensional differentiable manifold M
In [27]:
X_H.<xh1, xh2, xh3, xh4, xh5> = H.chart(); X_H
Out[27]:
In [28]:
Phi = H.diff_map(M, {(X_H, X): [-xh1, xh1, xh2, xh3, xh4, xh5]}, 
                 name='Phi', latex_name=r'\Phi')
Phi.display()
Out[28]:
In [29]:
Phi_inv = M.diff_map(H, {(X, X_H): [x1, x2, x3, x4, x5]}, 
                     name='Phi_inv', latex_name=r'\Phi^{-1}')
Phi_inv.display()
Out[29]:
In [30]:
H.set_immersion(Phi, inverse=Phi_inv)
H.declare_embedding()

The vector field $v=-\partial x0-\partial x1$ is everywhere neither orthogonal nor tangent to $H$. Hence, $v$ is a rigging for the null hypersurface $H$.

In [31]:
v = M.vector_field()
v[:2] = [-1, -1]
v.display()
Out[31]:
In [32]:
H.set_transverse(rigging=[v])

The vector $\xi=\partial x0-\partial x1$ is tangent and orthogonal to $H$ and then spans the normal distribution $TH^\perp$. A complementary of $TH^\perp$ in $TH$, thus a screen distribution, is spanned by the vectors $e1=\exp(-2x0)\partial x2$, $e2=\exp(-2x0)\partial x3$, $e3=\exp(-2x1)\partial x4$, and $e4=\exp(-2x1)\partial x5$. Notice that the screen distribution associated with $v$ has to be othogonal to the chosen rigging $v$.

In [33]:
xi = M.vector_field()
e1 = M.vector_field()
e2 = M.vector_field()
e3 = M.vector_field()
e4 = M.vector_field()
In [34]:
xi[:2] = [1, -1]
e1[2] = exp(-2*x0)
e2[3] = exp(-2*x0)
e3[4] = exp(-2*x1)
e4[5] = exp(-2*x1)
In [35]:
S = H.screen('S', [e1, e2, e3, e4], [xi])
print(S)
screen distribution S along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M mapped into the 6-dimensional Lorentzian manifold M
In [36]:
H.default_screen()
Out[36]:

The null rigging is derived from the given rigging $v$ with the formula$$N=\frac{1}{g(\xi, v)}\left(v-\frac{g(v,v)}{2g(\xi, v)}\xi\right)$$ Projections onto $H$ will be done parallely to the null rigging $N$.

In [37]:
S.rigging().display()
Out[37]:
In [38]:
S.normal_tangent_vector().display()
Out[38]:

The null rigging $N$ and the normal tangent vector $\xi$ are normalized by$$g(N,\xi)=1.$$ This normalization is the one used by some mathematicians but is not physically relevant since $N$ and $\xi$ cannot be timelike at the same time. However, one can consider $\ell=\xi$ and $k=-N$.

In [39]:
g.along(Phi)(S.rigging(),xi.along(Phi)).display()
Out[39]:

Now, $S$ is a screen distribution along $H$ and we have the decompositions \begin{equation}TM|_H=TH\oplus Span(N)\end{equation} \begin{equation}TH=S\oplus_{orth}Span(\xi)\end{equation} Projection on $H$ is done with respect to the first decomposition and projection onto the screen distribution of a vector tangent to $H$ is done with respect to the second decomposition. So, any vector along $H$ (tangent or not to $H$), can be decomposed in the adapted frame $T=\{vv_0,vv_1,vv_2,vv_3,vv_4,vv_5)$, where along $H$ $$vv_0:=e1,~~vv_1=e2,~~vv_2=e3,~~vv_3=e4,~~vv_4=\xi,~~vv_5=N.$$

In [40]:
T = H.adapted_frame()
T
Out[40]:
In [41]:
T[4].display()
Out[41]:
In [42]:
T[0].disp()
Out[42]:

Projections on $H$ and on the screen distribution are now possible!

In [43]:
H.projection(v).display()
Out[43]:
In [44]:
H.projection(v+xi).display(T)
Out[44]:
In [45]:
H.screen_projection(v+xi).display()
Out[45]:
In [46]:
H.screen_projection(e1+xi).display(T)
Out[46]:

Let $\nabla$ be the Levi-Civita connection of $(M,g)$. The Weingarten map is the projection is $\nabla_\cdot\xi:\mathfrak X(H)\to\mathfrak X(H)$.

In [47]:
W = H.weingarten_map()
print(W)
Tensor field nabla_g(xi)|X(H) of type (1,1) along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M with values on the 6-dimensional Lorentzian manifold M
In [48]:
W.display()
Out[48]:
In [49]:
W.display(T)
Out[49]:
In [50]:
W(xi.along(Phi)).display()
Out[50]:
In [51]:
W(T[0]).display(T)
Out[51]:

We can write$$\nabla_U\xi=-A^\ast(U)-\tau(U)\xi,~~~~\forall U\in\mathfrak X(H).$$ $A^\ast$ is the shape operator and $\tau$ the roration $1-$form.

In [52]:
SO = H.shape_operator()
print(SO)
Tensor field A^* of type (1,1) along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M with values on the 6-dimensional Lorentzian manifold M
In [53]:
SO.display(T)
Out[53]:

The principal curvatures are the eigenfunctions of the shape operator.

In [54]:
m = H.mean_curvature()
m.display()
Out[54]:

So, the mean curvature of $H$ vanishes identically. Some people then say that $H$ is a maximal null hypersurface. But, $H$ is not totally geodesic since the shape operator is not zero. Hence, the ambient manifold $(M,g)$ cannot have constant sectional curvature.

In fact, the principal curvatures are $-1,-1,0,1,1$ and we can write the following short code to get them.

In [55]:
curvatures = matrix([[SO[:][i, j].expr() for i in H.irange()]
                     for j in H.irange()]).eigenvalues()
counter = H.irange()
for i in range(5):
    curvatures[i] = H.scalar_field(curvatures[i], name="k_{}".format(next(counter)))
In [56]:
curvatures[0].display()
Out[56]:

The principal directions are $vv_0,vv_1,vv_2,vv_3=\xi$.

In [57]:
PD = H.principal_directions(S)
PD[0][0].disp(T), PD[1][0].disp(T), PD[2][0].disp(T), PD[3][0].disp(T)
Out[57]:

Defining a second screen distribution

Since the screen distribution has to be orthogonal to the rigging, the screen distribution is unique ones the rigging has been set. One can just change the basis but the result is the same subbundle.

In [58]:
u1 = M.vector_field()
u2 = M.vector_field()
u3 = M.vector_field()
u4 = M.vector_field()
In [59]:
u1[2] = 1; u2[3] = 1; u3[4] = 1; u4[5] = 1
In [60]:
S1 = H.screen('S1', [u1, u2, u3, u4], [xi])
print(S1)
screen distribution S1 along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M mapped into the 6-dimensional Lorentzian manifold M

The default screen distribution is always the last defined one.

In [61]:
H.default_screen()
Out[61]:
In [62]:
T1 = H.adapted_frame(screen=S1)
T1
Out[62]:
In [63]:
T1[4].display()
Out[63]:
In [64]:
T1[0].display()
Out[64]:
In [65]:
SO1 = H.shape_operator(S1)
print(SO1)
Tensor field A^* of type (1,1) along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M with values on the 6-dimensional Lorentzian manifold M
In [66]:
SO1.display(T1)
Out[66]:
In [67]:
SO == SO1
Out[67]:

Let's now define a new rigging and from that a different screen distribution.

In [68]:
v2 = M.vector_field()
v2[1:3] = [1,1]
v2.display()
Out[68]:
In [69]:
H.set_transverse(rigging=[v2])
In [70]:
e21 = M.vector_field()
e22 = M.vector_field()
e23 = M.vector_field()
e24 = M.vector_field()
In [71]:
e21[0:3] = [1,-1,exp(-2*x0)]
e22[3] = 1
e23[4] = 1
e24[5] = 1
In [72]:
S2 = H.screen('S2', [e21, e22, e23, e24], [xi])
print(S2)
screen distribution S2 along the degenerate hypersurface H embedded in 6-dimensional differentiable manifold M mapped into the 6-dimensional Lorentzian manifold M
In [73]:
T2 = H.adapted_frame(screen=S2)
T2
Out[73]:
In [ ]:
SO2 = H.shape_operator(S2)
SO2.display(T2)
In [ ]:
SO == SO2

This is because the shape operator depends on the chosen rigging.

In [ ]:
H.list_of_screens()
In [ ]:
W2 = H.weingarten_map(S2)
W2.display(T2)
In [ ]:
W2(xi.along(Phi)).display()

The Weingarten map can only be applied to vectors tangent to $H$. However, we can consider its extension which can evaluate any vector along $H$ (tangent to $H$ or not).

In [ ]:
W2.extension()(v2.along(Phi)).display(T2)
In [ ]:
W.extension() == W2.extension()