This notebook demonstrates some differential geometry capabilities of SageMath on the example of the 3-dimensional sphere, $\mathbb{S}^3$. The corresponding tools have been developed within the SageManifolds project.

Click here to download the notebook 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 7.5 is required to run this notebook:

In [1]:

```
version()
```

Out[1]:

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

In [2]:

```
%display latex
```

and we initialize a time counter for benchmarking:

In [3]:

```
import time
comput_time0 = time.perf_counter()
```

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

In [4]:

```
Parallelism().set(nproc=8)
```

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

In [5]:

```
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 [6]:

```
print(S3)
```

In [7]:

```
S3
```

Out[7]:

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 [8]:

```
U = S3.open_subset('U') ; print(U)
```

In [9]:

```
V = S3.open_subset('V') ; print(V)
```

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

In [10]:

```
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 [11]:

```
stereoN.<x,y,z> = U.chart()
stereoN
```

Out[11]:

In [12]:

```
stereoN.coord_range()
```

Out[12]:

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

In [13]:

```
stereoS.<xp,yp,zp> = V.chart("xp:x' yp:y' zp:z'")
stereoS
```

Out[13]:

In [14]:

```
stereoS.coord_range()
```

Out[14]:

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 [15]:

```
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[15]:

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 [16]:

```
stereoS_to_N = stereoN_to_S.inverse()
stereoS_to_N.display()
```

Out[16]:

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 [17]:

```
S3.atlas()
```

Out[17]:

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

In [18]:

```
W = U.intersection(V)
print(W)
```

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

In [19]:

```
N = V((0,0,0), chart=stereoS, name='N')
print(N)
```

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

In [20]:

```
S = U((0,0,0), chart=stereoN, name='S')
print(S)
```

We have of course

In [21]:

```
all([N not in U, N in V, S in U, S not in V])
```

Out[21]:

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

In [22]:

```
R4 = Manifold(4, 'R^4', r'\mathbb{R}^4')
X4.<T,X,Y,Z> = R4.chart()
X4
```

Out[22]:

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 [23]:

```
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[23]:

From this choice of stereographic projection, the "North" pole is actually the point of coordinates $(-1,0,0,0)$ in $\mathbb{R}^4$:

In [24]:

```
X4(Phi(N))
```

Out[24]:

while the "South" pole is the point of coordinates $(1,0,0,0)$:

In [25]:

```
X4(Phi(S))
```

Out[25]:

We may use the embedding $\Phi$ to plot the stereographic coordinate grid in terms of the $\mathbb{R}^4$'s Cartesian coordinates:

In [26]:

```
graph_stereoN = stereoN.plot(chart=X4, mapping=Phi,
ambient_coords=(X,Y,Z),
number_values=9,
color={x: 'red', y: 'green', z: 'gold'},
label_axes=False)
show(graph_stereoN, axes_labels=['X', 'Y', 'Z'])
```