Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Merge #32102
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoeppe committed Jul 12, 2021
2 parents c45c030 + 141ccb5 commit 9626b54
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 106 deletions.
211 changes: 163 additions & 48 deletions src/sage/manifolds/chart.py

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions src/sage/manifolds/continuous_map.py
Expand Up @@ -837,8 +837,7 @@ def image(self, subset=None, inverse=None):
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, u^2]}, name='Phi')
sage: Phi.image()
Image of the Continuous map Phi
Expand Down
12 changes: 4 additions & 8 deletions src/sage/manifolds/continuous_map_image.py
Expand Up @@ -48,8 +48,7 @@ def __init__(self, map, inverse=None, name=None, latex_name=None, domain_subset=
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_inv = M.continuous_map(N, {(CM, CN): [x]}, name='Phi_inv')
sage: Phi_N = Phi.image(inverse=Phi_inv)
Expand Down Expand Up @@ -81,8 +80,7 @@ def _repr_(self):
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi.image() # indirect doctest
Image of the Continuous map Phi
Expand Down Expand Up @@ -114,8 +112,7 @@ def _an_element_(self):
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_N = Phi.image()
sage: p = Phi_N.an_element(); p # indirect doctest
Expand All @@ -134,8 +131,7 @@ def __contains__(self, point):
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: Phi = N.continuous_map(M, {(CN,CM): [u, 1 + u^2]}, name='Phi')
sage: Phi_inv = M.continuous_map(N, {(CM, CN): [x]}, name='Phi_inv')
sage: Phi_N = Phi.image(inverse=Phi_inv)
Expand Down
69 changes: 52 additions & 17 deletions src/sage/manifolds/differentiable/chart.py
Expand Up @@ -72,10 +72,6 @@ class DiffChart(Chart):
If no period and no LaTeX spelling are to be set for any coordinate, the
argument ``coordinates`` can be omitted when the shortcut operator
``<,>`` is used to declare the chart (see examples below).
- ``names`` -- (default: ``None``) unused argument, except if
``coordinates`` is not provided; it must then be a tuple containing
the coordinate symbols (this is guaranteed if the shortcut operator
``<,>`` is used).
- ``calc_method`` -- (default: ``None``) string defining the calculus
method for computations involving coordinates of the chart; must be
one of
Expand All @@ -85,6 +81,27 @@ class DiffChart(Chart):
- ``None``: the default of
:class:`~sage.manifolds.calculus_method.CalculusMethod` will be
used
- ``names`` -- (default: ``None``) unused argument, except if
``coordinates`` is not provided; it must then be a tuple containing
the coordinate symbols (this is guaranteed if the shortcut operator
``<,>`` is used).
- ``coord_restrictions``: Additional restrictions on the coordinates.
A restriction can be any symbolic equality or inequality involving
the coordinates, such as ``x > y`` or ``x^2 + y^2 != 0``. The items
of the list (or set or frozenset) ``coord_restrictions`` are combined
with the ``and`` operator; if some restrictions are to be combined with
the ``or`` operator instead, they have to be passed as a tuple in some
single item of the list (or set or frozenset) ``coord_restrictions``.
For example::
coord_restrictions=[x > y, (x != 0, y != 0), z^2 < x]
means ``(x > y) and ((x != 0) or (y != 0)) and (z^2 < x)``.
If the list ``coord_restrictions`` contains only one item, this
item can be passed as such, i.e. writing ``x > y`` instead
of the single element list ``[x > y]``. If the chart variables have
not been declared as variables yet, ``coord_restrictions`` must
be ``lambda``-quoted.
EXAMPLES:
Expand Down Expand Up @@ -259,7 +276,7 @@ class DiffChart(Chart):
on differentiable manifolds over `\RR`.
"""
def __init__(self, domain, coordinates, calc_method=None, periods=None):
def __init__(self, domain, coordinates, calc_method=None, periods=None, coord_restrictions=None):
r"""
Construct a chart.
Expand All @@ -276,8 +293,8 @@ def __init__(self, domain, coordinates, calc_method=None, periods=None):
sage: TestSuite(X).run()
"""
super().__init__(domain, coordinates,
calc_method=calc_method, periods=periods)
super().__init__(domain, coordinates, calc_method=calc_method,
periods=periods, coord_restrictions=coord_restrictions)
# Construction of the coordinate frame associated to the chart:
self._frame = CoordFrame(self)
self._coframe = self._frame._coframe
Expand Down Expand Up @@ -709,10 +726,6 @@ class RealDiffChart(DiffChart, RealChart):
If interval range, no period and no LaTeX spelling are to be set for any
coordinate, the argument ``coordinates`` can be omitted when the shortcut
operator ``<,>`` is used to declare the chart (see examples below).
- ``names`` -- (default: ``None``) unused argument, except if
``coordinates`` is not provided; it must then be a tuple containing
the coordinate symbols (this is guaranteed if the shortcut operator
``<,>`` is used).
- ``calc_method`` -- (default: ``None``) string defining the calculus
method for computations involving coordinates of the chart; must be
one of
Expand All @@ -722,6 +735,27 @@ class RealDiffChart(DiffChart, RealChart):
- ``None``: the default of
:class:`~sage.manifolds.calculus_method.CalculusMethod` will be
used
- ``names`` -- (default: ``None``) unused argument, except if
``coordinates`` is not provided; it must then be a tuple containing
the coordinate symbols (this is guaranteed if the shortcut operator
``<,>`` is used).
- ``coord_restrictions``: Additional restrictions on the coordinates.
A restriction can be any symbolic equality or inequality involving
the coordinates, such as ``x > y`` or ``x^2 + y^2 != 0``. The items
of the list (or set or frozenset) ``coord_restrictions`` are combined
with the ``and`` operator; if some restrictions are to be combined with
the ``or`` operator instead, they have to be passed as a tuple in some
single item of the list (or set or frozenset) ``coord_restrictions``.
For example::
coord_restrictions=[x > y, (x != 0, y != 0), z^2 < x]
means ``(x > y) and ((x != 0) or (y != 0)) and (z^2 < x)``.
If the list ``coord_restrictions`` contains only one item, this
item can be passed as such, i.e. writing ``x > y`` instead
of the single element list ``[x > y]``. If the chart variables have
not been declared as variables yet, ``coord_restrictions`` must
be ``lambda``-quoted.
EXAMPLES:
Expand Down Expand Up @@ -908,9 +942,9 @@ class RealDiffChart(DiffChart, RealChart):
`\{y=0, x\geq 0\}`, we must have `y\not=0` or `x<0` on U. Accordingly,
we set::
sage: c_cartU.<x,y,z> = U.chart()
sage: c_cartU.add_restrictions((y!=0, x<0)) # the tuple (y!=0, x<0) means y!=0 or x<0
sage: # c_cartU.add_restrictions([y!=0, x<0]) would have meant y!=0 AND x<0
sage: c_cartU.<x,y,z> = U.chart(coord_restrictions=lambda x,y,z: (y!=0, x<0))
....: # the tuple (y!=0, x<0) means y!=0 or x<0
....: # [y!=0, x<0] would have meant y!=0 AND x<0
sage: U.atlas()
[Chart (U, (r, th, ph)), Chart (U, (x, y, z))]
sage: M.atlas()
Expand Down Expand Up @@ -942,7 +976,8 @@ class RealDiffChart(DiffChart, RealChart):
:meth:`~sage.manifolds.chart.RealChart.plot`.
"""
def __init__(self, domain, coordinates, calc_method=None, bounds=None, periods=None):
def __init__(self, domain, coordinates, calc_method=None,
bounds=None, periods=None, coord_restrictions=None):
r"""
Construct a chart on a real differentiable manifold.
Expand All @@ -960,8 +995,8 @@ def __init__(self, domain, coordinates, calc_method=None, bounds=None, periods=N
sage: TestSuite(X).run()
"""
RealChart.__init__(self, domain, coordinates,
calc_method=calc_method, bounds=bounds, periods=periods)
RealChart.__init__(self, domain, coordinates, calc_method=calc_method,
bounds=bounds, periods=periods, coord_restrictions=coord_restrictions)
# Construction of the coordinate frame associated to the chart:
self._frame = CoordFrame(self)
self._coframe = self._frame._coframe
Expand Down
13 changes: 5 additions & 8 deletions src/sage/manifolds/differentiable/examples/real_line.py
Expand Up @@ -368,8 +368,6 @@ def __init__(self, lower, upper, ambient_interval=None,
coordinate = 't'
else:
coordinate = names[0]
self._canon_chart = self.chart(coordinates=coordinate)
t = self._canon_chart[start_index]
else:
if lower < ambient_interval.lower_bound():
raise ValueError("the lower bound is smaller than that of "
Expand All @@ -379,20 +377,19 @@ def __init__(self, lower, upper, ambient_interval=None,
+ "the containing interval")
self.declare_subset(ambient_interval)
ambient_interval._top_subsets.add(self)
t = ambient_interval.canonical_coordinate()
if lower != minus_infinity:
if upper != infinity:
restrictions = [t > lower, t < upper]
restrictions = lambda t: [t > lower, t < upper]
else:
restrictions = t > lower
restrictions = lambda t: t > lower
else:
if upper != infinity:
restrictions = t < upper
restrictions = lambda t: t < upper
else:
restrictions = None
if ambient_interval is None:
if restrictions is not None:
self._canon_chart.add_restrictions(restrictions)
self._canon_chart = self.chart(coordinates=coordinate,
coord_restrictions=restrictions)
else:
self._canon_chart = ambient_interval.canonical_chart().restrict(self,
restrictions=restrictions)
Expand Down
18 changes: 6 additions & 12 deletions src/sage/manifolds/differentiable/integrated_curve.py
Expand Up @@ -1469,17 +1469,13 @@ def solve_across_charts(self, charts=None, step=None, solution_key=None,
maps::
sage: M = Manifold(2, 'M', structure="Riemannian")
sage: C.<x,y> = M.chart()
sage: P.<r,th> = M.chart()
sage: C.<x,y> = M.chart(coord_restrictions=lambda x,y: x**2+y**2 < 3**2)
sage: P.<r,th> = M.chart(coord_restrictions=lambda r, th: r > 2)
sage: P_to_C = P.transition_map(C,(r*cos(th), r*sin(th)))
sage: C_to_P = C.transition_map(P,(sqrt(x**2+y**2), atan2(y,x)))
Let us also add restrictions on those charts, to avoid any
singularity. We have to make sure that the charts still intersect.
Here the intersection is the donut region `2 < r < 3`::
sage: P.add_restrictions(r > 2)
sage: C.add_restrictions(x**2+y**2 < 3**2)
Here we added restrictions on those charts, to avoid any
singularity. The intersection is the donut region `2 < r < 3`.
We still have to define the metric. This is done in the Cartesian
frame. The metric in the polar frame is computed automatically::
Expand Down Expand Up @@ -1574,14 +1570,12 @@ def solve_across_charts(self, charts=None, step=None, solution_key=None,
.. PLOT::
M = Manifold(2, 'M', structure="Riemannian")
C= M.chart(names = ("x", "y"))
C= M.chart(names = ("x", "y"), coord_restrictions=lambda x,y: x**2+y**2 < 3**2)
x, y = C[:]
P = M.chart(names = ("r", "ph"))
P = M.chart(names = ("r", "th"), coord_restrictions=lambda r,th: r > 2)
r, th = P[:]
P_to_C = P.transition_map(C,(r*cos(th), r*sin(th)))
C_to_P = C.transition_map(P,(sqrt(x**2+y**2), atan2(y,x)))
P.add_restrictions(r > 2)
C.add_restrictions(x**2+y**2 < 3**2)
g = M.metric()
g[0,0,C] = 1
g[1,1,C] = 1
Expand Down
4 changes: 2 additions & 2 deletions src/sage/manifolds/differentiable/levi_civita_connection.py
Expand Up @@ -628,8 +628,8 @@ def riemann(self, name=None, latex_name=None):
metric of the hyperbolic plane (Poincaré disk model)::
sage: M = Manifold(2, 'M', start_index=1)
sage: X.<x,y> = M.chart('x:(-1,1) y:(-1,1)') # Cartesian coord. on the Poincaré disk
sage: X.add_restrictions(x^2+y^2<1)
sage: X.<x,y> = M.chart('x:(-1,1) y:(-1,1)', coord_restrictions=lambda x,y: x^2+y^2<1)
....: # Cartesian coord. on the Poincaré disk
sage: g = M.metric('g')
sage: g[1,1], g[2,2] = 4/(1-x^2-y^2)^2, 4/(1-x^2-y^2)^2
sage: nab = g.connection()
Expand Down
4 changes: 2 additions & 2 deletions src/sage/manifolds/differentiable/manifold.py
Expand Up @@ -1017,8 +1017,8 @@ def diffeomorphism(self, codomain=None, coord_functions=None, chart1=None,
sage: M = Manifold(2, 'M') # the open unit disk
sage: forget() # for doctests only
sage: c_xy.<x,y> = M.chart('x:(-1,1) y:(-1,1)') # Cartesian coord on M
sage: c_xy.add_restrictions(x^2+y^2<1)
sage: c_xy.<x,y> = M.chart('x:(-1,1) y:(-1,1)', coord_restrictions=lambda x,y: x^2+y^2<1)
....: # Cartesian coord on M
sage: N = Manifold(2, 'N') # R^2
sage: c_XY.<X,Y> = N.chart() # canonical coordinates on R^2
sage: Phi = M.diffeomorphism(N, [x/sqrt(1-x^2-y^2), y/sqrt(1-x^2-y^2)],
Expand Down
44 changes: 39 additions & 5 deletions src/sage/manifolds/manifold.py
Expand Up @@ -669,7 +669,7 @@ def _an_element_(self):
sage: p in V
True
sage: p.coord()
(-pi - 1, 2)
(-pi - 1, 0)
"""
from sage.rings.infinity import Infinity
Expand Down Expand Up @@ -1429,7 +1429,8 @@ def is_manifestly_coordinate_domain(self):
"""
return bool(self._covering_charts)

def chart(self, coordinates='', names=None, calc_method=None):
def chart(self, coordinates='', names=None, calc_method=None,
coord_restrictions=None):
r"""
Define a chart, the domain of which is the manifold.
Expand Down Expand Up @@ -1461,6 +1462,8 @@ def chart(self, coordinates='', names=None, calc_method=None):
- ``'sympy'``: SymPy
- ``None``: the current calculus method defined on the manifold is
used (cf. :meth:`set_calculus_method`)
- ``coord_restrictions``: Additional restrictions on the coordinates.
See below.
The coordinates declared in the string ``coordinates`` are
separated by ``' '`` (whitespace) and each coordinate has at most four
Expand Down Expand Up @@ -1493,6 +1496,26 @@ def chart(self, coordinates='', names=None, calc_method=None):
omitted when the shortcut operator ``<,>`` is used to declare the
chart (see examples below).
Additional restrictions on the coordinates can be set using the
argument ``coord_restrictions``.
A restriction can be any symbolic equality or inequality involving
the coordinates, such as ``x > y`` or ``x^2 + y^2 != 0``. The items
of the list (or set or frozenset) ``coord_restrictions`` are combined
with the ``and`` operator; if some restrictions are to be combined with
the ``or`` operator instead, they have to be passed as a tuple in some
single item of the list (or set or frozenset) ``coord_restrictions``.
For example::
coord_restrictions=[x > y, (x != 0, y != 0), z^2 < x]
means ``(x > y) and ((x != 0) or (y != 0)) and (z^2 < x)``.
If the list ``coord_restrictions`` contains only one item, this
item can be passed as such, i.e. writing ``x > y`` instead
of the single element list ``[x > y]``. If the chart variables have
not been declared as variables yet, ``coord_restrictions`` must
be ``lambda``-quoted.
OUTPUT:
- the created chart, as an instance of
Expand Down Expand Up @@ -1560,6 +1583,16 @@ def chart(self, coordinates='', names=None, calc_method=None):
sage: latex(P)
\left(U,(r, {\phi})\right)
Using ``coord_restrictions``::
sage: D = Manifold(2, 'D', structure='topological')
sage: X.<x,y> = D.chart(coord_restrictions=lambda x,y: [x^2+y^2<1, x>0]); X
Chart (D, (x, y))
sage: X.valid_coordinates(0, 0)
False
sage: X.valid_coordinates(1/2, 0)
True
See the documentation of classes
:class:`~sage.manifolds.chart.Chart` and
:class:`~sage.manifolds.chart.RealChart` for more examples,
Expand All @@ -1569,7 +1602,8 @@ def chart(self, coordinates='', names=None, calc_method=None):
if calc_method is None:
calc_method = self._calculus_method
return self._structure.chart(self, coordinates=coordinates,
names=names, calc_method=calc_method)
names=names, calc_method=calc_method,
coord_restrictions=coord_restrictions)

def is_open(self):
"""
Expand Down Expand Up @@ -2347,8 +2381,8 @@ def homeomorphism(self, codomain, coord_functions=None, chart1=None,
sage: forget() # for doctests only
sage: M = Manifold(2, 'M', structure='topological') # the open unit disk
sage: c_xy.<x,y> = M.chart('x:(-1,1) y:(-1,1)') # Cartesian coord on M
sage: c_xy.add_restrictions(x^2+y^2<1)
sage: c_xy.<x,y> = M.chart('x:(-1,1) y:(-1,1)', coord_restrictions=lambda x,y: x^2+y^2<1)
....: # Cartesian coord on M
sage: N = Manifold(2, 'N', structure='topological') # R^2
sage: c_XY.<X,Y> = N.chart() # canonical coordinates on R^2
sage: Phi = M.homeomorphism(N, [x/sqrt(1-x^2-y^2), y/sqrt(1-x^2-y^2)],
Expand Down
3 changes: 1 addition & 2 deletions src/sage/manifolds/topological_submanifold.py
Expand Up @@ -881,8 +881,7 @@ def as_subset(self):
sage: M = Manifold(2, 'M', structure="topological")
sage: N = Manifold(1, 'N', ambient=M, structure="topological")
sage: CM.<x,y> = M.chart()
sage: CN.<u> = N.chart()
sage: CN.add_restrictions([u > -1, u < 1])
sage: CN.<u> = N.chart(coord_restrictions=lambda u: [u > -1, u < 1])
sage: phi = N.continuous_map(M, {(CN,CM): [u, u^2]})
sage: N.set_embedding(phi)
sage: N
Expand Down

0 comments on commit 9626b54

Please sign in to comment.