Euclidean Spaces¶
A Euclidean space of dimension \(n\) is an affine space \(E\), whose associated vector space is a \(n\)-dimensional vector space over \(\RR\) and is equipped with a positive definite symmetric bilinear form, called the scalar product or dot product [Ber1987]. A Euclidean space of dimension \(n\) can also be viewed as a Riemannian manifold that is diffeomorphic to \(\RR^n\) and that has a flat metric \(g\). The Euclidean scalar product is then that defined by the Riemannian metric \(g\).
The current implementation of Euclidean spaces is based on the second point of
view. This allows for the introduction of various coordinate systems in
addition to the usual the Cartesian systems. Standard curvilinear systems
(planar, spherical and cylindrical coordinates) are predefined for
2-dimensional and 3-dimensional Euclidean spaces, along with the corresponding
transition maps between them. Another benefit of such an implementation is
the direct use of methods for vector calculus already implemented at the
level of Riemannian manifolds (see, e.g., the methods
cross_product()
and
curl()
,
as well as the module operators
).
Euclidean spaces are implemented via the following classes:
EuclideanSpace
for generic values \(n\),EuclideanPlane
for \(n = 2\),Euclidean3dimSpace
for \(n = 3\).
The user interface is provided by EuclideanSpace
.
Example 1: the Euclidean plane
We start by declaring the Euclidean plane E
, with (x, y)
as
Cartesian coordinates:
sage: E.<x,y> = EuclideanSpace()
sage: E
Euclidean plane E^2
sage: dim(E)
2
>>> from sage.all import *
>>> E = EuclideanSpace(names=('x', 'y',)); (x, y,) = E._first_ngens(2)
>>> E
Euclidean plane E^2
>>> dim(E)
2
E.<x,y> = EuclideanSpace() E dim(E)
E
is automatically endowed with the chart of Cartesian coordinates:
sage: E.atlas()
[Chart (E^2, (x, y))]
sage: cartesian = E.default_chart(); cartesian
Chart (E^2, (x, y))
>>> from sage.all import *
>>> E.atlas()
[Chart (E^2, (x, y))]
>>> cartesian = E.default_chart(); cartesian
Chart (E^2, (x, y))
E.atlas() cartesian = E.default_chart(); cartesian
Thanks to the use of <x,y>
when declaring E
, the coordinates \((x,y)\)
have been injected in the global namespace, i.e. the Python variables x
and y
have been created and are available to form symbolic expressions:
sage: y
y
sage: type(y)
<class 'sage.symbolic.expression.Expression'>
sage: assumptions()
[x is real, y is real]
>>> from sage.all import *
>>> y
y
>>> type(y)
<class 'sage.symbolic.expression.Expression'>
>>> assumptions()
[x is real, y is real]
y type(y) assumptions()
The metric tensor of E
is predefined:
sage: g = E.metric(); g
Riemannian metric g on the Euclidean plane E^2
sage: g.display()
g = dx⊗dx + dy⊗dy
sage: g[:]
[1 0]
[0 1]
>>> from sage.all import *
>>> g = E.metric(); g
Riemannian metric g on the Euclidean plane E^2
>>> g.display()
g = dx⊗dx + dy⊗dy
>>> g[:]
[1 0]
[0 1]
g = E.metric(); g g.display() g[:]
It is a flat metric, i.e. it has a vanishing Riemann tensor:
sage: g.riemann()
Tensor field Riem(g) of type (1,3) on the Euclidean plane E^2
sage: g.riemann().display()
Riem(g) = 0
>>> from sage.all import *
>>> g.riemann()
Tensor field Riem(g) of type (1,3) on the Euclidean plane E^2
>>> g.riemann().display()
Riem(g) = 0
g.riemann() g.riemann().display()
Polar coordinates \((r,\phi)\) are introduced by:
sage: polar.<r,ph> = E.polar_coordinates()
sage: polar
Chart (E^2, (r, ph))
>>> from sage.all import *
>>> polar = E.polar_coordinates(names=('r', 'ph',)); (r, ph,) = polar._first_ngens(2)
>>> polar
Chart (E^2, (r, ph))
polar.<r,ph> = E.polar_coordinates() polar
E
is now endowed with two coordinate charts:
sage: E.atlas()
[Chart (E^2, (x, y)), Chart (E^2, (r, ph))]
>>> from sage.all import *
>>> E.atlas()
[Chart (E^2, (x, y)), Chart (E^2, (r, ph))]
E.atlas()
The ranges of the coordinates introduced so far are:
sage: cartesian.coord_range()
x: (-oo, +oo); y: (-oo, +oo)
sage: polar.coord_range()
r: (0, +oo); ph: [0, 2*pi] (periodic)
>>> from sage.all import *
>>> cartesian.coord_range()
x: (-oo, +oo); y: (-oo, +oo)
>>> polar.coord_range()
r: (0, +oo); ph: [0, 2*pi] (periodic)
cartesian.coord_range() polar.coord_range()
The transition map from polar coordinates to Cartesian ones is:
sage: E.coord_change(polar, cartesian).display()
x = r*cos(ph)
y = r*sin(ph)
>>> from sage.all import *
>>> E.coord_change(polar, cartesian).display()
x = r*cos(ph)
y = r*sin(ph)
E.coord_change(polar, cartesian).display()
while the reverse one is:
sage: E.coord_change(cartesian, polar).display()
r = sqrt(x^2 + y^2)
ph = arctan2(y, x)
>>> from sage.all import *
>>> E.coord_change(cartesian, polar).display()
r = sqrt(x^2 + y^2)
ph = arctan2(y, x)
E.coord_change(cartesian, polar).display()
A point of E
is constructed from its coordinates (by default in the
Cartesian chart):
sage: p = E((-1,1), name='p'); p
Point p on the Euclidean plane E^2
sage: p.parent()
Euclidean plane E^2
>>> from sage.all import *
>>> p = E((-Integer(1),Integer(1)), name='p'); p
Point p on the Euclidean plane E^2
>>> p.parent()
Euclidean plane E^2
p = E((-1,1), name='p'); p p.parent()
The coordinates of a point are obtained by letting the corresponding chart act on it:
sage: cartesian(p)
(-1, 1)
sage: polar(p)
(sqrt(2), 3/4*pi)
>>> from sage.all import *
>>> cartesian(p)
(-1, 1)
>>> polar(p)
(sqrt(2), 3/4*pi)
cartesian(p) polar(p)
At this stage, E
is endowed with three vector frames:
sage: E.frames()
[Coordinate frame (E^2, (e_x,e_y)),
Coordinate frame (E^2, (∂/∂r,∂/∂ph)),
Vector frame (E^2, (e_r,e_ph))]
>>> from sage.all import *
>>> E.frames()
[Coordinate frame (E^2, (e_x,e_y)),
Coordinate frame (E^2, (∂/∂r,∂/∂ph)),
Vector frame (E^2, (e_r,e_ph))]
E.frames()
The third one is the standard orthonormal frame associated with polar coordinates, as we can check from the metric components in it:
sage: polar_frame = E.polar_frame(); polar_frame
Vector frame (E^2, (e_r,e_ph))
sage: g[polar_frame,:]
[1 0]
[0 1]
>>> from sage.all import *
>>> polar_frame = E.polar_frame(); polar_frame
Vector frame (E^2, (e_r,e_ph))
>>> g[polar_frame,:]
[1 0]
[0 1]
polar_frame = E.polar_frame(); polar_frame g[polar_frame,:]
The expression of the metric tensor in terms of polar coordinates is:
sage: g.display(polar)
g = dr⊗dr + r^2 dph⊗dph
>>> from sage.all import *
>>> g.display(polar)
g = dr⊗dr + r^2 dph⊗dph
g.display(polar)
A vector field on E
:
sage: v = E.vector_field(-y, x, name='v'); v
Vector field v on the Euclidean plane E^2
sage: v.display()
v = -y e_x + x e_y
sage: v[:]
[-y, x]
>>> from sage.all import *
>>> v = E.vector_field(-y, x, name='v'); v
Vector field v on the Euclidean plane E^2
>>> v.display()
v = -y e_x + x e_y
>>> v[:]
[-y, x]
v = E.vector_field(-y, x, name='v'); v v.display() v[:]
By default, the components of v
, as returned by display
or the bracket
operator, refer to the Cartesian frame on E
; to get the components with
respect to the orthonormal polar frame, one has to specify it explicitly,
generally along with the polar chart for the coordinate expression of the
components:
sage: v.display(polar_frame, polar)
v = r e_ph
sage: v[polar_frame,:,polar]
[0, r]
>>> from sage.all import *
>>> v.display(polar_frame, polar)
v = r e_ph
>>> v[polar_frame,:,polar]
[0, r]
v.display(polar_frame, polar) v[polar_frame,:,polar]
Note that the default frame for the display of vector fields can be changed
thanks to the method
set_default_frame()
;
in the same vein, the default coordinates can be changed via the method
set_default_chart()
:
sage: E.set_default_frame(polar_frame)
sage: E.set_default_chart(polar)
sage: v.display()
v = r e_ph
sage: v[:]
[0, r]
sage: E.set_default_frame(E.cartesian_frame()) # revert to Cartesian frame
sage: E.set_default_chart(cartesian) # and chart
>>> from sage.all import *
>>> E.set_default_frame(polar_frame)
>>> E.set_default_chart(polar)
>>> v.display()
v = r e_ph
>>> v[:]
[0, r]
>>> E.set_default_frame(E.cartesian_frame()) # revert to Cartesian frame
>>> E.set_default_chart(cartesian) # and chart
E.set_default_frame(polar_frame) E.set_default_chart(polar) v.display() v[:] E.set_default_frame(E.cartesian_frame()) # revert to Cartesian frame E.set_default_chart(cartesian) # and chart
When defining a vector field from components relative to a vector frame different from the default one, the vector frame has to be specified explicitly:
sage: v = E.vector_field(1, 0, frame=polar_frame)
sage: v.display(polar_frame)
e_r
sage: v.display()
x/sqrt(x^2 + y^2) e_x + y/sqrt(x^2 + y^2) e_y
>>> from sage.all import *
>>> v = E.vector_field(Integer(1), Integer(0), frame=polar_frame)
>>> v.display(polar_frame)
e_r
>>> v.display()
x/sqrt(x^2 + y^2) e_x + y/sqrt(x^2 + y^2) e_y
v = E.vector_field(1, 0, frame=polar_frame) v.display(polar_frame) v.display()
The argument chart
must be used to specify in which coordinate
chart the components are expressed:
sage: v = E.vector_field(0, r, frame=polar_frame, chart=polar)
sage: v.display(polar_frame, polar)
r e_ph
sage: v.display()
-y e_x + x e_y
>>> from sage.all import *
>>> v = E.vector_field(Integer(0), r, frame=polar_frame, chart=polar)
>>> v.display(polar_frame, polar)
r e_ph
>>> v.display()
-y e_x + x e_y
v = E.vector_field(0, r, frame=polar_frame, chart=polar) v.display(polar_frame, polar) v.display()
It is also possible to pass the components as a dictionary, with a pair (vector frame, chart) as a key:
sage: v = E.vector_field({(polar_frame, polar): (0, r)})
sage: v.display(polar_frame, polar)
r e_ph
>>> from sage.all import *
>>> v = E.vector_field({(polar_frame, polar): (Integer(0), r)})
>>> v.display(polar_frame, polar)
r e_ph
v = E.vector_field({(polar_frame, polar): (0, r)}) v.display(polar_frame, polar)
The key can be reduced to the vector frame if the chart is the default one:
sage: v = E.vector_field({polar_frame: (0, 1)})
sage: v.display(polar_frame)
e_ph
>>> from sage.all import *
>>> v = E.vector_field({polar_frame: (Integer(0), Integer(1))})
>>> v.display(polar_frame)
e_ph
v = E.vector_field({polar_frame: (0, 1)}) v.display(polar_frame)
Finally, it is possible to construct the vector field without initializing any component:
sage: v = E.vector_field(); v
Vector field on the Euclidean plane E^2
>>> from sage.all import *
>>> v = E.vector_field(); v
Vector field on the Euclidean plane E^2
v = E.vector_field(); v
The components can then by set in a second stage, via the square bracket operator, the unset components being assumed to be zero:
sage: v[1] = -y
sage: v.display() # v[2] is zero
-y e_x
sage: v[2] = x
sage: v.display()
-y e_x + x e_y
>>> from sage.all import *
>>> v[Integer(1)] = -y
>>> v.display() # v[2] is zero
-y e_x
>>> v[Integer(2)] = x
>>> v.display()
-y e_x + x e_y
v[1] = -y v.display() # v[2] is zero v[2] = x v.display()
The above is equivalent to:
sage: v[:] = -y, x
sage: v.display()
-y e_x + x e_y
>>> from sage.all import *
>>> v[:] = -y, x
>>> v.display()
-y e_x + x e_y
v[:] = -y, x v.display()
The square bracket operator can also be used to set components in a vector frame that is not the default one:
sage: v = E.vector_field(name='v')
sage: v[polar_frame, 2, polar] = r
sage: v.display(polar_frame, polar)
v = r e_ph
sage: v.display()
v = -y e_x + x e_y
>>> from sage.all import *
>>> v = E.vector_field(name='v')
>>> v[polar_frame, Integer(2), polar] = r
>>> v.display(polar_frame, polar)
v = r e_ph
>>> v.display()
v = -y e_x + x e_y
v = E.vector_field(name='v') v[polar_frame, 2, polar] = r v.display(polar_frame, polar) v.display()
The value of the vector field v
at point p
:
sage: vp = v.at(p); vp
Vector v at Point p on the Euclidean plane E^2
sage: vp.display()
v = -e_x - e_y
sage: vp.display(polar_frame.at(p))
v = sqrt(2) e_ph
>>> from sage.all import *
>>> vp = v.at(p); vp
Vector v at Point p on the Euclidean plane E^2
>>> vp.display()
v = -e_x - e_y
>>> vp.display(polar_frame.at(p))
v = sqrt(2) e_ph
vp = v.at(p); vp vp.display() vp.display(polar_frame.at(p))
A scalar field on E
:
sage: f = E.scalar_field(x*y, name='f'); f
Scalar field f on the Euclidean plane E^2
sage: f.display()
f: E^2 → ℝ
(x, y) ↦ x*y
(r, ph) ↦ r^2*cos(ph)*sin(ph)
>>> from sage.all import *
>>> f = E.scalar_field(x*y, name='f'); f
Scalar field f on the Euclidean plane E^2
>>> f.display()
f: E^2 → ℝ
(x, y) ↦ x*y
(r, ph) ↦ r^2*cos(ph)*sin(ph)
f = E.scalar_field(x*y, name='f'); f f.display()
The value of f
at point p
:
sage: f(p)
-1
>>> from sage.all import *
>>> f(p)
-1
f(p)
The gradient of f
:
sage: from sage.manifolds.operators import * # to get grad, div, etc.
sage: w = grad(f); w
Vector field grad(f) on the Euclidean plane E^2
sage: w.display()
grad(f) = y e_x + x e_y
sage: w.display(polar_frame, polar)
grad(f) = 2*r*cos(ph)*sin(ph) e_r + (2*cos(ph)^2 - 1)*r e_ph
>>> from sage.all import *
>>> from sage.manifolds.operators import * # to get grad, div, etc.
>>> w = grad(f); w
Vector field grad(f) on the Euclidean plane E^2
>>> w.display()
grad(f) = y e_x + x e_y
>>> w.display(polar_frame, polar)
grad(f) = 2*r*cos(ph)*sin(ph) e_r + (2*cos(ph)^2 - 1)*r e_ph
from sage.manifolds.operators import * # to get grad, div, etc. w = grad(f); w w.display() w.display(polar_frame, polar)
The dot product of two vector fields:
sage: s = v.dot(w); s
Scalar field v.grad(f) on the Euclidean plane E^2
sage: s.display()
v.grad(f): E^2 → ℝ
(x, y) ↦ x^2 - y^2
(r, ph) ↦ (2*cos(ph)^2 - 1)*r^2
sage: s.expr()
x^2 - y^2
>>> from sage.all import *
>>> s = v.dot(w); s
Scalar field v.grad(f) on the Euclidean plane E^2
>>> s.display()
v.grad(f): E^2 → ℝ
(x, y) ↦ x^2 - y^2
(r, ph) ↦ (2*cos(ph)^2 - 1)*r^2
>>> s.expr()
x^2 - y^2
s = v.dot(w); s s.display() s.expr()
The norm is related to the dot product by the standard formula:
sage: norm(v)^2 == v.dot(v)
True
>>> from sage.all import *
>>> norm(v)**Integer(2) == v.dot(v)
True
norm(v)^2 == v.dot(v)
The divergence of the vector field v
:
sage: s = div(v); s
Scalar field div(v) on the Euclidean plane E^2
sage: s.display()
div(v): E^2 → ℝ
(x, y) ↦ 0
(r, ph) ↦ 0
>>> from sage.all import *
>>> s = div(v); s
Scalar field div(v) on the Euclidean plane E^2
>>> s.display()
div(v): E^2 → ℝ
(x, y) ↦ 0
(r, ph) ↦ 0
s = div(v); s s.display()
Example 2: Vector calculus in the Euclidean 3-space
We start by declaring the 3-dimensional Euclidean space E
, with
(x,y,z)
as Cartesian coordinates:
sage: E.<x,y,z> = EuclideanSpace()
sage: E
Euclidean space E^3
>>> from sage.all import *
>>> E = EuclideanSpace(names=('x', 'y', 'z',)); (x, y, z,) = E._first_ngens(3)
>>> E
Euclidean space E^3
E.<x,y,z> = EuclideanSpace() E
A simple vector field on E
:
sage: v = E.vector_field(-y, x, 0, name='v')
sage: v.display()
v = -y e_x + x e_y
sage: v[:]
[-y, x, 0]
>>> from sage.all import *
>>> v = E.vector_field(-y, x, Integer(0), name='v')
>>> v.display()
v = -y e_x + x e_y
>>> v[:]
[-y, x, 0]
v = E.vector_field(-y, x, 0, name='v') v.display() v[:]
The Euclidean norm of v
:
sage: s = norm(v); s
Scalar field |v| on the Euclidean space E^3
sage: s.display()
|v|: E^3 → ℝ
(x, y, z) ↦ sqrt(x^2 + y^2)
sage: s.expr()
sqrt(x^2 + y^2)
>>> from sage.all import *
>>> s = norm(v); s
Scalar field |v| on the Euclidean space E^3
>>> s.display()
|v|: E^3 → ℝ
(x, y, z) ↦ sqrt(x^2 + y^2)
>>> s.expr()
sqrt(x^2 + y^2)
s = norm(v); s s.display() s.expr()
The divergence of v
is zero:
sage: from sage.manifolds.operators import *
sage: div(v)
Scalar field div(v) on the Euclidean space E^3
sage: div(v).display()
div(v): E^3 → ℝ
(x, y, z) ↦ 0
>>> from sage.all import *
>>> from sage.manifolds.operators import *
>>> div(v)
Scalar field div(v) on the Euclidean space E^3
>>> div(v).display()
div(v): E^3 → ℝ
(x, y, z) ↦ 0
from sage.manifolds.operators import * div(v) div(v).display()
while its curl is a constant vector field along \(e_z\):
sage: w = curl(v); w
Vector field curl(v) on the Euclidean space E^3
sage: w.display()
curl(v) = 2 e_z
>>> from sage.all import *
>>> w = curl(v); w
Vector field curl(v) on the Euclidean space E^3
>>> w.display()
curl(v) = 2 e_z
w = curl(v); w w.display()
The gradient of a scalar field:
sage: f = E.scalar_field(sin(x*y*z), name='f')
sage: u = grad(f); u
Vector field grad(f) on the Euclidean space E^3
sage: u.display()
grad(f) = y*z*cos(x*y*z) e_x + x*z*cos(x*y*z) e_y + x*y*cos(x*y*z) e_z
>>> from sage.all import *
>>> f = E.scalar_field(sin(x*y*z), name='f')
>>> u = grad(f); u
Vector field grad(f) on the Euclidean space E^3
>>> u.display()
grad(f) = y*z*cos(x*y*z) e_x + x*z*cos(x*y*z) e_y + x*y*cos(x*y*z) e_z
f = E.scalar_field(sin(x*y*z), name='f') u = grad(f); u u.display()
The curl of a gradient is zero:
sage: curl(u).display()
curl(grad(f)) = 0
>>> from sage.all import *
>>> curl(u).display()
curl(grad(f)) = 0
curl(u).display()
The dot product of two vector fields:
sage: s = u.dot(v); s
Scalar field grad(f).v on the Euclidean space E^3
sage: s.expr()
(x^2 - y^2)*z*cos(x*y*z)
>>> from sage.all import *
>>> s = u.dot(v); s
Scalar field grad(f).v on the Euclidean space E^3
>>> s.expr()
(x^2 - y^2)*z*cos(x*y*z)
s = u.dot(v); s s.expr()
The cross product of two vector fields:
sage: a = u.cross(v); a
Vector field grad(f) x v on the Euclidean space E^3
sage: a.display()
grad(f) x v = -x^2*y*cos(x*y*z) e_x - x*y^2*cos(x*y*z) e_y
+ 2*x*y*z*cos(x*y*z) e_z
>>> from sage.all import *
>>> a = u.cross(v); a
Vector field grad(f) x v on the Euclidean space E^3
>>> a.display()
grad(f) x v = -x^2*y*cos(x*y*z) e_x - x*y^2*cos(x*y*z) e_y
+ 2*x*y*z*cos(x*y*z) e_z
a = u.cross(v); a a.display()
The scalar triple product of three vector fields:
sage: triple_product = E.scalar_triple_product()
sage: s = triple_product(u, v, w); s
Scalar field epsilon(grad(f),v,curl(v)) on the Euclidean space E^3
sage: s.expr()
4*x*y*z*cos(x*y*z)
>>> from sage.all import *
>>> triple_product = E.scalar_triple_product()
>>> s = triple_product(u, v, w); s
Scalar field epsilon(grad(f),v,curl(v)) on the Euclidean space E^3
>>> s.expr()
4*x*y*z*cos(x*y*z)
triple_product = E.scalar_triple_product() s = triple_product(u, v, w); s s.expr()
Let us check that the scalar triple product of \(u\), \(v\) and \(w\) is \(u\cdot(v\times w)\):
sage: s == u.dot(v.cross(w))
True
>>> from sage.all import *
>>> s == u.dot(v.cross(w))
True
s == u.dot(v.cross(w))
AUTHORS:
Eric Gourgoulhon (2018): initial version
REFERENCES:
M. Berger: Geometry I [Ber1987]
- class sage.manifolds.differentiable.examples.euclidean.Euclidean3dimSpace(name=None, latex_name=None, coordinates='Cartesian', symbols=None, metric_name='g', metric_latex_name=None, start_index=1, base_manifold=None, category=None, unique_tag=None)[source]¶
Bases:
EuclideanSpace
3-dimensional Euclidean space.
A 3-dimensional Euclidean space is an affine space \(E\), whose associated vector space is a 3-dimensional vector space over \(\RR\) and is equipped with a positive definite symmetric bilinear form, called the scalar product or dot product.
The class
Euclidean3dimSpace
inherits fromPseudoRiemannianManifold
(viaEuclideanSpace
) since a 3-dimensional Euclidean space can be viewed as a Riemannian manifold that is diffeomorphic to \(\RR^3\) and that has a flat metric \(g\). The Euclidean scalar product is the one defined by the Riemannian metric \(g\).INPUT:
name
– (default:None
) string; name (symbol) given to the Euclidean 3-space; ifNone
, the name will be set to'E^3'
latex_name
– (default:None
) string; LaTeX symbol to denote the Euclidean 3-space; ifNone
, it is set to'\mathbb{E}^{3}'
ifname
isNone
and toname
otherwisecoordinates
– (default:'Cartesian'
) string describing the type of coordinates to be initialized at the Euclidean 3-space creation; allowed values are'Cartesian'
(seecartesian_coordinates()
),'spherical'
(seespherical_coordinates()
) and'cylindrical'
(seecylindrical_coordinates()
)symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
, namelysymbols
is a string of coordinate fields separated by a blank space, where 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 (:
); ifNone
, the symbols will be automatically generated according to the value ofcoordinates
metric_name
– (default:'g'
) string; name (symbol) given to the Euclidean metric tensormetric_latex_name
– (default:None
) string; LaTeX symbol to denote the Euclidean metric tensor; if none is provided, it is set tometric_name
start_index
– (default: 1) integer; lower value of the range of indices used for “indexed objects” in the Euclidean 3-space, e.g. coordinates of a chartbase_manifold
– (default:None
) if notNone
, must be a Euclidean 3-space; the created object is then an open subset ofbase_manifold
category
– (default:None
) to specify the category; ifNone
,Manifolds(RR).Smooth() & MetricSpaces().Complete()
is assumednames
– (default:None
) unused argument, except ifsymbols
is not provided; it must then be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)init_coord_methods
– (default:None
) dictionary of methods to initialize the various type of coordinates, with each key being a string describing the type of coordinates; to be used by derived classes onlyunique_tag
– (default:None
) tag used to force the construction of a new object when all the other arguments have been used previously (withoutunique_tag
, theUniqueRepresentation
behavior inherited fromPseudoRiemannianManifold
would return the previously constructed object corresponding to these arguments)
EXAMPLES:
A 3-dimensional Euclidean space:
sage: E = EuclideanSpace(3); E Euclidean space E^3 sage: latex(E) \mathbb{E}^{3}
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)); E Euclidean space E^3 >>> latex(E) \mathbb{E}^{3}
E = EuclideanSpace(3); E latex(E)
E
belongs to the classEuclidean3dimSpace
(actually to a dynamically generated subclass of it via SageMath’s category framework):sage: type(E) <class 'sage.manifolds.differentiable.examples.euclidean.Euclidean3dimSpace_with_category'>
>>> from sage.all import * >>> type(E) <class 'sage.manifolds.differentiable.examples.euclidean.Euclidean3dimSpace_with_category'>
type(E)
E
is both a real smooth manifold of dimension \(3\) and a complete metric space:sage: E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces sage: dim(E) 3
>>> from sage.all import * >>> E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces >>> dim(E) 3
E.category() dim(E)
It is endowed with a default coordinate chart, which is that of Cartesian coordinates \((x,y,z)\):
sage: E.atlas() [Chart (E^3, (x, y, z))] sage: E.default_chart() Chart (E^3, (x, y, z)) sage: cartesian = E.cartesian_coordinates() sage: cartesian is E.default_chart() True
>>> from sage.all import * >>> E.atlas() [Chart (E^3, (x, y, z))] >>> E.default_chart() Chart (E^3, (x, y, z)) >>> cartesian = E.cartesian_coordinates() >>> cartesian is E.default_chart() True
E.atlas() E.default_chart() cartesian = E.cartesian_coordinates() cartesian is E.default_chart()
A point of
E
:sage: p = E((3,-2,1)); p Point on the Euclidean space E^3 sage: cartesian(p) (3, -2, 1) sage: p in E True sage: p.parent() is E True
>>> from sage.all import * >>> p = E((Integer(3),-Integer(2),Integer(1))); p Point on the Euclidean space E^3 >>> cartesian(p) (3, -2, 1) >>> p in E True >>> p.parent() is E True
p = E((3,-2,1)); p cartesian(p) p in E p.parent() is E
E
is endowed with a default metric tensor, which defines the Euclidean scalar product:sage: g = E.metric(); g Riemannian metric g on the Euclidean space E^3 sage: g.display() g = dx⊗dx + dy⊗dy + dz⊗dz
>>> from sage.all import * >>> g = E.metric(); g Riemannian metric g on the Euclidean space E^3 >>> g.display() g = dx⊗dx + dy⊗dy + dz⊗dz
g = E.metric(); g g.display()
Curvilinear coordinates can be introduced on
E
: seespherical_coordinates()
andcylindrical_coordinates()
.- cartesian_coordinates(symbols=None, names=None)[source]¶
Return the chart of Cartesian coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the Cartesian chart has not been already defined; ifNone
the symbols are generated as \((x,y,z)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of Cartesian coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(3) sage: E.cartesian_coordinates() Chart (E^3, (x, y, z)) sage: E.cartesian_coordinates().coord_range() x: (-oo, +oo); y: (-oo, +oo); z: (-oo, +oo)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.cartesian_coordinates() Chart (E^3, (x, y, z)) >>> E.cartesian_coordinates().coord_range() x: (-oo, +oo); y: (-oo, +oo); z: (-oo, +oo)
E = EuclideanSpace(3) E.cartesian_coordinates() E.cartesian_coordinates().coord_range()
An example where the Cartesian coordinates have not been previously created:
sage: E = EuclideanSpace(3, coordinates='spherical') sage: E.atlas() # only spherical coordinates have been initialized [Chart (E^3, (r, th, ph))] sage: E.cartesian_coordinates(symbols='X Y Z') Chart (E^3, (X, Y, Z)) sage: E.atlas() # the Cartesian chart has been added to the atlas [Chart (E^3, (r, th, ph)), Chart (E^3, (X, Y, Z))]
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3), coordinates='spherical') >>> E.atlas() # only spherical coordinates have been initialized [Chart (E^3, (r, th, ph))] >>> E.cartesian_coordinates(symbols='X Y Z') Chart (E^3, (X, Y, Z)) >>> E.atlas() # the Cartesian chart has been added to the atlas [Chart (E^3, (r, th, ph)), Chart (E^3, (X, Y, Z))]
E = EuclideanSpace(3, coordinates='spherical') E.atlas() # only spherical coordinates have been initialized E.cartesian_coordinates(symbols='X Y Z') E.atlas() # the Cartesian chart has been added to the atlas
The coordinate variables are returned by the square bracket operator:
sage: E.cartesian_coordinates()[1] X sage: E.cartesian_coordinates()[3] Z sage: E.cartesian_coordinates()[:] (X, Y, Z)
>>> from sage.all import * >>> E.cartesian_coordinates()[Integer(1)] X >>> E.cartesian_coordinates()[Integer(3)] Z >>> E.cartesian_coordinates()[:] (X, Y, Z)
E.cartesian_coordinates()[1] E.cartesian_coordinates()[3] E.cartesian_coordinates()[:]
It is also possible to use the operator
<,>
to set symbolic variable containing the coordinates:sage: E = EuclideanSpace(3, coordinates='spherical') sage: cartesian.<u,v,w> = E.cartesian_coordinates() sage: cartesian Chart (E^3, (u, v, w)) sage: u, v, w (u, v, w)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3), coordinates='spherical') >>> cartesian = E.cartesian_coordinates(names=('u', 'v', 'w',)); (u, v, w,) = cartesian._first_ngens(3) >>> cartesian Chart (E^3, (u, v, w)) >>> u, v, w (u, v, w)
E = EuclideanSpace(3, coordinates='spherical') cartesian.<u,v,w> = E.cartesian_coordinates() cartesian u, v, w
The command
cartesian.<u,v,w> = E.cartesian_coordinates()
is actually a shortcut for:sage: cartesian = E.cartesian_coordinates(symbols='u v w') sage: u, v, w = cartesian[:]
>>> from sage.all import * >>> cartesian = E.cartesian_coordinates(symbols='u v w') >>> u, v, w = cartesian[:]
cartesian = E.cartesian_coordinates(symbols='u v w') u, v, w = cartesian[:]
- cylindrical_coordinates(symbols=None, names=None)[source]¶
Return the chart of cylindrical coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the cylindrical chart has not been already defined; ifNone
the symbols are generated as \((\rho,\phi,z)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of cylindrical coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(3) sage: E.cylindrical_coordinates() Chart (E^3, (rh, ph, z)) sage: latex(_) \left(\mathbb{E}^{3},({\rho}, {\phi}, z)\right) sage: E.cylindrical_coordinates().coord_range() rh: (0, +oo); ph: [0, 2*pi] (periodic); z: (-oo, +oo)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.cylindrical_coordinates() Chart (E^3, (rh, ph, z)) >>> latex(_) \left(\mathbb{E}^{3},({\rho}, {\phi}, z)\right) >>> E.cylindrical_coordinates().coord_range() rh: (0, +oo); ph: [0, 2*pi] (periodic); z: (-oo, +oo)
E = EuclideanSpace(3) E.cylindrical_coordinates() latex(_) E.cylindrical_coordinates().coord_range()
The relation to Cartesian coordinates is:
sage: E.coord_change(E.cylindrical_coordinates(), ....: E.cartesian_coordinates()).display() x = rh*cos(ph) y = rh*sin(ph) z = z sage: E.coord_change(E.cartesian_coordinates(), ....: E.cylindrical_coordinates()).display() rh = sqrt(x^2 + y^2) ph = arctan2(y, x) z = z
>>> from sage.all import * >>> E.coord_change(E.cylindrical_coordinates(), ... E.cartesian_coordinates()).display() x = rh*cos(ph) y = rh*sin(ph) z = z >>> E.coord_change(E.cartesian_coordinates(), ... E.cylindrical_coordinates()).display() rh = sqrt(x^2 + y^2) ph = arctan2(y, x) z = z
E.coord_change(E.cylindrical_coordinates(), E.cartesian_coordinates()).display() E.coord_change(E.cartesian_coordinates(), E.cylindrical_coordinates()).display()
The coordinate variables are returned by the square bracket operator:
sage: E.cylindrical_coordinates()[1] rh sage: E.cylindrical_coordinates()[3] z sage: E.cylindrical_coordinates()[:] (rh, ph, z)
>>> from sage.all import * >>> E.cylindrical_coordinates()[Integer(1)] rh >>> E.cylindrical_coordinates()[Integer(3)] z >>> E.cylindrical_coordinates()[:] (rh, ph, z)
E.cylindrical_coordinates()[1] E.cylindrical_coordinates()[3] E.cylindrical_coordinates()[:]
They can also be obtained via the operator
<,>
:sage: cylindrical.<rh,ph,z> = E.cylindrical_coordinates() sage: cylindrical Chart (E^3, (rh, ph, z)) sage: rh, ph, z (rh, ph, z)
>>> from sage.all import * >>> cylindrical = E.cylindrical_coordinates(names=('rh', 'ph', 'z',)); (rh, ph, z,) = cylindrical._first_ngens(3) >>> cylindrical Chart (E^3, (rh, ph, z)) >>> rh, ph, z (rh, ph, z)
cylindrical.<rh,ph,z> = E.cylindrical_coordinates() cylindrical rh, ph, z
Actually,
cylindrical.<rh,ph,z> = E.cylindrical_coordinates()
is a shortcut for:sage: cylindrical = E.cylindrical_coordinates() sage: rh, ph, z = cylindrical[:]
>>> from sage.all import * >>> cylindrical = E.cylindrical_coordinates() >>> rh, ph, z = cylindrical[:]
cylindrical = E.cylindrical_coordinates() rh, ph, z = cylindrical[:]
The coordinate symbols can be customized:
sage: E = EuclideanSpace(3) sage: E.cylindrical_coordinates(symbols=r"R Phi:\Phi Z") Chart (E^3, (R, Phi, Z)) sage: latex(E.cylindrical_coordinates()) \left(\mathbb{E}^{3},(R, {\Phi}, Z)\right)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.cylindrical_coordinates(symbols=r"R Phi:\Phi Z") Chart (E^3, (R, Phi, Z)) >>> latex(E.cylindrical_coordinates()) \left(\mathbb{E}^{3},(R, {\Phi}, Z)\right)
E = EuclideanSpace(3) E.cylindrical_coordinates(symbols=r"R Phi:\Phi Z") latex(E.cylindrical_coordinates())
Note that if the cylindrical coordinates have been already initialized, the argument
symbols
has no effect:sage: E.cylindrical_coordinates(symbols=r"rh:\rho ph:\phi z") Chart (E^3, (R, Phi, Z))
>>> from sage.all import * >>> E.cylindrical_coordinates(symbols=r"rh:\rho ph:\phi z") Chart (E^3, (R, Phi, Z))
E.cylindrical_coordinates(symbols=r"rh:\rho ph:\phi z")
- cylindrical_frame()[source]¶
Return the orthonormal vector frame associated with cylindrical coordinates.
OUTPUT:
VectorFrame
EXAMPLES:
sage: E = EuclideanSpace(3) sage: E.cylindrical_frame() Vector frame (E^3, (e_rh,e_ph,e_z)) sage: E.cylindrical_frame()[1] Vector field e_rh on the Euclidean space E^3 sage: E.cylindrical_frame()[:] (Vector field e_rh on the Euclidean space E^3, Vector field e_ph on the Euclidean space E^3, Vector field e_z on the Euclidean space E^3)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.cylindrical_frame() Vector frame (E^3, (e_rh,e_ph,e_z)) >>> E.cylindrical_frame()[Integer(1)] Vector field e_rh on the Euclidean space E^3 >>> E.cylindrical_frame()[:] (Vector field e_rh on the Euclidean space E^3, Vector field e_ph on the Euclidean space E^3, Vector field e_z on the Euclidean space E^3)
E = EuclideanSpace(3) E.cylindrical_frame() E.cylindrical_frame()[1] E.cylindrical_frame()[:]
The cylindrical frame expressed in terms of the Cartesian one:
sage: for e in E.cylindrical_frame(): ....: e.display(E.cartesian_frame(), E.cylindrical_coordinates()) e_rh = cos(ph) e_x + sin(ph) e_y e_ph = -sin(ph) e_x + cos(ph) e_y e_z = e_z
>>> from sage.all import * >>> for e in E.cylindrical_frame(): ... e.display(E.cartesian_frame(), E.cylindrical_coordinates()) e_rh = cos(ph) e_x + sin(ph) e_y e_ph = -sin(ph) e_x + cos(ph) e_y e_z = e_z
for e in E.cylindrical_frame(): e.display(E.cartesian_frame(), E.cylindrical_coordinates())
The orthonormal frame \((e_r, e_\phi, e_z)\) expressed in terms of the coordinate frame \(\left(\frac{\partial}{\partial r}, \frac{\partial}{\partial\phi}, \frac{\partial}{\partial z}\right)\):
sage: for e in E.cylindrical_frame(): ....: e.display(E.cylindrical_coordinates()) e_rh = ∂/∂rh e_ph = 1/rh ∂/∂ph e_z = ∂/∂z
>>> from sage.all import * >>> for e in E.cylindrical_frame(): ... e.display(E.cylindrical_coordinates()) e_rh = ∂/∂rh e_ph = 1/rh ∂/∂ph e_z = ∂/∂z
for e in E.cylindrical_frame(): e.display(E.cylindrical_coordinates())
- scalar_triple_product(name=None, latex_name=None)[source]¶
Return the scalar triple product operator, as a 3-form.
The scalar triple product (also called mixed product) of three vector fields \(u\), \(v\) and \(w\) defined on a Euclidean space \(E\) is the scalar field
\[\epsilon(u,v,w) = u \cdot (v \times w).\]The scalar triple product operator \(\epsilon\) is a 3-form, i.e. a field of fully antisymmetric trilinear forms; it is also called the volume form of \(E\) or the Levi-Civita tensor of \(E\).
INPUT:
name
– (default:None
) string; name given to the scalar triple product operator; ifNone
,'epsilon'
is usedlatex_name
– (default:None
) string; LaTeX symbol to denote the scalar triple product; ifNone
, it is set tor'\epsilon'
ifname
isNone
and toname
otherwise.
OUTPUT:
the scalar triple product operator \(\epsilon\), as an instance of
DiffFormParal
EXAMPLES:
sage: E.<x,y,z> = EuclideanSpace() sage: triple_product = E.scalar_triple_product() sage: triple_product 3-form epsilon on the Euclidean space E^3 sage: latex(triple_product) \epsilon sage: u = E.vector_field(x, y, z, name='u') sage: v = E.vector_field(-y, x, 0, name='v') sage: w = E.vector_field(y*z, x*z, x*y, name='w') sage: s = triple_product(u, v, w); s Scalar field epsilon(u,v,w) on the Euclidean space E^3 sage: s.display() epsilon(u,v,w): E^3 → ℝ (x, y, z) ↦ x^3*y + x*y^3 - 2*x*y*z^2 sage: s.expr() x^3*y + x*y^3 - 2*x*y*z^2 sage: latex(s) \epsilon\left(u,v,w\right) sage: s == - triple_product(w, v, u) True
>>> from sage.all import * >>> E = EuclideanSpace(names=('x', 'y', 'z',)); (x, y, z,) = E._first_ngens(3) >>> triple_product = E.scalar_triple_product() >>> triple_product 3-form epsilon on the Euclidean space E^3 >>> latex(triple_product) \epsilon >>> u = E.vector_field(x, y, z, name='u') >>> v = E.vector_field(-y, x, Integer(0), name='v') >>> w = E.vector_field(y*z, x*z, x*y, name='w') >>> s = triple_product(u, v, w); s Scalar field epsilon(u,v,w) on the Euclidean space E^3 >>> s.display() epsilon(u,v,w): E^3 → ℝ (x, y, z) ↦ x^3*y + x*y^3 - 2*x*y*z^2 >>> s.expr() x^3*y + x*y^3 - 2*x*y*z^2 >>> latex(s) \epsilon\left(u,v,w\right) >>> s == - triple_product(w, v, u) True
E.<x,y,z> = EuclideanSpace() triple_product = E.scalar_triple_product() triple_product latex(triple_product) u = E.vector_field(x, y, z, name='u') v = E.vector_field(-y, x, 0, name='v') w = E.vector_field(y*z, x*z, x*y, name='w') s = triple_product(u, v, w); s s.display() s.expr() latex(s) s == - triple_product(w, v, u)
Check of the identity \(\epsilon(u,v,w) = u\cdot(v\times w)\):
sage: s == u.dot(v.cross(w)) True
>>> from sage.all import * >>> s == u.dot(v.cross(w)) True
s == u.dot(v.cross(w))
Customizing the name:
sage: E.scalar_triple_product(name='S') 3-form S on the Euclidean space E^3 sage: latex(_) S sage: E.scalar_triple_product(name='Omega', latex_name=r'\Omega') 3-form Omega on the Euclidean space E^3 sage: latex(_) \Omega
>>> from sage.all import * >>> E.scalar_triple_product(name='S') 3-form S on the Euclidean space E^3 >>> latex(_) S >>> E.scalar_triple_product(name='Omega', latex_name=r'\Omega') 3-form Omega on the Euclidean space E^3 >>> latex(_) \Omega
E.scalar_triple_product(name='S') latex(_) E.scalar_triple_product(name='Omega', latex_name=r'\Omega') latex(_)
- spherical_coordinates(symbols=None, names=None)[source]¶
Return the chart of spherical coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the spherical chart has not been already defined; ifNone
the symbols are generated as \((r,\theta,\phi)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of spherical coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(3) sage: E.spherical_coordinates() Chart (E^3, (r, th, ph)) sage: latex(_) \left(\mathbb{E}^{3},(r, {\theta}, {\phi})\right) sage: E.spherical_coordinates().coord_range() r: (0, +oo); th: (0, pi); ph: [0, 2*pi] (periodic)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.spherical_coordinates() Chart (E^3, (r, th, ph)) >>> latex(_) \left(\mathbb{E}^{3},(r, {\theta}, {\phi})\right) >>> E.spherical_coordinates().coord_range() r: (0, +oo); th: (0, pi); ph: [0, 2*pi] (periodic)
E = EuclideanSpace(3) E.spherical_coordinates() latex(_) E.spherical_coordinates().coord_range()
The relation to Cartesian coordinates is:
sage: E.coord_change(E.spherical_coordinates(), ....: E.cartesian_coordinates()).display() x = r*cos(ph)*sin(th) y = r*sin(ph)*sin(th) z = r*cos(th) sage: E.coord_change(E.cartesian_coordinates(), ....: E.spherical_coordinates()).display() r = sqrt(x^2 + y^2 + z^2) th = arctan2(sqrt(x^2 + y^2), z) ph = arctan2(y, x)
>>> from sage.all import * >>> E.coord_change(E.spherical_coordinates(), ... E.cartesian_coordinates()).display() x = r*cos(ph)*sin(th) y = r*sin(ph)*sin(th) z = r*cos(th) >>> E.coord_change(E.cartesian_coordinates(), ... E.spherical_coordinates()).display() r = sqrt(x^2 + y^2 + z^2) th = arctan2(sqrt(x^2 + y^2), z) ph = arctan2(y, x)
E.coord_change(E.spherical_coordinates(), E.cartesian_coordinates()).display() E.coord_change(E.cartesian_coordinates(), E.spherical_coordinates()).display()
The coordinate variables are returned by the square bracket operator:
sage: E.spherical_coordinates()[1] r sage: E.spherical_coordinates()[3] ph sage: E.spherical_coordinates()[:] (r, th, ph)
>>> from sage.all import * >>> E.spherical_coordinates()[Integer(1)] r >>> E.spherical_coordinates()[Integer(3)] ph >>> E.spherical_coordinates()[:] (r, th, ph)
E.spherical_coordinates()[1] E.spherical_coordinates()[3] E.spherical_coordinates()[:]
They can also be obtained via the operator
<,>
:sage: spherical.<r,th,ph> = E.spherical_coordinates() sage: spherical Chart (E^3, (r, th, ph)) sage: r, th, ph (r, th, ph)
>>> from sage.all import * >>> spherical = E.spherical_coordinates(names=('r', 'th', 'ph',)); (r, th, ph,) = spherical._first_ngens(3) >>> spherical Chart (E^3, (r, th, ph)) >>> r, th, ph (r, th, ph)
spherical.<r,th,ph> = E.spherical_coordinates() spherical r, th, ph
Actually,
spherical.<r,th,ph> = E.spherical_coordinates()
is a shortcut for:sage: spherical = E.spherical_coordinates() sage: r, th, ph = spherical[:]
>>> from sage.all import * >>> spherical = E.spherical_coordinates() >>> r, th, ph = spherical[:]
spherical = E.spherical_coordinates() r, th, ph = spherical[:]
The coordinate symbols can be customized:
sage: E = EuclideanSpace(3) sage: E.spherical_coordinates(symbols=r"R T:\Theta F:\Phi") Chart (E^3, (R, T, F)) sage: latex(E.spherical_coordinates()) \left(\mathbb{E}^{3},(R, {\Theta}, {\Phi})\right)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.spherical_coordinates(symbols=r"R T:\Theta F:\Phi") Chart (E^3, (R, T, F)) >>> latex(E.spherical_coordinates()) \left(\mathbb{E}^{3},(R, {\Theta}, {\Phi})\right)
E = EuclideanSpace(3) E.spherical_coordinates(symbols=r"R T:\Theta F:\Phi") latex(E.spherical_coordinates())
Note that if the spherical coordinates have been already initialized, the argument
symbols
has no effect:sage: E.spherical_coordinates(symbols=r"r th:\theta ph:\phi") Chart (E^3, (R, T, F))
>>> from sage.all import * >>> E.spherical_coordinates(symbols=r"r th:\theta ph:\phi") Chart (E^3, (R, T, F))
E.spherical_coordinates(symbols=r"r th:\theta ph:\phi")
- spherical_frame()[source]¶
Return the orthonormal vector frame associated with spherical coordinates.
OUTPUT:
VectorFrame
EXAMPLES:
sage: E = EuclideanSpace(3) sage: E.spherical_frame() Vector frame (E^3, (e_r,e_th,e_ph)) sage: E.spherical_frame()[1] Vector field e_r on the Euclidean space E^3 sage: E.spherical_frame()[:] (Vector field e_r on the Euclidean space E^3, Vector field e_th on the Euclidean space E^3, Vector field e_ph on the Euclidean space E^3)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(3)) >>> E.spherical_frame() Vector frame (E^3, (e_r,e_th,e_ph)) >>> E.spherical_frame()[Integer(1)] Vector field e_r on the Euclidean space E^3 >>> E.spherical_frame()[:] (Vector field e_r on the Euclidean space E^3, Vector field e_th on the Euclidean space E^3, Vector field e_ph on the Euclidean space E^3)
E = EuclideanSpace(3) E.spherical_frame() E.spherical_frame()[1] E.spherical_frame()[:]
The spherical frame expressed in terms of the Cartesian one:
sage: for e in E.spherical_frame(): ....: e.display(E.cartesian_frame(), E.spherical_coordinates()) 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
>>> from sage.all import * >>> for e in E.spherical_frame(): ... e.display(E.cartesian_frame(), E.spherical_coordinates()) 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
for e in E.spherical_frame(): e.display(E.cartesian_frame(), E.spherical_coordinates())
The orthonormal frame \((e_r, e_\theta, e_\phi)\) expressed in terms of the coordinate frame \(\left(\frac{\partial}{\partial r}, \frac{\partial}{\partial\theta}, \frac{\partial}{\partial\phi}\right)\):
sage: for e in E.spherical_frame(): ....: e.display(E.spherical_coordinates()) e_r = ∂/∂r e_th = 1/r ∂/∂th e_ph = 1/(r*sin(th)) ∂/∂ph
>>> from sage.all import * >>> for e in E.spherical_frame(): ... e.display(E.spherical_coordinates()) e_r = ∂/∂r e_th = 1/r ∂/∂th e_ph = 1/(r*sin(th)) ∂/∂ph
for e in E.spherical_frame(): e.display(E.spherical_coordinates())
- class sage.manifolds.differentiable.examples.euclidean.EuclideanPlane(name=None, latex_name=None, coordinates='Cartesian', symbols=None, metric_name='g', metric_latex_name=None, start_index=1, base_manifold=None, category=None, unique_tag=None)[source]¶
Bases:
EuclideanSpace
Euclidean plane.
A Euclidean plane is an affine space \(E\), whose associated vector space is a 2-dimensional vector space over \(\RR\) and is equipped with a positive definite symmetric bilinear form, called the scalar product or dot product.
The class
EuclideanPlane
inherits fromPseudoRiemannianManifold
(viaEuclideanSpace
) since a Euclidean plane can be viewed as a Riemannian manifold that is diffeomorphic to \(\RR^2\) and that has a flat metric \(g\). The Euclidean scalar product is the one defined by the Riemannian metric \(g\).INPUT:
name
– (default:None
) string; name (symbol) given to the Euclidean plane; ifNone
, the name will be set to'E^2'
latex_name
– (default:None
) string; LaTeX symbol to denote the Euclidean plane; ifNone
, it is set to'\mathbb{E}^{2}'
ifname
isNone
and toname
otherwisecoordinates
– (default:'Cartesian'
) string describing the type of coordinates to be initialized at the Euclidean plane creation; allowed values are'Cartesian'
(seecartesian_coordinates()
) and'polar'
(seepolar_coordinates()
)symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
, namelysymbols
is a string of coordinate fields separated by a blank space, where 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 (:
); ifNone
, the symbols will be automatically generated according to the value ofcoordinates
metric_name
– (default:'g'
) string; name (symbol) given to the Euclidean metric tensormetric_latex_name
– (default:None
) string; LaTeX symbol to denote the Euclidean metric tensor; if none is provided, it is set tometric_name
start_index
– (default: 1) integer; lower value of the range of indices used for “indexed objects” in the Euclidean plane, e.g. coordinates of a chartbase_manifold
– (default:None
) if notNone
, must be an Euclidean plane; the created object is then an open subset ofbase_manifold
category
– (default:None
) to specify the category; ifNone
,Manifolds(RR).Smooth() & MetricSpaces().Complete()
is assumednames
– (default:None
) unused argument, except ifsymbols
is not provided; it must then be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)init_coord_methods
– (default:None
) dictionary of methods to initialize the various type of coordinates, with each key being a string describing the type of coordinates; to be used by derived classes onlyunique_tag
– (default:None
) tag used to force the construction of a new object when all the other arguments have been used previously (withoutunique_tag
, theUniqueRepresentation
behavior inherited fromPseudoRiemannianManifold
would return the previously constructed object corresponding to these arguments)
EXAMPLES:
One creates a Euclidean plane
E
with:sage: E.<x,y> = EuclideanSpace(); E Euclidean plane E^2
>>> from sage.all import * >>> E = EuclideanSpace(names=('x', 'y',)); (x, y,) = E._first_ngens(2); E Euclidean plane E^2
E.<x,y> = EuclideanSpace(); E
E
is both a real smooth manifold of dimension \(2\) and a complete metric space:sage: E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces sage: dim(E) 2
>>> from sage.all import * >>> E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces >>> dim(E) 2
E.category() dim(E)
It is endowed with a default coordinate chart, which is that of Cartesian coordinates \((x,y)\):
sage: E.atlas() [Chart (E^2, (x, y))] sage: E.default_chart() Chart (E^2, (x, y)) sage: cartesian = E.cartesian_coordinates() sage: cartesian is E.default_chart() True
>>> from sage.all import * >>> E.atlas() [Chart (E^2, (x, y))] >>> E.default_chart() Chart (E^2, (x, y)) >>> cartesian = E.cartesian_coordinates() >>> cartesian is E.default_chart() True
E.atlas() E.default_chart() cartesian = E.cartesian_coordinates() cartesian is E.default_chart()
A point of
E
:sage: p = E((3,-2)); p Point on the Euclidean plane E^2 sage: cartesian(p) (3, -2) sage: p in E True sage: p.parent() is E True
>>> from sage.all import * >>> p = E((Integer(3),-Integer(2))); p Point on the Euclidean plane E^2 >>> cartesian(p) (3, -2) >>> p in E True >>> p.parent() is E True
p = E((3,-2)); p cartesian(p) p in E p.parent() is E
E
is endowed with a default metric tensor, which defines the Euclidean scalar product:sage: g = E.metric(); g Riemannian metric g on the Euclidean plane E^2 sage: g.display() g = dx⊗dx + dy⊗dy
>>> from sage.all import * >>> g = E.metric(); g Riemannian metric g on the Euclidean plane E^2 >>> g.display() g = dx⊗dx + dy⊗dy
g = E.metric(); g g.display()
Curvilinear coordinates can be introduced on
E
: seepolar_coordinates()
.See also
- cartesian_coordinates(symbols=None, names=None)[source]¶
Return the chart of Cartesian coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the Cartesian chart has not been already defined; ifNone
the symbols are generated as \((x,y)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of Cartesian coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(2) sage: E.cartesian_coordinates() Chart (E^2, (x, y)) sage: E.cartesian_coordinates().coord_range() x: (-oo, +oo); y: (-oo, +oo)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)) >>> E.cartesian_coordinates() Chart (E^2, (x, y)) >>> E.cartesian_coordinates().coord_range() x: (-oo, +oo); y: (-oo, +oo)
E = EuclideanSpace(2) E.cartesian_coordinates() E.cartesian_coordinates().coord_range()
An example where the Cartesian coordinates have not been previously created:
sage: E = EuclideanSpace(2, coordinates='polar') sage: E.atlas() # only polar coordinates have been initialized [Chart (E^2, (r, ph))] sage: E.cartesian_coordinates(symbols='X Y') Chart (E^2, (X, Y)) sage: E.atlas() # the Cartesian chart has been added to the atlas [Chart (E^2, (r, ph)), Chart (E^2, (X, Y))]
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2), coordinates='polar') >>> E.atlas() # only polar coordinates have been initialized [Chart (E^2, (r, ph))] >>> E.cartesian_coordinates(symbols='X Y') Chart (E^2, (X, Y)) >>> E.atlas() # the Cartesian chart has been added to the atlas [Chart (E^2, (r, ph)), Chart (E^2, (X, Y))]
E = EuclideanSpace(2, coordinates='polar') E.atlas() # only polar coordinates have been initialized E.cartesian_coordinates(symbols='X Y') E.atlas() # the Cartesian chart has been added to the atlas
Note that if the Cartesian coordinates have been already initialized, the argument
symbols
has no effect:sage: E.cartesian_coordinates(symbols='x y') Chart (E^2, (X, Y))
>>> from sage.all import * >>> E.cartesian_coordinates(symbols='x y') Chart (E^2, (X, Y))
E.cartesian_coordinates(symbols='x y')
The coordinate variables are returned by the square bracket operator:
sage: E.cartesian_coordinates()[1] X sage: E.cartesian_coordinates()[2] Y sage: E.cartesian_coordinates()[:] (X, Y)
>>> from sage.all import * >>> E.cartesian_coordinates()[Integer(1)] X >>> E.cartesian_coordinates()[Integer(2)] Y >>> E.cartesian_coordinates()[:] (X, Y)
E.cartesian_coordinates()[1] E.cartesian_coordinates()[2] E.cartesian_coordinates()[:]
It is also possible to use the operator
<,>
to set symbolic variable containing the coordinates:sage: E = EuclideanSpace(2, coordinates='polar') sage: cartesian.<u,v> = E.cartesian_coordinates() sage: cartesian Chart (E^2, (u, v)) sage: u,v (u, v)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2), coordinates='polar') >>> cartesian = E.cartesian_coordinates(names=('u', 'v',)); (u, v,) = cartesian._first_ngens(2) >>> cartesian Chart (E^2, (u, v)) >>> u,v (u, v)
E = EuclideanSpace(2, coordinates='polar') cartesian.<u,v> = E.cartesian_coordinates() cartesian u,v
The command
cartesian.<u,v> = E.cartesian_coordinates()
is actually a shortcut for:sage: cartesian = E.cartesian_coordinates(symbols='u v') sage: u, v = cartesian[:]
>>> from sage.all import * >>> cartesian = E.cartesian_coordinates(symbols='u v') >>> u, v = cartesian[:]
cartesian = E.cartesian_coordinates(symbols='u v') u, v = cartesian[:]
- polar_coordinates(symbols=None, names=None)[source]¶
Return the chart of polar coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the polar chart has not been already defined; ifNone
the symbols are generated as \((r,\phi)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of polar coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(2) sage: E.polar_coordinates() Chart (E^2, (r, ph)) sage: latex(_) \left(\mathbb{E}^{2},(r, {\phi})\right) sage: E.polar_coordinates().coord_range() r: (0, +oo); ph: [0, 2*pi] (periodic)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)) >>> E.polar_coordinates() Chart (E^2, (r, ph)) >>> latex(_) \left(\mathbb{E}^{2},(r, {\phi})\right) >>> E.polar_coordinates().coord_range() r: (0, +oo); ph: [0, 2*pi] (periodic)
E = EuclideanSpace(2) E.polar_coordinates() latex(_) E.polar_coordinates().coord_range()
The relation to Cartesian coordinates is:
sage: E.coord_change(E.polar_coordinates(), ....: E.cartesian_coordinates()).display() x = r*cos(ph) y = r*sin(ph) sage: E.coord_change(E.cartesian_coordinates(), ....: E.polar_coordinates()).display() r = sqrt(x^2 + y^2) ph = arctan2(y, x)
>>> from sage.all import * >>> E.coord_change(E.polar_coordinates(), ... E.cartesian_coordinates()).display() x = r*cos(ph) y = r*sin(ph) >>> E.coord_change(E.cartesian_coordinates(), ... E.polar_coordinates()).display() r = sqrt(x^2 + y^2) ph = arctan2(y, x)
E.coord_change(E.polar_coordinates(), E.cartesian_coordinates()).display() E.coord_change(E.cartesian_coordinates(), E.polar_coordinates()).display()
The coordinate variables are returned by the square bracket operator:
sage: E.polar_coordinates()[1] r sage: E.polar_coordinates()[2] ph sage: E.polar_coordinates()[:] (r, ph)
>>> from sage.all import * >>> E.polar_coordinates()[Integer(1)] r >>> E.polar_coordinates()[Integer(2)] ph >>> E.polar_coordinates()[:] (r, ph)
E.polar_coordinates()[1] E.polar_coordinates()[2] E.polar_coordinates()[:]
They can also be obtained via the operator
<,>
:sage: polar.<r,ph> = E.polar_coordinates(); polar Chart (E^2, (r, ph)) sage: r, ph (r, ph)
>>> from sage.all import * >>> polar = E.polar_coordinates(names=('r', 'ph',)); (r, ph,) = polar._first_ngens(2); polar Chart (E^2, (r, ph)) >>> r, ph (r, ph)
polar.<r,ph> = E.polar_coordinates(); polar r, ph
Actually,
polar.<r,ph> = E.polar_coordinates()
is a shortcut for:sage: polar = E.polar_coordinates() sage: r, ph = polar[:]
>>> from sage.all import * >>> polar = E.polar_coordinates() >>> r, ph = polar[:]
polar = E.polar_coordinates() r, ph = polar[:]
The coordinate symbols can be customized:
sage: E = EuclideanSpace(2) sage: E.polar_coordinates(symbols=r"r th:\theta") Chart (E^2, (r, th)) sage: latex(E.polar_coordinates()) \left(\mathbb{E}^{2},(r, {\theta})\right)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)) >>> E.polar_coordinates(symbols=r"r th:\theta") Chart (E^2, (r, th)) >>> latex(E.polar_coordinates()) \left(\mathbb{E}^{2},(r, {\theta})\right)
E = EuclideanSpace(2) E.polar_coordinates(symbols=r"r th:\theta") latex(E.polar_coordinates())
Note that if the polar coordinates have been already initialized, the argument
symbols
has no effect:sage: E.polar_coordinates(symbols=r"R Th:\Theta") Chart (E^2, (r, th))
>>> from sage.all import * >>> E.polar_coordinates(symbols=r"R Th:\Theta") Chart (E^2, (r, th))
E.polar_coordinates(symbols=r"R Th:\Theta")
- polar_frame()[source]¶
Return the orthonormal vector frame associated with polar coordinates.
OUTPUT:
instance of
VectorFrame
EXAMPLES:
sage: E = EuclideanSpace(2) sage: E.polar_frame() Vector frame (E^2, (e_r,e_ph)) sage: E.polar_frame()[1] Vector field e_r on the Euclidean plane E^2 sage: E.polar_frame()[:] (Vector field e_r on the Euclidean plane E^2, Vector field e_ph on the Euclidean plane E^2)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)) >>> E.polar_frame() Vector frame (E^2, (e_r,e_ph)) >>> E.polar_frame()[Integer(1)] Vector field e_r on the Euclidean plane E^2 >>> E.polar_frame()[:] (Vector field e_r on the Euclidean plane E^2, Vector field e_ph on the Euclidean plane E^2)
E = EuclideanSpace(2) E.polar_frame() E.polar_frame()[1] E.polar_frame()[:]
The orthonormal polar frame expressed in terms of the Cartesian one:
sage: for e in E.polar_frame(): ....: e.display(E.cartesian_frame(), E.polar_coordinates()) e_r = cos(ph) e_x + sin(ph) e_y e_ph = -sin(ph) e_x + cos(ph) e_y
>>> from sage.all import * >>> for e in E.polar_frame(): ... e.display(E.cartesian_frame(), E.polar_coordinates()) e_r = cos(ph) e_x + sin(ph) e_y e_ph = -sin(ph) e_x + cos(ph) e_y
for e in E.polar_frame(): e.display(E.cartesian_frame(), E.polar_coordinates())
The orthonormal frame \((e_r, e_\phi)\) expressed in terms of the coordinate frame \(\left(\frac{\partial}{\partial r}, \frac{\partial}{\partial\phi}\right)\):
sage: for e in E.polar_frame(): ....: e.display(E.polar_coordinates()) e_r = ∂/∂r e_ph = 1/r ∂/∂ph
>>> from sage.all import * >>> for e in E.polar_frame(): ... e.display(E.polar_coordinates()) e_r = ∂/∂r e_ph = 1/r ∂/∂ph
for e in E.polar_frame(): e.display(E.polar_coordinates())
- class sage.manifolds.differentiable.examples.euclidean.EuclideanSpace(n, name=None, latex_name=None, coordinates='Cartesian', symbols=None, metric_name='g', metric_latex_name=None, start_index=1, base_manifold=None, category=None, init_coord_methods=None, unique_tag=None)[source]¶
Bases:
PseudoRiemannianManifold
Euclidean space.
A Euclidean space of dimension \(n\) is an affine space \(E\), whose associated vector space is a \(n\)-dimensional vector space over \(\RR\) and is equipped with a positive definite symmetric bilinear form, called the scalar product or dot product.
Euclidean space of dimension \(n\) can be viewed as a Riemannian manifold that is diffeomorphic to \(\RR^n\) and that has a flat metric \(g\). The Euclidean scalar product is the one defined by the Riemannian metric \(g\).
INPUT:
n
– positive integer; dimension of the space over the real fieldname
– (default:None
) string; name (symbol) given to the Euclidean space; ifNone
, the name will be set to'E^n'
latex_name
– (default:None
) string; LaTeX symbol to denote the space; ifNone
, it is set to'\mathbb{E}^{n}'
ifname
isNone
and toname
otherwisecoordinates
– (default:'Cartesian'
) string describing the type of coordinates to be initialized at the Euclidean space creation; allowed values are'Cartesian'
(canonical coordinates on \(\RR^n\))'polar'
forn=2
only (seepolar_coordinates()
)'spherical'
forn=3
only (seespherical_coordinates()
)'cylindrical'
forn=3
only (seecylindrical_coordinates()
)
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
, namelysymbols
is a string of coordinate fields separated by a blank space, where 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 (:
); ifNone
, the symbols will be automatically generated according to the value ofcoordinates
metric_name
– (default:'g'
) string; name (symbol) given to the Euclidean metric tensormetric_latex_name
– (default:None
) string; LaTeX symbol to denote the Euclidean metric tensor; if none is provided, it is set tometric_name
start_index
– (default: 1) integer; lower value of the range of indices used for “indexed objects” in the Euclidean space, e.g. coordinates of a chartnames
– (default:None
) unused argument, except ifsymbols
is not provided; it must then be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
If
names
is specified, thenn
does not have to be specified.EXAMPLES:
Constructing a 2-dimensional Euclidean space:
sage: E = EuclideanSpace(2); E Euclidean plane E^2
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)); E Euclidean plane E^2
E = EuclideanSpace(2); E
Each call to
EuclideanSpace
creates a different object:sage: E1 = EuclideanSpace(2) sage: E1 is E False sage: E1 == E False
>>> from sage.all import * >>> E1 = EuclideanSpace(Integer(2)) >>> E1 is E False >>> E1 == E False
E1 = EuclideanSpace(2) E1 is E E1 == E
The LaTeX symbol of the Euclidean space is by default \(\mathbb{E}^n\), where \(n\) is the dimension:
sage: latex(E) \mathbb{E}^{2}
>>> from sage.all import * >>> latex(E) \mathbb{E}^{2}
latex(E)
But both the name and LaTeX names of the Euclidean space can be customized:
sage: F = EuclideanSpace(2, name='F', latex_name=r'\mathcal{F}'); F Euclidean plane F sage: latex(F) \mathcal{F}
>>> from sage.all import * >>> F = EuclideanSpace(Integer(2), name='F', latex_name=r'\mathcal{F}'); F Euclidean plane F >>> latex(F) \mathcal{F}
F = EuclideanSpace(2, name='F', latex_name=r'\mathcal{F}'); F latex(F)
By default, a Euclidean space is created with a single coordinate chart: that of Cartesian coordinates:
sage: E.atlas() [Chart (E^2, (x, y))] sage: E.cartesian_coordinates() Chart (E^2, (x, y)) sage: E.default_chart() is E.cartesian_coordinates() True
>>> from sage.all import * >>> E.atlas() [Chart (E^2, (x, y))] >>> E.cartesian_coordinates() Chart (E^2, (x, y)) >>> E.default_chart() is E.cartesian_coordinates() True
E.atlas() E.cartesian_coordinates() E.default_chart() is E.cartesian_coordinates()
The coordinate variables can be initialized, as the Python variables
x
andy
, by:sage: x, y = E.cartesian_coordinates()[:]
>>> from sage.all import * >>> x, y = E.cartesian_coordinates()[:]
x, y = E.cartesian_coordinates()[:]
However, it is possible to both construct the Euclidean space and initialize the coordinate variables in a single stage, thanks to SageMath operator
<,>
:sage: E.<x,y> = EuclideanSpace()
>>> from sage.all import * >>> E = EuclideanSpace(names=('x', 'y',)); (x, y,) = E._first_ngens(2)
E.<x,y> = EuclideanSpace()
Note that providing the dimension as an argument of
EuclideanSpace
is not necessary in that case, since it can be deduced from the number of coordinates within<,>
. Besides, the coordinate symbols can be customized:sage: E.<X,Y> = EuclideanSpace() sage: E.cartesian_coordinates() Chart (E^2, (X, Y))
>>> from sage.all import * >>> E = EuclideanSpace(names=('X', 'Y',)); (X, Y,) = E._first_ngens(2) >>> E.cartesian_coordinates() Chart (E^2, (X, Y))
E.<X,Y> = EuclideanSpace() E.cartesian_coordinates()
By default, the LaTeX symbols of the coordinates coincide with the text ones:
sage: latex(X+Y) X + Y
>>> from sage.all import * >>> latex(X+Y) X + Y
latex(X+Y)
However, it is possible to customize them, via the argument
symbols
, which must be a string, usually prefixed byr
(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 (:
):sage: E.<xi,ze> = EuclideanSpace(symbols=r"xi:\xi ze:\zeta") sage: E.cartesian_coordinates() Chart (E^2, (xi, ze)) sage: latex(xi+ze) {\xi} + {\zeta}
>>> from sage.all import * >>> E = EuclideanSpace(symbols=r"xi:\xi ze:\zeta", names=('xi', 'ze',)); (xi, ze,) = E._first_ngens(2) >>> E.cartesian_coordinates() Chart (E^2, (xi, ze)) >>> latex(xi+ze) {\xi} + {\zeta}
E.<xi,ze> = EuclideanSpace(symbols=r"xi:\xi ze:\zeta") E.cartesian_coordinates() latex(xi+ze)
Thanks to the argument
coordinates
, a Euclidean space can be constructed with curvilinear coordinates initialized instead of the Cartesian ones:sage: E.<r,ph> = EuclideanSpace(coordinates='polar') sage: E.atlas() # no Cartesian coordinates have been constructed [Chart (E^2, (r, ph))] sage: polar = E.polar_coordinates(); polar Chart (E^2, (r, ph)) sage: E.default_chart() is polar True sage: latex(r+ph) {\phi} + r
>>> from sage.all import * >>> E = EuclideanSpace(coordinates='polar', names=('r', 'ph',)); (r, ph,) = E._first_ngens(2) >>> E.atlas() # no Cartesian coordinates have been constructed [Chart (E^2, (r, ph))] >>> polar = E.polar_coordinates(); polar Chart (E^2, (r, ph)) >>> E.default_chart() is polar True >>> latex(r+ph) {\phi} + r
E.<r,ph> = EuclideanSpace(coordinates='polar') E.atlas() # no Cartesian coordinates have been constructed polar = E.polar_coordinates(); polar E.default_chart() is polar latex(r+ph)
The Cartesian coordinates, along with the transition maps to and from the curvilinear coordinates, can be constructed at any time by:
sage: cartesian.<x,y> = E.cartesian_coordinates() sage: E.atlas() # both polar and Cartesian coordinates now exist [Chart (E^2, (r, ph)), Chart (E^2, (x, y))]
>>> from sage.all import * >>> cartesian = E.cartesian_coordinates(names=('x', 'y',)); (x, y,) = cartesian._first_ngens(2) >>> E.atlas() # both polar and Cartesian coordinates now exist [Chart (E^2, (r, ph)), Chart (E^2, (x, y))]
cartesian.<x,y> = E.cartesian_coordinates() E.atlas() # both polar and Cartesian coordinates now exist
The transition maps have been initialized by the command
E.cartesian_coordinates()
:sage: E.coord_change(polar, cartesian).display() x = r*cos(ph) y = r*sin(ph) sage: E.coord_change(cartesian, polar).display() r = sqrt(x^2 + y^2) ph = arctan2(y, x)
>>> from sage.all import * >>> E.coord_change(polar, cartesian).display() x = r*cos(ph) y = r*sin(ph) >>> E.coord_change(cartesian, polar).display() r = sqrt(x^2 + y^2) ph = arctan2(y, x)
E.coord_change(polar, cartesian).display() E.coord_change(cartesian, polar).display()
The default name of the Euclidean metric tensor is \(g\):
sage: E.metric() Riemannian metric g on the Euclidean plane E^2 sage: latex(_) g
>>> from sage.all import * >>> E.metric() Riemannian metric g on the Euclidean plane E^2 >>> latex(_) g
E.metric() latex(_)
But this can be customized:
sage: E = EuclideanSpace(2, metric_name='h') sage: E.metric() Riemannian metric h on the Euclidean plane E^2 sage: latex(_) h sage: E = EuclideanSpace(2, metric_latex_name=r'\mathbf{g}') sage: E.metric() Riemannian metric g on the Euclidean plane E^2 sage: latex(_) \mathbf{g}
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2), metric_name='h') >>> E.metric() Riemannian metric h on the Euclidean plane E^2 >>> latex(_) h >>> E = EuclideanSpace(Integer(2), metric_latex_name=r'\mathbf{g}') >>> E.metric() Riemannian metric g on the Euclidean plane E^2 >>> latex(_) \mathbf{g}
E = EuclideanSpace(2, metric_name='h') E.metric() latex(_) E = EuclideanSpace(2, metric_latex_name=r'\mathbf{g}') E.metric() latex(_)
A 4-dimensional Euclidean space:
sage: E = EuclideanSpace(4); E 4-dimensional Euclidean space E^4 sage: latex(E) \mathbb{E}^{4}
>>> from sage.all import * >>> E = EuclideanSpace(Integer(4)); E 4-dimensional Euclidean space E^4 >>> latex(E) \mathbb{E}^{4}
E = EuclideanSpace(4); E latex(E)
E
is both a real smooth manifold of dimension \(4\) and a complete metric space:sage: E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces sage: dim(E) 4
>>> from sage.all import * >>> E.category() Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and Category of complete metric spaces >>> dim(E) 4
E.category() dim(E)
It is endowed with a default coordinate chart, which is that of Cartesian coordinates \((x_1,x_2,x_3,x_4)\):
sage: E.atlas() [Chart (E^4, (x1, x2, x3, x4))] sage: E.default_chart() Chart (E^4, (x1, x2, x3, x4)) sage: E.default_chart() is E.cartesian_coordinates() True
>>> from sage.all import * >>> E.atlas() [Chart (E^4, (x1, x2, x3, x4))] >>> E.default_chart() Chart (E^4, (x1, x2, x3, x4)) >>> E.default_chart() is E.cartesian_coordinates() True
E.atlas() E.default_chart() E.default_chart() is E.cartesian_coordinates()
E
is also endowed with a default metric tensor, which defines the Euclidean scalar product:sage: g = E.metric(); g Riemannian metric g on the 4-dimensional Euclidean space E^4 sage: g.display() g = dx1⊗dx1 + dx2⊗dx2 + dx3⊗dx3 + dx4⊗dx4
>>> from sage.all import * >>> g = E.metric(); g Riemannian metric g on the 4-dimensional Euclidean space E^4 >>> g.display() g = dx1⊗dx1 + dx2⊗dx2 + dx3⊗dx3 + dx4⊗dx4
g = E.metric(); g g.display()
- cartesian_coordinates(symbols=None, names=None)[source]¶
Return the chart of Cartesian coordinates, possibly creating it if it does not already exist.
INPUT:
symbols
– (default:None
) string defining the coordinate text symbols and LaTeX symbols, with the same conventions as the argumentcoordinates
inRealDiffChart
; this is used only if the Cartesian chart has not been already defined; ifNone
the symbols are generated as \((x_1,\ldots,x_n)\).names
– (default:None
) unused argument, except ifsymbols
is not provided; it must be a tuple containing the coordinate symbols (this is guaranteed if the shortcut operator<,>
is used)
OUTPUT:
the chart of Cartesian coordinates, as an instance of
RealDiffChart
EXAMPLES:
sage: E = EuclideanSpace(4) sage: X = E.cartesian_coordinates(); X Chart (E^4, (x1, x2, x3, x4)) sage: X.coord_range() x1: (-oo, +oo); x2: (-oo, +oo); x3: (-oo, +oo); x4: (-oo, +oo) sage: X[2] x2 sage: X[:] (x1, x2, x3, x4) sage: latex(X[:]) \left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\right)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(4)) >>> X = E.cartesian_coordinates(); X Chart (E^4, (x1, x2, x3, x4)) >>> X.coord_range() x1: (-oo, +oo); x2: (-oo, +oo); x3: (-oo, +oo); x4: (-oo, +oo) >>> X[Integer(2)] x2 >>> X[:] (x1, x2, x3, x4) >>> latex(X[:]) \left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\right)
E = EuclideanSpace(4) X = E.cartesian_coordinates(); X X.coord_range() X[2] X[:] latex(X[:])
- cartesian_frame()[source]¶
Return the orthonormal vector frame associated with Cartesian coordinates.
OUTPUT:
CoordFrame
EXAMPLES:
sage: E = EuclideanSpace(2) sage: E.cartesian_frame() Coordinate frame (E^2, (e_x,e_y)) sage: E.cartesian_frame()[1] Vector field e_x on the Euclidean plane E^2 sage: E.cartesian_frame()[:] (Vector field e_x on the Euclidean plane E^2, Vector field e_y on the Euclidean plane E^2)
>>> from sage.all import * >>> E = EuclideanSpace(Integer(2)) >>> E.cartesian_frame() Coordinate frame (E^2, (e_x,e_y)) >>> E.cartesian_frame()[Integer(1)] Vector field e_x on the Euclidean plane E^2 >>> E.cartesian_frame()[:] (Vector field e_x on the Euclidean plane E^2, Vector field e_y on the Euclidean plane E^2)
E = EuclideanSpace(2) E.cartesian_frame() E.cartesian_frame()[1] E.cartesian_frame()[:]
For Cartesian coordinates, the orthonormal frame coincides with the coordinate frame:
sage: E.cartesian_frame() is E.cartesian_coordinates().frame() True
>>> from sage.all import * >>> E.cartesian_frame() is E.cartesian_coordinates().frame() True
E.cartesian_frame() is E.cartesian_coordinates().frame()
- dist(p, q)[source]¶
Euclidean distance between two points.
INPUT:
p
– an element ofself
q
– an element ofself
OUTPUT:
the Euclidean distance \(d(p, q)\)
EXAMPLES:
sage: E.<x,y> = EuclideanSpace() sage: p = E((1,0)) sage: q = E((0,2)) sage: E.dist(p, q) sqrt(5) sage: p.dist(q) # indirect doctest sqrt(5)
>>> from sage.all import * >>> E = EuclideanSpace(names=('x', 'y',)); (x, y,) = E._first_ngens(2) >>> p = E((Integer(1),Integer(0))) >>> q = E((Integer(0),Integer(2))) >>> E.dist(p, q) sqrt(5) >>> p.dist(q) # indirect doctest sqrt(5)
E.<x,y> = EuclideanSpace() p = E((1,0)) q = E((0,2)) E.dist(p, q) p.dist(q) # indirect doctest
- sphere(radius=1, center=None, name=None, latex_name=None, coordinates='spherical', names=None)[source]¶
Return an \((n-1)\)-sphere smoothly embedded in
self
.INPUT:
radius
– (default:1
) the radius greater than 1 of the spherecenter
– (default:None
) point onself
representing the barycenter of the spherename
– (default:None
) string; name (symbol) given to the sphere; ifNone
, the name will be generated according to the inputlatex_name
– (default:None
) string; LaTeX symbol to denote the sphere; ifNone
, the symbol will be generated according to the inputcoordinates
– (default:'spherical'
) string describing the type of coordinates to be initialized at the sphere’s creation; allowed values are'spherical'
spherical coordinates (seespherical_coordinates()
))'stereographic'
stereographic coordinates given by the stereographic projection (seestereographic_coordinates()
)
names
– (default:None
) must be a tuple containing the coordinate symbols (this guarantees the shortcut operator<,>
to function); ifNone
, the usual conventions are used (see examples inSphere
for details)
EXAMPLES:
Define a 2-sphere with radius 2 centered at \((1,2,3)\) in Cartesian coordinates:
sage: E3 = EuclideanSpace(3) sage: c = E3.point((1,2,3), name='c'); c Point c on the Euclidean space E^3 sage: S2_2 = E3.sphere(radius=2, center=c); S2_2 2-sphere S^2_2(c) of radius 2 smoothly embedded in the Euclidean space E^3 centered at the Point c
>>> from sage.all import * >>> E3 = EuclideanSpace(Integer(3)) >>> c = E3.point((Integer(1),Integer(2),Integer(3)), name='c'); c Point c on the Euclidean space E^3 >>> S2_2 = E3.sphere(radius=Integer(2), center=c); S2_2 2-sphere S^2_2(c) of radius 2 smoothly embedded in the Euclidean space E^3 centered at the Point c
E3 = EuclideanSpace(3) c = E3.point((1,2,3), name='c'); c S2_2 = E3.sphere(radius=2, center=c); S2_2
The ambient space is precisely our previously defined Euclidean space:
sage: S2_2.ambient() is E3 True
>>> from sage.all import * >>> S2_2.ambient() is E3 True
S2_2.ambient() is E3
The embedding into Euclidean space:
sage: S2_2.embedding().display() iota: S^2_2(c) → E^3 on A: (theta, phi) ↦ (x, y, z) = (2*cos(phi)*sin(theta) + 1, 2*sin(phi)*sin(theta) + 2, 2*cos(theta) + 3)
>>> from sage.all import * >>> S2_2.embedding().display() iota: S^2_2(c) → E^3 on A: (theta, phi) ↦ (x, y, z) = (2*cos(phi)*sin(theta) + 1, 2*sin(phi)*sin(theta) + 2, 2*cos(theta) + 3)
S2_2.embedding().display()
See
Sphere
for more examples.