{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3-sphere: the round metric\n", "\n", "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](https://sagemanifolds.obspm.fr) project.\n", "\n", "Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Notebooks/SM_sphere_S3_metric.ipynb) to download the notebook file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, via the command sage -n jupyter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*NB:* a version of SageMath at least equal to 8.3 is required to run this notebook:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 9.0.beta1, Release Date: 2019-10-12'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display mathematical objects using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To increase the computational speed, we ask for demanding computations to be parallelly performed on 8 cores:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "Parallelism().set(nproc=8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## $\\mathbb{S}^3$ as a 3-dimensional Riemannian manifold\n", "\n", "We start by declaring $\\mathbb{S}^3$ as a Riemannian manifold of dimension 3:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "S3 = Manifold(3, 'S^3', latex_name=r'\\mathbb{S}^3', structure='Riemannian', \n", " start_index=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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\\}$." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "print(S3)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional Riemannian manifold S^3" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Coordinate charts on $\\mathbb{S}^3$\n", "\n", "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,\n", "which we may call the *North pole* and the *South pole* respectively. Let us introduce the open subsets covered by these two charts: \n", "$$U := \\mathbb{S}^3\\setminus\\{N\\}$$ \n", "$$V := \\mathbb{S}^3\\setminus\\{S\\}$$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Open subset U of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "U = S3.open_subset('U') ; print(U)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Open subset V of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "V = S3.open_subset('V') ; print(V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We declare that $\\mathbb{S}^3 = U \\cup V$:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "S3.declare_union(U, V)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "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:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (x, y, z))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoN. = U.chart()\n", "stereoN" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x: (-oo, +oo); y: (-oo, +oo); z: (-oo, +oo)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoN.coord_range()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we introduce on $V$ the coordinates $(x',y',z')$ corresponding to the stereographic projection from the South pole onto the equatorial plane:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (V, (xp, yp, zp))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoS. = V.chart(\"xp:x' yp:y' zp:z'\")\n", "stereoS" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "xp: (-oo, +oo); yp: (-oo, +oo); zp: (-oo, +oo)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoS.coord_range()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "xp = x/(x^2 + y^2 + z^2)\n", "yp = y/(x^2 + y^2 + z^2)\n", "zp = z/(x^2 + y^2 + z^2)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r2 = x^2+y^2+z^2\n", "stereoN_to_S = stereoN.transition_map(stereoS, \n", " (x/r2, y/r2, z/r2), \n", " intersection_name='W',\n", " restrictions1= x^2+y^2+z^2!=0, \n", " restrictions2= xp^2+yp^2+zp^2!=0)\n", "stereoN_to_S.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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$.\n", "\n", "The inverse coordinate transformation is computed by means of the method inverse():" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = xp/(xp^2 + yp^2 + zp^2)\n", "y = yp/(xp^2 + yp^2 + zp^2)\n", "z = zp/(xp^2 + yp^2 + zp^2)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoS_to_N = stereoN_to_S.inverse()\n", "stereoS_to_N.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the situation is of course perfectly symmetric regarding the coordinates $(x,y,z)$ and $(x',y',z')$.\n", "\n", "At this stage, the user's atlas has four charts:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (U, (x, y, z)),\n", " Chart (V, (xp, yp, zp)),\n", " Chart (W, (x, y, z)),\n", " Chart (W, (xp, yp, zp))]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S3.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For future reference, we store $W=U\\cap V$ into a Python variable:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Open subset W of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "W = U.intersection(V)\n", "print(W)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The North and South poles\n", "\n", "$N$ is the point of $V$ of stereographic coordinates $(x',y',z')=(0,0,0)$:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point N on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "N = V((0,0,0), chart=stereoS, name='N')\n", "print(N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "while $S$ is the point of $U$ of stereographic coordinates $(x,y,z)=(0,0,0)$:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point S on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "S = U((0,0,0), chart=stereoN, name='S')\n", "print(S)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have of course" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all([N not in U, N in V, S in U, S not in V])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Embedding of $\\mathbb{S}^3$ into $\\mathbb{R}^4$\n", "\n", "Let us first declare $\\mathbb{R}^4$ as the 4-dimensional Euclidean space, denoting the Cartesian coordinates by\n", "$(T,X,Y,Z)$:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (R^4, (T, X, Y, Z))" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R4. = EuclideanSpace(name='R^4', latex_name=r'\\mathbb{R}^4', metric_name='h')\n", "X4 = R4.cartesian_coordinates()\n", "X4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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$:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Phi: S^3 --> R^4\n", "on U: (x, y, z) |--> (T, X, Y, Z) = (-(x^2 + y^2 + z^2 - 1)/(x^2 + y^2 + z^2 + 1), 2*x/(x^2 + y^2 + z^2 + 1), 2*y/(x^2 + y^2 + z^2 + 1), 2*z/(x^2 + y^2 + z^2 + 1))\n", "on V: (xp, yp, zp) |--> (T, X, Y, Z) = ((xp^2 + yp^2 + zp^2 - 1)/(xp^2 + yp^2 + zp^2 + 1), 2*xp/(xp^2 + yp^2 + zp^2 + 1), 2*yp/(xp^2 + yp^2 + zp^2 + 1), 2*zp/(xp^2 + yp^2 + zp^2 + 1))" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rp2 = xp^2 + yp^2 + zp^2\n", "Phi = S3.diff_map(R4, {(stereoN, X4): \n", " [(1-r2)/(r2+1), 2*x/(r2+1), \n", " 2*y/(r2+1), 2*z/(r2+1)],\n", " (stereoS, X4):\n", " [(rp2-1)/(rp2+1), 2*xp/(rp2+1), \n", " 2*yp/(rp2+1), 2*zp/(rp2+1)]},\n", " name='Phi', latex_name=r'\\Phi')\n", "Phi.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hyperspherical coordinates\n", "\n", "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:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Open subset A of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "A = W.open_subset('A', coord_def={stereoN.restrict(W): (y!=0, x<0), \n", " stereoS.restrict(W): (yp!=0, xp<0)})\n", "print(A)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (A, (ch, th, ph))" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher. = A.chart(r'ch:(0,pi):\\chi th:(0,pi):\\theta ph:(0,2*pi):\\phi')\n", "spher" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = cos(ph)*sin(ch)*sin(th)/(cos(ch) + 1)\n", "y = sin(ch)*sin(ph)*sin(th)/(cos(ch) + 1)\n", "z = cos(th)*sin(ch)/(cos(ch) + 1)" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "den = 1 + cos(ch)\n", "spher_to_stereoN = spher.transition_map(stereoN.restrict(A), \n", " (sin(ch)*sin(th)*cos(ph)/den,\n", " sin(ch)*sin(th)*sin(ph)/den,\n", " sin(ch)*cos(th)/den))\n", "spher_to_stereoN.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also provide the inverse transition map by means of the method set_inverse, which (by default) performs a check that the provided formulas are indeed correct:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check of the inverse coordinate transformation:\n", " ch == 2*arctan(sqrt(-cos(ch) + 1)/sqrt(cos(ch) + 1)) **failed**\n", " th == arctan2(sqrt(-cos(ch) + 1)*sin(th)/sqrt(cos(ch) + 1), cos(th)*sin(ch)/(cos(ch) + 1)) **failed**\n", " ph == pi - arctan2(sin(ch)*sin(ph)*sin(th)/(cos(ch) + 1), -cos(ph)*sin(ch)*sin(th)/(cos(ch) + 1)) **failed**\n", " x == x *passed*\n", " y == y *passed*\n", " z == z *passed*\n", "NB: a failed report can reflect a mere lack of simplification.\n" ] } ], "source": [ "spher_to_stereoN.set_inverse(2*atan(sqrt(x^2+y^2+z^2)),\n", " atan2(sqrt(x^2+y^2), z),\n", " atan2(-y, -x) + pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The check is passed, modulo some lack of trigonometric simplifications in the first three lines." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ch = 2*arctan(sqrt(x^2 + y^2 + z^2))\n", "th = arctan2(sqrt(x^2 + y^2), z)\n", "ph = pi + arctan2(-y, -x)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher_to_stereoN.inverse().display()" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "xp = (cos(ch) + 1)*cos(ph)*sin(th)/sin(ch)\n", "yp = (cos(ch) + 1)*sin(ph)*sin(th)/sin(ch)\n", "zp = (cos(ch) + 1)*cos(th)/sin(ch)" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher_to_stereoS = stereoN_to_S.restrict(A) * spher_to_stereoN\n", "spher_to_stereoS.display()" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ch = 2*arctan(1/sqrt(xp^2 + yp^2 + zp^2))\n", "th = arctan2(sqrt(xp^2 + yp^2)/(xp^2 + yp^2 + zp^2), zp/(xp^2 + yp^2 + zp^2))\n", "ph = pi - arctan2(yp/(xp^2 + yp^2 + zp^2), -xp/(xp^2 + yp^2 + zp^2))" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoS_to_spher = spher_to_stereoN.inverse() * stereoS_to_N.restrict(A)\n", "stereoS_to_spher.display()" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Phi: S^3 --> R^4\n", "on A: (x, y, z) |--> (T, X, Y, Z) = (-(x^2 + y^2 + z^2 - 1)/(x^2 + y^2 + z^2 + 1), 2*x/(x^2 + y^2 + z^2 + 1), 2*y/(x^2 + y^2 + z^2 + 1), 2*z/(x^2 + y^2 + z^2 + 1))" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Phi.display(stereoN.restrict(A), X4)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Phi: S^3 --> R^4\n", "on A: (ch, th, ph) |--> (T, X, Y, Z) = (cos(ch), cos(ph)*sin(ch)*sin(th), sin(ch)*sin(ph)*sin(th), cos(th)*sin(ch))" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Phi.display(spher, X4)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Phi: S^3 --> R^4\n", "on U: (x, y, z) |--> (T, X, Y, Z) = (-(x^2 + y^2 + z^2 - 1)/(x^2 + y^2 + z^2 + 1), 2*x/(x^2 + y^2 + z^2 + 1), 2*y/(x^2 + y^2 + z^2 + 1), 2*z/(x^2 + y^2 + z^2 + 1))\n", "on V: (xp, yp, zp) |--> (T, X, Y, Z) = ((xp^2 + yp^2 + zp^2 - 1)/(xp^2 + yp^2 + zp^2 + 1), 2*xp/(xp^2 + yp^2 + zp^2 + 1), 2*yp/(xp^2 + yp^2 + zp^2 + 1), 2*zp/(xp^2 + yp^2 + zp^2 + 1))\n", "on A: (ch, th, ph) |--> (T, X, Y, Z) = (cos(ch), cos(ph)*sin(ch)*sin(th), sin(ch)*sin(ph)*sin(th), cos(th)*sin(ch))" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Phi.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Global left-invariant vector frame on $\\mathbb{S}^3$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The vector frames associated with the two stereographic charts are" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (U, (d/dx,d/dy,d/dz))" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "frameN = stereoN.frame()\n", "frameN" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (V, (d/dxp,d/dyp,d/dzp))" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "frameS = stereoS.frame()\n", "frameS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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 notebook\n", "[3-sphere: vector fields and left-invariant parallelization](http://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S3_vectors.ipynb). We first declare this vector frame on all $\\mathbb{S}^3$:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (S^3, (E_1,E_2,E_3))" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E = S3.vector_frame('E', latex_symbol=r'\\varepsilon')\n", "E" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On $U$, we relate this frame to the stereographic coordinate frame, by means of the formulas obtained in the vector field notebook mentioned above:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (U, (E_1,E_2,E_3))" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E_U = E.restrict(U); E_U" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "E_U[1][frameN,:,stereoN] = \\\n", " [(x^2-y^2-z^2+1)/2, x*y+z, x*z-y]\n", "E_U[2][frameN,:,stereoN] = \\\n", " [x*y-z, (1-x^2+y^2-z^2)/2, x+y*z] \n", "E_U[3][frameN,:,stereoN] = \\\n", " [x*z+y, y*z-x, (1-x^2-y^2+z^2)/2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, on $V$, we relate the global frame with the stereographic coordinate frame from the South pole:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (V, (E_1,E_2,E_3))" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E_V = E.restrict(V); E_V" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "E_V[1][frameS,:, stereoS] = \\\n", " [(yp^2+zp^2-xp^2-1)/2, zp-xp*yp, -yp-xp*zp]\n", "E_V[2][frameS,:, stereoS] = \\\n", " [-zp-xp*yp, (xp^2-yp^2+zp^2-1)/2, xp-yp*zp]\n", "E_V[3][frameS,:, stereoS] = \\\n", " [yp-xp*zp, -xp-yp*zp, (xp^2+yp^2-zp^2-1)/2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us display the links between the various frames:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "E_1 = (1/2*x^2 - 1/2*y^2 - 1/2*z^2 + 1/2) d/dx + (x*y + z) d/dy + (x*z - y) d/dz" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "E_2 = (x*y - z) d/dx + (-1/2*x^2 + 1/2*y^2 - 1/2*z^2 + 1/2) d/dy + (y*z + x) d/dz" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "E_3 = (x*z + y) d/dx + (y*z - x) d/dy + (-1/2*x^2 - 1/2*y^2 + 1/2*z^2 + 1/2) d/dz" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ " \n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "E_1 = (-1/2*xp^2 + 1/2*yp^2 + 1/2*zp^2 - 1/2) d/dxp + (-xp*yp + zp) d/dyp + (-xp*zp - yp) d/dzp" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "E_2 = (-xp*yp - zp) d/dxp + (1/2*xp^2 - 1/2*yp^2 + 1/2*zp^2 - 1/2) d/dyp + (-yp*zp + xp) d/dzp" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "E_3 = (-xp*zp + yp) d/dxp + (-yp*zp - xp) d/dyp + (1/2*xp^2 + 1/2*yp^2 - 1/2*zp^2 - 1/2) d/dzp" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in S3.irange():\n", " show(E[i].display(frameN))\n", "print(\" \")\n", "for i in S3.irange():\n", " show(E[i].display(frameS))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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)$:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "P = U.automorphism_field()\n", "for i in S3.irange():\n", " for j in S3.irange():\n", " P[j,i] = E_U[i][j]" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all([E_U[i] == P(frameN[i]) for i in S3.irange()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We add $P$ to the known changes of frame on $U$:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "U.set_change_of_frame(frameN, E_U, P)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, on $V$, we introduce the operator $P$ such that $\\epsilon_i = P(\\partial/\\partial {x'}^i)$, with ${x'}^i=(x',y',z')$:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "P = V.automorphism_field()\n", "for i in S3.irange():\n", " for j in S3.irange():\n", " P[j,i] = E_V[i][j]" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all([E_V[i] == P(frameS[i]) for i in S3.irange()])" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "V.set_change_of_frame(frameS, E_V, P)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hopf coordinates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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\n", "**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 notebook [3-sphere: charts, quaternions and Hopf fibration](http://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S3_Hopf.ipynb): " ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Open subset B of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "B = U.open_subset('B', coord_def={stereoN.restrict(U): \n", " [x^2+y^2!=0, x^2+y^2+z^2!=1, \n", " (1-x^2-y^2-z^2)*x-2*y*z!=0]})\n", "print(B)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (B, (eta, alpha, beta))" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Hcoord. = B.chart(r\"eta:(0,pi/2):\\eta alpha:(0,2*pi):\\alpha beta:(0,2*pi):\\beta\")\n", "Hcoord" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = cos(alpha + beta)*sin(eta)/(cos(eta)*sin(alpha) + 1)\n", "y = sin(alpha + beta)*sin(eta)/(cos(eta)*sin(alpha) + 1)\n", "z = cos(alpha)*cos(eta)/(cos(eta)*sin(alpha) + 1)" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Hcoord_to_stereoN = Hcoord.transition_map(\n", " stereoN.restrict(U),\n", " (sin(eta)*cos(alp+bet)/(1+cos(eta)*sin(alp)),\n", " sin(eta)*sin(alp+bet)/(1+cos(eta)*sin(alp)),\n", " cos(eta)*cos(alp)/(1+cos(eta)*sin(alp))))\n", "Hcoord_to_stereoN.display()" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check of the inverse coordinate transformation:\n", " eta == arcsin((cos(eta)*sin(alpha) + 1)*sqrt(cos(eta) + 1)*sqrt(-cos(eta) + 1)/abs(cos(eta)*sin(alpha) + 1)) **failed**\n", " alpha == pi - arctan2(2*cos(eta)*sin(alpha)/(cos(eta)*sin(alpha) + 1), -2*cos(alpha)*cos(eta)/(cos(eta)*sin(alpha) + 1)) **failed**\n", " 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)) **failed**\n", " x == x *passed*\n", " y == y *passed*\n", " z == z *passed*\n", "NB: a failed report can reflect a mere lack of simplification.\n" ] } ], "source": [ "Hcoord_to_stereoN.set_inverse(asin(2*sqrt(x^2+y^2)/(1+x^2+y^2+z^2)),\n", " atan2(x^2+y^2+z^2-1, -2*z) + pi,\n", " atan2(-y,-x) - atan2(x^2+y^2+z^2-1, -2*z))" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "eta = arcsin(2*sqrt(x^2 + y^2)/(x^2 + y^2 + z^2 + 1))\n", "alpha = pi + arctan2(x^2 + y^2 + z^2 - 1, -2*z)\n", "beta = -arctan2(x^2 + y^2 + z^2 - 1, -2*z) + arctan2(-y, -x)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Hcoord_to_stereoN.inverse().display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As explained in the notebook [3-sphere: vector fields and left-invariant parallelization](http://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S3_vectors.ipynb), due to some lack of simplification, it's better to set the components of $\\varepsilon_1$ and $\\varepsilon_2$ by hand:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "E_1 = sin(2*alpha + beta) d/deta - cos(2*alpha + beta)*tan(eta) d/dalpha + cos(2*alpha + beta)/(cos(eta)*sin(eta)) d/dbeta" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E_U[1].add_comp(Hcoord.frame())[1, Hcoord] = sin(2*alp+bet)\n", "E_U[1].add_comp(Hcoord.frame())[2, Hcoord] = -cos(2*alp+bet) * tan(eta)\n", "E_U[1].add_comp(Hcoord.frame())[3, Hcoord] = cos(2*alp+bet) / (cos(eta)*sin(eta))\n", "E_U[1].display(Hcoord.frame(), Hcoord)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "E_2 = -cos(2*alpha + beta) d/deta - sin(2*alpha + beta)*tan(eta) d/dalpha + sin(2*alpha + beta)/(cos(eta)*sin(eta)) d/dbeta" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E_U[2].add_comp(Hcoord.frame())[1, Hcoord] = -cos(2*alp+bet)\n", "E_U[2].add_comp(Hcoord.frame())[2, Hcoord] = -sin(2*alp+bet) * tan(eta)\n", "E_U[2].add_comp(Hcoord.frame())[3, Hcoord] = sin(2*alp+bet) / (cos(eta)*sin(eta))\n", "E_U[2].display(Hcoord.frame(), Hcoord)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the contrary, the components of $\\varepsilon_3$ are particularly simple:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "E_3 = -d/dalpha" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E_U[3].display(Hcoord.frame(), Hcoord)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Round metric on $\\mathbb{S}^3$\n", "\n", "The standard metric on $\\mathbb{S}^3$ is that induced by the Euclidean metric of $\\mathbb{R}^4$. The latter\n", "is obtained by:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "h = dT*dT + dX*dX + dY*dY + dZ*dZ" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h = R4.metric()\n", "h.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The metric $g$ on $\\mathbb{S}^3$ is computed as being the pullback of $h$ by the embedding $\\Phi$:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Riemannian metric g on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "g = S3.metric()\n", "g.set( Phi.pullback(h) )\n", "print(g)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us display $g$ in terms of the coordinate frame associated with the stereographic chart from the North pole $(U,(x,y,z))$:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dx*dx + 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dy*dy + 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dz*dz" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(frameN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The components can be factored:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 4/(x^2 + y^2 + z^2 + 1)^2 dx*dx + 4/(x^2 + y^2 + z^2 + 1)^2 dy*dy + 4/(x^2 + y^2 + z^2 + 1)^2 dz*dz" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "for i in S3.irange():\n", " g[frameN, i,i].factor()\n", "g.display(frameN)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 4/(xp^4 + yp^4 + zp^4 + 2*(xp^2 + 1)*yp^2 + 2*(xp^2 + yp^2 + 1)*zp^2 + 2*xp^2 + 1) dxp*dxp + 4/(xp^4 + yp^4 + zp^4 + 2*(xp^2 + 1)*yp^2 + 2*(xp^2 + yp^2 + 1)*zp^2 + 2*xp^2 + 1) dyp*dyp + 4/(xp^4 + yp^4 + zp^4 + 2*(xp^2 + 1)*yp^2 + 2*(xp^2 + yp^2 + 1)*zp^2 + 2*xp^2 + 1) dzp*dzp" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(frameS)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 4/(xp^2 + yp^2 + zp^2 + 1)^2 dxp*dxp + 4/(xp^2 + yp^2 + zp^2 + 1)^2 dyp*dyp + 4/(xp^2 + yp^2 + zp^2 + 1)^2 dzp*dzp" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "for i in S3.irange():\n", " g[frameS, i,i].factor()\n", "g.display(frameS)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expression of the round metric in the global frame\n", "\n", "The expression of $g$ in terms of the global frame \n", "$(\\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:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = E^1*E^1 + E^2*E^2 + E^3*E^3" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(E_U)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = E^1*E^1 + E^2*E^2 + E^3*E^3" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(E_V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may then set the components globally:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = E^1*E^1 + E^2*E^2 + E^3*E^3" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "for i in S3.irange():\n", " g.add_comp(E)[i, i] = 1\n", "g.display(E)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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 \n", "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}}$\n", "in the notebook [3-sphere: vector fields and left-invariant parallelization](http://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S3_vectors.ipynb)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expression of the round metric in terms of the hyperspherical coordinates" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dch*dch + sin(ch)^2 dth*dth + sin(ch)^2*sin(th)^2 dph*dph" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expression of the round metric in terms of the Hopf coordinates" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = deta*deta + dalpha*dalpha + sin(eta)^2 dalpha*dbeta + sin(eta)^2 dbeta*dalpha + sin(eta)^2 dbeta*dbeta" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(Hcoord.frame(), Hcoord)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We note that the components of $g$ depend only on $\\eta$. This implies that the tori $\\eta=\\mathrm{const}$ are *flat* tori." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Christoffel symbols" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is necessary for what follows (should be fixed in a future version):" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "for chart in S3.top_charts():\n", " g.restrict(chart.domain()).inverse()" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^x_xx = -2*x/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_xy = -2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_xz = -2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_yy = 2*x/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_zz = 2*x/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_xx = 2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_xy = -2*x/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_yy = -2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_yz = -2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_zz = 2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_xx = 2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_xz = -2*x/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_yy = 2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_yz = -2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_zz = -2*z/(x^2 + y^2 + z^2 + 1) " ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(stereoN)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^ch_th,th = -cos(ch)*sin(ch) \n", "Gam^ch_ph,ph = -cos(ch)*sin(ch)*sin(th)^2 \n", "Gam^th_ch,th = cos(ch)/sin(ch) \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_ch,ph = cos(ch)/sin(ch) \n", "Gam^ph_th,ph = cos(th)/sin(th) " ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(spher)" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^eta_alpha,beta = -cos(eta)*sin(eta) \n", "Gam^eta_beta,beta = -cos(eta)*sin(eta) \n", "Gam^alpha_eta,alpha = -sin(eta)/cos(eta) \n", "Gam^beta_eta,alpha = -cos(eta)/(sin(eta)^3 - sin(eta)) \n", "Gam^beta_eta,beta = cos(eta)/sin(eta) " ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(Hcoord)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Riemann tensor" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field Riem(g) of type (1,3) on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "Riem = g.riemann()\n", "print(Riem)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g)^x_yxy = 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) \n", "Riem(g)^x_zxz = 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) \n", "Riem(g)^y_xxy = -4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) \n", "Riem(g)^y_zyz = 4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) \n", "Riem(g)^z_xxz = -4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) \n", "Riem(g)^z_yyz = -4/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) " ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem.display_comp(frameN, stereoN, only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g)^ch_th,ch,th = sin(ch)^2 \n", "Riem(g)^ch_ph,ch,ph = sin(ch)^2*sin(th)^2 \n", "Riem(g)^th_ch,ch,th = -1 \n", "Riem(g)^th_ph,th,ph = sin(ch)^2*sin(th)^2 \n", "Riem(g)^ph_ch,ch,ph = -1 \n", "Riem(g)^ph_th,th,ph = -sin(ch)^2 " ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem.display_comp(spher.frame(), spher, only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g)^eta_alpha,eta,alpha = 1 \n", "Riem(g)^eta_alpha,eta,beta = sin(eta)^2 \n", "Riem(g)^eta_beta,eta,alpha = sin(eta)^2 \n", "Riem(g)^eta_beta,eta,beta = sin(eta)^2 \n", "Riem(g)^alpha_eta,eta,alpha = -1 \n", "Riem(g)^alpha_alpha,alpha,beta = sin(eta)^2 \n", "Riem(g)^alpha_beta,alpha,beta = sin(eta)^2 \n", "Riem(g)^beta_eta,eta,beta = -1 \n", "Riem(g)^beta_alpha,alpha,beta = -1 \n", "Riem(g)^beta_beta,alpha,beta = -sin(eta)^2 " ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem.display_comp(Hcoord.frame(), Hcoord, only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g)^1_212 = 1 \n", "Riem(g)^1_313 = 1 \n", "Riem(g)^2_112 = -1 \n", "Riem(g)^2_323 = 1 \n", "Riem(g)^3_113 = -1 \n", "Riem(g)^3_223 = -1 " ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem.display_comp(E_U, stereoN, only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g) = E_1*E^2*E^1*E^2 - E_1*E^2*E^2*E^1 + E_1*E^3*E^1*E^3 - E_1*E^3*E^3*E^1 - E_2*E^1*E^1*E^2 + E_2*E^1*E^2*E^1 + E_2*E^3*E^2*E^3 - E_2*E^3*E^3*E^2 - E_3*E^1*E^1*E^3 + E_3*E^1*E^3*E^1 - E_3*E^2*E^2*E^3 + E_3*E^2*E^3*E^2" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem.display(E_U)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Ricci tensor" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Field of symmetric bilinear forms Ric(g) on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "Ric = g.ricci()\n", "print(Ric)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Ric(g) = 8/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dx*dx + 8/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dy*dy + 8/(x^4 + y^4 + z^4 + 2*(x^2 + 1)*y^2 + 2*(x^2 + y^2 + 1)*z^2 + 2*x^2 + 1) dz*dz" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Ric.display(frameN)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Ric(g) = 8/(x^2 + y^2 + z^2 + 1)^2 dx*dx + 8/(x^2 + y^2 + z^2 + 1)^2 dy*dy + 8/(x^2 + y^2 + z^2 + 1)^2 dz*dz" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "for i in S3.irange():\n", " Ric[frameN, i,i].factor()\n", "Ric.display(frameN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have $Ric(g) = 2 g$:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Ric.restrict(U) == 2 * g.restrict(U)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Ricci scalar" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field r(g) on the Open subset A of the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "R_A = g.restrict(A).ricci_scalar()\n", "print(R_A)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r(g): A --> R\n", " (x, y, z) |--> 6\n", " (xp, yp, zp) |--> 6\n", " (ch, th, ph) |--> 6" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R_A.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We note that the Ricci scalar is constant, as for any maximally symmetric space." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The volume 3-form (Levi-Civita tensor)\n", "\n", "We have" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form eps_g on the 3-dimensional Riemannian manifold S^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = E^1/\\E^2/\\E^3" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eps = S3.volume_form()\n", "print(eps)\n", "eps.display()" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module Omega^3(S^3) of 3-forms on the 3-dimensional Riemannian manifold S^3\n" ] } ], "source": [ "print(eps.parent())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expression of the volume 3-form in terms of the stereographic coordinates" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = 8/(x^6 + y^6 + z^6 + 3*(x^2 + 1)*y^4 + 3*(x^2 + y^2 + 1)*z^4 + 3*x^4 + 3*(x^4 + 2*x^2 + 1)*y^2 + 3*(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1)*z^2 + 3*x^2 + 1) dx/\\dy/\\dz" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eps.display(frameN, stereoN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The component $\\epsilon_{xyz}$ can be factored:" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "8/(x^6 + y^6 + z^6 + 3*(x^2 + 1)*y^4 + 3*(x^2 + y^2 + 1)*z^4 + 3*x^4 + 3*(x^4 + 2*x^2 + 1)*y^2 + 3*(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1)*z^2 + 3*x^2 + 1)" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eps_xyz = eps[frameN, 1,2,3, stereoN]\n", "eps_xyz" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "8/(x^2 + y^2 + z^2 + 1)^3" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eps_xyz.factor()" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = 8/(x^2 + y^2 + z^2 + 1)^3 dx/\\dy/\\dz" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eps.display(frameN, stereoN)" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.0.beta1", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 1 }