3-sphere: the round metric

This worksheet demonstrates a few capabilities of SageManifolds (version 1.0.2, as included in SageMath 8.0) on the example of the 3-dimensional sphere, $\mathbb{S}^3$.

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

NB: a version of SageMath at least equal to 8.0 is required to run this worksheet:

In [1]:
version()
Out[1]:
'SageMath version 8.0, Release Date: 2017-07-21'

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

In [2]:
%display latex

To increase the computational speed, we ask for demanding computations to be parallelly performed on 8 cores:

In [3]:
Parallelism().set(nproc=8)

$\mathbb{S}^3$ as a 3-dimensional differentiable manifold

We start by declaring $\mathbb{S}^3$ as a differentiable manifold of dimension 3 over $\mathbb{R}$:

In [4]:
S3 = Manifold(3, 'S^3', latex_name=r'\mathbb{S}^3', start_index=1)

The first argument, 3, is the dimension of the manifold, while the second argument is the symbol used to label the manifold, with the LaTeX output specified by the argument latex_name. The argument start_index sets the index range to be used on the manifold for labelling components w.r.t. a basis or a frame: start_index=1 corresponds to $\{1,2,3\}$; the default value is start_index=0, yielding to $\{0,1,2\}$.

In [5]:
print(S3)
3-dimensional differentiable manifold S^3
In [6]:
S3
Out[6]:

Coordinate charts on $\mathbb{S}^3$

The 3-sphere cannot be covered by a single chart. At least two charts are necessary, for instance the charts associated with the stereographic projections from two distinct points, $N$ and $S$ say, which we may call the North pole and the South pole respectively. Let us introduce the open subsets covered by these two charts: $$ U := \mathbb{S}^3\setminus\{N\} $$
$$ V := \mathbb{S}^3\setminus\{S\} $$

In [7]:
U = S3.open_subset('U') ; print(U)
Open subset U of the 3-dimensional differentiable manifold S^3
In [8]:
V = S3.open_subset('V') ; print(V)
Open subset V of the 3-dimensional differentiable manifold S^3

We declare that $\mathbb{S}^3 = U \cup V$:

In [9]:
S3.declare_union(U, V)

Then we introduce the stereographic chart on $U$, denoting by $(x,y,z)$ the coordinates resulting from the stereographic projection from the North pole onto the equatorial plane:

In [10]:
stereoN.<x,y,z> = U.chart()
stereoN
Out[10]:
In [11]:
stereoN.coord_range()
Out[11]:

Similarly, we introduce on $V$ the coordinates $(x',y',z')$ corresponding to the stereographic projection from the South pole onto the equatorial plane:

In [12]:
stereoS.<xp,yp,zp> = V.chart("xp:x' yp:y' zp:z'")
stereoS
Out[12]:
In [13]:
stereoS.coord_range()
Out[13]:

We have to specify the transition map between the charts stereoN = $(U,(x,y,z))$ and stereoS = $(V,(x',y',z'))$; it is given by the standard inversion formulas:

In [14]:
r2 = x^2+y^2+z^2
stereoN_to_S = stereoN.transition_map(stereoS, 
                                      (x/r2, y/r2, z/r2), 
                                      intersection_name='W',
                                      restrictions1= x^2+y^2+z^2!=0, 
                                      restrictions2= xp^2+yp^2+zp^2!=0)
stereoN_to_S.display()
Out[14]:

In the above declaration, 'W' is the name given to the open subset where the two charts overlap: $W := U\cap V$, the condition $x^2+y^2+z^2\not=0$ defines $W$ as a subset of $U$, and the condition $x'^2+y'^2+z'^2\not=0$ defines $W$ as a subset of $V$.

The inverse coordinate transformation is computed by means of the method inverse():

In [15]:
stereoS_to_N = stereoN_to_S.inverse()
stereoS_to_N.display()
Out[15]:

Note that the situation is of course perfectly symmetric regarding the coordinates $(x,y,z)$ and $(x',y',z')$.

At this stage, the user's atlas has four charts:

In [16]:
S3.atlas()
Out[16]:

For future reference, we store $W=U\cap V$ into a Python variable:

In [17]:
W = U.intersection(V)
print(W)
Open subset W of the 3-dimensional differentiable manifold S^3

The North and South poles

$N$ is the point of $V$ of stereographic coordinates $(x',y',z')=(0,0,0)$:

In [18]:
N = V((0,0,0), chart=stereoS, name='N')
print(N)
Point N on the 3-dimensional differentiable manifold S^3

while $S$ is the point of $U$ of stereographic coordinates $(x,y,z)=(0,0,0)$:

In [19]:
S = U((0,0,0), chart=stereoN, name='S')
print(S)
Point S on the 3-dimensional differentiable manifold S^3

We have of course

In [20]:
all([N not in U, N in V, S in U, S not in V])
Out[20]:

Embedding of $\mathbb{S}^3$ into $\mathbb{R}^4$

Let us first declare $\mathbb{R}^4$ as a 4-dimensional manifold covered by a single chart (the so-called Cartesian coordinates):

In [21]:
R4 = Manifold(4, 'R^4', r'\mathbb{R}^4')
X4.<T,X,Y,Z> = R4.chart()
X4
Out[21]:

The embedding of $\mathbb{S}^3$ into $\mathbb{R}^4$ is then defined by the standard formulas relating the stereographic coordinates to the ambient Cartesian ones when considering a stereographic projection from the point $(-1,0,0,0)$ to the equatorial plane $T=0$:

In [22]:
rp2 = xp^2 + yp^2 + zp^2
Phi = S3.diff_map(R4, {(stereoN, X4): 
                       [(1-r2)/(r2+1), 2*x/(r2+1), 
                        2*y/(r2+1), 2*z/(r2+1)],
                       (stereoS, X4):
                       [(rp2-1)/(rp2+1), 2*xp/(rp2+1), 
                        2*yp/(rp2+1), 2*zp/(rp2+1)]},
                  name='Phi', latex_name=r'\Phi')
Phi.display()
Out[22]:

Hyperspherical coordinates

The hyperspherical coordinates $(\chi, \theta, \phi)$ generalize the standard spherical coordinates $(\theta, \phi)$ on $\mathbb{S}^2$. They are defined on the open domain $A\subset W \subset \mathbb{S}^3$ that is the complement of the "origin meridian"; since the latter is defined by $y=0$ and $x\geq 0$, we declare:

In [23]:
A = W.open_subset('A', coord_def={stereoN.restrict(W): (y!=0, x<0), 
                                  stereoS.restrict(W): (yp!=0, xp<0)})
print(A)
Open subset A of the 3-dimensional differentiable manifold S^3
In [24]:
spher.<ch,th,ph> = A.chart(r'ch:(0,pi):\chi th:(0,pi):\theta ph:(0,2*pi):\phi')
spher
Out[24]:
In [25]:
den = 1 + cos(ch)
spher_to_stereoN = spher.transition_map(stereoN.restrict(A), 
                                        (sin(ch)*sin(th)*cos(ph)/den,
                                         sin(ch)*sin(th)*sin(ph)/den,
                                         sin(ch)*cos(th)/den))
spher_to_stereoN.display()
Out[25]:
In [26]:
spher_to_stereoN.set_inverse(2*atan(sqrt(x^2+y^2+z^2)),
                             atan2(sqrt(x^2+y^2), z),
                             atan2(-y, -x)+pi,
                             verbose=True)
Check of the inverse coordinate transformation:
  ch == 2*arctan(sqrt(-cos(ch) + 1)/sqrt(cos(ch) + 1))
  th == arctan2(sqrt(-cos(ch) + 1)*sin(th)/sqrt(cos(ch) + 1), cos(th)*sin(ch)/(cos(ch) + 1))
  ph == pi - arctan2(sin(ch)*sin(ph)*sin(th)/(cos(ch) + 1), -cos(ph)*sin(ch)*sin(th)/(cos(ch) + 1))
  x == x
  y == y
  z == z
In [27]:
spher_to_stereoN.inverse().display()
Out[27]:
In [28]:
spher_to_stereoS = stereoN_to_S.restrict(A) * spher_to_stereoN
spher_to_stereoS.display()
Out[28]:
In [29]:
stereoS_to_spher = spher_to_stereoN.inverse() * stereoS_to_N.restrict(A)
stereoS_to_spher.display()
Out[29]:
In [30]:
Phi.display(stereoN.restrict(A), X4)
Out[30]:
In [31]:
Phi.display(spher, X4)
Out[31]:
In [32]:
Phi.display()
Out[32]:

Global left-invariant vector frame on $\mathbb{S}^3$

The vector frames associated with the two stereographic charts are

In [33]:
frameN = stereoN.frame()
frameN
Out[33]:
In [34]:
frameS = stereoS.frame()
frameS
Out[34]:

None of these two frames cover entirely the 3-sphere, since $U$ and $V$ are strict subsets of $\mathbb{S}^3$. Now, as it is well known, $\mathbb{S}^3$ admits global vector frames, i.e. $\mathbb{S}^3$ is a parallelizable manifold. Among all the spheres, it shares this remarkable property with $\mathbb{S}^1$ and $\mathbb{S}^7$. We shall use a global vector frame $(\mathbb{S}^3, (\epsilon_1, \epsilon_2, \epsilon_3))$ associated with the Lie group structure of $\mathbb{S}^3$, namely the left-invariant vector frame constructed in the worksheet 3-sphere: vector fields and left-invariant parallelization. We first declare this vector frame on all $\mathbb{S}^3$:

In [35]:
E = S3.vector_frame('E', latex_symbol=r'\varepsilon')
E
Out[35]:

On $U$, we relate this frame to the stereographic coordinate frame, by means of the formulas obtained in the vector field worksheet mentionned above:

In [36]:
E_U = E.restrict(U); E_U
Out[36]:
In [37]:
E_U[1][frameN,:,stereoN] = \
    [(x^2-y^2-z^2+1)/2, x*y+z, x*z-y]
E_U[2][frameN,:,stereoN] = \
    [x*y-z, (1-x^2+y^2-z^2)/2, x+y*z]  
E_U[3][frameN,:,stereoN] = \
    [x*z+y, y*z-x, (1-x^2-y^2+z^2)/2]

Similarly, on $V$, we relate the global frame with the stereographic coordinate frame from the South pole:

In [38]:
E_V = E.restrict(V); E_V
Out[38]:
In [39]:
E_V[1][frameS,:, stereoS] = \
    [(yp^2+zp^2-xp^2-1)/2, zp-xp*yp, -yp-xp*zp]
E_V[2][frameS,:, stereoS] = \
    [-zp-xp*yp, (xp^2-yp^2+zp^2-1)/2, xp-yp*zp]
E_V[3][frameS,:, stereoS] = \
    [yp-xp*zp, -xp-yp*zp, (xp^2+yp^2-zp^2-1)/2]

Let us display the links between the various frames:

In [40]:
for i in S3.irange():
    show(E[i].display(frameN))
print(" ")
for i in S3.irange():
    show(E[i].display(frameS))
 

To complete the links, we introduce the change-of-frame operators: first the operator $P$ such that, on $U$, $\epsilon_i = P(\partial/\partial{x^i})$, with $x^i=(x,y,z)$:

In [41]:
P = U.automorphism_field()
for i in S3.irange():
    for j in S3.irange():
        P[j,i] = E_U[i][j]
In [42]:
all([E_U[i] == P(frameN[i]) for i in S3.irange()])
Out[42]:

We add $P$ to the known changes of frame on $U$:

In [43]:
U.set_change_of_frame(frameN, E_U, P)

Similarly, on $V$, we introduce the operator $P$ such that $\epsilon_i = P(\partial/\partial {x'}^i)$, with ${x'}^i=(x',y',z')$:

In [44]:
P = V.automorphism_field()
for i in S3.irange():
    for j in S3.irange():
        P[j,i] = E_V[i][j]
In [45]:
all([E_V[i] == P(frameS[i]) for i in S3.irange()])
Out[45]:
In [46]:
V.set_change_of_frame(frameS, E_V, P)

Hopf coordinates

Despite there does not exist any coordinate chart associated to the global vector frame $(\mathbb{S}^3, (\epsilon_1, \epsilon_2, \epsilon_3))$, there exist a chart, called the Hopf chart, which has some link to it in the sense that some coordinate lines are integral curves of $\epsilon_3$. The Hopf coordinates have been introduced in the worksheet 3-sphere: charts, quaternions and Hopf fibration:

In [47]:
B = U.open_subset('B', coord_def={stereoN.restrict(U): 
                                   [x^2+y^2!=0, x^2+y^2+z^2!=1, 
                                    (1-x^2-y^2-z^2)*x-2*y*z!=0]})
print(B)
Open subset B of the 3-dimensional differentiable manifold S^3
In [48]:
Hcoord.<eta,alp,bet> = B.chart(r"eta:(0,pi/2):\eta alpha:(0,2*pi):\alpha beta:(0,2*pi):\beta")
Hcoord
Out[48]:
In [49]:
Hcoord_to_stereoN = Hcoord.transition_map(
                        stereoN.restrict(U),
                        (sin(eta)*cos(alp+bet)/(1+cos(eta)*sin(alp)),
                         sin(eta)*sin(alp+bet)/(1+cos(eta)*sin(alp)),
                         cos(eta)*cos(alp)/(1+cos(eta)*sin(alp))))
Hcoord_to_stereoN.display()
Out[49]:
In [50]:
Hcoord_to_stereoN.set_inverse(asin(2*sqrt(x^2+y^2)/(1+x^2+y^2+z^2)),
                              atan2(x^2+y^2+z^2-1, -2*z) + pi,
                              atan2(-y,-x) - atan2(x^2+y^2+z^2-1, -2*z),
                              verbose=True)
Check of the inverse coordinate transformation:
  eta == arcsin(sqrt(cos(eta) + 1)*sqrt(-cos(eta) + 1))
  alpha == pi - arctan2(2*cos(eta)*sin(alpha)/(cos(eta)*sin(alpha) + 1), -2*cos(alpha)*cos(eta)/(cos(eta)*sin(alpha) + 1))
  beta == arctan2(2*cos(eta)*sin(alpha)/(cos(eta)*sin(alpha) + 1), -2*cos(alpha)*cos(eta)/(cos(eta)*sin(alpha) + 1)) - arctan2((cos(beta)*sin(alpha) + cos(alpha)*sin(beta))*sin(eta)/(cos(eta)*sin(alpha) + 1), -(cos(alpha)*cos(beta) - sin(alpha)*sin(beta))*sin(eta)/(cos(eta)*sin(alpha) + 1))
  x == x
  y == y
  z == z
In [51]:
Hcoord_to_stereoN.inverse().display()
Out[51]:

As explained in the worksheet 3-sphere: vector fields and left-invariant parallelization, due to some lack of simplification, it's better to set the components of $\varepsilon_1$ and $\varepsilon_2$ by hand:

In [52]:
E_U[1].add_comp(Hcoord.frame())[1, Hcoord] = sin(2*alp+bet)
E_U[1].add_comp(Hcoord.frame())[2, Hcoord] = -cos(2*alp+bet) * tan(eta)
E_U[1].add_comp(Hcoord.frame())[3, Hcoord] = cos(2*alp+bet) / (cos(eta)*sin(eta))
E_U[1].display(Hcoord.frame(), Hcoord)
Out[52]:
In [53]:
E_U[2].add_comp(Hcoord.frame())[1, Hcoord] = -cos(2*alp+bet)
E_U[2].add_comp(Hcoord.frame())[2, Hcoord] = -sin(2*alp+bet) * tan(eta)
E_U[2].add_comp(Hcoord.frame())[3, Hcoord] = sin(2*alp+bet) / (cos(eta)*sin(eta))
E_U[2].display(Hcoord.frame(), Hcoord)
Out[53]:

On the contrary, the components of $\varepsilon_3$ are particularly simple:

In [54]:
E_U[3].display(Hcoord.frame(), Hcoord)
Out[54]:

Round metric on $\mathbb{S}^3$

The standard metric on $\mathbb{S}^3$ is that induced by the Euclidean metric of $\mathbb{R}^4$. Let us start by defining the latter:

In [55]:
h = R4.metric('h')
h[0,0], h[1,1], h[2,2], h[3, 3] = 1, 1, 1, 1
h.display()
Out[55]:

The metric $g$ on $\mathbb{S}^3$ is the pullback of $h$ by the embedding $\Phi$:

In [56]:
g = S3.metric('g')
g.set( Phi.pullback(h) )
print(g)
Riemannian metric g on the 3-dimensional differentiable manifold S^3

Let us display $g$ in terms of the coordinate frame associated with the stereographic chart from the North pole $(U,(x,y,z))$:

In [57]:
g.display(frameN)
Out[57]:

The components can be factored:

In [58]:
for i in S3.irange():
    g[frameN, i,i].factor()
g.display(frameN)
Out[58]:
In [59]:
g.display(frameS)
Out[59]:
In [60]:
for i in S3.irange():
    g[frameS, i,i].factor()
g.display(frameS)
Out[60]:

Expression of the round metric in the global frame

The expression of $g$ in terms of the global frame $(\varepsilon_1, \varepsilon_2, \varepsilon_3)$ is deduced from that w.r.t. the stereographic coordinates on the two domains $U$ and $V$, where the change-of-frame formulas are known:

In [61]:
g.display(E_U)
Out[61]:
In [62]:
g.display(E_V)
Out[62]:

We may then set the components globally:

In [63]:
for i in S3.irange():
    g.add_comp(E)[i, i] = 1
g.display(E)
Out[63]:

The above shows that the global frame $(\varepsilon_1, \varepsilon_2, \varepsilon_3)$ is orthonormal (w.r.t. to $g$), which is not surprising since this frame is induced by three vector fields of $\mathbb{R}^4$ which are clearly orthonormal for the Euclidean metric $h$, namely the three vector fields $E_{\mathbf{i}}$, $E_{\mathbf{j}}$ and $E_{\mathbf{k}}$ in the worksheet 3-sphere: vector fields and left-invariant parallelization.

Expression of the round metric in terms of the hyperspherical coordinates

In [64]:
g.display(spher.frame(), spher)
Out[64]:

Expression of the round metric in terms of the Hopf coordinates

In [65]:
g.display(Hcoord.frame(), Hcoord)
Out[65]:

We note that the components of $g$ depend only on $\eta$. This implies that the tori $\eta=\mathrm{const}$ are flat tori.

The Christoffel symbols

This is necessary for what follows (should be fixed in a future version):

In [66]:
for chart in S3.top_charts():
    g.restrict(chart.domain()).inverse()
In [67]:
g.christoffel_symbols_display(stereoN)
Out[67]:
In [68]:
g.christoffel_symbols_display(spher)
Out[68]:
In [69]:
g.christoffel_symbols_display(Hcoord)
Out[69]:

The Riemann tensor

In [70]:
Riem = g.riemann()
print(Riem)
Tensor field Riem(g) of type (1,3) on the 3-dimensional differentiable manifold S^3
In [71]:
Riem.display_comp(frameN, stereoN, only_nonredundant=True)
Out[71]:
In [72]:
Riem.display_comp(spher.frame(), spher, only_nonredundant=True)
Out[72]:
In [73]:
Riem.display_comp(Hcoord.frame(), Hcoord, only_nonredundant=True)
Out[73]:
In [74]:
Riem.display_comp(E_U, stereoN, only_nonredundant=True)
Out[74]:
In [75]:
Riem.display(E_U)
Out[75]:

The Ricci tensor

In [76]:
Ric = g.ricci()
print(Ric)
Field of symmetric bilinear forms Ric(g) on the 3-dimensional differentiable manifold S^3
In [77]:
Ric.display(frameN)
Out[77]:
In [78]:
for i in S3.irange():
    Ric[frameN, i,i].factor()
Ric.display(frameN)
Out[78]:

We have $Ric(g) = 2 g$:

In [79]:
Ric.restrict(U) == 2 * g.restrict(U)
Out[79]:

The Ricci scalar

In [80]:
R_A = g.restrict(A).ricci_scalar()
print(R_A)
Scalar field r(g) on the Open subset A of the 3-dimensional differentiable manifold S^3
In [81]:
R_A.display()
Out[81]:

We note that the Ricci scalar is constant, as for any maximally symmetric space.

The volume 3-form (Levi-Civita tensor)

We have

In [82]:
eps = g.volume_form()
print(eps)
eps.display()
3-form eps_g on the 3-dimensional differentiable manifold S^3
Out[82]:
In [83]:
print(eps.parent())
Free module /\^3(S^3) of 3-forms on the 3-dimensional differentiable manifold S^3

Expression of the volume 3-form in terms of the stereographic coordinates

In [84]:
eps.display(frameN, stereoN)
Out[84]:

The component $\epsilon_{xyz}$ can be factored:

In [85]:
eps_xyz = eps[frameN, 1,2,3, stereoN]
eps_xyz
Out[85]:
In [86]:
eps_xyz.factor()
Out[86]:
In [87]:
eps.display(frameN, stereoN)
Out[87]: