{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vector calculus in Cartesian and spherical coordinates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*This worksheet illustrates some features of [SageManifolds](http://sagemanifolds.obspm.fr/) (version 1.0, as included in SageMath 7.5) regarding vector calculus in the Euclidean 3-space by means of Cartesian and spherical coordinates.*\n", "\n", "Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Worksheets/v1.0/SM_Cartesian_spherical-3D.ipynb) to download the worksheet file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, via the command `sage -n jupyter`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*NB:* a version of SageMath at least equal to 7.5 is required to run this worksheet:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'SageMath version 7.5, Release Date: 2017-01-11'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Euclidean 3-space and Cartesian coordinates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display mathematical objects using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We then introduce the Euclidean space as a 3-dimensional differentiable manifold:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3-dimensional differentiable manifold M\n" ] } ], "source": [ "M = Manifold(3, 'M', start_index=1)\n", "print(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We then introduce the Cartesian coordinates $(x,y,z)$ as the chart `cart` on $M$:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Chart (M, (x, y, z))\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cart. = M.chart()\n", "print(cart)\n", "cart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Spherical coordinates\n", "\n", "We introduce spherical coordinates $(r,\\theta,\\phi)$ as the chart `spher` on $M$:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Chart (M, (r, th, ph))\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (r, th, ph))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher. = M.chart(r'r:(0,+oo) th:(0,pi):\\theta ph:(0,2*pi):\\phi')\n", "print(spher)\n", "spher" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Spherical coordinates do not form a regular coordinate system of the Euclidean space. So declaring that they span $M$ means that, strictly speaking, the manifold $M$ is not the whole Euclidean space, but the Euclidean space minus some half plane (the azimuthal origin). However, in this worksheet, this difference will not matter. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The change of coordinates $(r,\\theta,\\phi) \\rightarrow (x,y,z)$ is introduced as a transition map from chart `spher` to chart `cart`:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = r*cos(ph)*sin(th)\n", "y = r*sin(ph)*sin(th)\n", "z = r*cos(th)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher_to_cart = spher.transition_map(cart, [r*sin(th)*cos(ph), r*sin(th)*sin(ph), r*cos(th)])\n", "spher_to_cart.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The inverse is also set:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check of the inverse coordinate transformation:\n", " r == r\n", " th == arctan2(r*sin(th), r*cos(th))\n", " ph == arctan2(r*sin(ph)*sin(th), r*cos(ph)*sin(th))\n", " x == x\n", " y == y\n", " z == z\n" ] } ], "source": [ "spher_to_cart.set_inverse(sqrt(x^2+y^2+z^2), atan2(sqrt(x^2+y^2),z), atan2(y, x),\n", " verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The check that the provided formulas do correspond to the inverse change of coordinates is passed, modulo some lack of simplification in some trigonometrical formulas involving the function `arctan2`. " ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r = sqrt(x^2 + y^2 + z^2)\n", "th = arctan2(sqrt(x^2 + y^2), z)\n", "ph = arctan2(y, x)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cart_to_spher = spher_to_cart.inverse()\n", "cart_to_spher.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The natural vector frame of spherical coordinates is" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dr,d/dth,d/dph))" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spher.frame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We shall expand vector and tensor fields on the orthonormal frame $(e_1, e_2, e_3)$ associated with spherical coordinates, which is related to the natural frame $(\\partial/\\partial r, \\partial/\\partial\\theta, \\partial/\\partial\\phi)$ displayed above by means of the following field of automorphisms: " ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "d/dr*dr + 1/r d/dth*dth + 1/(r*sin(th)) d/dph*dph" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "to_orthonormal = M.automorphism_field()\n", "to_orthonormal[spher.frame(),1,1,spher] = 1\n", "to_orthonormal[spher.frame(),2,2,spher] = 1/r\n", "to_orthonormal[spher.frame(),3,3,spher] = 1/(r*sin(th))\n", "to_orthonormal.display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In other words, the change-of-basis matrix is " ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[ 1 0 0]\n", "[ 0 1/r 0]\n", "[ 0 0 1/(r*sin(th))]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "to_orthonormal[spher.frame(),:,spher] " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We construct the orthonormal frame from the natural frame of spherical coordinates by this change of basis:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector frame (M, (e_1,e_2,e_3))\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (M, (e_1,e_2,e_3))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es = spher.frame().new_frame(to_orthonormal, 'e')\n", "print(es)\n", "es" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_1 = d/dr" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[1].display(spher.frame(), spher)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_2 = 1/r d/dth" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[2].display(spher.frame(), spher)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_3 = 1/(r*sin(th)) d/dph" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[3].display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we do not specify the frame and coordinates for the display, we get it in terms of the default ones (i.e. Cartesian frame and Cartesian coordinates):" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_1 = x/sqrt(x^2 + y^2 + z^2) d/dx + y/sqrt(x^2 + y^2 + z^2) d/dy + z/sqrt(x^2 + y^2 + z^2) d/dz" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[1].display()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_2 = x*z/(sqrt(x^2 + y^2 + z^2)*sqrt(x^2 + y^2)) d/dx + y*z/(sqrt(x^2 + y^2 + z^2)*sqrt(x^2 + y^2)) d/dy - sqrt(x^2 + y^2)/sqrt(x^2 + y^2 + z^2) d/dz" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[2].display()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_3 = -y/sqrt(x^2 + y^2) d/dx + x/sqrt(x^2 + y^2) d/dy" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es[3].display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By construction, the change of frame $(\\partial/\\partial r, \\partial/\\partial \\theta, \\partial/\\partial \\phi) \\rightarrow (e_1,e_2,e_3)$ is known. We form the change of frame $(\\partial/\\partial x, \\partial/\\partial y, \\partial/\\partial z)\\rightarrow (e_1,e_2,e_3)$ by composition of $(\\partial/\\partial x, \\partial/\\partial y, \\partial/\\partial z)\\rightarrow (\\partial/\\partial r, \\partial/\\partial \\theta, \\partial/\\partial \\phi)$ with \n", "$(\\partial/\\partial r, \\partial/\\partial \\theta, \\partial/\\partial \\phi) \\rightarrow (e_1,e_2,e_3)$:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[cos(ph)*sin(th) cos(ph)*cos(th) -sin(ph)]\n", "[sin(ph)*sin(th) cos(th)*sin(ph) cos(ph)]\n", "[ cos(th) -sin(th) 0]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.set_change_of_frame(cart.frame(), es, \n", " M.change_of_frame(spher.frame(), es) * M.change_of_frame(cart.frame(), \n", " spher.frame()),\n", " compute_inverse=False)\n", "M.change_of_frame(cart.frame(), es)[:, spher]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we form the inverse change of frame as:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[cos(ph)*sin(th) sin(ph)*sin(th) cos(th)]\n", "[cos(ph)*cos(th) cos(th)*sin(ph) -sin(th)]\n", "[ -sin(ph) cos(ph) 0]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.set_change_of_frame(es, cart.frame(), \n", " M.change_of_frame(spher.frame(), cart.frame()) * \n", " M.change_of_frame(es, spher.frame()),\n", " compute_inverse=False)\n", "M.change_of_frame(es, cart.frame())[:, spher]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this stage, the manifold (user) atlas is" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (M, (x, y, z)), Chart (M, (r, th, ph))]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default chart is the first one introduced on the manifold (it can be changed by means of the function `M.set_default_chart`):" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (M, (x, y, z))" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_chart()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following vector frames have been introduced on the manifold:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (M, (d/dx,d/dy,d/dz)),\n", " Coordinate frame (M, (d/dr,d/dth,d/dph)),\n", " Vector frame (M, (e_1,e_2,e_3))]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default frame is the first one introduced on the manifold (it can be changed by means of the function `M.set_default_frame`):" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (M, (d/dx,d/dy,d/dz))" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.default_frame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following changes of frame have been defined:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "{(Coordinate frame (M, (d/dr,d/dth,d/dph)),\n", " Coordinate frame (M, (d/dx,d/dy,d/dz))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M,\n", " (Coordinate frame (M, (d/dr,d/dth,d/dph)),\n", " Vector frame (M, (e_1,e_2,e_3))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M,\n", " (Coordinate frame (M, (d/dx,d/dy,d/dz)),\n", " Coordinate frame (M, (d/dr,d/dth,d/dph))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M,\n", " (Coordinate frame (M, (d/dx,d/dy,d/dz)),\n", " Vector frame (M, (e_1,e_2,e_3))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M,\n", " (Vector frame (M, (e_1,e_2,e_3)),\n", " Coordinate frame (M, (d/dr,d/dth,d/dph))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M,\n", " (Vector frame (M, (e_1,e_2,e_3)),\n", " Coordinate frame (M, (d/dx,d/dy,d/dz))): Field of tangent-space automorphisms on the 3-dimensional differentiable manifold M}" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.changes_of_frame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vector field defined in terms of its Cartesian components\n", "\n", "We define the vector field $U$ in terms of its components with respect to the default frame, i.e. the Cartesian frame:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "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": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U = M.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": "markdown", "metadata": {}, "source": [ "We can ask for its components in terms of the spherical orthonormal frame:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U = (x*U_x(x, y, z) + y*U_y(x, y, z) + z*U_z(x, y, z))/sqrt(x^2 + y^2 + z^2) e_1 - (x^2*U_z(x, y, z) + y^2*U_z(x, y, z) - (x*U_x(x, y, z) + y*U_y(x, y, z))*z)/(sqrt(x^2 + y^2 + z^2)*sqrt(x^2 + y^2)) e_2 - (y*U_x(x, y, z) - x*U_y(x, y, z))/sqrt(x^2 + y^2) e_3" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display(es)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U^1 = (x*U_x(x, y, z) + y*U_y(x, y, z) + z*U_z(x, y, z))/sqrt(x^2 + y^2 + z^2) \n", "U^2 = -(x^2*U_z(x, y, z) + y^2*U_z(x, y, z) - (x*U_x(x, y, z) + y*U_y(x, y, z))*z)/(sqrt(x^2 + y^2 + z^2)*sqrt(x^2 + y^2)) \n", "U^3 = -(y*U_x(x, y, z) - x*U_y(x, y, z))/sqrt(x^2 + y^2) " ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display_comp(es)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above components are displayed in terms of the default chart (Cartesian coordinates). If we want them in terms of spherical coordinates, we have to specify it, by setting the second argument of the function `display` to `spher`:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U = (U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*sin(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph)*sin(th) + U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th)) e_1 + (U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*cos(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th)*sin(ph) - U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(th)) e_2 + (U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph) - U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph)) e_3" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display(es, spher)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U^1 = U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*sin(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph)*sin(th) + U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th) \n", "U^2 = U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*cos(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th)*sin(ph) - U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(th) \n", "U^3 = U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph) - U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph) " ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display_comp(es, spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may also ask for the components of $U$ w.r.t. the natural frame of spherical coordinates:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U = (x*U_x(x, y, z) + y*U_y(x, y, z) + z*U_z(x, y, z))/sqrt(x^2 + y^2 + z^2) d/dr - (x^2*U_z(x, y, z) + y^2*U_z(x, y, z) - (x*U_x(x, y, z) + y*U_y(x, y, z))*z)*sqrt(x^2 + y^2)/(x^4 + 2*x^2*y^2 + y^4 + (x^2 + y^2)*z^2) d/dth - (y*U_x(x, y, z) - x*U_y(x, y, z))/(x^2 + y^2) d/dph" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display(spher.frame())" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "U = (U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*sin(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph)*sin(th) + U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th)) d/dr + (U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph)*cos(th) + U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(th)*sin(ph) - U_z(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(th))/r d/dth + (U_y(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*cos(ph) - U_x(r*cos(ph)*sin(th), r*sin(ph)*sin(th), r*cos(th))*sin(ph))/(r*sin(th)) d/dph" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "U.display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vector field defined in terms of its spherical components\n", "\n", "Let us consider a vector field $V$ defined by its components with respect to the orthonormal spherical frame `es` = $(e_1, e_2, e_3)$:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "V = V_1(r, th, ph) e_1 + V_2(r, th, ph) e_2 + V_3(r, th, ph) e_3" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "V = M.vector_field(name='V')\n", "V[es,:,spher] = [function('V_1')(r,th,ph), function('V_2')(r,th,ph), function('V_3')(r,th,ph)]\n", "V.display(es, spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may ask for the components of this vector field with respect to the Cartesian frame (first argument `cart.frame()`), each component being expressed in terms of spherical coordinates (second argument `spher`):" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "V = (V_2(r, th, ph)*cos(ph)*cos(th) + V_1(r, th, ph)*cos(ph)*sin(th) - V_3(r, th, ph)*sin(ph)) d/dx + (V_2(r, th, ph)*cos(th)*sin(ph) + V_1(r, th, ph)*sin(ph)*sin(th) + V_3(r, th, ph)*cos(ph)) d/dy + (V_1(r, th, ph)*cos(th) - V_2(r, th, ph)*sin(th)) d/dz" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "V.display(cart.frame(), spher)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "V^x = V_2(r, th, ph)*cos(ph)*cos(th) + V_1(r, th, ph)*cos(ph)*sin(th) - V_3(r, th, ph)*sin(ph) \n", "V^y = V_2(r, th, ph)*cos(th)*sin(ph) + V_1(r, th, ph)*sin(ph)*sin(th) + V_3(r, th, ph)*cos(ph) \n", "V^z = V_1(r, th, ph)*cos(th) - V_2(r, th, ph)*sin(th) " ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "V.display_comp(cart.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Euclidean metric\n", "\n", "The standard Euclidean metric is introduced as a Riemannian metric on $M$, whose components with respect to the Cartesian frame are $\\mathrm{diag}(1,1,1)$:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dx*dx + dy*dy + dz*dz" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = M.riemannian_metric('g')\n", "g[1,1], g[2,2], g[3,3] = 1, 1, 1\n", "g.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The components of $g$ with respect to the spherical coordinates are then:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since `es` = $(e_1,e_2,e_3)$ is an orthonormal frame, the components of $g$ with respect to it are $\\mathrm{diag}(1,1,1)$:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g = e^1*e^1 + e^2*e^2 + e^3*e^3" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display(es, spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The covariant derivative operator $\\nabla$ is introduced as the (Levi-Civita) connection associated with $g$: " ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "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": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla = g.connection()\n", "print(nabla)\n", "nabla" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The connection coefficient with respect to the natural frame of spherical coordinates (Christoffel symbols) are:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Gam^r_th,th = -r \n", "Gam^r_ph,ph = -r*sin(th)^2 \n", "Gam^th_r,th = 1/r \n", "Gam^th_th,r = 1/r \n", "Gam^th_ph,ph = -cos(th)*sin(th) \n", "Gam^ph_r,ph = 1/r \n", "Gam^ph_th,ph = cos(th)/sin(th) \n", "Gam^ph_ph,r = 1/r \n", "Gam^ph_ph,th = cos(th)/sin(th) " ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(spher.frame(), spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "while those with respect to the orthonormal spherical frame are:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "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": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabla.display(es, spher)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The covariant derivative of $U$ is" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field nabla_g(U) of type (1,1) on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "nabU = nabla(U)\n", "print(nabU)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "nabla_g(U) = d(U_x)/dx d/dx*dx + d(U_x)/dy d/dx*dy + d(U_x)/dz d/dx*dz + d(U_y)/dx d/dy*dx + d(U_y)/dy d/dy*dy + d(U_y)/dz d/dy*dz + d(U_z)/dx d/dz*dx + d(U_z)/dy d/dz*dy + d(U_z)/dz d/dz*dz" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabU.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "while the covariant derivative of $V$ is" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensor field nabla_g(V) of type (1,1) on the 3-dimensional differentiable manifold M\n" ] } ], "source": [ "nabV = nabla(V)\n", "print(nabV)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "nabla_g(V) = d(V_1)/dr e_1*e^1 - (V_2(r, th, ph) - d(V_1)/dth)/r e_1*e^2 - (V_3(r, th, ph)*sin(th) - d(V_1)/dph)/(r*sin(th)) e_1*e^3 + d(V_2)/dr e_2*e^1 + (V_1(r, th, ph) + d(V_2)/dth)/r e_2*e^2 - (V_3(r, th, ph)*cos(th) - d(V_2)/dph)/(r*sin(th)) e_2*e^3 + d(V_3)/dr e_3*e^1 + d(V_3)/dth/r e_3*e^2 + (V_2(r, th, ph)*cos(th) + V_1(r, th, ph)*sin(th) + d(V_3)/dph)/(r*sin(th)) e_3*e^3" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nabV.display(es, spher)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "SageMath 7.5", "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.13" } }, "nbformat": 4, "nbformat_minor": 0 }