{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vector calculus with SageMath\n", "\n", "## 1. Using Cartesian coordinates\n", "\n", "This notebook illustrates operations on vector fields on Euclidean spaces, as introduced in Trac ticket [#24623](https://trac.sagemath.org/ticket/24623)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 8.2.rc4, Release Date: 2018-04-20'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from sage.manifolds.operators import * # to get the operators grad, div, curl, etc." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The 3-dimensional Euclidean space\n", "\n", "We start by declaring the 3-dimensional Euclidean space $\\mathbb{E}^3$, with $(x,y,z)$ as Cartesian coordinates:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Euclidean space E^3\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "Euclidean space E^3" ] }, "execution_count": 4, "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": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (x, y, z))]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "as well as with the associated orthonormal vector frame:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (E^3, (e_x,e_y,e_z))]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vector fields" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define a vector field on $\\mathbb{E}^3$ from its components in the vector frame $(e_x,e_y,e_z)$:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y e_x + x e_y + sin(x*y*z) e_z" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = E.vector_field(-y, x, sin(x*y*z), name='v')\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access to the components of $v$ via the square bracket operator:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-y" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[1]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[-y, x, sin(x*y*z)]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A vector field can evaluated at any point of $\\mathbb{E}^3$:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point p on the Euclidean space E^3\n" ] } ], "source": [ "p = E((3,-2,1), name='p')\n", "print(p)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(3, -2, 1)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.coordinates()" ] }, { "cell_type": "code", "execution_count": 12, "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": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = 2 e_x + 3 e_y - sin(6) e_z" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vp.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vector fields can be plotted (see the [list of options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/vectorfield.html#sage.manifolds.differentiable.vectorfield.VectorField.plot) for customizing the plot)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.plot(max_range=1.5, scale=0.5, viewer='threejs', online=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may define a vector field with generic components:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u = u_x(x, y, z) e_x + u_y(x, y, z) e_y + u_z(x, y, z) e_z" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u = E.vector_field(function('u_x')(x,y,z),\n", " function('u_y')(x,y,z),\n", " function('u_z')(x,y,z),\n", " name='u')\n", "u.display()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[u_x(x, y, z), u_y(x, y, z), u_z(x, y, z)]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u[:]" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u = u_x(3, -2, 1) e_x + u_y(3, -2, 1) e_y + u_z(3, -2, 1) e_z" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "up = u.at(p)\n", "up.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algebraic operations on vector fields\n", "\n", "### Dot product\n", "\n", "The dot (or scalar) product of the vector fields $u$ and $v$ is obtained by the method `dot_product`, which admits `dot` as a shortcut alias:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Scalar field u.v on the Euclidean space E^3" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = u.dot(v)\n", "s" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field u.v on the Euclidean space E^3\n" ] } ], "source": [ "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$s= u\\cdot v$ is a *scalar field*, i.e. a map $\\mathbb{E}^3 \\rightarrow \\mathbb{R}$:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u.v: E^3 --> R\n", " (x, y, z) |--> -y*u_x(x, y, z) + x*u_y(x, y, z) + sin(x*y*z)*u_z(x, y, z)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It maps point of $\\mathbb{E}^3$ to real numbers:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-sin(6)*u_z(3, -2, 1) + 2*u_x(3, -2, 1) + 3*u_y(3, -2, 1)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Its coordinate expression is" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-y*u_x(x, y, z) + x*u_y(x, y, z) + sin(x*y*z)*u_z(x, y, z)" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Norm\n", "\n", "The norm of a vector field is " ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Scalar field |u| on the Euclidean space E^3" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = norm(u)\n", "s" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "|u|: E^3 --> R\n", " (x, y, z) |--> sqrt(u_x(x, y, z)^2 + u_y(x, y, z)^2 + u_z(x, y, z)^2)" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "sqrt(u_x(x, y, z)^2 + u_y(x, y, z)^2 + u_z(x, y, z)^2)" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The norm is related to the dot product by $\\|u\\|^2 = u\\cdot u$, as we can check:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm(u)^2 == u.dot(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For $v$, we have:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "sqrt(x^2 + y^2 + sin(x*y*z)^2)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm(v).expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cross product\n", "\n", "The cross product of $u$ by $v$ is obtained by the method `cross_product`, which admits `cross` as a shortcut alias:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector field u x v on the Euclidean space E^3\n" ] } ], "source": [ "s = u.cross(v)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "u x v = (sin(x*y*z)*u_y(x, y, z) - x*u_z(x, y, z)) e_x + (-sin(x*y*z)*u_x(x, y, z) - y*u_z(x, y, z)) e_y + (x*u_x(x, y, z) + y*u_y(x, y, z)) e_z" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scalar triple product\n", "\n", "Let us introduce a third vector field. As a example, we do not pass the components as arguments of `vector_field`, as we did for $u$ and $v$; instead, we set them in a second stage, via the square bracket operator, any unset component being assumed to be zero:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "w = x*z e_x + y*z e_y" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w = E.vector_field(name='w')\n", "w[1] = x*z\n", "w[2] = y*z\n", "w.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The scalar triple product of the vector fields $u$, $v$ and $w$ is obtained as follows: " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scalar field epsilon(u,v,w) on the Euclidean space E^3\n" ] } ], "source": [ "triple_product = E.scalar_triple_product()\n", "s = triple_product(u, v, w)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "-(y*u_x(x, y, z) - x*u_y(x, y, z))*z*sin(x*y*z) - (x^2*u_z(x, y, z) + y^2*u_z(x, y, z))*z" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us check that the scalar triple product of $u$, $v$ and $w$ is $u\\cdot(v\\times w)$:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s == u.dot(v.cross(w))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Differential operators" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gradient of a scalar field\n", "\n", "We first introduce a scalar field, via its expression in terms of Cartesian coordinates; in this example, we consider a unspecified function of $(x,y,z)$:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "F: E^3 --> R\n", " (x, y, z) |--> f(x, y, z)" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F = E.scalar_field(function('f')(x,y,z), name='F')\n", "F.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The value of $F$ at a point:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "f(3, -2, 1)" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The gradient of $F$:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector field grad(F) on the Euclidean space E^3\n" ] } ], "source": [ "print(grad(F))" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "grad(F) = d(f)/dx e_x + d(f)/dy e_y + d(f)/dz e_z" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grad(F).display()" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "|grad(F)|: E^3 --> R\n", " (x, y, z) |--> sqrt((d(f)/dx)^2 + (d(f)/dy)^2 + (d(f)/dz)^2)" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "norm(grad(F)).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Divergence \n", "\n", "The divergence of a vector field:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "div(u): E^3 --> R\n", " (x, y, z) |--> d(u_x)/dx + d(u_y)/dy + d(u_z)/dz" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = div(u)\n", "s.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For $v$ and $w$, we have" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x*y*cos(x*y*z)" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(v).expr()" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "2*z" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(w).expr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An identity valid for any scalar field $F$ and any vector field $u$:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(F*u) == F*div(u) + u.dot(grad(F))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Curl\n", "\n", "The curl of a vector field:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Vector field curl(u) on the Euclidean space E^3\n" ] } ], "source": [ "s = curl(u)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(u) = (-d(u_y)/dz + d(u_z)/dy) e_x + (d(u_x)/dz - d(u_z)/dx) e_y + (-d(u_x)/dy + d(u_y)/dx) e_z" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To use the notation `rot` instead of `curl`, simply do" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "rot = curl" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An alternative is" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "from sage.manifolds.operators import curl as rot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have then" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(u) = (-d(u_y)/dz + d(u_z)/dy) e_x + (d(u_x)/dz - d(u_z)/dx) e_y + (-d(u_x)/dy + d(u_y)/dx) e_z" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rot(u).display()" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rot(u) == curl(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For $v$ and $w$, we have:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(v) = x*z*cos(x*y*z) e_x - y*z*cos(x*y*z) e_y + 2 e_z" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(v).display()" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(w) = -y e_x + x e_y" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(w).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The curl of a gradient is always zero:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(grad(F)) = 0" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(grad(F)).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The divergence of a curl is always zero:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "div(curl(u)): E^3 --> R\n", " (x, y, z) |--> 0" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "div(curl(u)).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An identity valid for any scalar field $F$ and any vector field $u$:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(F*u) == grad(F).cross(u) + F*curl(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Laplacian" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Laplacian of a scalar field:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Delta(F): E^3 --> R\n", " (x, y, z) |--> d^2(f)/dx^2 + d^2(f)/dy^2 + d^2(f)/dz^2" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = laplacian(F)\n", "s.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a scalar field, the Laplacian is nothing but the divergence of the gradient:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(F) == div(grad(F))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Laplacian of a vector field:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Delta(u) = (d^2(u_x)/dx^2 + d^2(u_x)/dy^2 + d^2(u_x)/dz^2) e_x + (d^2(u_y)/dx^2 + d^2(u_y)/dy^2 + d^2(u_y)/dz^2) e_y + (d^2(u_z)/dx^2 + d^2(u_z)/dy^2 + d^2(u_z)/dz^2) e_z" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(u).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the Cartesian frame, the components of the Laplacian of a vector field are nothing but the Laplacians of the components of the vector field, as we can check:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e = E.cartesian_frame()\n", "laplacian(u) == sum(laplacian(u[[i]])*e[i] for i in E.irange())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the above formula, `u[[i]]` return the $i$-th component of $u$ as a scalar field, while `u[i]` would have returned the coordinate expression of this scalar field; besides, `e` is the Cartesian frame:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "(Vector field e_x on the Euclidean space E^3,\n", " Vector field e_y on the Euclidean space E^3,\n", " Vector field e_z on the Euclidean space E^3)" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For $v$ and $w$, we have " ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Delta(v) = -(x^2*y^2 + (x^2 + y^2)*z^2)*sin(x*y*z) e_z" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(v).display()" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Delta(w) = 0" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplacian(w).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "curl(curl(u)) = (-d^2(u_x)/dy^2 - d^2(u_x)/dz^2 + d^2(u_y)/dxdy + d^2(u_z)/dxdz) e_x + (d^2(u_x)/dxdy - d^2(u_y)/dx^2 - d^2(u_y)/dz^2 + d^2(u_z)/dydz) e_y + (d^2(u_x)/dxdz + d^2(u_y)/dydz - d^2(u_z)/dx^2 - d^2(u_z)/dy^2) e_z" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(curl(u)).display()" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "grad(div(u)) = (d^2(u_x)/dx^2 + d^2(u_y)/dxdy + d^2(u_z)/dxdz) e_x + (d^2(u_x)/dxdy + d^2(u_y)/dy^2 + d^2(u_z)/dydz) e_y + (d^2(u_x)/dxdz + d^2(u_y)/dydz + d^2(u_z)/dz^2) e_z" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grad(div(u)).display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and we may check a famous identity:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "True" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curl(curl(u)) == grad(div(u)) - laplacian(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Customizations\n", "\n", "### Customizing the symbols of the orthonormal frame vectors\n", "\n", "By default, the vectors of the orthonormal frame associated with Cartesian coordinates are denoted $(e_x,e_y,e_z)$:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (e_x,e_y,e_z))" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "frame = E.cartesian_frame()\n", "frame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But this can be changed, thanks to the method `set_name`:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (a_x,a_y,a_z))" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "frame.set_name('a', indices=('x', 'y', 'z'))\n", "frame" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y a_x + x a_y + sin(x*y*z) a_z" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (hx,hy,hz))" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "frame.set_name(('hx', 'hy', 'hz'), \n", " latex_symbol=(r'\\mathbf{\\hat{x}}', r'\\mathbf{\\hat{y}}', \n", " r'\\mathbf{\\hat{z}}'))\n", "frame" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -y hx + x hy + sin(x*y*z) hz" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Customizing the coordinate symbols\n", "\n", "The coordinates symbols are defined within the angle brackets `<...>` at the construction of the Euclidean space. Above we did " ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [], "source": [ "E. = EuclideanSpace()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "which resulted in the coordinate symbols $(x,y,z)$ and in the corresponding Python variables `x`, `y` and `z` (SageMath symbolic expressions). To use other symbols, for instance $(X,Y,Z)$, it suffices to create `E` as" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [], "source": [ "E. = EuclideanSpace()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have then:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (X, Y, Z))]" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.atlas()" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Coordinate frame (E^3, (e_X,e_Y,e_Z))" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.cartesian_frame()" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -Y e_X + X e_Y + sin(X*Y*Z) e_Z" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = E.vector_field(-Y, X, sin(X*Y*Z), name='v')\n", "v.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default the LaTeX symbols of the coordinate coincide with the letters given within the angle brackets. But this can be adjusted through the optional argument `symbols` of the function `EuclideanSpace`, which has to be a string, usually prefixed by r (for raw string, in order to allow for the backslash character of LaTeX expressions). This string contains the coordinate fields separated by a blank space; each field contains the coordinate’s text symbol and possibly the coordinate’s LaTeX symbol (when the latter is different from the text symbol), both symbols being separated by a colon (`:`):" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Chart (E^3, (xi, et, ze))]" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E. = EuclideanSpace(symbols=r\"xi:\\xi et:\\eta ze:\\zeta\")\n", "E.atlas()" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = -et e_xi + xi e_et + sin(et*xi*ze) e_ze" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = E.vector_field(-et, xi, sin(xi*et*ze), name='v')\n", "v.display()" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 8.2.rc4", "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.14" } }, "nbformat": 4, "nbformat_minor": 2 }