{ "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 }