{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3D Plots of charts, vector fields and curves on $\\mathbb{S}^2$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This worksheet is based on SageMath 7.5.beta4 and the **three.js** viewer developed at [trac #12402](https://trac.sagemath.org/ticket/12402). \n", "\n", "*NB:* a version of SageMath at least equal to 7.5.beta4 is required:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'SageMath version 7.5.beta4, Release Date: 2016-11-24'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display mathematical objects using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also define a viewer for 3D plots (use `'threejs'` or `'jmol'` for interactive 3D graphics):" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "viewer3D = 'threejs' # must be 'jmol', 'tachyon', 'threejs' or None (default)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### $\\mathbb{S}^2$ as a 2-dimensional differentiable manifold\n", "\n", "We declare $\\mathbb{S}^2$ as a differentiable manifold of dimension 2 over $\\mathbb{R}$ and we endow it with the stereographic charts from the North pole (`stereoN`) and the South pole (`stereoS`):" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "[Coordinate frame (U, (d/dx,d/dy)),\n", " Coordinate frame (V, (d/dxp,d/dyp)),\n", " Coordinate frame (W, (d/dx,d/dy)),\n", " Coordinate frame (W, (d/dxp,d/dyp))]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S2 = Manifold(2, 'S^2', latex_name=r'\\mathbb{S}^2', start_index=1)\n", "U = S2.open_subset('U')\n", "V = S2.open_subset('V')\n", "S2.declare_union(U, V)\n", "stereoN. = U.chart()\n", "stereoS. = V.chart(r\"xp:x' yp:y'\")\n", "stereoN_to_S = stereoN.transition_map(stereoS, (x/(x^2+y^2), y/(x^2+y^2)), \n", " intersection_name='W',\n", " restrictions1= x^2+y^2!=0, \n", " restrictions2= xp^2+xp^2!=0)\n", "stereoS_to_N = stereoN_to_S.inverse()\n", "W = U.intersection(V)\n", "eU = stereoN.frame()\n", "eV = stereoS.frame()\n", "S2.frames()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Spherical coordinates

\n", "

The standard spherical (or polar) coordinates $(\\theta,\\phi)$ are defined on the open domain $A\\subset W \\subset \\mathbb{S}^2$ that is the complement of the \"origin meridian\"; since the latter is the half-circle defined by $y=0$ and $x\\geq 0$, we declare:

" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "x = -cos(ph)*sin(th)/(cos(th) - 1)\n", "y = -sin(ph)*sin(th)/(cos(th) - 1)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = W.open_subset('A', coord_def={stereoN.restrict(W): (y!=0, x<0), \n", " stereoS.restrict(W): (yp!=0, xp<0)})\n", "spher. = A.chart(r'th:(0,pi):\\theta ph:(0,2*pi):\\phi')\n", "spher_to_stereoN = spher.transition_map(stereoN.restrict(A), \n", " (sin(th)*cos(ph)/(1-cos(th)),\n", " sin(th)*sin(ph)/(1-cos(th))) )\n", "spher_to_stereoN.set_inverse(2*atan(1/sqrt(x^2+y^2)), atan2(-y,-x)+pi)\n", "spher_to_stereoN.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Embedding of $\\mathbb{S}^2$ into $\\mathbb{R}^3$\n", "\n", "Let us first declare $\\mathbb{R}^3$ as a 3-dimensional manifold covered by a single chart (Cartesian coordinates):" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Chart (R^3, (X, Y, Z))" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R3 = Manifold(3, 'R^3', r'\\mathbb{R}^3', start_index=1)\n", "cart. = R3.chart() ; cart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

The embedding of the sphere is defined as a differential mapping $\\Phi: \\mathbb{S}^2 \\rightarrow \\mathbb{R}^3$:

" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "Phi = S2.diff_map(R3, {(stereoN, cart): [2*x/(1+x^2+y^2), 2*y/(1+x^2+y^2),\n", " (x^2+y^2-1)/(1+x^2+y^2)],\n", " (stereoS, cart): [2*xp/(1+xp^2+yp^2), 2*yp/(1+xp^2+yp^2),\n", " (1-xp^2-yp^2)/(1+xp^2+yp^2)]},\n", " name='Phi', latex_name=r'\\Phi')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Phi: S^2 --> R^3\n", "on U: (x, y) |--> (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1), (x^2 + y^2 - 1)/(x^2 + y^2 + 1))\n", "on V: (xp, yp) |--> (X, Y, Z) = (2*xp/(xp^2 + yp^2 + 1), 2*yp/(xp^2 + yp^2 + 1), -(xp^2 + yp^2 - 1)/(xp^2 + yp^2 + 1))\n", "on A: (th, ph) |--> (X, Y, Z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Phi.expr(stereoN.restrict(A), cart)\n", "Phi.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3D plots of coordinate charts on $\\mathbb{S}^2$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Let us use $\\Phi$ to draw the grid of spherical coordinates $(\\theta,\\phi)$ in terms of the Cartesian coordinates $(X,Y,Z)$ of $\\mathbb{R}^3$:

" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "graph_spher = spher.plot(chart=cart, mapping=Phi, number_values=11, color='blue',\n", " label_axes=False)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show(graph_spher, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may also use the embedding $\\Phi$ to display the stereographic coordinate grid in terms of the Cartesian coordinates in $\\mathbb{R}^3$. First for the stereographic coordinates from the North pole:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_stereoN = stereoN.plot(chart=cart, mapping=Phi, number_values=25,\n", " label_axes=False)\n", "show(graph_stereoN, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and then have a view with the stereographic coordinates from the South pole superposed (in green):" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_stereoS = stereoS.plot(chart=cart, mapping=Phi, number_values=25, \n", " color='green', label_axes=False)\n", "show(graph_stereoN + graph_stereoS, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us add the North and South poles to the graphic:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "N = V.point((0,0), chart=stereoS, name='N')\n", "S = U.point((0,0), chart=stereoN, name='S')\n", "graph_N = N.plot(chart=cart, mapping=Phi, color='red', label_offset=0.05)\n", "graph_S = S.plot(chart=cart, mapping=Phi, color='green', label_offset=0.05)\n", "show(graph_stereoN + graph_stereoS + graph_N + graph_S, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3D plot of a vector field on $\\mathbb{S}^2$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define the vector field $v$ in terms of its components in the frame `eU` = $(\\partial_x, \\partial_y)$ associated with stereographic coordinates from the North pole: " ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = d/dx - 2 d/dy" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v = S2.vector_field(name='v')\n", "v[eU,:] = [1, -2]\n", "v.display(eU)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "v = (-xp^2 + 4*xp*yp + yp^2) d/dxp + (-2*xp^2 - 2*xp*yp + 2*yp^2) d/dyp" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.add_comp_by_continuation(eV, W, chart=stereoS)\n", "v.display(eV)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

A 3D view of the vector field $v$ is obtained via the embedding $\\Phi$:

" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_v = v.plot(chart=cart, mapping=Phi, chart_domain=spher, number_values=11, \n", " scale=0.2, label_axes=False)\n", "show(graph_v, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us superpose the plot of the spherical coordinate grid:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph = graph_v + graph_spher\n", "show(graph, viewer=viewer3D, aspect_ratio=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, let us draw the first vector field of the stereographic frame from the North pole, namely $\\frac{\\partial}{\\partial x}$" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector field d/dx on the Open subset U of the 2-dimensional differentiable manifold S^2" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ex = stereoN.frame()[1]\n", "ex" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_ex = ex.plot(chart=cart, mapping=Phi, chart_domain=spher,\n", " number_values=11, scale=0.4, label_axes=False)\n", "show(graph_ex + graph_spher, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the second vector field of the stereographic frame from the North pole, namely $\\frac{\\partial}{\\partial y}$, we get:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Vector field d/dy on the Open subset U of the 2-dimensional differentiable manifold S^2" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ey = stereoN.frame()[2]\n", "ey" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_ey = ey.plot(chart=cart, mapping=Phi, chart_domain=spher,\n", " number_values=11, scale=0.4, color='red', label_axes=False)\n", "show(graph_ey + graph_spher, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may superpose the two graphs, to get a 3D view of the frame associated with the stereographic coordinates from the North pole:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show(graph_spher + graph_ex + graph_ey + sphere(color='lightgrey', opacity=0.4),\n", " viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3D plot of a curve in $\\mathbb{S}^2$\n", "\n", "In order to define curves in $\\mathbb{S}^2$, we first introduce the field of real numbers $\\mathbb{R}$ as a 1-dimensional smooth manifold with a canonical coordinate chart:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Real number line R\n" ] } ], "source": [ "R. = RealLine() ; print(R)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define a **loxodrome of the sphere** in terms of its parametric equation with respect to the chart `spher` = $(A,(\\theta,\\phi))$" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "c = S2.curve({spher: [2*atan(exp(-t/10)), t]}, (t, -oo, +oo), name='c')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Curves in $\\mathbb{S}^2$ are considered as morphisms from the manifold $\\mathbb{R}$ to the manifold $\\mathbb{S}^2$:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "Set of Morphisms from Real number line R to 2-dimensional differentiable manifold S^2 in Category of smooth manifolds over Real Field with 53 bits of precision" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.parent()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "c: R --> S^2\n", " t |--> (x, y) = (cos(t)*e^(1/10*t), e^(1/10*t)*sin(t))\n", " t |--> (xp, yp) = (cos(t)*e^(-1/10*t), e^(-1/10*t)*sin(t))\n", " t |--> (th, ph) = (2*arctan(e^(-1/10*t)), t)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Thanks to the embedding $\\Phi$, we may plot $c$ in terms of the Cartesian coordinates of $\\mathbb{R}^3$:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_c = c.plot(mapping=Phi, max_range=40, plot_points=200, thickness=2,\n", " label_axes=False)\n", "show(graph_c + graph_spher, viewer=viewer3D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The **tangent vector field** (or **velocity vector**) to the curve $c$ is" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "c' = (1/10*cos(t)*e^(1/10*t) - e^(1/10*t)*sin(t)) d/dx + (cos(t)*e^(1/10*t) + 1/10*e^(1/10*t)*sin(t)) d/dy" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vc = c.tangent_vector_field()\n", "vc.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us plot $c'$ atop $c$:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "graph_vc = vc.plot(chart=cart, mapping=Phi, ranges={t: (-20, 20)}, number_values=30, \n", " scale=0.5, color='red', label_axes=False)\n", "show(graph_spher + graph_c + graph_vc , viewer=viewer3D)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "SageMath 7.5.beta4", "language": "", "name": "sagemath" }, "language": "python", "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.10" } }, "nbformat": 4, "nbformat_minor": 0 }