{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# Sage manifold tutorial\n", "\n", "This worksheet provides a short introduction to differentiable manifolds in SageMath. The tools described below have been implemented through the\n", "[SageManifolds](http://sagemanifolds.obspm.fr) project (version 1.1, included in SageMath 8.1).\n", "\n", "Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Worksheets/v1.1/SM_tutorial.ipynb) to download the worksheet file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, via the command `sage -n jupyter`" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The following assumes that you are using version 7.5 (or higher) of SageMath, since lower versions do not include all features of SageManifolds:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'SageMath version 8.1, Release Date: 2017-12-07'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "First we set up the notebook to display mathematical objects using LaTeX rendering:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "## Defining a manifold\n", "\n", "As an example let us define a differentiable manifold of dimension 3 over $\\mathbb{R}$:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "M = Manifold(3, 'M', latex_name=r'\\mathcal{M}', start_index=1)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "- The first argument, `3`, is the manifold dimension. In SageManifolds, it can be any\n", " positive integer.\n", "- The second argument, `'M'`, is a string defining the manifold's name; it may be \n", " different from the symbol set on the left-hand side of the = sign (here `M`): the latter\n", " stands for a mere Python variable, which refers to the manifold object in the computer \n", " memory, while the string `'M'` is the mathematical symbol chosen for the manifold.\n", "- The optional argument `latex_name=r'\\mathcal{M}'` sets the LaTeX\n", " symbol to display the manifold. Note the letter 'r' in front on the first quote: \n", " it indicates that the string is a *raw* one, so that the backslash character \n", " in `\\mathcal` is considered as an ordinary character (otherwise, the backslash is \n", " used to escape some special characters). If the argument `latex_name` is not \n", " provided by the user, it is set to the string used as the second argument (here `'M'`)\n", "- The optional argument `start_index=1` defines the range of indices to be used for \n", " tensor components on the manifold: setting it to 1 means that indices will range \n", " in $\\{1,2,3\\}$. The default value is `start_index=0`.\n", "\n", "Note that the default base field is $\\mathbb{R}$. If we would have used the optional\n", "argument `field='complex'`, we would have defined a manifold over $\\mathbb{C}$. See the\n", "[list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/manifold.html#sage.manifolds.manifold.Manifold) for more details. \n", "\n", "If we ask for M, it is displayed via its LaTeX symbol:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "If we use the `print` function instead, we get a short description of the object:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(M)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Via the command type, we get the type of the Python object corresponding to M (here the Python class DifferentiableManifold_with_category):

" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(M)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "We can also ask for the category of M and see that it is the category of smooth manifolds over $\\mathbb{R}$:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Category of smooth manifolds over Real Field with 53 bits of precision" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "category(M)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The indices on the manifold are generated by the method irange(), to be used in loops:

" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] } ], "source": [ "for i in M.irange():\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

If the parameter start_index had not been specified, the default range of the indices would have been $\\{0,1,2\\}$ instead:

" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n" ] } ], "source": [ "M0 = Manifold(3, 'M', r'\\mathcal{M}')\n", "for i in M0.irange():\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Defining a chart on the manifold

\n", "

Let us assume that the manifold $\\mathcal{M}$ can be covered by a single chart (other cases are discussed below); the chart is declared as follows:

" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "X. = M.chart()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The writing `.` in the left-hand side means that the Python variables `x`, `y` and `z` are set to the three coordinates of the chart. This allows one to refer subsequently to the coordinates by their names.\n", "\n", "In this example, the function `chart()` has no arguments, which implies that the coordinate symbols will be `x`, `y` and `z` (i.e. exactly the characters set in the `<...>` operator) and that each coordinate range is $(-\\infty,+\\infty)$. For other cases, an argument must be passed to `chart()`  to specify the coordinate symbols and range, as well as the LaTeX symbol of a coordinate if the latter is different from the coordinate name (an example will be provided below)." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The chart is displayed as a pair formed by the open set covered by it (here the whole manifold) and the coordinates:

" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Chart (M, (x, y, z))\n" ] } ], "source": [ "print(X)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The coordinates can be accessed individually, by means of their indices, following the convention defined by start_index=1 in the manifold's definition:

" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[1]" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "y" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[2]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[3]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The full set of coordinates is obtained by means of the operator [:]:

" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Thanks to the operator `` used in the chart declaration, each coordinate can be accessed directly via its name:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z is X[3]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Coordinates are SageMath symbolic expressions:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(z)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Functions of the chart coordinates

\n", "

Real-valued functions of the chart coordinates (mathematically speaking, functions defined on the chart codomain) are generated via the method function() acting on the chart:

" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z^3 + y^2 + x" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = X.function(x+y^2+z^3) ; f" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> z^3 + y^2 + x" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "32" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(1,2,3)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

They belong to SageManifolds class CoordFunctionSymb:

" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(f)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

and differ from SageMath standard symbolic functions by automatic simplifications in all operations. For instance, adding the two symbolic functions

" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "f0(x,y,z) = cos(x)^2 ; g0(x,y,z) = sin(x)^2" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

results in

" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)^2 + sin(x)^2" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f0 + g0" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

while the sum of the corresponding functions in the class CoordFunctionSymb is automatically simplified:

" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "1" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1 = X.function(cos(x)^2) ; g1 = X.function(sin(x)^2)\n", "f1 + g1" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

To get the same output with symbolic functions, one has to invoke the method simplify_trig():

" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> 1" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(f0 + g0).simplify_trig()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Another difference regards the display; if we ask for the symbolic function f0, we get:

" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)^2" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f0" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

while if we ask for the chart function f1, we get only the coordinate expression:

" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "cos(x)^2" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

To get an output similar to that of f0, one should call the method display():

" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)^2" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Note that the method `expr()` returns the underlying symbolic expression:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "cos(x)^2" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1.expr()" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(f1.expr())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "### Introducing a second chart on the manifold\n", "\n", "Let us first consider an open subset of $\\mathcal{M}$, for instance the complement $U$ of the region defined by $\\{y=0, x\\geq 0\\}$ (note that `(y!=0, x<0)` stands for $y\\not=0$ OR $x<0$; the condition $y\\not=0$ AND $x<0$ would have been written `[y!=0, x<0]` instead):" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "U = M.open_subset('U', coord_def={X: (y!=0, x<0)})" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "Let us call `X_U` the restriction of the chart `X` to the open subset $U$:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (x, y, z))" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_U = X.restrict(U) ; X_U" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We introduce another chart on $U$, with spherical-type coordinates $(r,\\theta,\\phi)$:

" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (r, th, ph))" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y. = U.chart(r'r:(0,+oo) th:(0,pi):\\theta ph:(0,2*pi):\\phi') ; Y" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The function chart() has now some argument; it is a string, which contains specific LaTeX symbols, hence the prefix 'r' to it (for raw string). It also contains the coordinate ranges, since they are different from the default value, which is $(-\\infty, +\\infty)$. For a given coordinate, the various fields are separated by the character ':' and a space character separates the coordinates. Note that for the coordinate $r$, there are only two fields, since the LaTeX symbol has not to be specified. The LaTeX symbols are used for the outputs:

" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(th, ph)" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "th, ph" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(th, ph)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y[2], Y[3]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The declared coordinate ranges are now known to Sage, as we may check by means of the command assumptions():

" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[x is real,\n", " y is real,\n", " z is real,\n", " r is real,\n", " r > 0,\n", " th is real,\n", " th > 0,\n", " th < pi,\n", " ph is real,\n", " ph > 0,\n", " ph < 2*pi]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "assumptions()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

They are used in simplifications:

" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simplify(abs(r))" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "abs(x)" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simplify(abs(x)) # no simplification occurs since x can take any value in R" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

After having been declared, the chart Y can be fully specified by its relation to the chart X_U, via a transition map:

" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "transit_Y_to_X = Y.transition_map(X_U, [r*sin(th)*cos(ph), r*sin(th)*sin(ph), r*cos(th)])" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Change of coordinates from Chart (U, (r, th, ph)) to Chart (U, (x, y, z))" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transit_Y_to_X" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = r*cos(ph)*sin(th)\n", "y = r*sin(ph)*sin(th)\n", "z = r*cos(th)" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transit_Y_to_X.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The inverse of the transition map can be specified by means of the method set_inverse():

" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r = sqrt(x^2 + y^2 + z^2)\n", "th = arctan2(sqrt(x^2 + y^2), z)\n", "ph = arctan2(y, x)" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transit_Y_to_X.set_inverse(sqrt(x^2+y^2+z^2), atan2(sqrt(x^2+y^2),z), atan2(y, x))\n", "transit_Y_to_X.inverse().display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

At this stage, the manifold's atlas (the \"user atlas\", not the maximal atlas!) contains three charts:

" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (M, (x, y, z)), Chart (U, (x, y, z)), Chart (U, (r, th, ph))]" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.atlas()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The first chart defined on the manifold is considered as the manifold's default chart (it can be changed by the method set_default_chart()):

" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_chart()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Each open subset has its own atlas (since an open subset of a manifold is a manifold by itself):

" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (U, (x, y, z)), Chart (U, (r, th, ph))]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.atlas()" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (x, y, z))" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.default_chart()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "We can draw the chart $Y$ in terms of the chart $X$. \n", "Let us first define a viewer for 3D plots (use `'threejs'` or `'jmol'` for interactive 3D graphics):" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": true, "deletable": true, "editable": true }, "outputs": [], "source": [ "viewer3D = 'threejs' # must be 'threejs', 'jmol', 'tachyon' or None (default)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The plot shows lines of constant coordinates from the $Y$ chart in a \"Cartesian frame\" based on the $X$ coordinates:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph = Y.plot(X)\n", "show(graph, viewer=viewer3D, online=True)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The command plot() allows for many options, to control the number of coordinate lines to be drawn, their style and color, as well as the coordinate ranges (cf. the [list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/chart.html#sage.manifolds.chart.RealChart.plot)):" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph = Y.plot(X, ranges={r:(1,2), th:(0,pi/2)}, number_values=4, \n", " color={r:'blue', th:'green', ph:'red'})\n", "show(graph, aspect_ratio=1, viewer=viewer3D, online=True)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Conversly, the chart $X|_{U}$ can be plotted in terms of the chart $Y$ (this is not possible for the whole chart $X$ since its domain is larger than that of chart $Y$):

" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph = X_U.plot(Y)\n", "show(graph, viewer=viewer3D, online=True, axes_labels=['r','theta','phi'])" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Points on the manifold

\n", "

A point on $\\mathcal{M}$ is defined by its coordinates in a given chart:

" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = M.point((1,2,-1), chart=X, name='p') ; print(p) ; p" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Since $X=(\\mathcal{M}, (x,y,z))$ is the manifold's default chart, its name can be omitted:

" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = M.point((1,2,-1), name='p') ; print(p) ; p" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Of course, $p$ belongs to $\\mathcal{M}$:

" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p in M" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

It is also in $U$:

" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p in U" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Indeed the coordinates of $p$ have $y\\not=0$:

" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord(X)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Note in passing that since $X$ is the default chart on $\\mathcal{M}$, its name can be omitted in the arguments of coord():

" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The coordinates of $p$ can also be obtained by letting the chart acting of the point (from the very definition of a chart!):

" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X(p)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Let $q$ be a point with $y = 0$ and $x \\geq 0$:

" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "q = M.point((1,0,2), name='q')" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

This time, the point does not belong to $U$:

" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q in U" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Accordingly, we cannot ask for the coordinates of $q$ in the chart $Y=(U, (r,\\theta,\\phi))$:

" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error: the point does not belong to the domain of Chart (U, (r, th, ph))\n" ] } ], "source": [ "try:\n", " q.coord(Y)\n", "except ValueError as exc:\n", " print(\"Error: \" + str(exc))" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

but we can for point $p$:

" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(3)*sqrt(2), pi - arctan(sqrt(5)), arctan(2))" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord(Y)" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(3)*sqrt(2), pi - arctan(sqrt(5)), arctan(2))" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y(p)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Points can be compared:

" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q == p" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p1 = U.point((sqrt(6), pi-atan(sqrt(5)), atan(2)), Y)\n", "p1 == p" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In SageMath's terminology, points are elements, whose parents are the manifold on which they have been defined:

" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.parent()" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q.parent()" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p1.parent()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Scalar fields

\n", "

A scalar field is a differentiable mapping $U \\longrightarrow \\mathbb{R}$, where $U$ is an open subset of $\\mathcal{M}$.

\n", "

The scalar field is defined by its expressions in terms of charts covering its domain (in general more than one chart is necessary to cover all the domain):

" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field f on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "f = U.scalar_field({X_U: x+y^2+z^3}, name='f') ; print(f)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The coordinate expressions of the scalar field are passed as a Python dictionary, with the charts as keys, hence the writing {X_U: x+y^2+z^3}.

\n", "

Since in the present case, there is only one chart in the dictionary, an alternative writing is

" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field f on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "f = U.scalar_field(x+y^2+z^3, chart=X_U, name='f') ; print(f)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Since X_U is the domain's default chart, it can be omitted in the above declaration:

" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field f on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "f = U.scalar_field(x+y^2+z^3, name='f') ; print(f)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "As a mapping $U\\subset\\mathcal{M}\\longrightarrow\\mathbb{R}$, a scalar field acts on points, not on coordinates:" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "4" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(p)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The method `display()` provides the expression of the scalar field in terms of a given chart:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> z^3 + y^2 + x" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display(X_U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "If no argument is provided, the method `display()` shows the coordinate expression of the scalar field in all the charts defined on the domain (except for *subcharts*, i.e. the restrictions of some chart to a subdomain):" ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> z^3 + y^2 + x\n", " (r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Note that the expression of $f$ in terms of the coordinates $(r,\\theta,\\phi)$ has not been provided by the user but has been automatically computed by means of the change-of-coordinate formula declared above in the transition map.

" ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display(Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In each chart, the scalar field is represented by a function of the chart coordinates (an object of the type CoordFunctionSymb described above), which is accessible via the method coord_function():

" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z^3 + y^2 + x" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(X_U)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> z^3 + y^2 + x" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(X_U).display()" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(Y)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(Y).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The \"raw\" symbolic expression is returned by the method expr():

" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z^3 + y^2 + x" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(X_U)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(Y)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(Y) is f.coord_function(Y).expr()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A scalar field can also be defined by some unspecified function of the coordinates:

" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field h on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "h = U.scalar_field(function('H')(x, y, z), name='h') ; print(h)" ] }, { "cell_type": "code", "execution_count": 84, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "h: U --> R\n", " (x, y, z) |--> H(x, y, z)\n", " (r, th, ph) |--> H(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display()" ] }, { "cell_type": "code", "execution_count": 85, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "h: U --> R\n", " (r, th, ph) |--> H(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display(Y)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "H(1, 2, -1)" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h(p) # remember that p is the point of coordinates (1,2,-1) in the chart X_U" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The parent of $f$ is the set $C^\\infty(U)$ of all smooth scalar fields on $U$, which is a commutative algebra over $\\mathbb{R}$:

" ] }, { "cell_type": "code", "execution_count": 87, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Algebra of differentiable scalar fields on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CU = f.parent() ; CU" ] }, { "cell_type": "code", "execution_count": 88, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Algebra of differentiable scalar fields on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(CU)" ] }, { "cell_type": "code", "execution_count": 89, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Category of commutative algebras over Symbolic Ring" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CU.category()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "
 
\n", "
\n", "

The base ring of the algebra is the field $\\mathbb{R}$, which is represented here by SageMath's Symbolic Ring (SR):

\n", "
\n", "
 
" ] }, { "cell_type": "code", "execution_count": 90, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Symbolic Ring" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CU.base_ring()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Arithmetic operations on scalar fields are defined through the algebra structure:

" ] }, { "cell_type": "code", "execution_count": 91, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = f + 2*h ; print(s)" ] }, { "cell_type": "code", "execution_count": 92, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U --> R\n", "(x, y, z) |--> z^3 + y^2 + x + 2*H(x, y, z)\n", "(r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th) + 2*H(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Tangent spaces

\n", "

The tangent vector space to the manifold at point $p$ is obtained as follows:

" ] }, { "cell_type": "code", "execution_count": 93, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Tangent space at Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp = M.tangent_space(p) ; Tp" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent space at Point p on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(Tp)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

$T_p\\, \\mathcal{M}$ is a 2-dimensional vector space over $\\mathbb{R}$ (represented here by SageMath's Symbolic Ring (SR)) :

" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Category of finite dimensional vector spaces over Symbolic Ring\n" ] } ], "source": [ "print(Tp.category())" ] }, { "cell_type": "code", "execution_count": 96, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp.dim()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

$T_p\\, \\mathcal{M}$ is automatically endowed with vector bases deduced from the vector frames defined around the point:

" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Basis (d/dx,d/dy,d/dz) on the Tangent space at Point p on the 3-dimensional differentiable manifold M,\n", " Basis (d/dr,d/dth,d/dph) on the Tangent space at Point p on the 3-dimensional differentiable manifold M]" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp.bases()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

For the tangent space at the point $q$, on the contrary, there is only one pre-defined basis, since $q$ is not in the domain $U$ of the frame associated with coordinates $(r,\\theta,\\phi)$:

" ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Basis (d/dx,d/dy,d/dz) on the Tangent space at Point q on the 3-dimensional differentiable manifold M]" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tq = M.tangent_space(q)\n", "Tq.bases()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A random element:

" ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector at Point p on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "v = Tp.an_element() ; print(v)" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx + 2 d/dy + 3 d/dz" ] }, "execution_count": 100, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "code", "execution_count": 101, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector at Point q on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "u = Tq.an_element() ; print(u)" ] }, { "cell_type": "code", "execution_count": 102, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx + 2 d/dy + 3 d/dz" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Note that, despite what the above simplified writing may suggest (the mention of the point $p$ or $q$ is omitted in the basis vectors), $u$ and $v$ are different vectors, for they belong to different vector spaces:

" ] }, { "cell_type": "code", "execution_count": 103, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Tangent space at Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.parent()" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Tangent space at Point q on the 3-dimensional differentiable manifold M" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u.parent()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In particular, it is not possible to add $u$ and $v$:

" ] }, { "cell_type": "code", "execution_count": 105, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error: unsupported operand parent(s) for +: 'Tangent space at Point q on the 3-dimensional differentiable manifold M' and 'Tangent space at Point p on the 3-dimensional differentiable manifold M'\n" ] } ], "source": [ "try:\n", " s = u + v\n", "except TypeError as exc:\n", " print(\"Error: \" + str(exc))" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Vector Fields

\n", "

Each chart defines a vector frame on the chart domain: the so-called coordinate basis:

" ] }, { "cell_type": "code", "execution_count": 106, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dx,d/dy,d/dz))" ] }, "execution_count": 106, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X.frame()" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X.frame().domain() # this frame is defined on the whole manifold" ] }, { "cell_type": "code", "execution_count": 108, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (U, (d/dr,d/dth,d/dph))" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y.frame()" ] }, { "cell_type": "code", "execution_count": 109, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y.frame().domain() # this frame is defined only on U" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The list of frames defined on a given open subset is returned by the method frames():

" ] }, { "cell_type": "code", "execution_count": 110, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (M, (d/dx,d/dy,d/dz)),\n", " Coordinate frame (U, (d/dx,d/dy,d/dz)),\n", " Coordinate frame (U, (d/dr,d/dth,d/dph))]" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.frames()" ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (U, (d/dx,d/dy,d/dz)),\n", " Coordinate frame (U, (d/dr,d/dth,d/dph))]" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.frames()" ] }, { "cell_type": "code", "execution_count": 112, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dx,d/dy,d/dz))" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_frame()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Unless otherwise specified (via the command set_default_frame()), the default frame is that associated with the default chart:

" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_frame() is M.default_chart().frame()" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.default_frame() is U.default_chart().frame()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Individual elements of a frame can be accessed by means of their indices:

" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector field d/dy on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e = U.default_frame() ; e2 = e[2] ; e2" ] }, { "cell_type": "code", "execution_count": 116, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector field d/dy on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(e2)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We may define a new vector field as follows:

" ] }, { "cell_type": "code", "execution_count": 117, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector field on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "v = e[2] + 2*x*e[3] ; print(v)" ] }, { "cell_type": "code", "execution_count": 118, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dy + 2*x d/dz" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A vector field can be defined by its components with respect to a given vector frame. When the latter is not specified, the open set's default frame is of course assumed:

" ] }, { "cell_type": "code", "execution_count": 119, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (y + 1) d/dx - x d/dy + x*y*z d/dz" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = U.vector_field(name='v') # vector field defined on the open set U\n", "v[1] = 1+y\n", "v[2] = -x\n", "v[3] = x*y*z\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Vector fields on $U$ are Sage element objects, whose parent is the set $\\mathfrak{X}(U)$ of vector fields defined on $U$:

" ] }, { "cell_type": "code", "execution_count": 120, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Free module X(U) of vector fields on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.parent()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The set $\\mathfrak{X}(U)$ is a module over the commutative algebra $C^\\infty(U)$ of scalar fields on $U$:

" ] }, { "cell_type": "code", "execution_count": 121, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module X(U) of vector fields on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(v.parent())" ] }, { "cell_type": "code", "execution_count": 122, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Category of finite dimensional modules over Algebra of differentiable scalar fields on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(v.parent().category())" ] }, { "cell_type": "code", "execution_count": 123, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Algebra of differentiable scalar fields on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.parent().base_ring()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A vector field acts on scalar fields:

" ] }, { "cell_type": "code", "execution_count": 124, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> z^3 + y^2 + x\n", " (r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "code", "execution_count": 125, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field v(f) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = v(f) ; print(s)" ] }, { "cell_type": "code", "execution_count": 126, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v(f): U --> R\n", " (x, y, z) |--> 3*x*y*z^3 - (2*x - 1)*y + 1\n", " (r, th, ph) |--> -3*r^5*cos(ph)*cos(th)^5*sin(ph) + 3*r^5*cos(ph)*cos(th)^3*sin(ph) - 2*r^2*cos(ph)*sin(ph)*sin(th)^2 + r*sin(ph)*sin(th) + 1" ] }, "execution_count": 126, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 127, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dz = d/dz" ] }, "execution_count": 127, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[3].display()" ] }, { "cell_type": "code", "execution_count": 128, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dz(f): U --> R\n", " (x, y, z) |--> 3*z^2\n", " (r, th, ph) |--> 3*r^2*cos(th)^2" ] }, "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[3](f).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Unset components are assumed to be zero:

" ] }, { "cell_type": "code", "execution_count": 129, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "w = 3 d/dy" ] }, "execution_count": 129, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w = U.vector_field(name='w')\n", "w[2] = 3\n", "w.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A vector field on $U$ can be expanded in the vector frame associated with the chart $(r,\\theta,\\phi)$:

" ] }, { "cell_type": "code", "execution_count": 130, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (x*y*z^2 + x)/sqrt(x^2 + y^2 + z^2) d/dr - (x^3*y + x*y^3 - x)*sqrt(x^2 + y^2)*z/(x^4 + 2*x^2*y^2 + y^4 + (x^2 + y^2)*z^2) d/dth - (x^2 + y^2 + y)/(x^2 + y^2) d/dph" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(Y.frame())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

By default, the components are expressed in terms of the default coordinates $(x,y,z)$. To express them in terms of the coordinates $(r,\\theta,\\phi)$, one should add the corresponding chart as the second argument of the method display():

" ] }, { "cell_type": "code", "execution_count": 131, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (r^3*cos(ph)*cos(th)^2*sin(ph)*sin(th)^2 + cos(ph)*sin(th)) d/dr - (r^3*cos(ph)*cos(th)*sin(ph)*sin(th)^3 - cos(ph)*cos(th))/r d/dth - (r*sin(th) + sin(ph))/(r*sin(th)) d/dph" ] }, "execution_count": 131, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(Y.frame(), Y)" ] }, { "cell_type": "code", "execution_count": 132, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx = cos(ph)*sin(th) d/dr + cos(ph)*cos(th)/r d/dth - sin(ph)/(r*sin(th)) d/dph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "d/dy = sin(ph)*sin(th) d/dr + cos(th)*sin(ph)/r d/dth + cos(ph)/(r*sin(th)) d/dph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "d/dz = cos(th) d/dr - sin(th)/r d/dth" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in M.irange(): \n", " show(e[i].display(Y.frame(), Y))" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The components of a tensor field w.r.t. the default frame can also be obtained as a list, via the command [:]:

" ] }, { "cell_type": "code", "execution_count": 133, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[y + 1, -x, x*y*z]" ] }, "execution_count": 133, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

An alternative is to use the method display_comp():

" ] }, { "cell_type": "code", "execution_count": 134, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v^x = y + 1 \n", "v^y = -x \n", "v^z = x*y*z " ] }, "execution_count": 134, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display_comp()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

To obtain the components w.r.t. to another frame, one may go through the method comp() and specify the frame:

" ] }, { "cell_type": "code", "execution_count": 135, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[(x*y*z^2 + x)/sqrt(x^2 + y^2 + z^2),\n", " -(x^3*y + x*y^3 - x)*sqrt(x^2 + y^2)*z/(x^4 + 2*x^2*y^2 + y^4 + (x^2 + y^2)*z^2),\n", " -(x^2 + y^2 + y)/(x^2 + y^2)]" ] }, "execution_count": 135, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.comp(Y.frame())[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

However a shortcut is to provide the frame as the first argument of the square brackets:

" ] }, { "cell_type": "code", "execution_count": 136, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[(x*y*z^2 + x)/sqrt(x^2 + y^2 + z^2),\n", " -(x^3*y + x*y^3 - x)*sqrt(x^2 + y^2)*z/(x^4 + 2*x^2*y^2 + y^4 + (x^2 + y^2)*z^2),\n", " -(x^2 + y^2 + y)/(x^2 + y^2)]" ] }, "execution_count": 136, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[Y.frame(), :]" ] }, { "cell_type": "code", "execution_count": 137, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v^r = (x*y*z^2 + x)/sqrt(x^2 + y^2 + z^2) \n", "v^th = -(x^3*y + x*y^3 - x)*sqrt(x^2 + y^2)*z/(x^4 + 2*x^2*y^2 + y^4 + (x^2 + y^2)*z^2) \n", "v^ph = -(x^2 + y^2 + y)/(x^2 + y^2) " ] }, "execution_count": 137, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display_comp(Y.frame())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Components are shown expressed in terms of the default's coordinates; to get them in terms of the coordinates $(r,\\theta,\\phi)$ instead, add the chart name as the last argument in the square brackets:

" ] }, { "cell_type": "code", "execution_count": 138, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[r^3*cos(ph)*cos(th)^2*sin(ph)*sin(th)^2 + cos(ph)*sin(th),\n", " -(r^3*cos(ph)*cos(th)*sin(ph)*sin(th)^3 - cos(ph)*cos(th))/r,\n", " -(r*sin(th) + sin(ph))/(r*sin(th))]" ] }, "execution_count": 138, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[Y.frame(), :, Y]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

or specify the chart in display_comp():

" ] }, { "cell_type": "code", "execution_count": 139, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v^r = r^3*cos(ph)*cos(th)^2*sin(ph)*sin(th)^2 + cos(ph)*sin(th) \n", "v^th = -(r^3*cos(ph)*cos(th)*sin(ph)*sin(th)^3 - cos(ph)*cos(th))/r \n", "v^ph = -(r*sin(th) + sin(ph))/(r*sin(th)) " ] }, "execution_count": 139, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display_comp(Y.frame(), chart=Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "To get some vector component as a scalar field instead of a coordinate expression, use double square brackets:" ] }, { "cell_type": "code", "execution_count": 140, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(v[[1]])" ] }, { "cell_type": "code", "execution_count": 141, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U --> R\n", "(x, y, z) |--> y + 1\n", "(r, th, ph) |--> r*sin(ph)*sin(th) + 1" ] }, "execution_count": 141, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[[1]].display()" ] }, { "cell_type": "code", "execution_count": 142, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "y + 1" ] }, "execution_count": 142, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[[1]].expr(X_U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A vector field can be defined with components being unspecified functions of the coordinates:

" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u = u_x(x, y, z) d/dx + u_y(x, y, z) d/dy + u_z(x, y, z) d/dz" ] }, "execution_count": 143, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u = U.vector_field(name='u')\n", "u[:] = [function('u_x')(x,y,z), function('u_y')(x,y,z), function('u_z')(x,y,z)]\n", "u.display()" ] }, { "cell_type": "code", "execution_count": 144, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "s = (y + u_x(x, y, z) + 1) d/dx + (-x + u_y(x, y, z)) d/dy + (x*y*z + u_z(x, y, z)) d/dz" ] }, "execution_count": 144, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = v + u ; s.set_name('s') ; s.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Values of vector fields at a given point

\n", "

The value of a vector field at some point of the manifold is obtained via the method at():

" ] }, { "cell_type": "code", "execution_count": 145, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector v at Point p on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "vp = v.at(p) ; print(vp)" ] }, { "cell_type": "code", "execution_count": 146, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 3 d/dx - d/dy - 2 d/dz" ] }, "execution_count": 146, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Indeed, recall that, w.r.t. chart X_U=$(x,y,z)$,  the coordinates of the point $p$ and the components of the vector field $v$ are

" ] }, { "cell_type": "code", "execution_count": 147, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 147, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord(X_U)" ] }, { "cell_type": "code", "execution_count": 148, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (y + 1) d/dx - x d/dy + x*y*z d/dz" ] }, "execution_count": 148, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(X_U.frame(), X_U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Note that to simplify the writing, the symbol used to denote the value of the vector field at point $p$ is the same as that of the vector field itself (namely $v$); this can be changed by the method set_name():

" ] }, { "cell_type": "code", "execution_count": 149, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 3 d/dx - d/dy - 2 d/dz" ] }, "execution_count": 149, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.set_name(latex_name='v|_p')\n", "vp.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Of course, $v|_p$ belongs to the tangent space at $p$:

" ] }, { "cell_type": "code", "execution_count": 150, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Tangent space at Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 150, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.parent()" ] }, { "cell_type": "code", "execution_count": 151, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp in M.tangent_space(p)" ] }, { "cell_type": "code", "execution_count": 152, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector u at Point p on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "up = u.at(p) ; print(up)" ] }, { "cell_type": "code", "execution_count": 153, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u = u_x(1, 2, -1) d/dx + u_y(1, 2, -1) d/dy + u_z(1, 2, -1) d/dz" ] }, "execution_count": 153, "metadata": {}, "output_type": "execute_result" } ], "source": [ "up.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

1-forms

\n", "

A 1-form on $\\mathcal{M}$ is a field of linear forms. For instance, it can be the differential of a scalar field:

" ] }, { "cell_type": "code", "execution_count": 154, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form df on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "df = f.differential() ; print(df)" ] }, { "cell_type": "code", "execution_count": 155, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "df = dx + 2*y dy + 3*z^2 dz" ] }, "execution_count": 155, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In the above writing, the 1-form is expanded over the basis $(\\mathrm{d}x, \\mathrm{d}y, \\mathrm{d}z)$ associated with the chart $(x,y,z)$. This basis can be accessed via the method coframe():

" ] }, { "cell_type": "code", "execution_count": 156, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate coframe (M, (dx,dy,dz))" ] }, "execution_count": 156, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dX = X.coframe() ; dX" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The list of all coframes defined on a given manifold open subset is returned by the method coframes():

" ] }, { "cell_type": "code", "execution_count": 157, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate coframe (M, (dx,dy,dz)),\n", " Coordinate coframe (U, (dx,dy,dz)),\n", " Coordinate coframe (U, (dr,dth,dph))]" ] }, "execution_count": 157, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.coframes()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

As for a vector field, the value of the differential form at some point on the manifold is obtained by the method at():

" ] }, { "cell_type": "code", "execution_count": 158, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Linear form df on the Tangent space at Point p on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "dfp = df.at(p) ; print(dfp)" ] }, { "cell_type": "code", "execution_count": 159, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "df = dx + 4 dy + 3 dz" ] }, "execution_count": 159, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Recall that

" ] }, { "cell_type": "code", "execution_count": 160, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 160, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The linear form $\\mathrm{d}f|_p$ belongs to the dual of the tangent vector space at $p$:

" ] }, { "cell_type": "code", "execution_count": 161, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Dual of the Tangent space at Point p on the 3-dimensional differentiable manifold M" ] }, "execution_count": 161, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp.parent()" ] }, { "cell_type": "code", "execution_count": 162, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 162, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp.parent() is M.tangent_space(p).dual()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

As such, it is acting on vectors at $p$, yielding a real number:

" ] }, { "cell_type": "code", "execution_count": 163, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector v at Point p on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "v = 3 d/dx - d/dy - 2 d/dz" ] }, "execution_count": 163, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(vp) ; vp.display()" ] }, { "cell_type": "code", "execution_count": 164, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-7" ] }, "execution_count": 164, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp(vp)" ] }, { "cell_type": "code", "execution_count": 165, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent vector u at Point p on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "u = u_x(1, 2, -1) d/dx + u_y(1, 2, -1) d/dy + u_z(1, 2, -1) d/dz" ] }, "execution_count": 165, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(up) ; up.display()" ] }, { "cell_type": "code", "execution_count": 166, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u_x(1, 2, -1) + 4*u_y(1, 2, -1) + 3*u_z(1, 2, -1)" ] }, "execution_count": 166, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp(up)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The differential 1-form of the unspecified scalar field $h$:

" ] }, { "cell_type": "code", "execution_count": 167, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "dh = d(H)/dx dx + d(H)/dy dy + d(H)/dz dz" ] }, "execution_count": 167, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display() ; dh = h.differential() ; dh.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A 1-form can also be defined from scratch:

" ] }, { "cell_type": "code", "execution_count": 168, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form omega on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "om = U.one_form('omega', r'\\omega') ; print(om)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

It can be specified by providing its components in a given coframe:

" ] }, { "cell_type": "code", "execution_count": 169, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = (x^2 + y^2) dx + z dy + (x - z) dz" ] }, "execution_count": 169, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om[:] = [x^2+y^2, z, x-z] # components in the default coframe (dx,dy,dz)\n", "om.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Of course, one may set the components in a frame different from the default one:

" ] }, { "cell_type": "code", "execution_count": 170, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = r*cos(ph)*sin(th) dr + r*sin(ph)*sin(th) dph" ] }, "execution_count": 170, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om[Y.frame(), :, Y] = [r*sin(th)*cos(ph), 0, r*sin(th)*sin(ph)]\n", "om.display(Y.frame(), Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The components in the coframe $(\\mathrm{d}x,\\mathrm{d}y,\\mathrm{d}z)$ are updated automatically:

" ] }, { "cell_type": "code", "execution_count": 171, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = (x^4 + x^2*y^2 - sqrt(x^2 + y^2 + z^2)*y^2)/(sqrt(x^2 + y^2 + z^2)*(x^2 + y^2)) dx + (x^3*y + x*y^3 + sqrt(x^2 + y^2 + z^2)*x*y)/(sqrt(x^2 + y^2 + z^2)*(x^2 + y^2)) dy + x*z/sqrt(x^2 + y^2 + z^2) dz" ] }, "execution_count": 171, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Let us revert to the values set previously:

" ] }, { "cell_type": "code", "execution_count": 172, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = (x^2 + y^2) dx + z dy + (x - z) dz" ] }, "execution_count": 172, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om[:] = [x^2+y^2, z, x-z]\n", "om.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

This time, the components in the coframe $(\\mathrm{d}r, \\mathrm{d}\\theta,\\mathrm{d}\\phi)$ are those that are updated:

" ] }, { "cell_type": "code", "execution_count": 173, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = (r^2*cos(ph)*sin(th)^3 + r*(cos(ph) + sin(ph))*cos(th)*sin(th) - r*cos(th)^2) dr + (r^2*cos(th)^2*sin(ph) + r^2*cos(th)*sin(th) + (r^3*cos(ph)*cos(th) - r^2*cos(ph))*sin(th)^2) dth + (-r^3*sin(ph)*sin(th)^3 + r^2*cos(ph)*cos(th)*sin(th)) dph" ] }, "execution_count": 173, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om.display(Y.frame(), Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A 1-form acts on vector fields, resulting in a scalar field:

" ] }, { "cell_type": "code", "execution_count": 174, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field omega(v) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "omega(v): U --> R\n", " (x, y, z) |--> -x*y*z^2 + x^2*y + y^3 + x^2 + y^2 + (x^2*y - x)*z\n", " (r, th, ph) |--> -r^2*cos(ph)*cos(th)*sin(th) + (r^4*cos(ph)^2*cos(th)*sin(ph) + r^3*sin(ph))*sin(th)^3 - (r^4*cos(ph)*cos(th)^2*sin(ph) - r^2)*sin(th)^2" ] }, "execution_count": 174, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display() ; om.display() ; print(om(v)) ; om(v).display()" ] }, { "cell_type": "code", "execution_count": 175, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field df(v) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "df(v): U --> R\n", " (x, y, z) |--> 3*x*y*z^3 - (2*x - 1)*y + 1\n", " (r, th, ph) |--> r*sin(ph)*sin(th) + (3*r^5*cos(ph)*cos(th)^3*sin(ph) - 2*r^2*cos(ph)*sin(ph))*sin(th)^2 + 1" ] }, "execution_count": 175, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.display() ; print(df(v)) ; df(v).display()" ] }, { "cell_type": "code", "execution_count": 176, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega(u): U --> R\n", " (x, y, z) |--> x^2*u_x(x, y, z) + y^2*u_x(x, y, z) + z*(u_y(x, y, z) - u_z(x, y, z)) + x*u_z(x, y, z)\n", " (r, th, ph) |--> r^2*sin(th)^2*u_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) + r*cos(th)*u_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) + (r*cos(ph)*sin(th) - r*cos(th))*u_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 176, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u.display() ; om(u).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In the case of a differential 1-form, the following identity holds:

" ] }, { "cell_type": "code", "execution_count": 177, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 177, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df(v) == v(f)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "1-forms are Sage *element* objects, whose *parent* is the $C^\\infty(U)$-module $\\Omega^{1}(U)$ of all 1-forms defined on $U$:" ] }, { "cell_type": "code", "execution_count": 178, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Free module Omega^1(U) of 1-forms on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 178, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.parent()" ] }, { "cell_type": "code", "execution_count": 179, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module Omega^1(U) of 1-forms on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(df.parent())" ] }, { "cell_type": "code", "execution_count": 180, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module Omega^1(U) of 1-forms on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(om.parent())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "$\\Omega^{1}(U)$ is actually the dual of the free module $\\mathfrak{X}(U)$:" ] }, { "cell_type": "code", "execution_count": 181, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 181, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.parent() is v.parent().dual()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Differential forms and exterior calculus

\n", "

The exterior product of two 1-forms is taken via the method wedge() and results in a 2-form:

" ] }, { "cell_type": "code", "execution_count": 182, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2-form omega/\\df on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "omega/\\df = (2*x^2*y + 2*y^3 - z) dx/\\dy + (3*(x^2 + y^2)*z^2 - x + z) dx/\\dz + (3*z^3 - 2*x*y + 2*y*z) dy/\\dz" ] }, "execution_count": 182, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = om.wedge(df) ; print(a) ; a.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A matrix view of the components:

" ] }, { "cell_type": "code", "execution_count": 183, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[ 0 2*x^2*y + 2*y^3 - z 3*(x^2 + y^2)*z^2 - x + z]\n", "[ -2*x^2*y - 2*y^3 + z 0 3*z^3 - 2*x*y + 2*y*z]\n", "[-3*(x^2 + y^2)*z^2 + x - z -3*z^3 + 2*x*y - 2*y*z 0]" ] }, "execution_count": 183, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Displaying only the non-vanishing components, skipping the redundant ones (i.e. those that can be deduced by antisymmetry):

" ] }, { "cell_type": "code", "execution_count": 184, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega/\\df_xy = 2*x^2*y + 2*y^3 - z \n", "omega/\\df_xz = 3*(x^2 + y^2)*z^2 - x + z \n", "omega/\\df_yz = 3*z^3 - 2*x*y + 2*y*z " ] }, "execution_count": 184, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.display_comp(only_nonredundant=True)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The 2-form $\\omega\\wedge\\mathrm{d}f$ can be expanded on the $(\\mathrm{d}r,\\mathrm{d}\\theta,\\mathrm{d}\\phi)$ coframe:

" ] }, { "cell_type": "code", "execution_count": 185, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega/\\df = (3*r^5*cos(ph)*sin(th)^4 - (3*r^5*cos(ph) - 3*r^4*cos(th)*sin(ph) - 2*r^3*cos(ph)*sin(ph)^2)*sin(th)^2 - (3*r^4*sin(ph) + r^2*cos(ph))*cos(th) - (2*r^3*cos(th)*sin(ph)^2 + (sin(ph)^2 - 1)*r^2)*sin(th)) dr/\\dth + (2*r^4*sin(ph)*sin(th)^5 + (3*r^5*cos(th)^3*sin(ph) + 2*r^3*cos(ph)^2*cos(th)*sin(ph))*sin(th)^3 - (2*r^3*cos(ph)*cos(th)^2*sin(ph) + (cos(ph)*sin(ph) + 1)*r^2*cos(th))*sin(th)^2 - (3*r^4*cos(ph)*cos(th)^4 - r^2*cos(th)^2*sin(ph))*sin(th)) dr/\\dph + (-r^3*cos(th)^2*sin(th) - (3*r^6*cos(th)^2*sin(ph) + 2*r^4*cos(ph)^2*sin(ph) - 2*r^5*cos(th)*sin(ph))*sin(th)^4 + (2*r^4*cos(ph)*cos(th)*sin(ph) + r^3*cos(ph)*sin(ph))*sin(th)^3 + (3*r^5*cos(ph)*cos(th)^3 - r^3*cos(th)*sin(ph))*sin(th)^2) dth/\\dph" ] }, "execution_count": 185, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.display(Y.frame(), Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

As a 2-form, $A:=\\omega\\wedge\\mathrm{d}f$ can be applied to a pair of vectors and is antisymmetric:

" ] }, { "cell_type": "code", "execution_count": 186, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field A(u,v) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "A(u,v): U --> R\n", " (x, y, z) |--> 3*x*y*z^4*u_y(x, y, z) - 2*x^2*y^2*u_y(x, y, z) - 2*y^4*u_y(x, y, z) - 2*(x*u_x(x, y, z) + u_y(x, y, z))*y^3 + 3*(x^3*y*u_x(x, y, z) + x*y^3*u_x(x, y, z) + x*u_z(x, y, z))*z^3 - (3*y^3*u_z(x, y, z) - (2*x*u_y(x, y, z) - 3*u_z(x, y, z))*y^2 + 3*x^2*u_z(x, y, z) + (3*x^2*u_z(x, y, z) - x*u_x(x, y, z))*y)*z^2 - (2*x^3*u_x(x, y, z) + 2*x^2*u_y(x, y, z) + (2*x^2 - x)*u_z(x, y, z))*y - (2*x^2*y^2*u_y(x, y, z) + (x^2*u_x(x, y, z) - (2*x - 1)*u_z(x, y, z) - u_y(x, y, z))*y - x*u_x(x, y, z) - u_y(x, y, z) + u_z(x, y, z))*z + x*u_z(x, y, z)\n", " (r, th, ph) |--> (r^4*cos(ph)*cos(th)^2*sin(ph)*sin(th)^2 + (sin(ph)^3 - sin(ph))*r^4*cos(th)*sin(th)^3 + r^2*cos(ph)*cos(th)*sin(th) + (3*r^7*cos(ph)*cos(th)^3*sin(ph) - 2*r^4*cos(ph)*sin(ph))*sin(th)^4)*u_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) + (3*r^6*cos(ph)*cos(th)^4*sin(ph)*sin(th)^2 + r^2*cos(th)*sin(ph)*sin(th) + 2*((sin(ph)^4 - sin(ph)^2)*r^5*cos(th) - r^4*sin(ph)^2)*sin(th)^4 + 2*(r^5*cos(ph)*cos(th)^2*sin(ph)^2 - r^3*sin(ph))*sin(th)^3 + r*cos(th))*u_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) - ((3*r^5*cos(th)^2*sin(ph) - 2*(sin(ph)^3 - sin(ph))*r^3)*sin(th)^3 + (3*r^4*cos(th)^2 - 2*r^3*cos(ph)*cos(th)*sin(ph) - r^2*cos(ph)*sin(ph))*sin(th)^2 + r*cos(th) - (3*r^4*cos(ph)*cos(th)^3 - r^2*cos(th)*sin(ph) + r*cos(ph))*sin(th))*u_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 186, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.set_name('A')\n", "print(a(u,v)) ; a(u,v).display()" ] }, { "cell_type": "code", "execution_count": 187, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 187, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a(u,v) == - a(v,u)" ] }, { "cell_type": "code", "execution_count": 188, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "no symmetry; antisymmetry: (0, 1)\n" ] } ], "source": [ "a.symmetries()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The exterior derivative  of a differential form:

" ] }, { "cell_type": "code", "execution_count": 189, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2-form domega on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "domega = -2*y dx/\\dy + dx/\\dz - dy/\\dz" ] }, "execution_count": 189, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dom = om.exterior_derivative() ; print(dom) ; dom.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Instead of invoking the method exterior_derivative(), one can use the function xder, after having imported it from sage.manifolds.utilities:

" ] }, { "cell_type": "code", "execution_count": 190, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "from sage.manifolds.utilities import xder\n", "dom = xder(om)" ] }, { "cell_type": "code", "execution_count": 191, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form dA on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "dA = (-6*y*z^2 - 2*y - 1) dx/\\dy/\\dz" ] }, "execution_count": 191, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da = xder(a) ; print(da) ; da.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The exterior derivative is nilpotent:

" ] }, { "cell_type": "code", "execution_count": 192, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ddf = 0" ] }, "execution_count": 192, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ddf = xder(df) ; ddf.display()" ] }, { "cell_type": "code", "execution_count": 193, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ddomega = 0" ] }, "execution_count": 193, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ddom = xder(dom) ; ddom.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Lie derivative

\n", "

The Lie derivative of any tensor field with respect to a vector field is computed by the method lie_derivative(), with the vector field as the argument:

" ] }, { "cell_type": "code", "execution_count": 194, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "(-y*z^2 + (x*y - 1)*z + 2*x) dx + (-x*z^2 + x^2 + y^2 + (x^2 + x*y)*z) dy + (-2*x*y*z + (x^2 + 1)*y + 1) dz" ] }, "execution_count": 194, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lv_om = om.lie_derivative(v) ; print(lv_om) ; lv_om.display()" ] }, { "cell_type": "code", "execution_count": 195, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "(u_x(x, y, z)*d^2(H)/dx^2 + u_y(x, y, z)*d^2(H)/dxdy + u_z(x, y, z)*d^2(H)/dxdz + d(H)/dx*d(u_x)/dx + d(H)/dy*d(u_y)/dx + d(H)/dz*d(u_z)/dx) dx + (u_x(x, y, z)*d^2(H)/dxdy + u_y(x, y, z)*d^2(H)/dy^2 + u_z(x, y, z)*d^2(H)/dydz + d(H)/dx*d(u_x)/dy + d(H)/dy*d(u_y)/dy + d(H)/dz*d(u_z)/dy) dy + (u_x(x, y, z)*d^2(H)/dxdz + u_y(x, y, z)*d^2(H)/dydz + u_z(x, y, z)*d^2(H)/dz^2 + d(H)/dx*d(u_x)/dz + d(H)/dy*d(u_y)/dz + d(H)/dz*d(u_z)/dz) dz" ] }, "execution_count": 195, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lu_dh = dh.lie_derivative(u) ; print(lu_dh) ; lu_dh.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Let us check Cartan identity on the 1-form $\\omega$:

\n", "

$\\mathcal{L}_v \\omega = v\\cdot \\mathrm{d}\\omega + \\mathrm{d}\\langle \\omega, v\\rangle$

\n", "

and on the 2-form $A$:

\n", "

$\\mathcal{L}_v A = v\\cdot \\mathrm{d}A + \\mathrm{d}(v\\cdot A)$

" ] }, { "cell_type": "code", "execution_count": 196, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 196, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om.lie_derivative(v) == v.contract(xder(om)) + xder(om(v))" ] }, { "cell_type": "code", "execution_count": 197, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 197, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.lie_derivative(v) == v.contract(xder(a)) + xder(v.contract(a))" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Lie derivative of a vector field along another one is the commutator of the two vectors fields:

" ] }, { "cell_type": "code", "execution_count": 198, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 198, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.lie_derivative(u)(f) == u(v(f)) - v(u(f)) # see comment below" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The answer used to be `True` but became `False` after some change introduced in SageMath 8.0\n", "and which made Sage no longer capable to show that the two expressions are equal, due to some lack of simplification. This is fixed thanks to improved simplifications introduced in SageMath 8.2.beta0 (via the Trac ticket [#24232](https://trac.sagemath.org/ticket/24232)). Hence the next stable release of SageMath (8.2) will no longer have this issue." ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Tensor fields of arbitrary rank

\n", "

Up to now, we have encountered tensor fields

\n", "
    \n", "
  • of type (0,0) (i.e. scalar fields),
  • \n", "
  • of type (1,0) (i.e. vector fields),
  • \n", "
  • of type (0,1) (i.e. 1-forms),
  • \n", "
  • of type (0,2) and antisymmetric (i.e. 2-forms).
  • \n", "
\n", "

More generally, tensor fields of any type $(p,q)$ can be introduced in SageManifolds. For instance a tensor field of type (1,2) on the open subset $U$ is declared as follows:

" ] }, { "cell_type": "code", "execution_count": 199, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field T of type (1,2) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "t = U.tensor_field(1, 2, name='T') ; print(t)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

As for vectors or 1-forms, the tensor's components with respect to the domain's default frame are set by means of square brackets:

" ] }, { "cell_type": "code", "execution_count": 200, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "t[1,2,1] = 1 + x^2\n", "t[3,2,1] = x*y*z" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Unset components are zero:

" ] }, { "cell_type": "code", "execution_count": 201, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "T = (x^2 + 1) d/dx*dy*dx + x*y*z d/dz*dy*dx" ] }, "execution_count": 201, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display()" ] }, { "cell_type": "code", "execution_count": 202, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[[0, 0, 0], [x^2 + 1, 0, 0], [0, 0, 0]],\n", " [[0, 0, 0], [0, 0, 0], [0, 0, 0]],\n", " [[0, 0, 0], [x*y*z, 0, 0], [0, 0, 0]]]" ] }, "execution_count": 202, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Display of the nonzero components:

" ] }, { "cell_type": "code", "execution_count": 203, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "T^x_yx = x^2 + 1 \n", "T^z_yx = x*y*z " ] }, "execution_count": 203, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display_comp()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Double square brackets return the component (still w.r.t. the default frame) as a scalar field, while single square brackets return the expression of this scalar field in terms of the domain's default coordinates:

" ] }, { "cell_type": "code", "execution_count": 204, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "U --> R\n", "(x, y, z) |--> x^2 + 1\n", "(r, th, ph) |--> r^2*cos(ph)^2*sin(th)^2 + 1" ] }, "execution_count": 204, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(t[[1,2,1]]) ; t[[1,2,1]].display()" ] }, { "cell_type": "code", "execution_count": 205, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x^2 + 1\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "x^2 + 1" ] }, "execution_count": 205, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(t[1,2,1]) ; t[1,2,1]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A tensor field of type (1,2) maps a 3-tuple (1-form, vector field, vector field) to a scalar field:

" ] }, { "cell_type": "code", "execution_count": 206, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field T(omega,u,v) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "T(omega,u,v): U --> R\n", " (x, y, z) |--> (x^2 + 1)*y^3*u_y(x, y, z) + (x^2 + 1)*y^2*u_y(x, y, z) - (x*y^2*u_y(x, y, z) + x*y*u_y(x, y, z))*z^2 + (x^4 + x^2)*y*u_y(x, y, z) + (x^2*y^2*u_y(x, y, z) + x^2*y*u_y(x, y, z))*z + (x^4 + x^2)*u_y(x, y, z)\n", " (r, th, ph) |--> (r^5*cos(ph)^2*sin(ph)*sin(th)^5 - ((cos(ph)^4 - cos(ph)^2)*r^5*cos(th) - r^4*cos(ph)^2)*sin(th)^4 + ((cos(ph)^3 - cos(ph))*r^5*cos(th)^2 + r^4*cos(ph)^2*cos(th)*sin(ph) + r^3*sin(ph))*sin(th)^3 - (r^4*cos(ph)*cos(th)^2*sin(ph) - r^2)*sin(th)^2)*u_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 206, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(t(om, u, v)) ; t(om, u, v).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

As for vectors and differential forms, the tensor components can be taken in any frame defined on the manifold:

" ] }, { "cell_type": "code", "execution_count": 207, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r^2*cos(ph)^4*sin(ph)*sin(th)^5 + (cos(ph)^4 - cos(ph)^2)*r^3*sin(th)^6 - (cos(ph)^4 - cos(ph)^2)*r^3*sin(th)^4 + cos(ph)^2*sin(ph)*sin(th)^3" ] }, "execution_count": 207, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[Y.frame(), 1,1,1, Y]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Tensor calculus

\n", "

The tensor product $\\otimes$ is denoted by `*`:

" ] }, { "cell_type": "code", "execution_count": 208, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(0, 2)" ] }, "execution_count": 208, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.tensor_type() ; a.tensor_type()" ] }, { "cell_type": "code", "execution_count": 209, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field v*A of type (1,2) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Tensor field v*A of type (1,2) on the Open subset U of the 3-dimensional differentiable manifold M" ] }, "execution_count": 209, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = v*a ; print(b) ; b" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The tensor product preserves the (anti)symmetries: since $A$ is a 2-form, it is antisymmetric with respect to its two arguments (positions 0 and 1); as a result, b is antisymmetric with respect to its last two arguments (positions 1 and 2):

" ] }, { "cell_type": "code", "execution_count": 210, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "no symmetry; antisymmetry: (0, 1)\n" ] } ], "source": [ "a.symmetries()" ] }, { "cell_type": "code", "execution_count": 211, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "no symmetry; antisymmetry: (1, 2)\n" ] } ], "source": [ "b.symmetries()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Standard tensor arithmetics is implemented:

" ] }, { "cell_type": "code", "execution_count": 212, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (1,2) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = - t + 2*f* b ; print(s)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Tensor contractions are dealt with by the methods trace() and contract(): for instance, let us contract the tensor $T$ w.r.t. its first two arguments (positions 0 and 1), i.e. let us form the tensor $c$ of components $c_i = T^k_{\\ \\, k i}$:

" ] }, { "cell_type": "code", "execution_count": 213, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "c = t.trace(0,1)\n", "print(c)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

An alternative to the writing trace(0,1) is to use the index notation to denote the contraction: the indices are given in a string inside the [] operator, with '^' in front of the contravariant indices and '_' in front of the covariant ones:

" ] }, { "cell_type": "code", "execution_count": 214, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 214, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c1 = t['^k_ki']\n", "print(c1)\n", "c1 == c" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The contraction is performed on the repeated index (here k); the letter denoting the remaining index (here i) is arbitrary:

" ] }, { "cell_type": "code", "execution_count": 215, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 215, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^k_kj'] == c" ] }, { "cell_type": "code", "execution_count": 216, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 216, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^b_ba'] == c" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

It can even be replaced by a dot:

" ] }, { "cell_type": "code", "execution_count": 217, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 217, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^k_k.'] == c" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

LaTeX notations are allowed:

" ] }, { "cell_type": "code", "execution_count": 218, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 218, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^{k}_{ki}'] == c" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The contraction $T^i_{\\ j k} v^k$ of the tensor fields $T$ and $v$ is taken as follows (2 refers to the last index position of $T$ and 0 to the only index position of v):

" ] }, { "cell_type": "code", "execution_count": 219, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (1,1) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "tv = t.contract(2, v, 0)\n", "print(tv)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Since 2 corresponds to the last index position of $T$ and 0 to the first index position of $v$, a shortcut for the above is

" ] }, { "cell_type": "code", "execution_count": 220, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (1,1) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "tv1 = t.contract(v)\n", "print(tv1)" ] }, { "cell_type": "code", "execution_count": 221, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 221, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tv1 == tv" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Instead of contract(), the index notation, combined with the * operator, can be used to denote the contraction:

" ] }, { "cell_type": "code", "execution_count": 222, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 222, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^i_jk']*v['^k'] == tv" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The non-repeated indices can be replaced by dots:

" ] }, { "cell_type": "code", "execution_count": 223, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 223, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t['^._.k']*v['^k'] == tv" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Metric structures

\n", "

A Riemannian metric on the manifold $\\mathcal{M}$ is declared as follows:

" ] }, { "cell_type": "code", "execution_count": 224, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Riemannian metric g on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "g = M.riemannian_metric('g')\n", "print(g)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

It is a symmetric tensor field of type (0,2):

" ] }, { "cell_type": "code", "execution_count": 225, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Free module T^(0,2)(M) of type-(0,2) tensors fields on the 3-dimensional differentiable manifold M" ] }, "execution_count": 225, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.parent()" ] }, { "cell_type": "code", "execution_count": 226, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module T^(0,2)(M) of type-(0,2) tensors fields on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(g.parent())" ] }, { "cell_type": "code", "execution_count": 227, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "symmetry: (0, 1); no antisymmetry\n" ] } ], "source": [ "g.symmetries()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The metric is initialized by its components with respect to some vector frame. For instance, using the default frame of $\\mathcal{M}$:

" ] }, { "cell_type": "code", "execution_count": 228, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dx*dx + dy*dy + dz*dz" ] }, "execution_count": 228, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[1,1], g[2,2], g[3,3] = 1, 1, 1\n", "g.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The components w.r.t. another vector frame are obtained as for any tensor field:

" ] }, { "cell_type": "code", "execution_count": 229, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph" ] }, "execution_count": 229, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(Y.frame(), Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Of course, the metric acts on vector pairs:

" ] }, { "cell_type": "code", "execution_count": 230, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field g(u,v) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "g(u,v): U --> R\n", " (x, y, z) |--> x*y*z*u_z(x, y, z) + y*u_x(x, y, z) - x*u_y(x, y, z) + u_x(x, y, z)\n", " (r, th, ph) |--> r^3*cos(ph)*cos(th)*sin(ph)*sin(th)^2*u_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) - r*cos(ph)*sin(th)*u_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th)) + (r*sin(ph)*sin(th) + 1)*u_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))" ] }, "execution_count": 230, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u.display() ; v.display(); print(g(u,v)) ; g(u,v).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Levi-Civita connection associated to the metric $g$:

" ] }, { "cell_type": "code", "execution_count": 231, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Levi-Civita connection nabla_g associated with the Riemannian metric g on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Levi-Civita connection nabla_g associated with the Riemannian metric g on the 3-dimensional differentiable manifold M" ] }, "execution_count": 231, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla = g.connection() \n", "print(nabla) ; nabla" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Christoffel symbols with respect to the manifold's default coordinates:

" ] }, { "cell_type": "code", "execution_count": 232, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],\n", " [[0, 0, 0], [0, 0, 0], [0, 0, 0]],\n", " [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]" ] }, "execution_count": 232, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.coef()[:]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Christoffel symbols with respect to the coordinates $(r,\\theta,\\phi)$:

" ] }, { "cell_type": "code", "execution_count": 233, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[[0, 0, 0], [0, -r, 0], [0, 0, -r*sin(th)^2]],\n", " [[0, 1/r, 0], [1/r, 0, 0], [0, 0, -cos(th)*sin(th)]],\n", " [[0, 0, 1/r], [0, 0, cos(th)/sin(th)], [1/r, cos(th)/sin(th), 0]]]" ] }, "execution_count": 233, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.coef(Y.frame())[:, Y]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "A nice view is obtained via the method `display()` (by default, only the nonzero connection coefficients are shown):" ] }, { "cell_type": "code", "execution_count": 234, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_th,th = -r \n", "Gam^r_ph,ph = -r*sin(th)^2 \n", "Gam^th_r,th = 1/r \n", "Gam^th_th,r = 1/r \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_r,ph = 1/r \n", "Gam^ph_th,ph = cos(th)/sin(th) \n", "Gam^ph_ph,r = 1/r \n", "Gam^ph_ph,th = cos(th)/sin(th) " ] }, "execution_count": 234, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(frame=Y.frame(), chart=Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "One may also use the method `christoffel_symbols_display()` of the metric, which (by default) displays only the non-redundant Christoffel symbols:" ] }, { "cell_type": "code", "execution_count": 235, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_th,th = -r \n", "Gam^r_ph,ph = -r*sin(th)^2 \n", "Gam^th_r,th = 1/r \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_r,ph = 1/r \n", "Gam^ph_th,ph = cos(th)/sin(th) " ] }, "execution_count": 235, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The connection acting as a covariant derivative:

" ] }, { "cell_type": "code", "execution_count": 236, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field nabla_g(v) of type (1,1) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "nabla_g(v) = d/dx*dy - d/dy*dx + y*z d/dz*dx + x*z d/dz*dy + x*y d/dz*dz" ] }, "execution_count": 236, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nab_v = nabla(v)\n", "print(nab_v) ; nab_v.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Being a Levi-Civita connection, $\\nabla_g$ is torsion.free:

" ] }, { "cell_type": "code", "execution_count": 237, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (1,2) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "0" ] }, "execution_count": 237, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(nabla.torsion()) ; nabla.torsion().display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In the present case, it is also flat:

" ] }, { "cell_type": "code", "execution_count": 238, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field Riem(g) of type (1,3) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g) = 0" ] }, "execution_count": 238, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(nabla.riemann()) ; nabla.riemann().display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Let us consider a non-flat metric, by changing $g_{rr}$ to $1/(1+r^2)$:

" ] }, { "cell_type": "code", "execution_count": 239, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 1/(r^2 + 1) dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph" ] }, "execution_count": 239, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[Y.frame(), 1,1, Y] = 1/(1+r^2)\n", "g.display(Y.frame(), Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

For convenience, we change the default chart on the domain $U$ to Y=$(U,(r,\\theta,\\phi))$:

" ] }, { "cell_type": "code", "execution_count": 240, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "U.set_default_chart(Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In this way, we do not have to specify Y when asking for coordinate expressions in terms of $(r,\\theta,\\phi)$:

" ] }, { "cell_type": "code", "execution_count": 241, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 1/(r^2 + 1) dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph" ] }, "execution_count": 241, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(Y.frame())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We recognize the metric of the hyperbolic space $\\mathbb{H}^3$. Its expression in terms of the chart $(U,(x,y,z))$ is

" ] }, { "cell_type": "code", "execution_count": 242, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = (y^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) dx*dx - x*y/(x^2 + y^2 + z^2 + 1) dx*dy - x*z/(x^2 + y^2 + z^2 + 1) dx*dz - x*y/(x^2 + y^2 + z^2 + 1) dy*dx + (x^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) dy*dy - y*z/(x^2 + y^2 + z^2 + 1) dy*dz - x*z/(x^2 + y^2 + z^2 + 1) dz*dx - y*z/(x^2 + y^2 + z^2 + 1) dz*dy + (x^2 + y^2 + 1)/(x^2 + y^2 + z^2 + 1) dz*dz" ] }, "execution_count": 242, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(X_U.frame(), X_U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

A matrix view of the components may be more appropriate:

" ] }, { "cell_type": "code", "execution_count": 243, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[(y^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) -x*y/(x^2 + y^2 + z^2 + 1) -x*z/(x^2 + y^2 + z^2 + 1)]\n", "[ -x*y/(x^2 + y^2 + z^2 + 1) (x^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) -y*z/(x^2 + y^2 + z^2 + 1)]\n", "[ -x*z/(x^2 + y^2 + z^2 + 1) -y*z/(x^2 + y^2 + z^2 + 1) (x^2 + y^2 + 1)/(x^2 + y^2 + z^2 + 1)]" ] }, "execution_count": 243, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[X_U.frame(), :, X_U]" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We extend these components, a priori defined only on $U$, to the whole manifold $\\mathcal{M}$, by demanding the same coordinate expressions in the frame associated to the chart X=$(\\mathcal{M},(x,y,z))$:

" ] }, { "cell_type": "code", "execution_count": 244, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = (y^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) dx*dx - x*y/(x^2 + y^2 + z^2 + 1) dx*dy - x*z/(x^2 + y^2 + z^2 + 1) dx*dz - x*y/(x^2 + y^2 + z^2 + 1) dy*dx + (x^2 + z^2 + 1)/(x^2 + y^2 + z^2 + 1) dy*dy - y*z/(x^2 + y^2 + z^2 + 1) dy*dz - x*z/(x^2 + y^2 + z^2 + 1) dz*dx - y*z/(x^2 + y^2 + z^2 + 1) dz*dy + (x^2 + y^2 + 1)/(x^2 + y^2 + z^2 + 1) dz*dz" ] }, "execution_count": 244, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.add_comp_by_continuation(X.frame(), U, X)\n", "g.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Levi-Civita connection is automatically recomputed, after the change in $g$:

" ] }, { "cell_type": "code", "execution_count": 245, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "nabla = g.connection()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In particular, the Christoffel symbols are different:

" ] }, { "cell_type": "code", "execution_count": 246, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^x_xx = -(x*y^2 + x*z^2 + x)/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_xy = x^2*y/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_xz = x^2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_yy = -(x^3 + x*z^2 + x)/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_yz = x*y*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^x_zz = -(x^3 + x*y^2 + x)/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_xx = -(y^3 + y*z^2 + y)/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_xy = x*y^2/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_xz = x*y*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_yy = -(y*z^2 + (x^2 + 1)*y)/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_yz = y^2*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^y_zz = -(y^3 + (x^2 + 1)*y)/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_xx = -(z^3 + (y^2 + 1)*z)/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_xy = x*y*z/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_xz = x*z^2/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_yy = -(z^3 + (x^2 + 1)*z)/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_yz = y*z^2/(x^2 + y^2 + z^2 + 1) \n", "Gam^z_zz = -(x^2 + y^2 + 1)*z/(x^2 + y^2 + z^2 + 1) " ] }, "execution_count": 246, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 247, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_r,r = -r/(r^2 + 1) \n", "Gam^r_th,th = -r^3 - r \n", "Gam^r_ph,ph = -(r^3 + r)*sin(th)^2 \n", "Gam^th_r,th = 1/r \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_r,ph = 1/r \n", "Gam^ph_th,ph = cos(th)/sin(th) " ] }, "execution_count": 247, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(frame=Y.frame(), chart=Y, only_nonredundant=True)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Riemann tensor is now

" ] }, { "cell_type": "code", "execution_count": 248, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field Riem(g) of type (1,3) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g) = -r^2 d/dr*dth*dr*dth + r^2 d/dr*dth*dth*dr - r^2*sin(th)^2 d/dr*dph*dr*dph + r^2*sin(th)^2 d/dr*dph*dph*dr + 1/(r^2 + 1) d/dth*dr*dr*dth - 1/(r^2 + 1) d/dth*dr*dth*dr - r^2*sin(th)^2 d/dth*dph*dth*dph + r^2*sin(th)^2 d/dth*dph*dph*dth + 1/(r^2 + 1) d/dph*dr*dr*dph - 1/(r^2 + 1) d/dph*dr*dph*dr + r^2 d/dph*dth*dth*dph - r^2 d/dph*dth*dph*dth" ] }, "execution_count": 248, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Riem = nabla.riemann()\n", "print(Riem) ; Riem.display(Y.frame())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Note that it can be accessed directely via the metric, without any explicit mention of the connection:

" ] }, { "cell_type": "code", "execution_count": 249, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 249, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.riemann() is nabla.riemann()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Ricci tensor is

" ] }, { "cell_type": "code", "execution_count": 250, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Field of symmetric bilinear forms Ric(g) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Ric(g) = -2/(r^2 + 1) dr*dr - 2*r^2 dth*dth - 2*r^2*sin(th)^2 dph*dph" ] }, "execution_count": 250, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Ric = g.ricci()\n", "print(Ric) ; Ric.display(Y.frame())" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Weyl tensor is:

" ] }, { "cell_type": "code", "execution_count": 251, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field C(g) of type (1,3) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "C(g) = 0" ] }, "execution_count": 251, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = g.weyl()\n", "print(C) ; C.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Weyl tensor vanishes identically because the dimension of $\\mathcal{M}$ is 3.

\n", "

Finally, the Ricci scalar is

" ] }, { "cell_type": "code", "execution_count": 252, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field r(g) on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "r(g): M --> R\n", " (x, y, z) |--> -6\n", "on U: (r, th, ph) |--> -6" ] }, "execution_count": 252, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R = g.ricci_scalar()\n", "print(R) ; R.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We recover the fact that $\\mathbb{H}^3$ is a Riemannian manifold of constant negative curvature.

\n", "\n", "

Tensor transformations induced by a metric

\n", "

The most important tensor transformation induced by the metric $g$ is the so-called musical isomorphism, or index raising and index lowering:

" ] }, { "cell_type": "code", "execution_count": 253, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field T of type (1,2) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(t)" ] }, { "cell_type": "code", "execution_count": 254, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "T = (r^2*cos(ph)^2*sin(th)^2 + 1) d/dx*dy*dx + r^3*cos(ph)*cos(th)*sin(ph)*sin(th)^2 d/dz*dy*dx" ] }, "execution_count": 254, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display()" ] }, { "cell_type": "code", "execution_count": 255, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "T = (x^2 + 1) d/dx*dy*dx + x*y*z d/dz*dy*dx" ] }, "execution_count": 255, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display(X_U.frame(), X_U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Raising the last index of $T$ with $g$:

" ] }, { "cell_type": "code", "execution_count": 256, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (2,1) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = t.up(g, 2)\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Raising all the covariant indices of $T$ (i.e. those at the positions 1 and 2):

" ] }, { "cell_type": "code", "execution_count": 257, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (3,0) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = t.up(g)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 258, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field of type (0,3) on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "s = t.down(g)\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Hodge duality

\n", "

The volume 3-form (Levi-Civita tensor) associated with the metric $g$ is

" ] }, { "cell_type": "code", "execution_count": 259, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form eps_g on the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = 1/sqrt(x^2 + y^2 + z^2 + 1) dx/\\dy/\\dz" ] }, "execution_count": 259, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon = g.volume_form()\n", "print(epsilon) ; epsilon.display()" ] }, { "cell_type": "code", "execution_count": 260, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = r^2*sin(th)/sqrt(r^2 + 1) dr/\\dth/\\dph" ] }, "execution_count": 260, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon.display(Y.frame())" ] }, { "cell_type": "code", "execution_count": 261, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field f on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> z^3 + y^2 + x\n", " (r, th, ph) |--> r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th)" ] }, "execution_count": 261, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(f) ; f.display()" ] }, { "cell_type": "code", "execution_count": 262, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form *f on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "*f = (r^3*cos(th)^3 + r^2*sin(ph)^2*sin(th)^2 + r*cos(ph)*sin(th))/sqrt(r^2 + 1) dx/\\dy/\\dz" ] }, "execution_count": 262, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sf = f.hodge_dual(g)\n", "print(sf) ; sf.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

We check the classical formula $\\star f = f\\, \\epsilon_g$, or, more precisely, $\\star f = f\\, \\epsilon_g|_U$ (for $f$ is defined on $U$ only):

" ] }, { "cell_type": "code", "execution_count": 263, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 263, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sf == f * epsilon.restrict(U)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Hodge dual of a 1-form is a 2-form:

" ] }, { "cell_type": "code", "execution_count": 264, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form omega on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "omega = r^2*sin(th)^2 dx + r*cos(th) dy + (r*cos(ph)*sin(th) - r*cos(th)) dz" ] }, "execution_count": 264, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(om) ; om.display()" ] }, { "cell_type": "code", "execution_count": 265, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2-form *omega on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "*omega = (r^4*cos(ph)*cos(th)*sin(th)^3 - r^3*cos(th)^3 - r*cos(th) + (r^3*(cos(ph) + sin(ph))*cos(th)^2 + r*cos(ph))*sin(th))/sqrt(r^2 + 1) dx/\\dy - (r^4*cos(ph)*sin(ph)*sin(th)^4 - r^3*cos(th)^2*sin(ph)*sin(th) + (cos(ph)*sin(ph) + sin(ph)^2)*r^3*cos(th)*sin(th)^2 + r*cos(th))/sqrt(r^2 + 1) dx/\\dz + (r^4*cos(ph)^2*sin(th)^4 - r^3*cos(ph)*cos(th)^2*sin(th) + ((cos(ph)^2 + cos(ph)*sin(ph))*r^3*cos(th) + r^2)*sin(th)^2)/sqrt(r^2 + 1) dy/\\dz" ] }, "execution_count": 265, "metadata": {}, "output_type": "execute_result" } ], "source": [ "som = om.hodge_dual(g)\n", "print(som) ; som.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The Hodge dual of a 2-form is a 1-form:

" ] }, { "cell_type": "code", "execution_count": 266, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2-form A on the Open subset U of the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "print(a)" ] }, { "cell_type": "code", "execution_count": 267, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form *A on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "*A = (3*r^5*cos(th)^5 + 3*r^3*cos(th)^3 + (3*r^6*cos(ph)*cos(th)^2*sin(ph) - 2*r^5*cos(ph)*cos(th)*sin(ph) - 2*r^4*cos(ph)*sin(ph)^3)*sin(th)^4 + (2*r^4*cos(th)*sin(ph)^3 + (sin(ph)^3 - sin(ph))*r^3)*sin(th)^3 + (3*r^5*cos(th)^3*sin(ph)^2 - 2*r^4*cos(ph)*cos(th)^2*sin(ph) + r^3*cos(ph)*cos(th)*sin(ph) - 2*r^2*cos(ph)*sin(ph))*sin(th)^2 + (2*r^4*cos(th)^3*sin(ph) + r^3*cos(ph)*cos(th)^2 + 2*r^2*cos(th)*sin(ph))*sin(th))/sqrt(r^2 + 1) dx - (r^3*cos(th)^3 - (3*(sin(ph)^2 - 1)*r^6*cos(th)^2 - 2*r^5*cos(th)*sin(ph)^2 - 2*(sin(ph)^4 - sin(ph)^2)*r^4)*sin(th)^4 + (2*r^4*cos(ph)*cos(th)*sin(ph)^2 + (cos(ph)*sin(ph)^2 - cos(ph))*r^3)*sin(th)^3 + (3*r^6*cos(th)^4 + 3*r^5*cos(ph)*cos(th)^3*sin(ph) + 3*r^4*cos(th)^2 - (sin(ph)^2 - 1)*r^3*cos(th))*sin(th)^2 + r*cos(th) - (r^3*(cos(ph) + sin(ph))*cos(th)^2 + r*cos(ph))*sin(th))/sqrt(r^2 + 1) dy + (2*r^5*sin(ph)*sin(th)^5 + (3*r^6*cos(th)^3*sin(ph) + 2*r^4*cos(ph)^2*cos(th)*sin(ph) + 2*r^3*sin(ph))*sin(th)^3 - (2*r^4*cos(ph)*cos(th)^2*sin(ph) + (cos(ph)*sin(ph) + 1)*r^3*cos(th))*sin(th)^2 - r*cos(th) - (3*r^5*cos(ph)*cos(th)^4 - r^3*cos(th)^2*sin(ph))*sin(th))/sqrt(r^2 + 1) dz" ] }, "execution_count": 267, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sa = a.hodge_dual(g)\n", "print(sa) ; sa.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Finally, the Hodge dual of a 3-form is a 0-form:

" ] }, { "cell_type": "code", "execution_count": 268, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form dA on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "dA = (-2*(3*r^3*cos(th)^2*sin(ph) + r*sin(ph))*sin(th) - 1) dx/\\dy/\\dz" ] }, "execution_count": 268, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(da) ; da.display()" ] }, { "cell_type": "code", "execution_count": 269, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field *dA on the Open subset U of the 3-dimensional differentiable manifold M\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "*dA: U --> R\n", " (x, y, z) |--> -(6*y*z^2 + 2*y + 1)*sqrt(x^2 + y^2 + z^2 + 1)\n", " (r, th, ph) |--> -sqrt(r^2 + 1)*(2*(3*r^3*cos(th)^2*sin(ph) + r*sin(ph))*sin(th) + 1)" ] }, "execution_count": 269, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sda = da.hodge_dual(g)\n", "print(sda) ; sda.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

In dimension 3 and for a Riemannian metric, the Hodge star is idempotent:

" ] }, { "cell_type": "code", "execution_count": 270, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 270, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sf.hodge_dual(g) == f" ] }, { "cell_type": "code", "execution_count": 271, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 271, "metadata": {}, "output_type": "execute_result" } ], "source": [ "som.hodge_dual(g) == om" ] }, { "cell_type": "code", "execution_count": 272, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 272, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sa.hodge_dual(g) == a" ] }, { "cell_type": "code", "execution_count": 273, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 273, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sda.hodge_dual(g) == da" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Getting help

\n", "

To get the list of functions (methods) that can be called on a object, type the name of the object, followed by a dot and the TAB key, e.g.

\n", "

sa.

\n", "

To get information on an object or a method, use the question mark:

" ] }, { "cell_type": "code", "execution_count": 274, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "nabla?" ] }, { "cell_type": "code", "execution_count": 275, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "g.ricci_scalar?" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Using a double question mark leads directly to the Python source code (SageMath is open source, isn't it?)

" ] }, { "cell_type": "code", "execution_count": 276, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "g.ricci_scalar??" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Going further

\n", "

Have a look at the examples on SageManifolds page, especially the 2-dimensional sphere example for usage on a non-parallelizable manifold (each scalar field has to be defined in at least two coordinate charts, the module $\\mathfrak{X}(\\mathcal{M})$ is no longer free and each tensor field has to be defined in at least two vector frames).

" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 8.1", "language": "", "name": "sagemath" }, "language": "python", "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.14" } }, "nbformat": 4, "nbformat_minor": 0 }