summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-17 12:06:41 +0100
committerEric Gourgoulhon <eric.gourgoulhon@obspm.fr>2015-11-17 12:06:41 +0100
commit22383e6be5277a36e07960c535d76715564d909e (patch)
treeb6852092bd0b8e96e18195b6aff4050b685467ea
parentRemove UniqueRepresentation, leaving only WithEqualityById, for scalar fields... (diff)
parentIntroduce the attribute _field_type in class TopologicalManifold to check for... (diff)
Check for real/complex manifold performed on base_field_type() instead of RR/CC
-rw-r--r--src/sage/manifolds/chart.py28
-rw-r--r--src/sage/manifolds/coord_func_symb.py3
-rw-r--r--src/sage/manifolds/manifold.py126
-rw-r--r--src/sage/manifolds/scalarfield.py7
-rw-r--r--src/sage/manifolds/scalarfield_algebra.py4
-rw-r--r--src/sage/manifolds/subset.py70
6 files changed, 199 insertions, 39 deletions
diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py
index a6ec6df..a9c993c 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
@@ -253,7 +251,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:
@@ -268,6 +267,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()
@@ -299,11 +307,12 @@ class Chart(WithEqualityById, SageObject):
# subsets of self._domain, with the
# subsets as keys
# The null and one functions of the coordinates:
- base_field = self._domain.base_field()
- if base_field in [RR, CC]:
+ base_field_type = self._domain.base_field_type()
+ if base_field_type in ['real', 'complex']:
self._zero_function = CoordFunctionSymb(self, 0)
self._one_function = CoordFunctionSymb(self, 1)
else:
+ base_field = self._domain.base_field()
self._zero_function = CoordFunctionSymb(self, base_field.zero())
self._one_function = CoordFunctionSymb(self, base_field.one())
# Expression in self of the zero and one scalar fields of open sets
@@ -2104,9 +2113,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)]
@@ -2128,7 +2138,7 @@ class CoordChange(SageObject):
for i in range(n1)]
for transf in x2_to_x1:
try:
- if self._domain.base_field() == RR:
+ if self._domain.base_field_type() == 'real':
transf = simplify_chain_real(transf)
else:
transf = simplify_chain_generic(transf)
@@ -2144,7 +2154,7 @@ class CoordChange(SageObject):
x2_to_x1 = [sol[x1[i]].subs(substitutions) for i in range(n1)]
for transf in x2_to_x1:
try:
- if self._domain.base_field() == RR:
+ if self._domain.base_field_type() == 'real':
transf = simplify_chain_real(transf)
else:
transf = simplify_chain_generic(transf)
diff --git a/src/sage/manifolds/coord_func_symb.py b/src/sage/manifolds/coord_func_symb.py
index fe5c64c..b9ee4f9 100644
--- a/src/sage/manifolds/coord_func_symb.py
+++ b/src/sage/manifolds/coord_func_symb.py
@@ -37,7 +37,6 @@ AUTHORS:
#*****************************************************************************
from sage.symbolic.ring import SR
-from sage.rings.real_mpfr import RR
from sage.structure.element import RingElement
from sage.misc.latex import latex
from sage.manifolds.coord_func import CoordFunction, MultiCoordFunction
@@ -292,7 +291,7 @@ class CoordFunctionSymb(CoordFunction):
self._express = SR(expression) # symbolic expression enforced
# Definition of the simplification chain to be applied in
# symbolic calculus:
- if self._chart.manifold().base_field() == RR:
+ if self._chart.manifold().base_field_type() == 'real':
self._simplify = simplify_chain_real
else:
self._simplify = simplify_chain_generic
diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py
index cc30d77..a05b248 100644
--- a/src/sage/manifolds/manifold.py
+++ b/src/sage/manifolds/manifold.py
@@ -320,7 +320,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
from sage.manifolds.scalarfield_algebra import ScalarFieldAlgebra
@@ -348,8 +349,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`)
@@ -493,12 +496,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
@@ -518,7 +529,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 = []
@@ -558,10 +573,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(
@@ -695,7 +710,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]
@@ -715,7 +730,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
@@ -826,7 +841,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:
@@ -847,6 +862,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.
@@ -1472,10 +1515,67 @@ 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 scalar_field_algebra(self):
r"""
Return the algebra of scalar fields defined the manifold.
@@ -1726,8 +1826,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/scalarfield.py b/src/sage/manifolds/scalarfield.py
index e20a814..55cff9a 100644
--- a/src/sage/manifolds/scalarfield.py
+++ b/src/sage/manifolds/scalarfield.py
@@ -36,8 +36,6 @@ REFERENCES:
from sage.structure.element import CommutativeAlgebraElement
from sage.rings.integer import Integer
-from sage.rings.all import CC
-from sage.rings.real_mpfr import RR
from sage.symbolic.expression import Expression
from sage.manifolds.coord_func import CoordFunction
@@ -1412,10 +1410,11 @@ class ScalarField(CommutativeAlgebraElement):
# Name of the base field:
field = self._domain.base_field()
- if field == RR:
+ field_type = self._domain.base_field_type()
+ if field_type == 'real':
field_name = 'R'
field_latex_name = r'\mathbb{R}'
- elif field == CC:
+ elif field_type == 'complex':
field_name = 'C'
field_latex_name = r'\mathbb{C}'
else:
diff --git a/src/sage/manifolds/scalarfield_algebra.py b/src/sage/manifolds/scalarfield_algebra.py
index 4134848..ebafc55 100644
--- a/src/sage/manifolds/scalarfield_algebra.py
+++ b/src/sage/manifolds/scalarfield_algebra.py
@@ -35,8 +35,6 @@ from sage.structure.parent import Parent
from sage.misc.fast_methods import WithEqualityById
from sage.categories.commutative_algebras import CommutativeAlgebras
from sage.symbolic.ring import SR
-from sage.rings.all import CC
-from sage.rings.real_mpfr import RR
from sage.manifolds.scalarfield import ScalarField
class ScalarFieldAlgebra(WithEqualityById, Parent):
@@ -387,7 +385,7 @@ class ScalarFieldAlgebra(WithEqualityById, Parent):
"""
base_field = domain.base_field()
- if base_field in [RR, CC]:
+ if domain.base_field_type() in ['real', 'complex']:
base_field = SR
Parent.__init__(self, base=base_field,
category=CommutativeAlgebras(base_field))
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: