{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "# SageMath manifold tutorial (SymPy version)\n", "\n", "This worksheet provides a short introduction to differentiable manifolds in SageMath, with [SymPy](http://www.sympy.org) as symbolic engine, instead of SageMath's default one (Pynac+Maxima). The tools described below have been implemented through the\n", "[SageManifolds project](http://sagemanifolds.obspm.fr) (version 1.1, included in SageMath 8.1).\n", "\n", "Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Worksheets/v1.1/SM_tutorial_sympy.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`\n" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The following assumes that you are using version 8.1 (or higher) of SageMath, since lower versions do not include the SymPy symbolic engine for computations on manifolds:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/plain": [ "'SageMath version 8.1.beta8, Release Date: 2017-10-16'" ] }, "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\n", "from sympy import init_printing\n", "init_printing()" ] }, { "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\n", "[list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/manifold.html#sage.manifolds.manifold.Manifold) 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": [ "We ask for all symbolic computations to be performed with [SymPy](http://www.sympy.org), instead of SageMath's default symbolic engine (Pynac+Maxima, implemented via SageMath's Symbolic Ring):" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "M.set_calculus_method('sympy')" ] }, { "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": 6, "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": 7, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 7, "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": 8, "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": 8, "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": 9, "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": 10, "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": 11, "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": 12, "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": 13, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 13, "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": 14, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[1]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "y" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X[2]" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z" ] }, "execution_count": 16, "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": 17, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z)" ] }, "execution_count": 17, "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": 18, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 18, "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": 19, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 19, "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": 20, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x + y**2 + z**3" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = X.function(x+y^2+z^3) ; f" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> x + y**2 + z**3" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAABQAAAAOBAMAAADd6iHDAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIom7VJlmdt1E7xDN\nMqsI8sYEAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAj0lEQVQIHWNgEFIyYWAQDbZlYGAMYPBP4H7A\noD+Bgf0LA38D3wYGrgUMnCsZ9h/gamDg+8sABP4JPL8hTO4mEJ/jN1CfRjSIOV8BRGpNABJ9IBYD\n12oGBtYAoLwAA/MXBoZSoBD/bxCTJYBBkIHLgIHjI8NVBoZCBrYEBv8CxialuAYGhqmhlgw8////\nbwAA/SMgBrNAMgkAAAAASUVORK5CYII=\n", "text/latex": [ "$$32$$" ], "text/plain": [ "32" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(1,2,3)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "They belong to SageMath class `ChartFunction`:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 23, "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": 24, "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": 25, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)^2 + sin(x)^2" ] }, "execution_count": 25, "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 `ChartFunction` is automatically simplified:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "1" ] }, "execution_count": 26, "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": 27, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> 1" ] }, "execution_count": 27, "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": 28, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)^2" ] }, "execution_count": 28, "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": 29, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "cos(x)**2" ] }, "execution_count": 29, "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": 30, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> cos(x)**2" ] }, "execution_count": 30, "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": 31, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEMAAAAZBAMAAACY8Y7RAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEJmJVCLvMs1Edmar\n3bti/yyrAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABfElEQVQoFX2SP0gDMRjF39le7/rn2sOCk2BB\nXZxqxcEqWEEnB28Xh4qbS6eCgnigsx4oCC696iK6iOAk4uTiVBDBzerY6ZSK6FKTI0l7FzFL3vfe\nL8kXEiA4Cm9m0JCqiJWyJTNoGJb2GXSkynDUb8kMG9H3sCPVhutbyyy4lgCg4Htqk0UpS2KSOd/S\neaLYEnKAI+pdiaAoFBPa7vwrlU8iGBCKiVin4xGpNkSgO0D/xAiU4qmDzcUzHiRygHJ+f0xOieSg\nrqFqbVloKU0YHElfAlncus9A0oZuY6nyCGxvlJHgiFECxjFrLgDRBobInlobyORfWhZHYqQBE3u0\n1DzUXEKSd8k0s/sfvQjwwxCxy6iJO7LYH/QgaF9Uxxu0F5RWgdqhixTp0h+03bmEh7rfrrqOiFWt\nYCdaRtpiCLlpvJ32VEL25YHBsUmowzNOfPpiihF0d+WhfnJDar3CzdDcfYCVUCLKf56RM6KrPz4D\nY8SXEixf3J17PuYv69hQl+GMuDIAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\cos^{2}{\\left (x \\right )}$$" ], "text/plain": [ "cos(x)**2" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1.expr()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "In the present case, it is a SymPy object:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 32, "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": 33, "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": 34, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (x, y, z))" ] }, "execution_count": 34, "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": 35, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (r, theta, phi))" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y. = U.chart(r'r:(0,+oo) theta:(0,pi):\\theta phi:(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": 36, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(theta, phi)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "th, ph" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(theta, phi)" ] }, "execution_count": 37, "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": 38, "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", " theta is real,\n", " theta > 0,\n", " theta < pi,\n", " phi is real,\n", " phi > 0,\n", " phi < 2*pi]" ] }, "execution_count": 38, "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": 39, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simplify(abs(r))" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "abs(x)" ] }, "execution_count": 40, "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": 41, "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": 42, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Change of coordinates from Chart (U, (r, theta, phi)) to Chart (U, (x, y, z))" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transit_Y_to_X" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = r*cos(phi)*sin(theta)\n", "y = r*sin(phi)*sin(theta)\n", "z = r*cos(theta)" ] }, "execution_count": 43, "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": 44, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r = sqrt(x^2 + y^2 + z^2)\n", "theta = arctan2(sqrt(x^2 + y^2), z)\n", "phi = arctan2(y, x)" ] }, "execution_count": 44, "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": 45, "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, theta, phi))]" ] }, "execution_count": 45, "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": 46, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 46, "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": 47, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (U, (x, y, z)), Chart (U, (r, theta, phi))]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.atlas()" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (U, (x, y, z))" ] }, "execution_count": 48, "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": 49, "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": 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)\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": 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 = 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": 52, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "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": 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), 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": 54, "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": 54, "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": 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 M" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

It is also in $U$:

" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 56, "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": 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(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": 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": [ "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": 59, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 59, "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": 60, "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": 61, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 61, "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": 62, "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, theta, phi))\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": 63, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$$\\left ( \\sqrt{6}, \\quad - \\operatorname{atan}{\\left (\\sqrt{5} \\right )} + \\pi, \\quad \\operatorname{atan}{\\left (2 \\right )}\\right )$$" ], "text/plain": [ "(sqrt(6), -atan(sqrt(5)) + pi, atan(2))" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord(Y)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$$\\left ( \\sqrt{6}, \\quad - \\operatorname{atan}{\\left (\\sqrt{5} \\right )} + \\pi, \\quad \\operatorname{atan}{\\left (2 \\right )}\\right )$$" ], "text/plain": [ "(sqrt(6), -atan(sqrt(5)) + pi, atan(2))" ] }, "execution_count": 64, "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": 65, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "False" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q == p" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 66, "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": 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": [ "p.parent()" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q.parent()" ] }, { "cell_type": "code", "execution_count": 69, "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": 69, "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": 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_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": 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, 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": 72, "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": 73, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAPBAMAAAAv0UM9AAAALVBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAMpndu3bvImbNiRBUq9OB\nhjcAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABESURBVAgdY2BgYBACYgYGExDBmgIiK6aAyAUgkqMA\nRG5lAJELQCSPAIjcxQAiz969++wqUIIBrIvhCYi55N0NEMXAAABbkhBrtxdTYQAAAABJRU5ErkJg\ngg==\n", "text/latex": [ "$$4$$" ], "text/plain": [ "4" ] }, "execution_count": 73, "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": 74, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> x + y**2 + z**3" ] }, "execution_count": 74, "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": 75, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> x + y**2 + z**3\n", " (r, theta, phi) |--> r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 75, "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": 76, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (r, theta, phi) |--> r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 76, "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 `ChartFunction` described above), which is accessible via the method `coord_function()`:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x + y**2 + z**3" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(X_U)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z) |--> x + y**2 + z**3" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(X_U).display()" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(Y)" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(r, theta, phi) |--> r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.coord_function(Y).display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "The \"raw\" symbolic expression (here a SymPy object) is returned by the method `expr()`:" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGYAAAAYBAMAAAD62ZXgAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHarIkSJZt3NVLsy\nme8Q6PJIAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABl0lEQVQ4EX2QP0zCQBTGXwstWKg24EwaTNwI\nrm5djImDMrpB0MWtcXBzIbIaoou3Gd10kOjoYEeNAxgHQzARBwcm/yTGxJgg7etrr9DS4e57v+++\n964HEPXJ3Ycwq/qohWFkm7AYYqqm2gzBLtqDljHuqpXExzglUoe1Eml+nzQH4CL05jmL7zCqa6PA\nrsWDMEpMbpMK7BPvths46hXxX0/a4oSvpIpkObWiczhnxX+4ciRzd3aObxDIJA3xNTrzPhigGcik\nqxsGQGZuaV5H172bUNBh1X9nL7P+ljadg0IlUUs2AhlZ6UERib1SRrgsdJHKmvypGKjdOStqA66R\n2KuXgXgTqQBTqLYY22fscEi1aR2+0AWZsaM+YwtOea+5FGZ0UvTWZS39R8yfAxImbadlkU+ZDog9\nYlzmlJiiFUF0Z1LmClJ+S+9/lDbEMFU+voFltwFlulA2qac/53Znu440m8880QHKZKsvxnimneiX\nfEqKMgAdQsOd3ppDnJxFHWsI3xwVDK6IkkkzpUd5UVzKP0dZDv8HqEZQsCeTCdYAAAAASUVORK5C\nYII=\n", "text/latex": [ "$$x + y^{2} + z^{3}$$" ], "text/plain": [ "x + y**2 + z**3" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(X_U)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$$r \\left(r^{2} \\cos^{3}{\\left (\\theta \\right )} + r \\sin^{2}{\\left (\\phi \\right )} \\sin^{2}{\\left (\\theta \\right )} + \\sin{\\left (\\theta \\right )} \\cos{\\left (\\phi \\right )}\\right)$$" ], "text/plain": [ "r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(Y)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 83, "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": 84, "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": 85, "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, theta, phi) |--> H(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display()" ] }, { "cell_type": "code", "execution_count": 86, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "h: U --> R\n", " (r, theta, phi) |--> H(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display(Y)" ] }, { "cell_type": "code", "execution_count": 87, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGMAAAAUBAMAAABrMp7fAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAZqvNmRDdRHYyiVS7\nIu/EmopNAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkElEQVQoFY1Tu04CURA9CCzLY9UYWxMl0VKJ\nsbFaYviADfZKo52RP5A/kE+gsDA2Wtia+AEmYMMfaGmIKL5I8NzHsBeCiZPMzjlnZvbO3XsXcOzR\nwX/AFa0vjXZAjxDcO3VB5aHpUIFzHY36fA7oSdL8k01WkfuwUILKpUuKZT6B7BvBMlDde7cF68CL\nhTaY3KViuS/A/yE4ofvS8gxsTU2mcweqJdkDCqwMam5LGM1uSdZZtXBPZ7lfJhmvQnwa8eGYzuXK\nVM62i8U2QWGRxGnJfJO7pnOJEqXrJnB+A3h0t8Vbdesll68RhfR2BMzXRWakVUzA/rGyXfu6bI/y\nkK6OZqpFb812maAHUy36WNTYU4PdIuhMdJihMzV7LOqgJ7efLcOf1aK273EldSzQn08tfkgV3auL\nDYNIjOnBUi1Uw9dGqj1scMIakNrsr8E7Ykk4Gg0MMvU2h2RTuIrqwmi7E4AYidQVoCOvpbGWAMRI\nJH0thaDQMTDdEClGY0XtMzb5xRJjKUYiyWuF/+9H/gWzjWck2ymR7gAAAABJRU5ErkJggg==\n", "text/latex": [ "$$H{\\left (1,2,-1 \\right )}$$" ], "text/plain": [ "H(1, 2, -1)" ] }, "execution_count": 87, "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": 88, "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": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CU = f.parent() ; CU" ] }, { "cell_type": "code", "execution_count": 89, "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": 90, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Category of commutative algebras over Symbolic Ring" ] }, "execution_count": 90, "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": 91, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Symbolic Ring" ] }, "execution_count": 91, "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": 92, "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": 93, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U --> R\n", "(x, y, z) |--> x + y**2 + z**3 + 2*H(x, y, z)\n", "(r, theta, phi) |--> r**3*cos(theta)**3 + r**2*sin(phi)**2*sin(theta)**2 + r*sin(theta)*cos(phi) + 2*H(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))" ] }, "execution_count": 93, "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": 94, "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": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp = M.tangent_space(p) ; Tp" ] }, { "cell_type": "code", "execution_count": 95, "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": 96, "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": 97, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3" ] }, "execution_count": 97, "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": 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 p on the 3-dimensional differentiable manifold M,\n", " Basis (d/dr,d/dtheta,d/dphi) on the Tangent space at Point p on the 3-dimensional differentiable manifold M]" ] }, "execution_count": 98, "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": 99, "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": 99, "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": 100, "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": 101, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx + 2 d/dy + 3 d/dz" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "code", "execution_count": 102, "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": 103, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx + 2 d/dy + 3 d/dz" ] }, "execution_count": 103, "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": 104, "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": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.parent()" ] }, { "cell_type": "code", "execution_count": 105, "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": 105, "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": 106, "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": 107, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dx,d/dy,d/dz))" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X.frame()" ] }, { "cell_type": "code", "execution_count": 108, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3-dimensional differentiable manifold M" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X.frame().domain() # this frame is defined on the whole manifold" ] }, { "cell_type": "code", "execution_count": 109, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (U, (d/dr,d/dtheta,d/dphi))" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y.frame()" ] }, { "cell_type": "code", "execution_count": 110, "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": 110, "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": 111, "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/dtheta,d/dphi))]" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.frames()" ] }, { "cell_type": "code", "execution_count": 112, "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/dtheta,d/dphi))]" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.frames()" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dx,d/dy,d/dz))" ] }, "execution_count": 113, "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": 114, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_frame() is M.default_chart().frame()" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 115, "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": 116, "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": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e = U.default_frame() ; e2 = e[2] ; e2" ] }, { "cell_type": "code", "execution_count": 117, "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": 118, "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": 119, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dy + 2*x d/dz" ] }, "execution_count": 119, "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": 120, "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": 120, "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": 121, "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": 121, "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": 122, "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": 123, "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": 124, "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": 124, "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": 125, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: U --> R\n", " (x, y, z) |--> x + y**2 + z**3\n", " (r, theta, phi) |--> r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "code", "execution_count": 126, "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": 127, "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*y + y + 1\n", " (r, theta, phi) |--> 3*r**5*sin(phi)*sin(theta)**4*cos(phi)*cos(theta)**3 + 3*r**5*sin(phi)*sin(theta)**2*cos(phi)*cos(theta)**5 - 2*r**2*sin(phi)*sin(theta)**2*cos(phi) + r*sin(phi)*sin(theta) + 1" ] }, "execution_count": 127, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 128, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dz = d/dz" ] }, "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[3].display()" ] }, { "cell_type": "code", "execution_count": 129, "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, theta, phi) |--> 3*r**2*cos(theta)**2" ] }, "execution_count": 129, "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": 130, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "w = 3 d/dy" ] }, "execution_count": 130, "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": 131, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = x*(y*z**2 + 1)/sqrt(x**2 + y**2 + z**2) d/dr + x*z*(-x**2*y - y**3 + 1)/(sqrt(x**2 + y**2)*(x**2 + y**2 + z**2)) d/dtheta - (x**2 + y**2 + y)/(x**2 + y**2) d/dphi" ] }, "execution_count": 131, "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": 132, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (r**3*sin(phi)*sin(theta)*cos(theta)**2 + 1)*sin(theta)*cos(phi) d/dr + (-r**3*sin(phi)*sin(theta)**3 + 1)*cos(phi)*cos(theta)/r d/dtheta - (r + sin(phi)/sin(theta))/r d/dphi" ] }, "execution_count": 132, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(Y.frame(), Y)" ] }, { "cell_type": "code", "execution_count": 133, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dx = sin(theta)*cos(phi) d/dr + (-sin(phi - 2*theta) + sin(phi + 2*theta))/(4*r*sqrt(sin(theta)**2)) d/dtheta - sin(phi)/(r*sin(theta)) d/dphi" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "d/dy = sin(phi)*sin(theta) d/dr + (cos(phi - 2*theta) - cos(phi + 2*theta))/(4*r*sqrt(sin(theta)**2)) d/dtheta + cos(phi)/(r*sin(theta)) d/dphi" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "d/dz = cos(theta) d/dr - sin(theta)/r d/dtheta" ] }, "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": 134, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[y + 1, -x, x*y*z]" ] }, "execution_count": 134, "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": 135, "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": 135, "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": 136, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[x*(y*z**2 + 1)/sqrt(x**2 + y**2 + z**2),\n", " x*z*(-x**2*y - y**3 + 1)/(sqrt(x**2 + y**2)*(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.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": 137, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[x*(y*z**2 + 1)/sqrt(x**2 + y**2 + z**2),\n", " x*z*(-x**2*y - y**3 + 1)/(sqrt(x**2 + y**2)*(x**2 + y**2 + z**2)),\n", " -(x**2 + y**2 + y)/(x**2 + y**2)]" ] }, "execution_count": 137, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[Y.frame(), :]" ] }, { "cell_type": "code", "execution_count": 138, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v^r = x*(y*z**2 + 1)/sqrt(x**2 + y**2 + z**2) \n", "v^theta = x*z*(-x**2*y - y**3 + 1)/(sqrt(x**2 + y**2)*(x**2 + y**2 + z**2)) \n", "v^phi = -(x**2 + y**2 + y)/(x**2 + y**2) " ] }, "execution_count": 138, "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": 139, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[(r**3*sin(phi)*sin(theta)*cos(theta)**2 + 1)*sin(theta)*cos(phi),\n", " (-r**3*sin(phi)*sin(theta)**3 + 1)*cos(phi)*cos(theta)/r,\n", " -(r + sin(phi)/sin(theta))/r]" ] }, "execution_count": 139, "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": 140, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v^r = (r**3*sin(phi)*sin(theta)*cos(theta)**2 + 1)*sin(theta)*cos(phi) \n", "v^theta = (-r**3*sin(phi)*sin(theta)**3 + 1)*cos(phi)*cos(theta)/r \n", "v^phi = -(r + sin(phi)/sin(theta))/r " ] }, "execution_count": 140, "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": 141, "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": 142, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U --> R\n", "(x, y, z) |--> y + 1\n", "(r, theta, phi) |--> r*sin(phi)*sin(theta) + 1" ] }, "execution_count": 142, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[[1]].display()" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAC4AAAASBAMAAADWL/HSAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHaZIu+JVM27RDKr\nZt2dj8xZAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAl0lEQVQYGWNgIAGwB6IoZleAcGVsPmIVZ2DC\nI86orMDgKgDWBzMHrJ6NPYBBH2Icirg7cwPDTCziAqwKDJ+A4mwdHX0RHR0HQErA9q4X4P4N4jAw\noJjDYMHAFIBNfA4D5wFs4pYM6y9gE5dJsndAFWc++uMsSMQCIoywF8TnaWD8BRVndIAyQBTfBU4F\nJC6cyaVkDWcjMQCNESDTdOqp9QAAAABJRU5ErkJggg==\n", "text/latex": [ "$$y + 1$$" ], "text/plain": [ "y + 1" ] }, "execution_count": 143, "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": 144, "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": 144, "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": 145, "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": 145, "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": 146, "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": 147, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 3 d/dx - d/dy - 2 d/dz" ] }, "execution_count": 147, "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": 148, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 148, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coord(X_U)" ] }, { "cell_type": "code", "execution_count": 149, "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": 149, "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": 150, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 3 d/dx - d/dy - 2 d/dz" ] }, "execution_count": 150, "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": 151, "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": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.parent()" ] }, { "cell_type": "code", "execution_count": 152, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 152, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp in M.tangent_space(p)" ] }, { "cell_type": "code", "execution_count": 153, "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": 154, "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": 154, "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": 155, "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": 156, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "df = dx + 2*y dy + 3*z**2 dz" ] }, "execution_count": 156, "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": 157, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate coframe (M, (dx,dy,dz))" ] }, "execution_count": 157, "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": 158, "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,dtheta,dphi))]" ] }, "execution_count": 158, "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": 159, "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": 160, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "df = dx + 4 dy + 3 dz" ] }, "execution_count": 160, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp.display()" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

Recall that

" ] }, { "cell_type": "code", "execution_count": 161, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(1, 2, -1)" ] }, "execution_count": 161, "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": 162, "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": 162, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp.parent()" ] }, { "cell_type": "code", "execution_count": 163, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 163, "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": 164, "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": 164, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(vp) ; vp.display()" ] }, { "cell_type": "code", "execution_count": 165, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOBAMAAADDIxFwAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEM3dMquZiWYiRHa7\nVO+0fdwUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAVUlEQVQIHWNggALnsPLyAhiHof////8BcF4m\nAwMrnMMAVFWC4DEwcG1A5vEgcxgqkHmMH4A8IWMQUGFg4FZAlmM+gMyTR9gNFPZPQJa7j8Kbd4GB\nAQCGAQ9DQk+A3gAAAABJRU5ErkJggg==\n", "text/latex": [ "$$-7$$" ], "text/plain": [ "-7" ] }, "execution_count": 165, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfp(vp)" ] }, { "cell_type": "code", "execution_count": 166, "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": 166, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(up) ; up.display()" ] }, { "cell_type": "code", "execution_count": 167, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAAVBAMAAABF1d8/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIkQyEJm7VHbNq2bv\nid2NdxwmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADgUlEQVRYCa2XTUhUURTH/2+ccZ7OhwPhSpSJ\naNHGZtPaiQhSDGeRFIJkEba1RRFROkGbVklBOC6yoCI0clq4CFxEhBBEuTEMsiaQIFBTETWo7Nzz\n7n1fM/qGN3MWc889797f/P/vvvs+AGc0ObslepFEiWJxqVogbw5eFv271mcrad39KVtXpY9UYrVH\nrFRmvkDNCxfdoHI49UUnto4q4beS1YHYugt7PQ20u2rU/VFU8gPSMhjKu0heHCE2OOyahCmgo2dD\nVh8D7x0Dgk8m00AsK4tX1UF9RmVm6wekb6GhYBKMZG+OFDvvmoTvVNCVjQ/AZMo54k6azL+WNdNG\n033nKOr5AQXeoMt9Yr04LLYT0A7g2H6lQitQZtoYS5e0gbtyuGljVtioBogvKjvIUxCLrUuicRNX\ntqUu6Bm7Dcp/pdUhoxWrgTlZUzYiCWGjCiAEl10gT0FsI0aySYJpozZPGHM1gMBfqVg1bOOV7Ckb\nJwSjGiDt6ykXyFMQi43QpdhvsxEfIIzNRvyhwNqCbQzKgrIxa9ioHAR8SRLbBvIUxGLDBcckRAXF\nZqObuhTBBysUP1MA22gTtc+53FIuN0pZOFVswxeIWFFxs7fZ2IWDdiFo5Z4UW7PqmOS2wVcmca2w\nbFBNrsZJvp6qANISqN0i7u42igXxOTdtHNqKbRLAtYaXQWRHsI1WWZI2ro2P/3lGJf731vXgO5rj\nC9SwYbPRdebbQBkcthEoAE+hbQMjoRQpce6omgz0UjbcWxyYEcYYpG0g4xcU7UN8TYGaxWnxFsQ2\nxBafRngmjc7TNAnizsV7gx9DLQtzL1wPJF6NXjGUQm1xQKykBI1oecp9gSJ5DGUVaJ8utoknh22E\nZmnk/K2lRUT40S1WJ/T89wTii8QY29n5Z2TU4ej5OEoiaWdxmDY+7UxQwQAN6uKYP9DB7vNisgFq\nS6a9OSwWdSkxTcTx29yIZz/HJZXAymRJK8jEtGGOpSR6g3uVg5ZB55hfahhoybAyPkA/LSrBhdqM\nyOlNzAiBcGeyYL4aHlVD7K2+xr2KQfXDgSyRyuFgXgmYXg1tipWpTRiVYNZo6ZlhZqpS4kVdHaI2\n2MedikGHe88OEKkcTvGLuvpKibAW8WNlqnROJSXbmiSXKwcZ9HI4yqpNj/c3494fsVMxCasUpDR5\nc0p8xKrJvtvGm76nVjLxP5tdbciPDDcZAAAAAElFTkSuQmCC\n", "text/latex": [ "$$\\operatorname{u_{x}}{\\left (1,2,-1 \\right )} + 4 \\operatorname{u_{y}}{\\left (1,2,-1 \\right )} + 3 \\operatorname{u_{z}}{\\left (1,2,-1 \\right )}$$" ], "text/plain": [ "u_x(1, 2, -1) + 4*u_y(1, 2, -1) + 3*u_z(1, 2, -1)" ] }, "execution_count": 167, "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": 168, "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, theta, phi) |--> H(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))" ] }, "execution_count": 168, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h.display()" ] }, { "cell_type": "code", "execution_count": 169, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "dh = Derivative(H(x, y, z), x) dx + Derivative(H(x, y, z), y) dy + Derivative(H(x, y, z), z) dz" ] }, "execution_count": 169, "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": 170, "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": 171, "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": 171, "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": 172, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = r*sin(theta)*cos(phi) dr + r*sin(phi)*sin(theta) dphi" ] }, "execution_count": 172, "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": 173, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = (x**4 + x**2*y**2 - y**2*sqrt(x**2 + y**2 + z**2))/((x**2 + y**2)*sqrt(x**2 + y**2 + z**2)) dx + x*y*(x**2 + y**2 + sqrt(x**2 + y**2 + z**2))/((x**2 + y**2)*sqrt(x**2 + y**2 + z**2)) dy + x*z/sqrt(x**2 + y**2 + z**2) dz" ] }, "execution_count": 173, "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": 174, "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": 174, "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": 175, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega = r*(r*sin(theta)**3*cos(phi) + sqrt(2)*(cos(phi - 2*theta + pi/4) - cos(phi + 2*theta + pi/4))/4 - cos(theta)**2) dr + r**2*(r*sin(theta)**2*cos(phi)*cos(theta) + sin(phi)*cos(theta)**2 - sin(theta)**2*cos(phi) + sin(2*theta)/2) dtheta + r**2*(-4*r*sin(phi)*sin(theta)**3 - sin(phi - 2*theta) + sin(phi + 2*theta))/4 dphi" ] }, "execution_count": 175, "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": 176, "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**2*y*z + x**2*y + x**2 - x*y*z**2 - x*z + y**3 + y**2\n", " (r, theta, phi) |--> r**2*(-r**2*(cos(2*phi - theta) - cos(2*phi + theta))/4 - r**2*sin(phi)**3*sin(theta)**2*cos(theta) + r**2*sin(phi)*sin(theta)**3*cos(phi) + r**2*sin(phi)*sin(theta)**2*cos(theta) + r*sin(phi)*sin(theta)**2 + sin(theta) - cos(phi)*cos(theta))*sin(theta)" ] }, "execution_count": 176, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display() ; om.display() ; print(om(v)) ; om(v).display()" ] }, { "cell_type": "code", "execution_count": 177, "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*y + y + 1\n", " (r, theta, phi) |--> 3*r**5*sin(phi)*sin(theta)**2*cos(phi)*cos(theta)**3 - 2*r**2*sin(phi)*sin(theta)**2*cos(phi) + r*sin(phi)*sin(theta) + 1" ] }, "execution_count": 177, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.display() ; print(df(v)) ; df(v).display()" ] }, { "cell_type": "code", "execution_count": 178, "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) + x*u_z(x, y, z) + y**2*u_x(x, y, z) + z*u_y(x, y, z) - z*u_z(x, y, z)\n", " (r, theta, phi) |--> r*(r*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)**2 + u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*cos(theta) + u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)*cos(phi) - u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*cos(theta))" ] }, "execution_count": 178, "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": 179, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 179, "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": 180, "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": 180, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.parent()" ] }, { "cell_type": "code", "execution_count": 181, "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": 182, "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": 183, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 183, "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": 184, "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*z**2 - x + 3*y**2*z**2 + z) dx/\\dz + (-2*x*y + 2*y*z + 3*z**3) dy/\\dz" ] }, "execution_count": 184, "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": 185, "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*z^2 + 3*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*z^2 - 3*y^2*z^2 + x - z -3*z^3 + 2*x*y - 2*y*z 0]" ] }, "execution_count": 185, "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": 186, "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*z**2 - x + 3*y**2*z**2 + z \n", "omega/\\df_yz = -2*x*y + 2*y*z + 3*z**3 " ] }, "execution_count": 186, "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": 187, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "omega/\\df = r**2*(3*r**3*sin(theta)**4*cos(phi) - 3*r**3*sin(theta)**2*cos(phi) - 3*r**2*sin(phi)*cos(theta)**3 - 2*r*sin(phi)**2*sin(theta)*cos(theta) - 2*r*sin(theta)**2*cos(phi)**3 + 2*r*sin(theta)**2*cos(phi) - sin(phi)**2*sin(theta) + sin(theta) - cos(phi)*cos(theta)) dr/\\dtheta + r**2*(3*r**3*sin(phi)*sin(theta)**2*cos(theta)**3 + 2*r**2*sin(phi)*sin(theta)**4 - 3*r**2*sin(theta)**4*cos(phi) + 6*r**2*sin(theta)**2*cos(phi) - 3*r**2*cos(phi) - r*(cos(2*phi - theta) - cos(2*phi + theta))/2 - 2*r*sin(phi)**3*sin(theta)**2*cos(theta) + 2*r*sin(phi)*sin(theta)**3*cos(phi) + 2*r*sin(phi)*sin(theta)**2*cos(theta) - sin(phi)*sin(theta)**2 + sin(phi) - sin(2*theta)/2 - cos(2*(phi - theta))/8 + cos(2*(phi + theta))/8)*sin(theta) dr/\\dphi + r**3*(3*r**3*sin(phi)*sin(theta)**5 - 3*r**3*sin(phi)*sin(theta)**3 + 2*r**2*sin(phi)*sin(theta)**3*cos(theta) + 3*r**2*sin(theta)*cos(phi)*cos(theta)**3 + 2*r*sin(phi)**3*sin(theta)**3 - 2*r*sin(phi)*sin(theta)**3 + 2*r*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) + sin(phi)*sin(theta)**2*cos(phi) + sin(theta)**2 - cos(phi - 2*theta)/4 + cos(phi + 2*theta)/4 - 1)*sin(theta) dtheta/\\dphi" ] }, "execution_count": 187, "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": 188, "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**3*y*z**3*u_x(x, y, z) - 2*x**3*y*u_x(x, y, z) - 2*x**2*y**2*z*u_y(x, y, z) - 2*x**2*y**2*u_y(x, y, z) - 3*x**2*y*z**2*u_z(x, y, z) - x**2*y*z*u_x(x, y, z) - 2*x**2*y*u_y(x, y, z) - 2*x**2*y*u_z(x, y, z) - 3*x**2*z**2*u_z(x, y, z) + 3*x*y**3*z**3*u_x(x, y, z) - 2*x*y**3*u_x(x, y, z) + 2*x*y**2*z**2*u_y(x, y, z) + 3*x*y*z**4*u_y(x, y, z) + x*y*z**2*u_x(x, y, z) + 2*x*y*z*u_z(x, y, z) + x*y*u_z(x, y, z) + 3*x*z**3*u_z(x, y, z) + x*z*u_x(x, y, z) + x*u_z(x, y, z) - 2*y**4*u_y(x, y, z) - 3*y**3*z**2*u_z(x, y, z) - 2*y**3*u_y(x, y, z) - 3*y**2*z**2*u_z(x, y, z) + y*z*u_y(x, y, z) - y*z*u_z(x, y, z) + z*u_y(x, y, z) - z*u_z(x, y, z)\n", " (r, theta, phi) |--> r*(3*r**6*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**3*sin(theta)**4*cos(phi)*cos(theta)**3 + 3*r**6*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**4*cos(phi)**3*cos(theta)**3 + 3*r**5*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**6*cos(phi) - 6*r**5*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**4*cos(phi) + 3*r**5*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**2*cos(phi) + 2*r**4*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**4*sin(theta)**4*cos(theta) - 2*r**4*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**2*sin(theta)**5*cos(phi) - 2*r**4*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**2*sin(theta)**4*cos(theta) + 2*r**4*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**2*sin(theta)**3*cos(phi) + 3*r**4*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**5 - 3*r**4*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**3 - 2*r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**3*sin(theta)**4*cos(phi) + r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**3*sin(theta)**3*cos(theta) - 2*r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**4*cos(phi)**3 - r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**4*cos(phi) - r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**3*cos(theta) + r**3*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**2*cos(phi) - 2*r**3*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**2*sin(theta)**4 + 3*r**3*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)**4 - 3*r**3*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)**2 + 3*r**3*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)*cos(phi)*cos(theta)**3 - 2*r**2*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**3 + 2*r**2*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)**3*sin(theta)**3 - 2*r**2*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**3 + 2*r**2*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) + r*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)*cos(phi)*cos(theta) + r*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)*cos(theta) + r*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**2*cos(phi) - r*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)*cos(theta) + u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*cos(theta) + u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)*cos(phi) - u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*cos(theta))" ] }, "execution_count": 188, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.set_name('A')\n", "print(a(u,v)) ; a(u,v).display()" ] }, { "cell_type": "code", "execution_count": 189, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 189, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a(u,v) == - a(v,u)" ] }, { "cell_type": "code", "execution_count": 190, "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": 191, "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": 191, "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": 192, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "from sage.manifolds.utilities import xder\n", "dom = xder(om)" ] }, { "cell_type": "code", "execution_count": 193, "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": 193, "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": 194, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ddf = 0" ] }, "execution_count": 194, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ddf = xder(df) ; ddf.display()" ] }, { "cell_type": "code", "execution_count": 195, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "ddomega = 0" ] }, "execution_count": 195, "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": 196, "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": [ "(x*y*z + 2*x - y*z**2 - z) dx + (x**2*z + x**2 + x*y*z - x*z**2 + y**2) dy + (x**2*y - 2*x*y*z + y + 1) dz" ] }, "execution_count": 196, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lv_om = om.lie_derivative(v) ; print(lv_om) ; lv_om.display()" ] }, { "cell_type": "code", "execution_count": 197, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "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": 198, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 198, "metadata": {}, "output_type": "execute_result" } ], "source": [ "om.lie_derivative(v) == v.contract(xder(om)) + xder(om(v))" ] }, { "cell_type": "code", "execution_count": 199, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 199, "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": 200, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "# v.lie_derivative(u)(f) == u(v(f)) - v(u(f))" ] }, { "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 SageMath. For instance a tensor field of type (1,2) on the open subset $U$ is declared as follows:

" ] }, { "cell_type": "code", "execution_count": 201, "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": 202, "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": 203, "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": 203, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display()" ] }, { "cell_type": "code", "execution_count": 204, "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": 204, "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": 205, "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": 205, "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": 206, "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, theta, phi) |--> r**2*sin(theta)**2*cos(phi)**2 + 1" ] }, "execution_count": 206, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(t[[1,2,1]]) ; t[[1,2,1]].display()" ] }, { "cell_type": "code", "execution_count": 207, "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": 207, "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": 208, "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**4*y + x**4 + x**2*y**3 + x**2*y**2*z + x**2*y**2 + x**2*y*z + x**2*y + x**2 - x*y**2*z**2 - x*y*z**2 + y**3 + y**2)*u_y(x, y, z)\n", " (r, theta, phi) |--> r**2*(-r**3*sin(phi)**4*sin(theta)**2*cos(theta) + sqrt(2)*r**3*sin(phi)**2*sin(theta)**3*cos(phi + pi/4) + r**3*sin(phi)**2*sin(theta)**2*cos(theta) - r**3*sin(phi)**2*sin(theta)*cos(phi) + r**3*sin(phi)*sin(theta)**3 + r**2*(cos(phi - 2*theta) - cos(phi + 2*theta))/4 - r**2*sin(phi)**3*sin(theta)*cos(theta) + sqrt(2)*r**2*sin(phi)*sin(theta)**2*cos(phi + pi/4) - r**2*sin(2*phi)/2 + r**2*sin(theta)**2 + r*sin(phi)*sin(theta) + 1)*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)**2" ] }, "execution_count": 208, "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": 209, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r**3*(r**3*sin(phi)*sin(theta)*cos(theta)**2 + r**2*sin(theta)**2*cos(phi)**2 + 1)*sin(phi)*sin(theta)**3*cos(phi)**2/(r**2)**(3/2)" ] }, "execution_count": 209, "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": 210, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAD8AAAAUBAMAAADIGvgZAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIma7zZnddlTvRIkQ\nMqvFy5UvAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJElEQVQoFXWSvUrEQBDHf0nuIyQXDQjXGt/A\njxeInd1tc/1Vcp2V+AT2VoJWVtaHcFiIkEblEDSPkMpKOQtRUeGcNRfIXsy/yMzO/NiZzCxYEbVa\n05kVuLm4rjBWfytlKZT4Nuxwqz1DD/hfdGKwFfYRvnimnuEELqEV4mS4P2YajmGaMoEuLGd4n4tA\nL9FA44x9eFR4H4uAnPcSfMUmrI4IvquAJzE7ZiiA+hdoZeAOOK0t0ZdLg1cNSJNupUnaKgekhLOO\nXflNDrFCvIFuUgbVjAU3FCjaIXbMWMJDJmnnzcjTvRo/QXPEucTvD15gNzGI3mz2Do1UjzqXWzhl\nTuYsy8rllxOFL8tiY364K4Ilq9etH8yforktG0eXtSL51Eie3C+wbD5oRkcPtwAAAABJRU5ErkJg\ngg==\n", "text/latex": [ "$$\\left ( 0, \\quad 2\\right )$$" ], "text/plain": [ "(0, 2)" ] }, "execution_count": 210, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.tensor_type() ; a.tensor_type()" ] }, { "cell_type": "code", "execution_count": 211, "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": 211, "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": 212, "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": 213, "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": 214, "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": 215, "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": 216, "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": 216, "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": 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_kj'] == c" ] }, { "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['^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": 219, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 219, "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": 220, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 220, "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": 221, "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": 222, "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": 223, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 223, "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": 224, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 224, "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": 225, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 225, "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": 226, "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": 227, "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": 227, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.parent()" ] }, { "cell_type": "code", "execution_count": 228, "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": 229, "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": 230, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dx*dx + dy*dy + dz*dz" ] }, "execution_count": 230, "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": 231, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dr*dr + r**2 dtheta*dtheta + r**2*sin(theta)**2 dphi*dphi" ] }, "execution_count": 231, "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": 232, "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) - x*u_y(x, y, z) + y*u_x(x, y, z) + u_x(x, y, z)\n", " (r, theta, phi) |--> r**3*u_z(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) + r*u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(phi)*sin(theta) - r*u_y(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))*sin(theta)*cos(phi) + u_x(r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta))" ] }, "execution_count": 232, "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": 233, "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": 233, "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": 234, "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": 234, "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": 235, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[[0, 0, 0], [0, -r, 0], [0, 0, -r*sin(theta)**2]],\n", " [[0, 1/r, 0], [1/r, 0, 0], [0, 0, -sin(2*theta)/2]],\n", " [[0, 0, 1/r], [0, 0, 1/tan(theta)], [1/r, 1/tan(theta), 0]]]" ] }, "execution_count": 235, "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": 236, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_theta,theta = -r \n", "Gam^r_phi,phi = -r*sin(theta)**2 \n", "Gam^theta_r,theta = 1/r \n", "Gam^theta_theta,r = 1/r \n", "Gam^theta_phi,phi = -sin(2*theta)/2 \n", "Gam^phi_r,phi = 1/r \n", "Gam^phi_theta,phi = 1/tan(theta) \n", "Gam^phi_phi,r = 1/r \n", "Gam^phi_phi,theta = 1/tan(theta) " ] }, "execution_count": 236, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(frame=Y.frame(), chart=Y)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

The connection acting as a covariant derivative:

" ] }, { "cell_type": "code", "execution_count": 237, "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" ] } ], "source": [ "nab_v = nabla(v)\n", "print(nab_v)\n", "# nab_v.display() # does not work with SymPy (trigsimp runs forever...)" ] }, { "cell_type": "markdown", "metadata": { "deletable": true, "editable": true }, "source": [ "

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

" ] }, { "cell_type": "code", "execution_count": 238, "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": 238, "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": 239, "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": 239, "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": 240, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 1/(r**2 + 1) dr*dr + r**2 dtheta*dtheta + r**2*sin(theta)**2 dphi*dphi" ] }, "execution_count": 240, "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": 241, "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": 242, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = 1/(r**2 + 1) dr*dr + r**2 dtheta*dtheta + r**2*sin(theta)**2 dphi*dphi" ] }, "execution_count": 242, "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": 243, "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": 243, "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": 244, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "image/png": "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\nAABJRU5ErkJggg==\n", "text/latex": [ "$$\\left [ \\left [ \\frac{y^{2} + z^{2} + 1}{x^{2} + y^{2} + z^{2} + 1}, \\quad - \\frac{x y}{x^{2} + y^{2} + z^{2} + 1}, \\quad - \\frac{x z}{x^{2} + y^{2} + z^{2} + 1}\\right ], \\quad \\left [ - \\frac{x y}{x^{2} + y^{2} + z^{2} + 1}, \\quad \\frac{x^{2} + z^{2} + 1}{x^{2} + y^{2} + z^{2} + 1}, \\quad - \\frac{y z}{x^{2} + y^{2} + z^{2} + 1}\\right ], \\quad \\left [ - \\frac{x z}{x^{2} + y^{2} + z^{2} + 1}, \\quad - \\frac{y z}{x^{2} + y^{2} + z^{2} + 1}, \\quad \\frac{x^{2} + y^{2} + 1}{x^{2} + y^{2} + z^{2} + 1}\\right ]\\right ]$$" ], "text/plain": [ "[[(y**2 + z**2 + 1)/(x**2 + y**2 + z**2 + 1),\n", " -x*y/(x**2 + y**2 + z**2 + 1),\n", " -x*z/(x**2 + y**2 + z**2 + 1)],\n", " [-x*y/(x**2 + y**2 + z**2 + 1),\n", " (x**2 + z**2 + 1)/(x**2 + y**2 + z**2 + 1),\n", " -y*z/(x**2 + y**2 + z**2 + 1)],\n", " [-x*z/(x**2 + y**2 + z**2 + 1),\n", " -y*z/(x**2 + y**2 + z**2 + 1),\n", " (x**2 + y**2 + 1)/(x**2 + y**2 + z**2 + 1)]]" ] }, "execution_count": 244, "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": 245, "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": 245, "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": 246, "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": 247, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^x_xx = -x*(y**2 + z**2 + 1)/(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*(x**2 + z**2 + 1)/(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*(x**2 + y**2 + 1)/(x**2 + y**2 + z**2 + 1) \n", "Gam^y_xx = -y*(y**2 + z**2 + 1)/(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*(x**2 + z**2 + 1)/(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*(x**2 + y**2 + 1)/(x**2 + y**2 + z**2 + 1) \n", "Gam^z_xx = -z*(y**2 + z**2 + 1)/(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*(x**2 + z**2 + 1)/(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 = -z*(x**2 + y**2 + 1)/(x**2 + y**2 + z**2 + 1) " ] }, "execution_count": 247, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(only_nonredundant=True)" ] }, { "cell_type": "code", "execution_count": 248, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_r,r = -r/(r**2 + 1) \n", "Gam^r_theta,theta = -r*(r**2 + 1) \n", "Gam^r_phi,phi = -r*(r**2 + 1)*sin(theta)**2 \n", "Gam^theta_r,theta = 1/r \n", "Gam^theta_phi,phi = -sin(2*theta)/2 \n", "Gam^phi_r,phi = 1/r \n", "Gam^phi_theta,phi = 1/tan(theta) " ] }, "execution_count": 248, "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": 249, "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*dtheta*dr*dtheta + r**2 d/dr*dtheta*dtheta*dr - r**2*sin(theta)**2 d/dr*dphi*dr*dphi + r**2*sin(theta)**2 d/dr*dphi*dphi*dr + 1/(r**2 + 1) d/dtheta*dr*dr*dtheta - 1/(r**2 + 1) d/dtheta*dr*dtheta*dr - r**2*sin(theta)**2 d/dtheta*dphi*dtheta*dphi + r**2*sin(theta)**2 d/dtheta*dphi*dphi*dtheta + 1/(r**2 + 1) d/dphi*dr*dr*dphi - 1/(r**2 + 1) d/dphi*dr*dphi*dr + r**2 d/dphi*dtheta*dtheta*dphi - r**2 d/dphi*dtheta*dphi*dtheta" ] }, "execution_count": 249, "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": 250, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 250, "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": 251, "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 dtheta*dtheta - 2*r**2*sin(theta)**2 dphi*dphi" ] }, "execution_count": 251, "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": 252, "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": 252, "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": 253, "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, theta, phi) |--> -6" ] }, "execution_count": 253, "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": 254, "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": 255, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "T = (r**2*sin(theta)**2*cos(phi)**2 + 1) d/dx*dy*dx + r**3*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) d/dz*dy*dx" ] }, "execution_count": 255, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.display()" ] }, { "cell_type": "code", "execution_count": 256, "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": 256, "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": 257, "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": 258, "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": 259, "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": 260, "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": 260, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon = g.volume_form()\n", "print(epsilon) ; epsilon.display()" ] }, { "cell_type": "code", "execution_count": 261, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "eps_g = r**2*sin(theta)/sqrt(r**2 + 1) dr/\\dtheta/\\dphi" ] }, "execution_count": 261, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon.display(Y.frame())" ] }, { "cell_type": "code", "execution_count": 262, "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) |--> x + y**2 + z**3\n", " (r, theta, phi) |--> r*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))" ] }, "execution_count": 262, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(f) ; f.display()" ] }, { "cell_type": "code", "execution_count": 263, "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*(r**2*cos(theta)**3 + r*sin(phi)**2*sin(theta)**2 + sin(theta)*cos(phi))/sqrt(r**2 + 1) dx/\\dy/\\dz" ] }, "execution_count": 263, "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": 264, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 264, "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": 265, "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(theta)**2 dx + r*cos(theta) dy + r*(sin(theta)*cos(phi) - cos(theta)) dz" ] }, "execution_count": 265, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(om) ; om.display()" ] }, { "cell_type": "code", "execution_count": 266, "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*(r**3*sin(theta)**3*cos(phi)*cos(theta) - sqrt(2)*r**2*sin(theta)**3*sin(phi + pi/4) + sqrt(2)*r**2*sin(theta)*sin(phi + pi/4) - r**2*cos(theta)**3 + sin(theta)*cos(phi) - cos(theta))/sqrt(r**2 + 1) dx/\\dy + r*(-r**3*(-cos(2*theta) + 1)**2*sin(2*phi)/8 - r**2*sin(phi)*sin(theta)**3 - sqrt(2)*r**2*sin(phi)*sin(theta)**2*sin(phi + pi/4)*cos(theta) + r**2*sin(phi)*sin(theta) - cos(theta))/sqrt(r**2 + 1) dx/\\dz + r**2*(r**2*sin(theta)**3*cos(phi)**2 + sqrt(2)*r*sin(phi)*sin(theta)*cos(theta)*cos(phi + pi/4) + r*sin(2*theta)/2 - r*cos(phi)*cos(theta)**2 + sin(theta))*sin(theta)/sqrt(r**2 + 1) dy/\\dz" ] }, "execution_count": 266, "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": 267, "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": 268, "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 = r**2*(3*r**4*sin(phi)**3*sin(theta)**4*cos(phi)*cos(theta)**2 + 3*r**4*sin(phi)*sin(theta)**4*cos(phi)**3*cos(theta)**2 - 2*r**3*sin(phi)**3*sin(theta)**4*cos(phi)*cos(theta) + 3*r**3*sin(phi)**2*sin(theta)**2*cos(theta)**3 - 2*r**3*sin(phi)*sin(theta)**4*cos(phi)**3*cos(theta) + 3*r**3*cos(theta)**5 - 2*r**2*sin(phi)**3*sin(theta)**4*cos(phi) + 2*r**2*sin(phi)**3*sin(theta)**3*cos(theta) + 2*r**2*sin(phi)*sin(theta)*cos(theta)**3 - r**2*sin(2*phi)/8 + r**2*sin(2*phi - 4*theta)/16 + r**2*sin(2*phi + 4*theta)/16 - r*sin(phi)*sin(theta)**3*cos(phi)**2 + r*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) + r*sin(theta)*cos(phi)*cos(theta)**2 + 3*r*cos(theta)**3 - 2*sin(phi)*sin(theta)**2*cos(phi) + cos(phi - 2*theta)/2 - cos(phi + 2*theta)/2)/sqrt(r**2 + 1) dx + r*(-3*r**5*sin(phi)**2*sin(theta)**6 + 3*r**5*sin(phi)**2*sin(theta)**4 + 3*r**5*sin(theta)**4 - 3*r**5*sin(theta)**2 - 2*r**4*sin(phi)**2*sin(theta)**4*cos(theta) - 3*r**4*sin(phi)*sin(theta)**2*cos(phi)*cos(theta)**3 - 2*r**3*sin(phi)**4*sin(theta)**4 + 2*r**3*sin(phi)**2*sin(theta)**4 - 2*r**3*sin(phi)**2*sin(theta)**3*cos(phi)*cos(theta) + 3*r**3*sin(theta)**4 - 3*r**3*sin(theta)**2 + r**2*sin(phi)**2*sin(theta)**2*cos(theta) - sqrt(2)*r**2*sin(theta)**3*sin(phi + pi/4) + r**2*sin(theta)**3*cos(phi)**3 - r**2*sin(theta)**2*cos(theta) + sqrt(2)*r**2*sin(theta)*sin(phi + pi/4) - r**2*cos(theta)**3 + sin(theta)*cos(phi) - cos(theta))/sqrt(r**2 + 1) dy + r*(3*r**5*sin(phi)*sin(theta)**3*cos(theta)**3 + 2*r**4*sin(phi)*sin(theta)**5 - 3*r**4*sin(theta)**5*cos(phi) + 6*r**4*sin(theta)**3*cos(phi) - 3*r**4*sin(theta)*cos(phi) + r**3*(-cos(2*theta) + 1)**2*sin(2*phi)/4 - 2*r**3*sin(phi)**3*sin(theta)**3*cos(theta) + 2*r**3*sin(phi)*sin(theta)**3*cos(theta) - 2*r**3*sin(phi)*sin(theta)**2*cos(phi) + r**2*sin(phi)*sin(theta)**3 - r**2*sin(phi)*sin(theta)**2*cos(phi)*cos(theta) + r**2*sin(phi)*sin(theta) - r**2*sin(theta)**2*cos(theta) - cos(theta))/sqrt(r**2 + 1) dz" ] }, "execution_count": 268, "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": 269, "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*r**3*sin(phi)*sin(theta)*cos(theta)**2 - 2*r*sin(phi)*sin(theta) - 1) dx/\\dy/\\dz" ] }, "execution_count": 269, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(da) ; da.display()" ] }, { "cell_type": "code", "execution_count": 270, "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) |--> -(36*y*z**2 + 12*y + 6)*sqrt(x**2 + y**2 + z**2 + 1)/6\n", " (r, theta, phi) |--> -sqrt(r**2 + 1)*(36*r**3*sin(phi)*sin(theta)*cos(theta)**2 + 12*r*sin(phi)*sin(theta) + 6)/6" ] }, "execution_count": 270, "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": 271, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 271, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sf.hodge_dual(g) == f" ] }, { "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": [ "som.hodge_dual(g) == om" ] }, { "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": [ "sa.hodge_dual(g) == a" ] }, { "cell_type": "code", "execution_count": 274, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 274, "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": 275, "metadata": { "collapsed": false, "deletable": true, "editable": true }, "outputs": [], "source": [ "nabla?" ] }, { "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": [ "

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

" ] }, { "cell_type": "code", "execution_count": 277, "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.beta8", "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 }