.. -*- coding: utf-8 -*- .. linkall .. _change_coord_euclidean: How to change coordinates ========================= This tutorial introduces some vector calculus capabilities of SageMath within the 3-dimensional Euclidean space. The corresponding tools have been developed via the `SageManifolds `__ project. The tutorial is also available as a Jupyter notebook, either `passive `__ (``nbviewer``) or `interactive `__ (``binder``). Starting from Cartesian coordinates ----------------------------------- In this tutorial, we choose to start from the Cartesian coordinates `(x,y,z)`. Hence, we declare the 3-dimensional Euclidean space `\mathbb{E}^3` as:: sage: E. = EuclideanSpace() sage: E Euclidean space E^3 By default, i.e. without the optional argument ``coordinates`` in :class:`EuclideanSpace`, `\mathbb{E}^3` is initialized with the chart of Cartesian coordinates:: sage: E.atlas() [Chart (E^3, (x, y, z))] See the tutorial :ref:`vector_calc_curvilinear` for examples of initialization of the Euclidean space with spherical coordinates or cylindrical coordinates instead of the Cartesian ones. Let us denote by ``cartesian`` the chart of Cartesian coordinates:: sage: cartesian = E.cartesian_coordinates() sage: cartesian Chart (E^3, (x, y, z)) The access to the individual coordinates is performed via the square bracket operator:: sage: cartesian[1] x sage: cartesian[:] (x, y, z) Thanks to use of ```` when declaring ``E``, the Python variables ``x``, ``y`` and ``z`` have been created to store the coordinates `(x,y,z)` as symbolic expressions. There is no need to declare them via :func:`var`, i.e. to type ``x, y, z = var('x y z')``; they are immediately available:: sage: y is cartesian[2] True sage: type(y) Each of the Cartesian coordinates spans the entire real line:: sage: cartesian.coord_range() x: (-oo, +oo); y: (-oo, +oo); z: (-oo, +oo) Being the only coordinate chart created so far, ``cartesian`` is the default chart on ``E``:: sage: cartesian is E.default_chart() True `\mathbb{E}^3` is endowed with the orthonormal vector frame `(e_x, e_y, e_z)` associated with Cartesian coordinates:: sage: E.frames() [Coordinate frame (E^3, (e_x,e_y,e_z))] Let us denote it by ``cartesian_frame``:: sage: cartesian_frame = E.cartesian_frame() sage: cartesian_frame Coordinate frame (E^3, (e_x,e_y,e_z)) sage: cartesian_frame is E.default_frame() True Each element of this frame is a unit vector field; for instance, we have `e_x\cdot e_x = 1`:: sage: e_x = cartesian_frame[1] sage: e_x Vector field e_x on the Euclidean space E^3 sage: e_x.dot(e_x).expr() 1 as well as `e_x\cdot e_y = 0`:: sage: e_y = cartesian_frame[2] sage: e_x.dot(e_y).expr() 0 Introducing spherical coordinates --------------------------------- Spherical coordinates are introduced by:: sage: spherical. = E.spherical_coordinates() sage: spherical Chart (E^3, (r, th, ph)) We have:: sage: spherical[:] (r, th, ph) sage: spherical.coord_range() r: (0, +oo); th: (0, pi); ph: [0, 2*pi] (periodic) `\mathbb{E}^3` is now endowed with two coordinate charts:: sage: E.atlas() [Chart (E^3, (x, y, z)), Chart (E^3, (r, th, ph))] The change-of-coordinate formulas have been automatically implemented during the above call ``E.spherical_coordinates()``:: sage: E.coord_change(spherical, cartesian).display() x = r*cos(ph)*sin(th) y = r*sin(ph)*sin(th) z = r*cos(th) sage: E.coord_change(cartesian, spherical).display() r = sqrt(x^2 + y^2 + z^2) th = arctan2(sqrt(x^2 + y^2), z) ph = arctan2(y, x) These formulas are automatically used if we ask to plot the grid of spherical coordinates in terms of Cartesian coordinates:: sage: spherical.plot(cartesian, color={r:'red', th:'green', ph:'orange'}) Graphics3d Object .. PLOT:: E = EuclideanSpace(3) cartesian = E.cartesian_coordinates() spherical = E.spherical_coordinates() r, th, ph = spherical[:] g = spherical.plot(cartesian, color={r:'red', th:'green', ph:'orange'}) sphinx_plot(g) Note that - the red lines are those along which `r` varies, while `(\theta,\phi)` are kept fixed; - the grid lines are those along which `\theta` varies, while `(r,\phi)` are kept fixed; - the orange lines are those along which `\phi` varies, while `(r,\theta)` are kept fixed. For customizing the plot, see the list of options in the documentation of :meth:`~sage.manifolds.chart.RealChart.plot`. For instance, we may draw the spherical coordinates in the plane `\theta=\pi/2` in terms of the coordinates `(x, y)`:: sage: spherical.plot(cartesian, fixed_coords={th: pi/2}, ambient_coords=(x,y), ....: color={r:'red', th:'green', ph:'orange'}) Graphics object consisting of 18 graphics primitives .. PLOT:: E = EuclideanSpace(3) cartesian = E.cartesian_coordinates() spherical = E.spherical_coordinates() x, y, z = cartesian[:] r, th, ph = spherical[:] g = spherical.plot(cartesian, fixed_coords={th: pi/2}, ambient_coords=(x,y), color={r:'red', th:'green', ph:'orange'}) sphinx_plot(g) Similarly the grid of spherical coordinates in the half-plane `\phi=0` drawn in terms of the coordinates `(x, z)` is obtained via:: sage: spherical.plot(cartesian, fixed_coords={ph: 0}, ambient_coords=(x,z), ....: color={r:'red', th:'green', ph:'orange'}) Graphics object consisting of 18 graphics primitives .. PLOT:: E = EuclideanSpace(3) cartesian = E.cartesian_coordinates() spherical = E.spherical_coordinates() x, y, z = cartesian[:] r, th, ph = spherical[:] g = spherical.plot(cartesian, fixed_coords={ph: 0}, ambient_coords=(x,z), color={r:'red', th:'green', ph:'orange'}) sphinx_plot(g) Relations between the Cartesian and spherical vector frames ----------------------------------------------------------- At this stage, `\mathbb{E}^3` is endowed with three vector frames:: sage: E.frames() [Coordinate frame (E^3, (e_x,e_y,e_z)), Coordinate frame (E^3, (d/dr,d/dth,d/dph)), Vector frame (E^3, (e_r,e_th,e_ph))] The second one is the *coordinate* frame `\left(\frac{\partial}{\partial r}, \frac{\partial}{\partial\theta}, \frac{\partial}{\partial \phi}\right)` of spherical coordinates, while the third one is the standard *orthonormal* frame `(e_r,e_\theta,e_\phi)` 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 returned by the method :meth:`~sage.manifolds.differentiable.euclidean.Euclidean3dimSpace.spherical_frame`:: sage: spherical_frame = E.spherical_frame() sage: spherical_frame Vector frame (E^3, (e_r,e_th,e_ph)) We may check that it is an orthonormal frame, i.e. that it obeys `e_i\cdot e_j = \delta_{ij}`:: sage: es = spherical_frame sage: [[es[i].dot(es[j]).expr() for j in E.irange()] for i in E.irange()] [[1, 0, 0], [0, 1, 0], [0, 0, 1]] Via the method ``display``, we may express the orthonormal spherical frame in terms of the Cartesian one:: sage: for vec in spherical_frame: ....: vec.display(cartesian_frame, spherical) e_r = cos(ph)*sin(th) e_x + sin(ph)*sin(th) e_y + cos(th) e_z e_th = cos(ph)*cos(th) e_x + cos(th)*sin(ph) e_y - sin(th) e_z e_ph = -sin(ph) e_x + cos(ph) e_y The reverse is:: sage: for vec in cartesian_frame: ....: vec.display(spherical_frame, spherical) e_x = cos(ph)*sin(th) e_r + cos(ph)*cos(th) e_th - sin(ph) e_ph e_y = sin(ph)*sin(th) e_r + cos(th)*sin(ph) e_th + cos(ph) e_ph e_z = cos(th) e_r - sin(th) e_th We may also express the orthonormal frame `(e_r,e_\theta,e_\phi)` 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 :meth:`~sage.manifolds.differentiable.chart.DiffChart.frame` acting on the chart ``spherical``):: sage: for vec in spherical_frame: ....: vec.display(spherical.frame(), spherical) e_r = d/dr e_th = 1/r d/dth e_ph = 1/(r*sin(th)) d/dph Introducing cylindrical coordinates ----------------------------------- Cylindrical coordinates are introduced in a way similar to spherical coordinates:: sage: cylindrical. = E.cylindrical_coordinates() sage: cylindrical Chart (E^3, (rh, ph, z)) We have:: sage: cylindrical[:] (rh, ph, z) sage: rh is cylindrical[1] True sage: cylindrical.coord_range() rh: (0, +oo); ph: [0, 2*pi] (periodic); z: (-oo, +oo) `\mathbb{E}^3` is now endowed with three coordinate charts:: sage: E.atlas() [Chart (E^3, (x, y, z)), Chart (E^3, (r, th, ph)), Chart (E^3, (rh, ph, z))] The transformations linking the cylindrical coordinates to the Cartesian ones are:: sage: E.coord_change(cylindrical, cartesian).display() x = rh*cos(ph) y = rh*sin(ph) z = z sage: E.coord_change(cartesian, cylindrical).display() rh = sqrt(x^2 + y^2) ph = arctan2(y, x) z = z There are now five vector frames defined on `\mathbb{E}^3`:: sage: E.frames() [Coordinate frame (E^3, (e_x,e_y,e_z)), Coordinate frame (E^3, (d/dr,d/dth,d/dph)), Vector frame (E^3, (e_r,e_th,e_ph)), Coordinate frame (E^3, (d/drh,d/dph,d/dz)), Vector frame (E^3, (e_rh,e_ph,e_z))] The orthonormal frame associated with cylindrical coordinates is `(e_\rho, e_\phi, e_z)`:: sage: cylindrical_frame = E.cylindrical_frame() sage: cylindrical_frame Vector frame (E^3, (e_rh,e_ph,e_z)) We may check that it is an orthonormal frame:: sage: ec = cylindrical_frame sage: [[ec[i].dot(ec[j]).expr() for j in E.irange()] for i in E.irange()] [[1, 0, 0], [0, 1, 0], [0, 0, 1]] and express it in terms of the Cartesian frame:: sage: for vec in cylindrical_frame: ....: vec.display(cartesian_frame, cylindrical) e_rh = cos(ph) e_x + sin(ph) e_y e_ph = -sin(ph) e_x + cos(ph) e_y e_z = e_z The reverse is:: sage: for vec in cartesian_frame: ....: vec.display(cylindrical_frame, cylindrical) e_x = cos(ph) e_rh - sin(ph) e_ph e_y = sin(ph) e_rh + cos(ph) e_ph e_z = e_z Of course, we may express the orthonormal cylindrical frame in terms of the spherical one:: sage: for vec in cylindrical_frame: ....: vec.display(spherical_frame, spherical) e_rh = sin(th) e_r + cos(th) e_th e_ph = e_ph e_z = cos(th) e_r - sin(th) e_th along with the reverse transformation:: sage: for vec in spherical_frame: ....: vec.display(cylindrical_frame, spherical) e_r = sin(th) e_rh + cos(th) e_z e_th = cos(th) e_rh - sin(th) e_z e_ph = e_ph The orthonormal frame `(e_\rho,e_\phi,e_z)` can be 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 :meth:`~sage.manifolds.differentiable.chart.DiffChart.frame` acting on the chart ``cylindrical``):: sage: for vec in cylindrical_frame: ....: vec.display(cylindrical.frame(), cylindrical) e_rh = d/drh e_ph = 1/rh d/dph e_z = d/dz How to evaluate the coordinates of a point in various systems ------------------------------------------------------------- Let us 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:: sage: p = E((-1, 1,0), chart=cartesian, name='p') sage: p Point p on the Euclidean space E^3 Actually, since the Cartesian coordinates are the default ones, the argument ``chart=cartesian`` can be omitted:: sage: p = E((-1, 1,0), name='p') sage: p Point p on the Euclidean space E^3 The coordinates of `p` in a given coordinate chart are obtained by letting the corresponding chart act on `p`:: sage: cartesian(p) (-1, 1, 0) sage: spherical(p) (sqrt(2), 1/2*pi, 3/4*pi) sage: cylindrical(p) (sqrt(2), 3/4*pi, 0) Here some example of a point defined from its spherical coordinates:: sage: q = E((4,pi/3,pi), chart=spherical, name='q') sage: q Point q on the Euclidean space E^3 We have then:: sage: spherical(q) (4, 1/3*pi, pi) sage: cartesian(q) (-2*sqrt(3), 0, 2) sage: cylindrical(q) (2*sqrt(3), pi, 2) How to express a scalar field in various coordinate systems ----------------------------------------------------------- Let us define a scalar field on `\mathbb{E}^3` from its expression in Cartesian coordinates:: sage: f = E.scalar_field(x^2+y^2 - z^2, name='f') Note that since the Cartesian coordinates are the default ones, we have not specified them in the above definition. Thanks to the known coordinate transformations, the expression of `f` in terms of other coordinates is automatically computed:: sage: f.display() f: E^3 --> R (x, y, z) |--> x^2 + y^2 - z^2 (r, th, ph) |--> -2*r^2*cos(th)^2 + r^2 (rh, ph, z) |--> rh^2 - z^2 We can limit the output to a single coordinate system:: sage: f.display(cartesian) f: E^3 --> R (x, y, z) |--> x^2 + y^2 - z^2 sage: f.display(cylindrical) f: E^3 --> R (rh, ph, z) |--> rh^2 - z^2 The coordinate expression in a given coordinate system is obtained via the method :meth:`~sage.manifolds.scalarfield.ScalarField.expr`:: sage: f.expr() # expression in the default chart (Cartesian coordinates) x^2 + y^2 - z^2 sage: f.expr(spherical) -2*r^2*cos(th)^2 + r^2 sage: f.expr(cylindrical) rh^2 - z^2 The values of `f` at points `p` and `q` are:: sage: f(p) 2 sage: f(q) 8 Of course, we may define a scalar field from its coordinate expression in a chart that is not the default one:: sage: g = E.scalar_field(r^2, chart=spherical, name='g') Instead of using the keyword argument ``chart``, one can pass a dictionary as the first argument, with the chart as key:: sage: g = E.scalar_field({spherical: r^2}, name='g') The computation of the expressions of `g` in the other coordinate systems is triggered by the method ``display()``:: sage: g.display() g: E^3 --> R (x, y, z) |--> x^2 + y^2 + z^2 (r, th, ph) |--> r^2 (rh, ph, z) |--> rh^2 + z^2 How to express a vector field in various frames ----------------------------------------------- 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:: sage: v = E.vector_field(-y, x, z^2, name='v') sage: v.display() v = -y e_x + x e_y + z^2 e_z Equivalently, a vector field can be defined directly from its expansion on the Cartesian frame:: sage: ex, ey, ez = cartesian_frame[:] sage: v = -y*ex + x*ey + z^2*ez sage: v.display() -y e_x + x e_y + z^2 e_z Let us provide ``v`` with some name, as above:: sage: v.set_name('v') sage: v.display() v = -y e_x + x e_y + z^2 e_z The components of `v` are returned by the square bracket operator:: sage: v[1] -y sage: v[:] [-y, x, z^2] The computation of the expression of `v` in terms of the orthonormal spherical frame is triggered by the method ``display()``:: sage: v.display(spherical_frame) 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 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()``:: sage: v.display(spherical_frame, spherical) v = r^2*cos(th)^3 e_r - r^2*cos(th)^2*sin(th) e_th + r*sin(th) e_ph Again, the components of `v` are obtained by means of the square bracket operator, by specifying the vector frame as first argument and the coordinate chart as the last one:: sage: v[spherical_frame, 1] z^3/sqrt(x^2 + y^2 + z^2) sage: v[spherical_frame, 1, spherical] r^2*cos(th)^3 sage: v[spherical_frame, :, spherical] [r^2*cos(th)^3, -r^2*cos(th)^2*sin(th), r*sin(th)] Similarly, the expression of `v` in terms of the cylindrical frame is:: sage: v.display(cylindrical_frame, cylindrical) v = rh e_ph + z^2 e_z sage: v[cylindrical_frame, :, cylindrical] [0, rh, z^2] The value of the vector field `v` at point `p` is:: sage: vp = v.at(p) sage: vp Vector v at Point p on the Euclidean space E^3 sage: vp.display() v = -e_x - e_y sage: vp.display(spherical_frame.at(p)) v = sqrt(2) e_ph sage: vp.display(cylindrical_frame.at(p)) v = sqrt(2) e_ph The value of the vector field `v` at point `q` is:: sage: vq = v.at(q) sage: vq Vector v at Point q on the Euclidean space E^3 sage: vq.display() v = -2*sqrt(3) e_y + 4 e_z sage: vq.display(spherical_frame.at(q)) v = 2 e_r - 2*sqrt(3) e_th + 2*sqrt(3) e_ph sage: vq.display(cylindrical_frame.at(q)) v = 2*sqrt(3) e_ph + 4 e_z How to change the default coordinates and default vector frame -------------------------------------------------------------- At any time, one may change the default coordinates by the method :meth:`~sage.manifolds.manifold.TopologicalManifold.set_default_chart`:: sage: E.set_default_chart(spherical) Then:: sage: f.expr() -2*r^2*cos(th)^2 + r^2 sage: v.display() v = -r*sin(ph)*sin(th) e_x + r*cos(ph)*sin(th) e_y + r^2*cos(th)^2 e_z Note that the default vector frame is still the Cartesian one; to change to the orthonormal spherical frame, use :meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.set_default_frame`:: sage: E.set_default_frame(spherical_frame) Then:: sage: v.display() v = r^2*cos(th)^3 e_r - r^2*cos(th)^2*sin(th) e_th + r*sin(th) e_ph sage: v.display(cartesian_frame, cartesian) v = -y e_x + x e_y + z^2 e_z