{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vector calculus with SageMath\n", "\n", "## Part 5: Advanced aspects: Euclidean spaces as Riemannian manifolds\n", "\n", "This notebook illustrates some vector calculus capabilities of SageMath within the 3-dimensional Euclidean space. The corresponding tools have been developed within\n", "the [SageManifolds](https://sagemanifolds.obspm.fr) project.\n", "\n", "Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Notebooks/SM_vector_calc_advanced.ipynb) to download the notebook file (ipynb format). To run it, you must start SageMath with the Jupyter interface, via the command `sage -n jupyter`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*NB:* a version of SageMath at least equal to 8.3 is required to run this notebook:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 8.8.beta2, Release Date: 2019-04-14'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display math formulas using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Euclidean 3-space\n", "\n", "We define the 3-dimensional Euclidean space $\\mathbb{E}^3$, with Cartesian coordinates $(x,y,z)$:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Euclidean space E^3" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E. = EuclideanSpace()\n", "print(E)\n", "E" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is actually a Riemannian manifold, i.e. a smooth real manifold endowed with a positive definite metric tensor:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Category of smooth manifolds over Real Field with 53 bits of precision" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.category()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Category of smooth manifolds over Real Field with 53 bits of precision\n" ] } ], "source": [ "print(E.category())" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.base_field() is RR" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Actually `RR` is used here as a proxy for the real field (this should be replaced in the future, see the discussion at [#24456](https://trac.sagemath.org/ticket/24456)) and the 53 bits of precision play of course no role for the symbolic computations. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us introduce spherical and cylindrical coordinates on $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "spherical. = E.spherical_coordinates()\n", "cylindrical. = E.cylindrical_coordinates()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The user atlas of $\\mathbb{E}^3$ has then three charts:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (x, y, z)), Chart (E^3, (r, th, ph)), Chart (E^3, (rh, ph, z))]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "while there are five vector frames defined on $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (E^3, (e_x,e_y,e_z)),\n", " Coordinate frame (E^3, (d/dr,d/dth,d/dph)),\n", " Vector frame (E^3, (e_r,e_th,e_ph)),\n", " Coordinate frame (E^3, (d/drh,d/dph,d/dz)),\n", " Vector frame (E^3, (e_rh,e_ph,e_z))]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indeed, there are two frames associated with each of the three coordinate systems: the coordinate frame (denoted with partial derivatives above) and an orthonormal frame, but for Cartesian coordinates, both frames coincide. \n", "\n", "We get the orthonormal spherical and cylindrical frames by " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (E^3, (e_r,e_th,e_ph))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical_frame = E.spherical_frame()\n", "spherical_frame" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (E^3, (e_rh,e_ph,e_z))" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical_frame = E.cylindrical_frame()\n", "cylindrical_frame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the other side, the coordinate frames are returned by the method `frame()` acting on the coordinate charts:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (d/dr,d/dth,d/dph))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical.frame()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (d/drh,d/dph,d/dz))" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical.frame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Charts as maps $\\mathbb{E}^3 \\rightarrow \\mathbb{R}^3$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The chart of Cartesian coordinates has been constructed at the declaration of `E`; let us denote it by `cartesian`:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (E^3, (x, y, z))" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian = E.cartesian_coordinates()\n", "cartesian" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us consider a point $p\\in \\mathbb{E}^3$, defined by its Cartesian coordinates:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the Euclidean space E^3\n" ] } ], "source": [ "p = E((-1, 1,0), chart=cartesian, name='p')\n", "print(p)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.parent() is E" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The coordinates of $p$ in a given coordinate chart are obtained by letting the corresponding chart act on $p$:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(-1, 1, 0)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian(p)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(2), 1/2*pi, 3/4*pi)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical(p)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(2), 3/4*pi, 0)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Riemannian metric\n", "\n", "The default metric tensor of $\\mathbb{E}^3$ is" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Riemannian metric g on the Euclidean space E^3\n" ] } ], "source": [ "g = E.metric()\n", "print(g)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dx*dx + dy*dy + dz*dz" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[1 0 0]\n", "[0 1 0]\n", "[0 0 1]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above display in performed in the default frame, which is the Cartesian one.\n", "Of course, we may ask for display with respect to other frames:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = e^r*e^r + e^th*e^th + e^ph*e^ph" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(spherical_frame)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[1 0 0]\n", "[0 1 0]\n", "[0 0 1]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[spherical_frame, :]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the above display, $e^r$, $e^\\theta$ and $e^\\phi$ are the 1-forms defining the coframe dual to the orthonormal spherical frame $(e_r,e_\\theta,e_\\phi)$:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coframe (E^3, (e^r,e^th,e^ph))" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical_frame.coframe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The fact that the above metric components are either 0 or 1 reflect the orthonormality of the vector frame $(e_r,e_\\theta,e_\\phi)$. On the contrary, in the coordinate frame\n", "$\\left(\\frac{\\partial}{\\partial r}, \\frac{\\partial}{\\partial\\theta}, \\frac{\\partial}{\\partial \\phi}\\right)$, which is not orthonormal, the components differ from 0 or 1:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dr*dr + (x^2 + y^2 + z^2) dth*dth + (x^2 + y^2) dph*dph" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(spherical.frame())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the components are expressed in terms of the default chart, namely the Cartesian one. To have them displayed in terms of the spherical chart, we have to provide the latter as the second argument of the method `display()`:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(spherical.frame(), spherical)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[ 1 0 0]\n", "[ 0 r^2 0]\n", "[ 0 0 r^2*sin(th)^2]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[spherical.frame(), :, spherical]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, for cylindrical coordinates, we have" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = e^rh*e^rh + e^ph*e^ph + e^z*e^z" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(cylindrical_frame)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = drh*drh + rh^2 dph*dph + dz*dz" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(cylindrical.frame(), cylindrical)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[ 1 0 0]\n", "[ 0 rh^2 0]\n", "[ 0 0 1]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g[cylindrical.frame(),:,cylindrical]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The metric $g$ is a *flat*: its (Riemann) curvature tensor is zero: " ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field Riem(g) of type (1,3) on the Euclidean space E^3\n" ] } ], "source": [ "print(g.riemann())" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Riem(g) = 0" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.riemann().display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The metric $g$ is defining the dot product on $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x*y e_x + y*z e_y + x*z e_z" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u = E.vector_field(x*y, y*z, z*x)\n", "u.display()" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y e_x + x e_y + z^2 e_z" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = E.vector_field(-y, x, z^2, name='v')\n", "v.display()" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u.dot(v) == g(u,v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consequently" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm(u) == sqrt(g(u,u))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Levi-Civita tensor\n", "\n", "The scalar triple product of $\\mathbb{E}^3$ is provided by the Levi-Civita tensor (also called *volume form*) associated with $g$ (and chosen such that $(e_x,e_y,e_z)$ is right-handed):" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-form epsilon on the Euclidean space E^3\n" ] } ], "source": [ "epsilon = E.scalar_triple_product()\n", "print(epsilon)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon is E.volume_form()" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon = dx/\\dy/\\dz" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon.display()" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon = r^2*sin(th) dr/\\dth/\\dph" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon.display(spherical.frame(), spherical)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon = rh drh/\\dph/\\dz" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon.display(cylindrical.frame(), cylindrical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Checking that all orthonormal frames introduced above are right-handed:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon(e_x,e_y,e_z): E^3 --> R\n", " (x, y, z) |--> 1\n", " (r, th, ph) |--> 1\n", " (rh, ph, z) |--> 1" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ex, ey, ez = E.cartesian_frame()[:]\n", "epsilon(ex, ey, ez).display()" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Scalar field epsilon(e_r,e_th,e_ph) on the Euclidean space E^3" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon(*spherical_frame)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon(e_r,e_th,e_ph): E^3 --> R\n", " (x, y, z) |--> 1\n", " (r, th, ph) |--> 1\n", " (rh, ph, z) |--> 1" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon(*spherical_frame).display()" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "epsilon(e_rh,e_ph,e_z): E^3 --> R\n", " (x, y, z) |--> 1\n", " (r, th, ph) |--> 1\n", " (rh, ph, z) |--> 1" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "epsilon(*cylindrical_frame).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vector fields as derivatives" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let $f$ be a scalar field on $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: E^3 --> R\n", " (x, y, z) |--> x^2 + y^2 - z^2\n", " (r, th, ph) |--> -2*r^2*cos(th)^2 + r^2\n", " (rh, ph, z) |--> rh^2 - z^2" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = E.scalar_field(x^2+y^2 - z^2, name='f')\n", "f.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vector fields acts as derivative on scalar fields: " ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field v(f) on the Euclidean space E^3\n" ] } ], "source": [ "print(v(f))" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v(f): E^3 --> R\n", " (x, y, z) |--> -2*z^3\n", " (r, th, ph) |--> -2*r^3*cos(th)^3\n", " (rh, ph, z) |--> -2*z^3" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v(f).display()" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v(f) == v.dot(f.gradient())" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1-form df on the Euclidean space E^3\n" ] } ], "source": [ "df = f.differential()\n", "print(df)" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "df = 2*x dx + 2*y dy - 2*z dz" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.display()" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v(f) == df(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The algebra of scalar fields\n", "\n", "The set $C^\\infty(\\mathbb{E}^3)$ of all smooth scalar fields on $\\mathbb{E}^3$ forms a commutative algebra over $\\mathbb{R}$:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Algebra of differentiable scalar fields on the Euclidean space E^3" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CE = E.scalar_field_algebra()\n", "CE" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Category of commutative algebras over Symbolic Ring" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CE.category()" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f in CE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In SageMath terminology $C^\\infty(\\mathbb{E}^3)$ is the parent of scalar fields:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.parent() is CE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The free module of vector fields\n", "\n", "The set $\\mathfrak{X}(\\mathbb{E}^3)$ of all vector fields on $\\mathbb{E}^3$ is a free module of rank 3 over the commutative algebra $C^\\infty(\\mathbb{E}^3)$:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Free module X(E^3) of vector fields on the Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Free module X(E^3) of vector fields on the Euclidean space E^3" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "XE = v.parent()\n", "print(XE)\n", "XE" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Category of finite dimensional modules over Algebra of differentiable scalar fields on the Euclidean space E^3\n" ] } ], "source": [ "print(XE.category())" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Algebra of differentiable scalar fields on the Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Algebra of differentiable scalar fields on the Euclidean space E^3" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(XE.base_ring())\n", "XE.base_ring()" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "XE.base_ring() is CE" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rank(XE)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The bases of the free module $\\mathfrak{X}(\\mathbb{E}^3)$ are nothing but the vector frames defined on $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (E^3, (e_x,e_y,e_z)),\n", " Coordinate frame (E^3, (d/dr,d/dth,d/dph)),\n", " Vector frame (E^3, (e_r,e_th,e_ph)),\n", " Coordinate frame (E^3, (d/drh,d/dph,d/dz)),\n", " Vector frame (E^3, (e_rh,e_ph,e_z))]" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "XE.bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tangent spaces" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vector fields evaluated at a point are vectors in the tangent space at this point:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the Euclidean space E^3\n" ] } ], "source": [ "print(p)" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -e_x - e_y" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp = v.at(p)\n", "vp.display()" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent space at Point p on the Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Tangent space at Point p on the Euclidean space E^3" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp = vp.parent()\n", "print(Tp)\n", "Tp" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "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": 68, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "3" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dim(Tp)" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(Tp, FiniteRankFreeModule)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The bases on $T_p\\mathbb{E}^3$ are inherited from the vector frames of $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Basis (e_x,e_y,e_z) on the Tangent space at Point p on the Euclidean space E^3,\n", " Basis (d/dr,d/dth,d/dph) on the Tangent space at Point p on the Euclidean space E^3,\n", " Basis (e_r,e_th,e_ph) on the Tangent space at Point p on the Euclidean space E^3,\n", " Basis (d/drh,d/dph,d/dz) on the Tangent space at Point p on the Euclidean space E^3,\n", " Basis (e_rh,e_ph,e_z) on the Tangent space at Point p on the Euclidean space E^3]" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Tp.bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For instance, we have" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Basis (e_r,e_th,e_ph) on the Tangent space at Point p on the Euclidean space E^3" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical_frame.at(p)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical_frame.at(p) in Tp.bases()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Levi-Civita connection\n", "\n", "The Levi-Civita connection associated to the Euclidean metric $g$ is" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Levi-Civita connection nabla_g associated with the Riemannian metric g on the Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Levi-Civita connection nabla_g associated with the Riemannian metric g on the Euclidean space E^3" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla = g.connection()\n", "print(nabla)\n", "nabla" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The corresponding Christoffel symbols with respect to Cartesian coordinates are identically zero: none of them appear in the output of `christoffel_symbols_display`, which by default displays only nonzero Christoffel symbols:" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(cartesian)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the contrary, some of the Christoffel symbols with respect to spherical coordinates differ from zero:" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_th,th = -r \n", "Gam^r_ph,ph = -r*sin(th)^2 \n", "Gam^th_r,th = 1/r \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_r,ph = 1/r \n", "Gam^ph_th,ph = cos(th)/sin(th) " ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(spherical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, only nonzero and nonredundant values are displayed (for instance $\\Gamma^\\phi_{\\ \\, \\phi r}$ is skipped, since it can be deduced from $\\Gamma^\\phi_{\\ \\, r \\phi}$ by symmetry on the last two indices).\n", "\n", "Similarly, the nonzero Christoffel symbols with respect to cylindrical coordinates are" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^rh_ph,ph = -rh \n", "Gam^ph_rh,ph = 1/rh " ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.christoffel_symbols_display(cylindrical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Christoffel symbols are nothing but the connection coefficient in the corresponding coordinate frame:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^rh_ph,ph = -rh \n", "Gam^ph_rh,ph = 1/rh " ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(cylindrical.frame(), cylindrical, only_nonredundant=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The connection coefficients with respect to the orthonormal (non-coordinate) frames are (again only nonzero values are displayed):" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^1_22 = -1/r \n", "Gam^1_33 = -1/r \n", "Gam^2_12 = 1/r \n", "Gam^2_33 = -cos(th)/(r*sin(th)) \n", "Gam^3_13 = 1/r \n", "Gam^3_23 = cos(th)/(r*sin(th)) " ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(spherical_frame, spherical)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^1_22 = -1/rh \n", "Gam^2_12 = 1/rh " ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(cylindrical_frame, cylindrical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\nabla_g$ is the connection involved in differential operators:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "from sage.manifolds.operators import * " ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grad(f) == nabla(f).up(g)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla(f) == grad(f).down(g)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(u) == nabla(u).trace()" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(v) == nabla(v).trace()" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(f) == nabla(nabla(f).up(g)).trace()" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(u) == nabla(nabla(u).up(g)).trace(1,2)" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(v) == nabla(nabla(v).up(g)).trace(1,2)" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 8.8.beta2", "language": "", "name": "sagemath" }, "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.15" } }, "nbformat": 4, "nbformat_minor": 2 }