{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vector calculus with SageMath\n", "\n", "## Part 4: Changing coordinates\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_change.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 9.0.beta1, Release Date: 2019-10-12'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display math formulas using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cartesian coordinates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start by declaring the 3-dimensional Euclidean space $\\mathbb{E}^3$, with $(x,y,z)$ as Cartesian coordinates:" ] }, { "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 endowed with the chart of Cartesian coordinates:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (x, y, z))]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us denote by `cartesian` the chart of Cartesian coordinates:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (E^3, (x, y, z))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian = E.cartesian_coordinates()\n", "cartesian" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The access to the individual coordinates is performed via the square bracket operator:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian[1]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(x, y, z)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Thanks to use of `` when declaring `E`, the Python variables `x`, `y` and `z` have been created (i.e. there is no need to declare them by something like `y = var('y')`); they represent the coordinates $(x,y,z)$ as symbolic expressions:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y is cartesian[2]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each of the Cartesian coordinates spans the entire real line:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x: (-oo, +oo); y: (-oo, +oo); z: (-oo, +oo)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian.coord_range()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Being the only coordinate chart created so far, `cartesian` is the default chart on `E`:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian is E.default_chart()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is endowed with the orthonormal vector frame $(e_x, e_y, e_z)$ associated with Cartesian coordinates: " ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (E^3, (e_x,e_y,e_z))]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us denote it by `cartesian_frame`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (e_x,e_y,e_z))" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian_frame = E.cartesian_frame()\n", "cartesian_frame" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian_frame is E.default_frame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each element of this frame is a unit vector field; for instance, we have $e_x\\cdot e_x = 1$:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector field e_x on the Euclidean space E^3" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e_x = cartesian_frame[1]\n", "e_x" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "1" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e_x.dot(e_x).expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "as well as $e_x\\cdot e_y = 0$:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "0" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e_y = cartesian_frame[2]\n", "e_x.dot(e_y).expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Spherical coordinates\n", "\n", "Spherical coordinates are introduced by" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (E^3, (r, th, ph))" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical. = E.spherical_coordinates()\n", "spherical" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(r, th, ph)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical[:]" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r: (0, +oo); th: (0, pi); ph: [0, 2*pi] (periodic)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical.coord_range()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is now endowed with two coordinate charts:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (x, y, z)), Chart (E^3, (r, th, ph))]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The change-of-coordinate formulas have been automatically implemented during the above call `E.spherical_coordinates()`:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "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": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.coord_change(spherical, cartesian).display()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "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": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.coord_change(cartesian, spherical).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is also now endowed with three vector frames:" ] }, { "cell_type": "code", "execution_count": 24, "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))]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second one is the coordinate frame of spherical coordinates, while the third one is the standard orthonormal frame associated with spherical coordinates. For Cartesian coordinates, the coordinate frame and the orthonormal frame coincide: it is $(e_x,e_y,e_z)$. For spherical coordinates, the orthonormal frame is denoted $(e_r,e_\\theta,e_\\phi)$ and is returned by the method `spherical_frame()`:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (E^3, (e_r,e_th,e_ph))" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical_frame = E.spherical_frame()\n", "spherical_frame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may check that it is an orthonormal frame:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[1, 0, 0], [0, 1, 0], [0, 0, 1]]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "es = spherical_frame\n", "[[es[i].dot(es[j]).expr() for j in E.irange()] for i in E.irange()]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal spherical frame expressed in terms of the Cartesian one: " ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_r = cos(ph)*sin(th) e_x + sin(ph)*sin(th) e_y + cos(th) e_z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_th = cos(ph)*cos(th) e_x + cos(th)*sin(ph) e_y - sin(th) e_z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = -sin(ph) e_x + cos(ph) e_y" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in spherical_frame:\n", " show(vec.display(cartesian_frame, spherical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reverse transformation:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_x = cos(ph)*sin(th) e_r + cos(ph)*cos(th) e_th - sin(ph) e_ph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_y = sin(ph)*sin(th) e_r + cos(th)*sin(ph) e_th + cos(ph) e_ph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_z = cos(th) e_r - sin(th) e_th" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in cartesian_frame:\n", " show(vec.display(spherical_frame, spherical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal frame $(e_r,e_\\theta,e_\\phi)$ expressed in terms on the coordinate frame $\\left(\\frac{\\partial}{\\partial r}, \\frac{\\partial}{\\partial\\theta}, \\frac{\\partial}{\\partial \\phi}\\right)$ (the latter being returned by the method `frame()` acting on the chart `spherical`):" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_r = d/dr" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_th = 1/r d/dth" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = 1/(r*sin(th)) d/dph" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in spherical_frame:\n", " show(vec.display(spherical.frame(), spherical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cylindrical coordinates\n", "\n", "Cylindrical coordinates are introduced by" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (E^3, (rh, ph, z))" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical. = E.cylindrical_coordinates()\n", "cylindrical" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(rh, ph, z)" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical[:]" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rh is cylindrical[1]" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "rh: (0, +oo); ph: [0, 2*pi] (periodic); z: (-oo, +oo)" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical.coord_range()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is now endowed with three coordinate charts:" ] }, { "cell_type": "code", "execution_count": 34, "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": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The transformations linking the cylindrical coordinates to the Cartesian ones are" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = rh*cos(ph)\n", "y = rh*sin(ph)\n", "z = z" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.coord_change(cylindrical, cartesian).display()" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "rh = sqrt(x^2 + y^2)\n", "ph = arctan2(y, x)\n", "z = z" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.coord_change(cartesian, cylindrical).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\mathbb{E}^3$ is also now endowed with five vector frames:" ] }, { "cell_type": "code", "execution_count": 37, "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": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal frame associated with cylindrical coordinates is $(e_\\rho, e_\\phi, e_z)$:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector frame (E^3, (e_rh,e_ph,e_z))" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical_frame = E.cylindrical_frame()\n", "cylindrical_frame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may check that it is an orthonormal frame:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[[1, 0, 0], [0, 1, 0], [0, 0, 1]]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ec = cylindrical_frame\n", "[[ec[i].dot(ec[j]).expr() for j in E.irange()] for i in E.irange()]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal cylindrical frame expressed in terms of the Cartesian one: " ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_rh = cos(ph) e_x + sin(ph) e_y" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = -sin(ph) e_x + cos(ph) e_y" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_z = e_z" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in cylindrical_frame:\n", " show(vec.display(cartesian_frame, cylindrical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reverse transformation:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_x = cos(ph) e_rh - sin(ph) e_ph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_y = sin(ph) e_rh + cos(ph) e_ph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_z = e_z" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in cartesian_frame:\n", " show(vec.display(cylindrical_frame, cylindrical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal cylindrical frame expressed in terms of the spherical one: " ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_rh = sin(th) e_r + cos(th) e_th" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = e_ph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_z = cos(th) e_r - sin(th) e_th" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in cylindrical_frame:\n", " show(vec.display(spherical_frame, spherical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reverse transformation:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_r = sin(th) e_rh + cos(th) e_z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_th = cos(th) e_rh - sin(th) e_z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = e_ph" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in spherical_frame:\n", " show(vec.display(cylindrical_frame, spherical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The orthonormal frame $(e_\\rho,e_\\phi,e_z)$ expressed in terms on the coordinate frame $\\left(\\frac{\\partial}{\\partial\\rho}, \\frac{\\partial}{\\partial\\phi}, \\frac{\\partial}{\\partial z}\\right)$ (the latter being returned by the method `frame()` acting on the chart `cylindrical`):" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "e_rh = d/drh" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_ph = 1/rh d/dph" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "e_z = d/dz" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for vec in cylindrical_frame:\n", " show(vec.display(cylindrical.frame(), cylindrical))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Coordinates of a point\n", "\n", "We introduce a point $p\\in \\mathbb{E}^3$ via the generic SageMath syntax for creating an element from its parent (here $\\mathbb{E}^3$), i.e. the call operator `()`, with the coordinates of the point as the first argument:" ] }, { "cell_type": "code", "execution_count": 45, "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": "markdown", "metadata": {}, "source": [ "Actually, since the Cartesian coordinates are the default ones, the above writting is equivalent to" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the Euclidean space E^3\n" ] } ], "source": [ "p = E((-1, 1,0), name='p')\n", "print(p)" ] }, { "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": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(-1, 1, 0)" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian(p)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(2), 1/2*pi, 3/4*pi)" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical(p)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(sqrt(2), 3/4*pi, 0)" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A point defined from its spherical coordinates:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point q on the Euclidean space E^3\n" ] } ], "source": [ "q = E((4,pi/3,pi), chart=spherical, name='q')\n", "print(q)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(4, 1/3*pi, pi)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spherical(q)" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(-2*sqrt(3), 0, 2)" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cartesian(q)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(2*sqrt(3), pi, 2)" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cylindrical(q)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Expressions of a scalar field in various coordinate systems" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define a scalar field on $\\mathbb{E}^3$ from its expression in Cartesian coordinates:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "f = E.scalar_field(x^2+y^2 - z^2, name='f')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that since the Cartesian coordinates are the default ones, we did not specify them in the above definition. Thanks to the known coordinate transformations, the expression of $f$ in terms of other coordinates is automatically computed:" ] }, { "cell_type": "code", "execution_count": 55, "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": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can limit the output to a single coordinate system:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: E^3 --> R\n", " (x, y, z) |--> x^2 + y^2 - z^2" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display(cartesian)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f: E^3 --> R\n", " (rh, ph, z) |--> rh^2 - z^2" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.display(cylindrical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The coordinate expression in a given coordinate system is obtained via the method `expr()`" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x^2 + y^2 - z^2" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr() # expression in the default chart (Cartesian coordinates)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-2*r^2*cos(th)^2 + r^2" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(spherical)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "rh^2 - z^2" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr(cylindrical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The value of $f$ at points $p$ and $q$:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "2" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(p)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "8" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(q)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course, we may define a scalar field from its coordinate expression in a chart that is not the default one:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "g = E.scalar_field(r^2, chart=spherical, name='g')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of using the keyword argument `chart`, one can pass a dictionary as the first argument, with the chart as key:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "g = E.scalar_field({spherical: r^2}, name='g')" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "g: E^3 --> R\n", " (x, y, z) |--> x^2 + y^2 + z^2\n", " (r, th, ph) |--> r^2\n", " (rh, ph, z) |--> rh^2 + z^2" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Expression of a vector field in various frames\n", "\n", "Let us introduce a vector field on $\\mathbb{E}^3$ by its components in the Cartesian frame. Since the latter is the default vector frame on $\\mathbb{E}^3$, it suffices to write:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y e_x + x e_y + z^2 e_z" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = E.vector_field(-y, x, z^2, name='v')\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Equivalently, a vector field can be defined directly from its expansion on the Cartesian frame: " ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-y e_x + x e_y + z^2 e_z" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ex, ey, ez = cartesian_frame[:]\n", "v = -y*ex + x*ey + z^2*ez\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us provide `v` with some name, as above:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y e_x + x e_y + z^2 e_z" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.set_name('v')\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The components of $v$ are returned by the square bracket operator:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-y" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[1]" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[-y, x, z^2]" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The expression of $v$ in terms of the orthonormal spherical frame is obtained by" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = z^3/sqrt(x^2 + y^2 + z^2) e_r - sqrt(x^2 + y^2)*z^2/sqrt(x^2 + y^2 + z^2) e_th + sqrt(x^2 + y^2) e_ph" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(spherical_frame)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We note that the components are still expressed in the default chart (Cartesian coordinates). To have them expressed in the spherical chart, it suffices to pass the latter as a second argument to `display()`:" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = r^2*cos(th)^3 e_r - r^2*cos(th)^2*sin(th) e_th + r*sin(th) e_ph" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(spherical_frame, spherical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, the components of $v$ are obtained by means of the square bracket operator, by specify the vector frame as first argument, and the coordinate chart as the last one:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "z^3/sqrt(x^2 + y^2 + z^2)" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[spherical_frame, 1]" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "r^2*cos(th)^3" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[spherical_frame, 1, spherical]" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[r^2*cos(th)^3, -r^2*cos(th)^2*sin(th), r*sin(th)]" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[spherical_frame, :, spherical]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, the expression of $v$ in terms of the cylindrical frame is" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = rh e_ph + z^2 e_z" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(cylindrical_frame, cylindrical)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[0, rh, z^2]" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[cylindrical_frame,:,cylindrical]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The value of the vector field $v$ at point $p$:" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector v at Point p on the Euclidean space E^3\n" ] } ], "source": [ "vp = v.at(p)\n", "print(vp)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -e_x - e_y" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.display()" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = sqrt(2) e_ph" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.display(spherical_frame.at(p))" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = sqrt(2) e_ph" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.display(cylindrical_frame.at(p))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The value of the vector field $v$ at point $q$:" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector v at Point q on the Euclidean space E^3\n" ] } ], "source": [ "vq = v.at(q)\n", "print(vq)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -2*sqrt(3) e_y + 4 e_z" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vq.display()" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 2 e_r - 2*sqrt(3) e_th + 2*sqrt(3) e_ph" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vq.display(spherical_frame.at(q))" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 2*sqrt(3) e_ph + 4 e_z" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vq.display(cylindrical_frame.at(q))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Changing the default coordinates and default vector frame\n", "\n", "At any time, one may change the default coordinates by the method `set_default_chart`:" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [], "source": [ "E.set_default_chart(spherical)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-2*r^2*cos(th)^2 + r^2" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.expr()" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -r*sin(ph)*sin(th) e_x + r*cos(ph)*sin(th) e_y + r^2*cos(th)^2 e_z" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the default vector frame is still the Cartesian one; to change to the orthonormal spherical frame, we use" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [], "source": [ "E.set_default_frame(spherical_frame)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = r^2*cos(th)^3 e_r - r^2*cos(th)^2*sin(th) e_th + r*sin(th) e_ph" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y e_x + x e_y + z^2 e_z" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display(cartesian_frame, cartesian)" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.0.beta1", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }