Topological Manifolds

Given a topological field \(K\) (in most applications, \(K = \RR\) or \(K = \CC\)) and a non-negative integer \(n\), a topological manifold of dimension \(n\) over K is a topological space \(M\) such that

  • \(M\) is a Hausdorff space,
  • \(M\) is second countable,
  • every point in \(M\) has a neighborhood homeomorphic to \(K^n\).

Topological manifolds are implemented via the class TopologicalManifold. Open subsets of topological manifolds are also implemented via TopologicalManifold, since they are topological manifolds by themselves.

In the current setting, topological manifolds are mostly described by means of charts (see Chart).

TopologicalManifold serves as a base class for more specific manifold classes.

The user interface is provided by the generic function Manifold(), with with the argument structure set to 'topological'.

Example 1: the 2-sphere as a topological manifold of dimension 2 over \(\RR\)

One starts by declaring \(S^2\) as a 2-dimensional topological manifold:

sage: M = Manifold(2, 'S^2', structure='topological')
sage: M
2-dimensional topological manifold S^2

Since the base topological field has not been specified in the argument list of Manifold, \(\RR\) is assumed:

sage: M.base_field()
Real Field with 53 bits of precision
sage: dim(M)
2

Let us consider the complement of a point, the “North pole” say; this is an open subset of \(S^2\), which we call \(U\):

sage: U = M.open_subset('U'); U
Open subset U of the 2-dimensional topological manifold S^2

A standard chart on \(U\) is provided by the stereographic projection from the North pole to the equatorial plane:

sage: stereoN.<x,y> = U.chart(); stereoN
Chart (U, (x, y))

Thanks to the operator <x,y> on the left-hand side, the coordinates declared in a chart (here \(x\) and \(y\)), are accessible by their names; they are Sage’s symbolic variables:

sage: y
y
sage: type(y)
<type 'sage.symbolic.expression.Expression'>

The South pole is the point of coordinates \((x, y) = (0, 0)\) in the above chart:

sage: S = U.point((0,0), chart=stereoN, name='S'); S
Point S on the 2-dimensional topological manifold S^2

Let us call \(V\) the open subset that is the complement of the South pole and let us introduce on it the chart induced by the stereographic projection from the South pole to the equatorial plane:

sage: V = M.open_subset('V'); V
Open subset V of the 2-dimensional topological manifold S^2
sage: stereoS.<u,v> = V.chart(); stereoS
Chart (V, (u, v))

The North pole is the point of coordinates \((u, v) = (0, 0)\) in this chart:

sage: N = V.point((0,0), chart=stereoS, name='N'); N
Point N on the 2-dimensional topological manifold S^2

To fully construct the manifold, we declare that it is the union of \(U\) and \(V\):

sage: M.declare_union(U,V)

and we provide the transition map between the charts stereoN = \((U, (x, y))\) and stereoS = \((V, (u, v))\), denoting by \(W\) the intersection of \(U\) and \(V\) (\(W\) is the subset of \(U\) defined by \(x^2 + y^2 \neq 0\), as well as the subset of \(V\) defined by \(u^2 + v^2 \neq 0\)):

sage: stereoN_to_S = stereoN.transition_map(stereoS, [x/(x^2+y^2), y/(x^2+y^2)],
....:                          intersection_name='W', restrictions1= x^2+y^2!=0,
....:                                                 restrictions2= u^2+v^2!=0)
sage: stereoN_to_S
Change of coordinates from Chart (W, (x, y)) to Chart (W, (u, v))
sage: stereoN_to_S.display()
u = x/(x^2 + y^2)
v = y/(x^2 + y^2)

We give the name W to the Python variable representing \(W = U \cap V\):

sage: W = U.intersection(V)

The inverse of the transition map is computed by the method sage.manifolds.chart.CoordChange.inverse():

sage: stereoN_to_S.inverse()
Change of coordinates from Chart (W, (u, v)) to Chart (W, (x, y))
sage: stereoN_to_S.inverse().display()
x = u/(u^2 + v^2)
y = v/(u^2 + v^2)

At this stage, we have four open subsets on \(S^2\):

sage: M.list_of_subsets()
[2-dimensional topological manifold S^2,
 Open subset U of the 2-dimensional topological manifold S^2,
 Open subset V of the 2-dimensional topological manifold S^2,
 Open subset W of the 2-dimensional topological manifold S^2]

\(W\) is the open subset that is the complement of the two poles:

sage: N in W or S in W
False

The North pole lies in \(V\) and the South pole in \(U\):

sage: N in V, N in U
(True, False)
sage: S in U, S in V
(True, False)

The manifold’s (user) atlas contains four charts, two of them being restrictions of charts to a smaller domain:

sage: M.atlas()
[Chart (U, (x, y)), Chart (V, (u, v)),
 Chart (W, (x, y)), Chart (W, (u, v))]

Let us consider the point of coordinates \((1, 2)\) in the chart stereoN:

sage: p = M.point((1,2), chart=stereoN, name='p'); p
Point p on the 2-dimensional topological manifold S^2
sage: p.parent()
2-dimensional topological manifold S^2
sage: p in W
True

The coordinates of \(p\) in the chart stereoS are computed by letting the chart act on the point:

sage: stereoS(p)
(1/5, 2/5)

Given the definition of \(p\), we have of course:

sage: stereoN(p)
(1, 2)

Similarly:

sage: stereoS(N)
(0, 0)
sage: stereoN(S)
(0, 0)

A continuous map \(S^2 \to \RR\) (scalar field):

sage: f = M.scalar_field({stereoN: atan(x^2+y^2), stereoS: pi/2-atan(u^2+v^2)},
....:                    name='f')
sage: f
Scalar field f on the 2-dimensional topological manifold S^2
sage: f.display()
f: S^2 --> R
on U: (x, y) |--> arctan(x^2 + y^2)
on V: (u, v) |--> 1/2*pi - arctan(u^2 + v^2)
sage: f(p)
arctan(5)
sage: f(N)
1/2*pi
sage: f(S)
0
sage: f.parent()
Algebra of scalar fields on the 2-dimensional topological manifold S^2
sage: f.parent().category()
Category of commutative algebras over Symbolic Ring

Example 2: the Riemann sphere as a topological manifold of dimension 1 over \(\CC\)

We declare the Riemann sphere \(\CC^*\) as a 1-dimensional topological manifold over \(\CC\):

sage: M = Manifold(1, 'C*', structure='topological', field='complex'); M
Complex 1-dimensional topological manifold C*

We introduce a first open subset, which is actually \(\CC = \CC^*\setminus\{\infty\}\) if we interpret \(\CC^*\) as the Alexandroff one-point compactification of \(\CC\):

sage: U = M.open_subset('U')

A natural chart on \(U\) is then nothing but the identity map of \(\CC\), hence we denote the associated coordinate by \(z\):

sage: Z.<z> = U.chart()

The origin of the complex plane is the point of coordinate \(z = 0\):

sage: O = U.point((0,), chart=Z, name='O'); O
Point O on the Complex 1-dimensional topological manifold C*

Another open subset of \(\CC^*\) is \(V = \CC^*\setminus\{O\}\):

sage: V = M.open_subset('V')

We define a chart on \(V\) such that the point at infinity is the point of coordinate \(0\) in this chart:

sage: W.<w> = V.chart(); W
Chart (V, (w,))
sage: inf = M.point((0,), chart=W, name='inf', latex_name=r'\infty')
sage: inf
Point inf on the Complex 1-dimensional topological manifold C*

To fully construct the Riemann sphere, we declare that it is the union of \(U\) and \(V\):

sage: M.declare_union(U,V)

and we provide the transition map between the two charts as \(w = 1 / z\) on \(A = U \cap V\):

sage: Z_to_W = Z.transition_map(W, 1/z, intersection_name='A',
....:                           restrictions1= z!=0, restrictions2= w!=0)
sage: Z_to_W
Change of coordinates from Chart (A, (z,)) to Chart (A, (w,))
sage: Z_to_W.display()
w = 1/z
sage: Z_to_W.inverse()
Change of coordinates from Chart (A, (w,)) to Chart (A, (z,))
sage: Z_to_W.inverse().display()
z = 1/w

Let consider the complex number \(i\) as a point of the Riemann sphere:

sage: i = M((I,), chart=Z, name='i'); i
Point i on the Complex 1-dimensional topological manifold C*

Its coordinates w.r.t. the charts Z and W are:

sage: Z(i)
(I,)
sage: W(i)
(-I,)

and we have:

sage: i in U
True
sage: i in V
True

The following subsets and charts have been defined:

sage: M.list_of_subsets()
[Open subset A of the Complex 1-dimensional topological manifold C*,
 Complex 1-dimensional topological manifold C*,
 Open subset U of the Complex 1-dimensional topological manifold C*,
 Open subset V of the Complex 1-dimensional topological manifold C*]
sage: M.atlas()
[Chart (U, (z,)), Chart (V, (w,)), Chart (A, (z,)), Chart (A, (w,))]

A constant map \(\CC^* \rightarrow \CC\):

sage: f = M.constant_scalar_field(3+2*I, name='f'); f
Scalar field f on the Complex 1-dimensional topological manifold C*
sage: f.display()
f: C* --> C
on U: z |--> 2*I + 3
on V: w |--> 2*I + 3
sage: f(O)
2*I + 3
sage: f(i)
2*I + 3
sage: f(inf)
2*I + 3
sage: f.parent()
Algebra of scalar fields on the Complex 1-dimensional topological
 manifold C*
sage: f.parent().category()
Category of commutative algebras over Symbolic Ring

AUTHORS:

REFERENCES:

sage.manifolds.manifold.Manifold(dim, name, latex_name=None, field='real', structure='smooth', start_index=0, **extra_kwds)

Construct a manifold of a given type over a topological field.

Given a topological field \(K\) (in most applications, \(K = \RR\) or \(K = \CC\)) and a non-negative integer \(n\), a topological manifold of dimension \(n\) over K is a topological space \(M\) such that

  • \(M\) is a Hausdorff space,
  • \(M\) is second countable, and
  • every point in \(M\) has a neighborhood homeomorphic to \(K^n\).

A real manifold is a manifold over \(\RR\). A differentiable (resp. smooth, resp. analytic) manifold is a manifold such that all transition maps are differentiable (resp. smooth, resp. analytic). A pseudo-Riemannian manifold is a real differentiable manifold equipped with a metric tensor \(g\) (i.e. a field of non-degenerate symmetric bilinear forms), with the two subcases of Riemannian manifold (\(g\) positive-definite) and Lorentzian manifold (\(g\) has signature \(n-2\) or \(2-n\)).

INPUT:

  • dim – positive integer; dimension of the manifold
  • name – string; name (symbol) given to the manifold
  • latex_name – (default: None) string; LaTeX symbol to denote the manifold; if none are provided, it is set to name
  • field – (default: 'real') field \(K\) on which the manifold is defined; allowed values are
    • 'real' or an object of type RealField (e.g. RR) for a manifold over \(\RR\)
    • 'complex' or an object of type ComplexField (e.g. CC) for a manifold over \(\CC\)
    • an object in the category of topological fields (see Fields and TopologicalSpaces) for other types of manifolds
  • structure – (default: 'smooth') to specify the structure or type of manifold; allowed values are
    • 'topological' or 'top' for a topological manifold
    • 'differentiable' or 'diff' for a differentiable manifold
    • 'smooth' for a smooth manifold
    • 'analytic' for an analytic manifold
    • 'pseudo-Riemannian' for a real differentiable manifold equipped with a pseudo-Riemannian metric; the signature is specified via the keyword argument signature (see below)
    • 'Riemannian' for a real differentiable manifold equipped with a Riemannian (i.e. positive definite) metric
    • 'Lorentzian' for a real differentiable manifold equipped with a Lorentzian metric; the signature convention is specified by the keyword argument signature='positive' (default) or 'negative'
  • start_index – (default: 0) integer; lower value of the range of indices used for “indexed objects” on the manifold, e.g. coordinates in a chart
  • extra_kwds – keywords meaningful only for some specific types of manifolds:
    • diff_degree – (only for differentiable manifolds; default: infinity): the degree of differentiability
    • ambient – (only to construct a submanifold): the ambient manifold
    • metric_name – (only for pseudo-Riemannian manifolds; default: 'g') string; name (symbol) given to the metric
    • metric_latex_name – (only for pseudo-Riemannian manifolds; default: None) string; LaTeX symbol to denote the metric; if none is provided, the symbol is set to metric_name
    • signature – (only for pseudo-Riemannian manifolds; default: None) signature \(S\) of the metric as a single integer: \(S = n_+ - n_-\), where \(n_+\) (resp. \(n_-\)) is the number of positive terms (resp. negative terms) in any diagonal writing of the metric components; if signature is not provided, \(S\) is set to the manifold’s dimension (Riemannian signature); for Lorentzian manifolds the values signature='positive' (default) or signature='negative' are allowed to indicate the chosen signature convention.

OUTPUT:

EXAMPLES:

A 3-dimensional real topological manifold:

sage: M = Manifold(3, 'M', structure='topological'); M
3-dimensional topological manifold M

Given the default value of the parameter field, the above is equivalent to:

sage: M = Manifold(3, 'M', structure='topological', field='real'); M
3-dimensional topological manifold M

A complex topological manifold:

sage: M = Manifold(3, 'M', structure='topological', field='complex'); M
Complex 3-dimensional topological manifold M

A topological manifold over \(\QQ\):

sage: M = Manifold(3, 'M', structure='topological', field=QQ); M
3-dimensional topological manifold M over the Rational Field

A 3-dimensional real differentiable manifold of class \(C^4\):

sage: M = Manifold(3, 'M', field='real', structure='differentiable',
....:              diff_degree=4); M
3-dimensional differentiable manifold M

Since the default value of the parameter field is 'real', the above is equivalent to:

sage: M = Manifold(3, 'M', structure='differentiable', diff_degree=4)
sage: M
3-dimensional differentiable manifold M
sage: M.base_field_type()
'real'

A 3-dimensional real smooth manifold:

sage: M = Manifold(3, 'M', structure='differentiable', diff_degree=+oo)
sage: M
3-dimensional differentiable manifold M

Instead of structure='differentiable', diff_degree=+oo, it suffices to use structure='smooth' to get the same result:

sage: M = Manifold(3, 'M', structure='smooth'); M
3-dimensional differentiable manifold M
sage: M.diff_degree()
+Infinity

Actually, since 'smooth' is the default value of the parameter structure, the creation of a real smooth manifold can be shortened to:

sage: M = Manifold(3, 'M'); M
3-dimensional differentiable manifold M
sage: M.diff_degree()
+Infinity

For a complex smooth manifold, we have to set the parameter field:

sage: M = Manifold(3, 'M', field='complex'); M
3-dimensional complex manifold M
sage: M.diff_degree()
+Infinity

See the documentation of classes TopologicalManifold, DifferentiableManifold and PseudoRiemannianManifold for more detailed examples.

Uniqueness of manifold objects

Suppose we construct a manifold named \(M\):

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()

At some point, we change our mind and would like to restart with a new manifold, using the same name \(M\) and keeping the previous manifold for reference:

sage: M_old = M  # for reference
sage: M = Manifold(2, 'M', structure='topological')

This results in a brand new object:

sage: M.atlas()
[]

The object M_old is intact:

sage: M_old.atlas()
[Chart (M, (x, y))]

Both objects have the same display:

sage: M
2-dimensional topological manifold M
sage: M_old
2-dimensional topological manifold M

but they are different:

sage: M != M_old
True

Let us introduce a chart on M, using the same coordinate symbols as for M_old:

sage: X.<x,y> = M.chart()

The charts are displayed in the same way:

sage: M.atlas()
[Chart (M, (x, y))]
sage: M_old.atlas()
[Chart (M, (x, y))]

but they are actually different:

sage: M.atlas()[0] != M_old.atlas()[0]
True

Moreover, the two manifolds M and M_old are still considered distinct:

sage: M != M_old
True

This reflects the fact that the equality of manifold objects holds only for identical objects, i.e. one has M1 == M2 if, and only if, M1 is M2. Actually, the manifold classes inherit from WithEqualityById:

sage: isinstance(M, sage.misc.fast_methods.WithEqualityById)
True
sage.manifolds.manifold.TopologicalManifold

Topological manifold over a topological field \(K\).

Given a topological field \(K\) (in most applications, \(K = \RR\) or \(K = \CC\)) and a non-negative integer \(n\), a topological manifold of dimension \(n\) over K is a topological space \(M\) such that

  • \(M\) is a Hausdorff space,
  • \(M\) is second countable, and
  • every point in \(M\) has a neighborhood homeomorphic to \(K^n\).

This is a Sage parent class, the corresponding element class being ManifoldPoint.

INPUT:

  • n – positive integer; dimension of the manifold
  • name – string; name (symbol) given to the manifold
  • field – field \(K\) on which the manifold is defined; allowed values are
    • 'real' or an object of type RealField (e.g., RR) for a manifold over \(\RR\)
    • 'complex' or an object of type ComplexField (e.g., CC) for a manifold over \(\CC\)
    • an object in the category of topological fields (see Fields and TopologicalSpaces) for other types of manifolds
  • structure – manifold structure (see TopologicalStructure or RealTopologicalStructure)
  • base_manifold – (default: None) if not None, must be a topological manifold; the created object is then an open subset of base_manifold
  • latex_name – (default: None) string; LaTeX symbol to denote the manifold; if none are provided, it is set to name
  • start_index – (default: 0) integer; lower value of the range of indices used for “indexed objects” on the manifold, e.g., coordinates in a chart
  • category – (default: None) to specify the category; if None, Manifolds(field) is assumed (see the category Manifolds)
  • unique_tag – (default: None) tag used to force the construction of a new object when all the other arguments have been used previously (without unique_tag, the UniqueRepresentation behavior inherited from ManifoldSubset would return the previously constructed object corresponding to these arguments)

EXAMPLES:

A 4-dimensional topological manifold (over \(\RR\)):

sage: M = Manifold(4, 'M', latex_name=r'\mathcal{M}', structure='topological')
sage: M
4-dimensional topological manifold M
sage: latex(M)
\mathcal{M}
sage: type(M)
<class 'sage.manifolds.manifold.TopologicalManifold_with_category'>
sage: M.base_field()
Real Field with 53 bits of precision
sage: dim(M)
4

The input parameter start_index defines the range of indices on the manifold:

sage: M = Manifold(4, 'M', structure='topological')
sage: list(M.irange())
[0, 1, 2, 3]
sage: M = Manifold(4, 'M', structure='topological', start_index=1)
sage: list(M.irange())
[1, 2, 3, 4]
sage: list(Manifold(4, 'M', structure='topological', start_index=-2).irange())
[-2, -1, 0, 1]

A complex manifold:

sage: N = Manifold(3, 'N', structure='topological', field='complex'); N
Complex 3-dimensional topological manifold N

A manifold over \(\QQ\):

sage: N = Manifold(6, 'N', structure='topological', field=QQ); N
6-dimensional topological manifold N over the Rational Field

A manifold over \(\QQ_5\), the field of 5-adic numbers:

sage: N = Manifold(2, 'N', structure='topological', field=Qp(5)); N
2-dimensional topological manifold N over the 5-adic Field with capped
 relative precision 20

A manifold is a Sage parent object, in the category of topological manifolds over a given topological field (see Manifolds):

sage: isinstance(M, Parent)
True
sage: M.category()
Category of manifolds over Real Field with 53 bits of precision
sage: from sage.categories.manifolds import Manifolds
sage: M.category() is Manifolds(RR)
True
sage: M.category() is Manifolds(M.base_field())
True
sage: M in Manifolds(RR)
True
sage: N in Manifolds(Qp(5))
True

The corresponding Sage elements are points:

sage: X.<t, x, y, z> = M.chart()
sage: p = M.an_element(); p
Point on the 4-dimensional topological manifold M
sage: p.parent()
4-dimensional topological manifold M
sage: M.is_parent_of(p)
True
sage: p in M
True

The manifold’s points are instances of class ManifoldPoint:

sage: isinstance(p, sage.manifolds.point.ManifoldPoint)
True

Since an open subset of a topological manifold \(M\) is itself a topological manifold, open subsets of \(M\) are instances of the class TopologicalManifold:

sage: U = M.open_subset('U'); U
Open subset U of the 4-dimensional topological manifold M
sage: isinstance(U, sage.manifolds.manifold.TopologicalManifold)
True
sage: U.base_field() == M.base_field()
True
sage: dim(U) == dim(M)
True
sage: U.category()
Join of Category of subobjects of sets and Category of manifolds over
 Real Field with 53 bits of precision

The manifold passes all the tests of the test suite relative to its category:

sage: TestSuite(M).run()