summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-17 11:18:29 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-17 11:18:29 +0100
commit65186990b1106f89652107356b60faa048113915 (patch)
tree836a6572f273769948b16fbe753a3bf57ac9c7b1
parentRemove UniqueRepresentation, leaving only WithEqualityById, for topological m... (diff)
Introduce the attribute _field_type in class TopologicalManifold to check for real and complex manifolds.
In addition two new accessors have been implemented: - TopologicalManifold.get_chart - TopologicalManifoldSubset.get_subset
-rw-r--r--src/sage/manifolds/chart.py19
-rw-r--r--src/sage/manifolds/manifold.py125
-rw-r--r--src/sage/manifolds/subset.py70
3 files changed, 188 insertions, 26 deletions
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index a7d967b..fc281cb 100644
--- a/src/sage/manifolds/chart.py
+++ b/src/sage/manifolds/chart.py
@@ -35,8 +35,6 @@ REFERENCES:
from sage.structure.sage_object import SageObject
from sage.misc.fast_methods import WithEqualityById
from sage.symbolic.ring import SR
-from sage.rings.all import CC
-from sage.rings.real_mpfr import RR
from sage.rings.infinity import Infinity
from sage.misc.latex import latex
from sage.manifolds.manifold import TopologicalManifold
@@ -252,7 +250,8 @@ class Chart(WithEqualityById, SageObject):
if coordinates == '':
for x in names:
coordinates += x + ' '
- self._coordinate_string = coordinates[:-1] # for pickling (cf. __reduce__)
+ coordinates = coordinates[:-1]
+ self._coordinate_string = coordinates # for pickling (cf. __reduce__)
self._manifold = domain.manifold()
self._domain = domain
# Treatment of the coordinates:
@@ -267,6 +266,15 @@ class Chart(WithEqualityById, SageObject):
# _init_coordinates, which sets self._xx and
# which may be redefined for subclasses (for instance RealChart).
self._init_coordinates(coord_list)
+ coord_string = ''
+ for x in self._xx:
+ coord_string += str(x) + ' '
+ coord_string = coord_string[:-1]
+ if coord_string in self._domain._charts_by_coord:
+ raise ValueError("the chart with coordinates " + coord_string +
+ " has already been declared on " +
+ "the {}".format(self._domain))
+ self._domain._charts_by_coord[coord_string] = self
#
# Additional restrictions on the coordinates
self._restrictions = [] # to be set with method add_restrictions()
@@ -1863,9 +1871,10 @@ class CoordChange(SageObject):
"charts)")
# New symbolic variables (different from x2 to allow for a
# correct solution even when chart2 = chart1):
- if self._chart1.domain().base_field() == RR:
+ base_field = self._chart1.domain().base_field_type()
+ if base_field == 'real':
coord_domain = ['real' for i in range(n2)]
- elif self._chart1.domain().base_field() == CC:
+ elif base_field == 'complex':
coord_domain = ['complex' for i in range(n2)]
else:
coord_domain = [None for i in range(n2)]
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index ab5a8ab..6a6ed52 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -280,7 +280,8 @@ REFERENCES:
from sage.categories.fields import Fields
from sage.categories.manifolds import Manifolds
from sage.rings.all import CC
-from sage.rings.real_mpfr import RR
+from sage.rings.real_mpfr import RR, RealField_class
+from sage.rings.complex_field import ComplexField_class
from sage.manifolds.subset import TopologicalManifoldSubset
class TopologicalManifold(TopologicalManifoldSubset):
@@ -307,8 +308,10 @@ class TopologicalManifold(TopologicalManifoldSubset):
- ``field`` -- (default: ``'real'``) field `K` on which the manifold is
defined; allowed values are
- - ``'real'`` or ``RR`` for a manifold over `\RR`
- - ``'complex'`` or ``CC`` for a manifold over `\CC`
+ - ``'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
:class:`~sage.categories.fields.Fields` and
:class:`~sage.categories.topological_spaces.TopologicalSpaces`)
@@ -452,12 +455,20 @@ class TopologicalManifold(TopologicalManifoldSubset):
self._dim = n
if field == 'real':
self._field = RR
+ self._field_type = 'real'
elif field == 'complex':
self._field = CC
+ self._field_type = 'complex'
else:
if field not in Fields():
raise TypeError("the argument 'field' must be a field")
self._field = field
+ if isinstance(field, RealField_class):
+ self._field_type = 'real'
+ elif isinstance(field, ComplexField_class):
+ self._field_type = 'complex'
+ else:
+ self._field_type = 'neither_real_nor_complex'
if not isinstance(start_index, (int, Integer)):
raise TypeError("the starting index must be an integer")
self._sindex = start_index
@@ -477,7 +488,11 @@ class TopologicalManifold(TopologicalManifoldSubset):
self._top_charts = [] # list of charts defined on subsets of self
# that are not subcharts of charts on larger subsets
self._def_chart = None # default chart
- self._coord_changes = {} # dictionary of transition maps
+ self._charts_by_coord = {} # dictionary of charts whose domain is self
+ # (key: string formed by the coordinate
+ # symbols separated by a white space)
+ self._coord_changes = {} # dictionary of transition maps (key: pair of
+ # of charts)
# List of charts that individually cover self, i.e. whose
# domains are self (if non-empty, self is a coordinate domain):
self._covering_charts = []
@@ -511,10 +526,10 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
if self._manifold is self:
- if self._field == RR:
+ if self._field_type == 'real':
return "{}-dimensional topological manifold {}".format(
self._dim, self._name)
- elif self._field == CC:
+ elif self._field_type == 'complex':
return "Complex {}-dimensional topological manifold {}".format(
self._dim, self._name)
return "{}-dimensional topological manifold {} over the {}".format(
@@ -648,7 +663,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
return self.element_class(self)
# Attempt to construct a point in the domain of the default chart
chart = self._def_chart
- if self._field == RR:
+ if self._field_type == 'real':
coords = []
for coord_range in chart._bounds:
xmin = coord_range[0][0]
@@ -668,7 +683,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
coords = self._dim*[0]
if not chart.valid_coordinates(*coords):
# Attempt to construct a point in the domain of other charts
- if self._field == RR:
+ if self._field_type == 'real':
for ch in self._atlas:
if ch is self._def_chart:
continue # since this case has already been attempted
@@ -779,7 +794,7 @@ class TopologicalManifold(TopologicalManifoldSubset):
def base_field(self):
r"""
- Return the field on which the manifolds is defined.
+ Return the field on which the manifold is defined.
OUTPUT:
@@ -800,6 +815,34 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
return self._field
+ def base_field_type(self):
+ r"""
+ Return the type of topological field on which the manifold is defined.
+
+ OUTPUT:
+
+ - a string describing the field, with three possible values:
+
+ - ``'real'`` for the real field `\RR`
+ - ``'complex'`` for the complex field `\CC`
+ - ``'neither_real_nor_complex'`` for a field different from `\RR` and
+ `\CC`
+
+ EXAMPLES::
+
+ sage: M = Manifold(3, 'M', type='topological')
+ sage: M.base_field_type()
+ 'real'
+ sage: M = Manifold(3, 'M', type='topological', field='complex')
+ sage: M.base_field_type()
+ 'complex'
+ sage: M = Manifold(3, 'M', type='topological', field=QQ)
+ sage: M.base_field_type()
+ 'neither_real_nor_complex'
+
+ """
+ return self._field_type
+
def start_index(self):
r"""
Return the first value of the index range used on the manifold.
@@ -1425,10 +1468,66 @@ class TopologicalManifold(TopologicalManifoldSubset):
"""
from sage.manifolds.chart import Chart, RealChart
- if self._field == RR:
+ if self._field_type == 'real':
return RealChart(self, coordinates=coordinates, names=names)
return Chart(self, coordinates=coordinates, names=names)
+ def get_chart(self, coordinates, domain=None):
+ r"""
+ Get a chart from its coordinates.
+
+ The chart must have been previously created by the method
+ :meth:`chart`.
+
+ INPUT:
+
+ - ``coordinates`` -- single string composed of the coordinate symbols
+ separated by a space
+ - ``domain`` -- (default: ``None``) string containing the name of the
+ chart's domain, which must be a subset of the current manifold; if
+ ``None``, the current manifold is assumed.
+
+ OUTPUT:
+
+ - instance of
+ :class:`~sage.manifolds.chart.Chart` (or of the subclass
+ :class:`~sage.manifolds.chart.RealChart`) representing the chart
+ corresponding to the above specifications.
+
+ EXAMPLES::
+
+ sage: M = Manifold(2, 'M', type='topological')
+ sage: X.<x,y> = M.chart()
+ sage: M.get_chart('x y')
+ Chart (M, (x, y))
+ sage: M.get_chart('x y') is X
+ True
+ sage: U = M.open_subset('U', coord_def={X: (y!=0,x<0)})
+ sage: Y.<r, ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi')
+ sage: M.atlas()
+ [Chart (M, (x, y)), Chart (U, (x, y)), Chart (U, (r, ph))]
+ sage: M.get_chart('x y', domain='U')
+ Chart (U, (x, y))
+ sage: M.get_chart('x y', domain='U') is X.restrict(U)
+ True
+ sage: U.get_chart('r ph')
+ Chart (U, (r, ph))
+ sage: M.get_chart('r ph', domain='U')
+ Chart (U, (r, ph))
+ sage: M.get_chart('r ph', domain='U') is Y
+ True
+
+ """
+ if domain is None:
+ dom = self
+ else:
+ dom = self.get_subset(domain)
+ try:
+ return dom._charts_by_coord[coordinates]
+ except KeyError:
+ raise KeyError("the coordinates '{}' ".format(coordinates) +
+ "do not correspond to any chart with " +
+ "the {} as domain".format(dom))
def Manifold(dim, name, latex_name=None, field='real', type='smooth',
start_index=0, **extra_kwds):
@@ -1444,8 +1543,10 @@ def Manifold(dim, name, latex_name=None, field='real', type='smooth',
- ``field`` -- (default: ``'real'``) field `K` on which the manifold is
defined; allowed values are
- - ``'real'`` or ``RR`` for a manifold over `\RR`
- - ``'complex'`` or ``CC`` for a manifold over `\CC`
+ - ``'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
:class:`~sage.categories.fields.Fields` and
:class:`~sage.categories.topological_spaces.TopologicalSpaces`)
diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py
index 8df3d34..8eb231f 100644
--- a/src/sage/manifolds/subset.py
+++ b/src/sage/manifolds/subset.py
@@ -560,14 +560,15 @@ class TopologicalManifoldSubset(WithEqualityById, Parent):
- ``name`` -- name given to the subset
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
subset; if none is provided, it is set to ``name``
- - ``is_open`` -- (default: False) if ``True``, the created subset is
- assumed to be open with respect to the manifold's topology
+ - ``is_open`` -- (default: ``False``) if ``True``, the created subset
+ is assumed to be open with respect to the manifold's topology
OUTPUT:
- the subset, as an instance of :class:`TopologicalManifoldSubset`, or
- of the derived class :class:`TopologicalManifold` if ``is_open`` is
- ``True``.
+ of the derived class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` if ``is_open``
+ is ``True``.
EXAMPLES:
@@ -595,13 +596,63 @@ class TopologicalManifoldSubset(WithEqualityById, Parent):
"""
if is_open:
return self.open_subset(name, latex_name=latex_name)
- res = TopologicalManifoldSubset(self._manifold, name, latex_name=latex_name)
+ res = TopologicalManifoldSubset(self._manifold, name,
+ latex_name=latex_name)
res._supersets.update(self._supersets)
for sd in self._supersets:
sd._subsets.add(res)
self._top_subsets.add(res)
return res
+ def get_subset(self, name):
+ r"""
+ Get a subset by its name.
+
+ The subset must have been previously created by the method
+ :meth:`subset` (or
+ :meth:`~sage.manifolds.manifold.TopologicalManifold.open_subset`)
+
+ INPUT:
+
+ - ``name`` -- (string) name of the subset
+
+ OUTPUT:
+
+ - instance of :class:`TopologicalManifoldSubset` (or
+ of the derived class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` for an open
+ subset) representing the subset whose name is ``name``.
+
+ EXAMPLES::
+
+ sage: M = Manifold(4, 'M', type='topological')
+ sage: A = M.subset('A')
+ sage: B = A.subset('B')
+ sage: U = M.open_subset('U')
+ sage: M.list_of_subsets()
+ [Subset A of the 4-dimensional topological manifold M,
+ Subset B of the 4-dimensional topological manifold M,
+ 4-dimensional topological manifold M,
+ Open subset U of the 4-dimensional topological manifold M]
+ sage: M.get_subset('A')
+ Subset A of the 4-dimensional topological manifold M
+ sage: M.get_subset('A') is A
+ True
+ sage: M.get_subset('B') is B
+ True
+ sage: A.get_subset('B') is B
+ True
+ sage: M.get_subset('U')
+ Open subset U of the 4-dimensional topological manifold M
+ sage: M.get_subset('U') is U
+ True
+
+ """
+ for ss in self._subsets:
+ if ss._name == name:
+ return ss
+ raise ValueError("no subset of name '{}' found".format(name))
+
def superset(self, name, latex_name=None, is_open=False):
r"""
Create a superset of the current subset.
@@ -614,14 +665,15 @@ class TopologicalManifoldSubset(WithEqualityById, Parent):
- ``name`` -- name given to the superset
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
superset; if none is provided, it is set to ``name``
- - ``is_open`` -- (default: False) if ``True``, the created subset is
- assumed to be open with respect to the manifold's topology
+ - ``is_open`` -- (default: ``False``) if ``True``, the created subset
+ is assumed to be open with respect to the manifold's topology
OUTPUT:
- the superset, as an instance of :class:`TopologicalManifoldSubset` or
- of the derived class :class:`TopologicalManifold` if ``is_open`` is
- ``True``.
+ of the derived class
+ :class:`~sage.manifolds.manifold.TopologicalManifold` if ``is_open``
+ is ``True``.
EXAMPLES: