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

Commit

Permalink
Merge #31677
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoeppe committed Apr 25, 2021
2 parents f1bc8bc + b35eca1 commit afe10a0
Show file tree
Hide file tree
Showing 12 changed files with 490 additions and 64 deletions.
16 changes: 6 additions & 10 deletions src/sage/manifolds/chart.py
Expand Up @@ -318,9 +318,9 @@ def __init__(self, domain, coordinates='', names=None, calc_method=None):
self._restrictions = [] # to be set with method add_restrictions()
#
# The chart is added to the domain's atlas, as well as to all the
# atlases of the domain's supersets; moreover the fist defined chart
# atlases of the domain's supersets; moreover the first defined chart
# is considered as the default chart
for sd in self._domain._supersets:
for sd in self._domain.open_supersets():
# the chart is added in the top charts only if its coordinates have
# not been used:
for chart in sd._atlas:
Expand All @@ -346,13 +346,9 @@ def __init__(self, domain, coordinates='', names=None, calc_method=None):
# The null and one functions of the coordinates:
# Expression in self of the zero and one scalar fields of open sets
# containing the domain of self:
for dom in self._domain._supersets:
if hasattr(dom, '_zero_scalar_field'):
# dom is an open set
dom._zero_scalar_field._express[self] = self.function_ring().zero()
if hasattr(dom, '_one_scalar_field'):
# dom is an open set
dom._one_scalar_field._express[self] = self.function_ring().one()
for dom in self._domain.open_supersets():
dom._zero_scalar_field._express[self] = self.function_ring().zero()
dom._one_scalar_field._express[self] = self.function_ring().one()

def _init_coordinates(self, coord_list):
r"""
Expand Down Expand Up @@ -3006,7 +3002,7 @@ def __init__(self, chart1, chart2, *transformations):
# is added to the subset (and supersets) dictionary:
if chart1._domain == chart2._domain:
domain = chart1._domain
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._coord_changes[(chart1, chart2)] = self

def _repr_(self):
Expand Down
8 changes: 4 additions & 4 deletions src/sage/manifolds/differentiable/chart.py
Expand Up @@ -559,7 +559,7 @@ def restrict(self, subset, restrictions=None):
sframe._restrictions[subset] = resu._frame
# The subchart frame is not a "top frame" in the supersets
# (including self._domain):
for dom in self._domain._supersets:
for dom in self._domain.open_supersets():
if resu._frame in dom._top_frames:
# it was added by the Chart constructor invoked in
# Chart.restrict above
Expand Down Expand Up @@ -1042,7 +1042,7 @@ def restrict(self, subset, restrictions=None):
sframe._restrictions[subset] = resu._frame
# The subchart frame is not a "top frame" in the supersets
# (including self._domain):
for dom in self._domain._supersets:
for dom in self._domain.open_supersets():
if resu._frame in dom._top_frames:
# it was added by the Chart constructor invoked in
# Chart.restrict above
Expand Down Expand Up @@ -1134,15 +1134,15 @@ def __init__(self, chart1, chart2, *transformations):
ch_basis.add_comp(frame1)[:, chart1] = self._jacobian
ch_basis.add_comp(frame2)[:, chart1] = self._jacobian
vf_module._basis_changes[(frame2, frame1)] = ch_basis
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._frame_changes[(frame2, frame1)] = ch_basis
# The inverse is computed only if it does not exist already
# (because if it exists it may have a simpler expression than that
# obtained from the matrix inverse)
if (frame1, frame2) not in vf_module._basis_changes:
ch_basis_inv = ch_basis.inverse()
vf_module._basis_changes[(frame1, frame2)] = ch_basis_inv
for sdom in domain._supersets:
for sdom in domain.open_supersets():
sdom._frame_changes[(frame1, frame2)] = ch_basis_inv

def jacobian(self):
Expand Down
Expand Up @@ -12,7 +12,7 @@
lightlike submanifold) and in General Relativity. In geometry of lightlike
submanifolds, according to the dimension `r` of the radical distribution
(see below for definition of radical distribution), degenerate submanifolds
have been classify into 4 subgroups: `r`-lightlike submanifolds, Coisotropic
have been classified into 4 subgroups: `r`-lightlike submanifolds, Coisotropic
submanifolds, Isotropic submanifolds and Totally lightlike submanifolds.
(See the book of Krishan L. Duggal and Aurel Bejancu [DS2010]_.)
Expand Down
73 changes: 73 additions & 0 deletions src/sage/manifolds/differentiable/differentiable_submanifold.py
Expand Up @@ -208,10 +208,83 @@ def _repr_(self):
3-dimensional differentiable manifold M
"""
if self is not self._manifold:
return "Open subset {} of the {}".format(self._name, self._manifold)
if self._ambient is None:
return super(DifferentiableManifold, self).__repr__()
if self._embedded:
return "{}-dimensional {} submanifold {} embedded in the {}".format(
self._dim, self._structure.name, self._name, self._ambient)
return "{}-dimensional {} submanifold {} immersed in the {}".format(
self._dim, self._structure.name, self._name, self._ambient)

def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
r"""
Create an open subset of the manifold.
An open subset is a set that is (i) included in the manifold and (ii)
open with respect to the manifold's topology. It is a differentiable
manifold by itself.
As ``self`` is a submanifold of its ambient manifold,
the new open subset is also considered a submanifold of that.
Hence the returned object is an instance of
:class:`DifferentiableSubmanifold`.
INPUT:
- ``name`` -- name given to the open subset
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
subset; if none is provided, it is set to ``name``
- ``coord_def`` -- (default: {}) definition of the subset in
terms of coordinates; ``coord_def`` must a be dictionary with keys
charts in the manifold's atlas and values the symbolic expressions
formed by the coordinates to define the subset.
- ``supersets`` -- (default: only ``self``) list of sets that the
new open subset is a subset of
OUTPUT:
- the open subset, as an instance of :class:`DifferentiableSubmanifold`
EXAMPLES::
sage: M = Manifold(3, 'M', structure="differentiable")
sage: N = Manifold(2, 'N', ambient=M, structure="differentiable"); N
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: S = N.subset('S'); S
Subset S of the
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: O = N.subset('O', is_open=True); O # indirect doctest
Open subset O of the
2-dimensional differentiable submanifold N immersed in the
3-dimensional differentiable manifold M
sage: phi = N.diff_map(M)
sage: N.set_embedding(phi)
sage: N
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
sage: S = N.subset('S'); S
Subset S of the
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
sage: O = N.subset('O', is_open=True); O # indirect doctest
Open subset O of the
2-dimensional differentiable submanifold N embedded in the
3-dimensional differentiable manifold M
"""
resu = DifferentiableSubmanifold(self._dim, name, self._field,
self._structure, ambient=self._ambient,
base_manifold=self._manifold,
diff_degree=self._diff_degree,
latex_name=latex_name,
start_index=self._sindex)
if supersets is None:
supersets = [self]
for superset in supersets:
superset._init_open_subset(resu, coord_def=coord_def)
return resu
62 changes: 39 additions & 23 deletions src/sage/manifolds/differentiable/manifold.py
Expand Up @@ -717,7 +717,7 @@ def diff_degree(self):
"""
return self._diff_degree

def open_subset(self, name, latex_name=None, coord_def={}):
def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
r"""
Create an open subset of the manifold.
Expand All @@ -735,6 +735,8 @@ def open_subset(self, name, latex_name=None, coord_def={}):
terms of coordinates; ``coord_def`` must a be dictionary with keys
charts in the manifold's atlas and values the symbolic expressions
formed by the coordinates to define the subset.
- ``supersets`` -- (default: only ``self``) list of sets that the
new open subset is a subset of
OUTPUT:
Expand Down Expand Up @@ -819,25 +821,39 @@ def open_subset(self, name, latex_name=None, coord_def={}):
diff_degree=self._diff_degree,
latex_name=latex_name,
start_index=self._sindex)
resu._calculus_method = self._calculus_method
resu._supersets.update(self._supersets)
for sd in self._supersets:
sd._subsets.add(resu)
self._top_subsets.add(resu)
# Charts on the result from the coordinate definition:
for chart, restrictions in coord_def.items():
if chart not in self._atlas:
raise ValueError("the {} does not belong to ".format(chart) +
"the atlas of {}".format(self))
chart.restrict(resu, restrictions)
# Transition maps on the result inferred from those of self:
for chart1 in coord_def:
for chart2 in coord_def:
if chart2 != chart1 and (chart1, chart2) in self._coord_changes:
self._coord_changes[(chart1, chart2)].restrict(resu)
#!# update vector frames and change of frames
if supersets is None:
supersets = [self]
for superset in supersets:
superset._init_open_subset(resu, coord_def=coord_def)
return resu

def _init_open_subset(self, resu, coord_def):
r"""
Initialize ``resu`` as an open subset of ``self``.
INPUT:
- ``resu`` -- an instance of ``:class:`TopologicalManifold` or
a subclass.
- ``coord_def`` -- (default: {}) definition of the subset in
terms of coordinates; ``coord_def`` must a be dictionary with keys
charts on the manifold and values the symbolic expressions formed
by the coordinates to define the subset
EXAMPLES::
sage: M = Manifold(2, 'R^2', structure='differentiable')
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
sage: from sage.manifolds.differentiable.manifold import DifferentiableManifold
sage: U = DifferentiableManifold(2, 'U', field=M._field, structure=M._structure, base_manifold=M)
sage: M._init_open_subset(U, coord_def={c_cart: x^2+y^2<1})
sage: U
Open subset U of the 2-dimensional differentiable manifold R^2
"""
super()._init_open_subset(resu, coord_def=coord_def)
#!# update vector frames and change of frames

def diff_map(self, codomain, coord_functions=None, chart1=None,
chart2=None, name=None, latex_name=None):
r"""
Expand Down Expand Up @@ -2736,7 +2752,7 @@ def orientation(self):
"""
if not self._orientation:
# try to get an orientation from super domains:
for sdom in self._supersets:
for sdom in self.open_supersets():
sorient = sdom._orientation
if sorient:
rst_orient = [f.restrict(self) for f in sorient]
Expand Down Expand Up @@ -2944,11 +2960,11 @@ def set_change_of_frame(self, frame1, frame2, change_of_frame,
"instance of AutomorphismFieldParal")
fmodule.set_change_of_basis(frame1, frame2, change_of_frame,
compute_inverse=compute_inverse)
for sdom in self._supersets:
for sdom in self.open_supersets():
sdom._frame_changes[(frame1, frame2)] = change_of_frame
if compute_inverse:
if (frame2, frame1) not in self._frame_changes:
for sdom in self._supersets:
for sdom in self.open_supersets():
sdom._frame_changes[(frame2, frame1)] = change_of_frame.inverse()

def vector_frame(self, *args, **kwargs):
Expand Down Expand Up @@ -3134,7 +3150,7 @@ def vector_frame(self, *args, **kwargs):
# dictionary _frame_changes of self and its supersets:
for frame_pair, chge in resu._fmodule._basis_changes.items():
if resu in frame_pair:
for sdom in self._supersets:
for sdom in self.open_supersets():
sdom._frame_changes[frame_pair] = chge
return resu

Expand All @@ -3161,7 +3177,7 @@ def _set_covering_frame(self, frame):
self._covering_frames.append(frame)
self._parallelizable_parts = set([self])
# if self contained smaller parallelizable parts, they are forgotten
for sd in self._supersets:
for sd in self.open_supersets():
if not sd.is_manifestly_parallelizable():
sd._parallelizable_parts.add(self)

Expand Down
26 changes: 7 additions & 19 deletions src/sage/manifolds/differentiable/pseudo_riemannian.py
Expand Up @@ -672,7 +672,7 @@ def volume_form(self, contra=0):
"""
return self.metric().volume_form(contra=contra)

def open_subset(self, name, latex_name=None, coord_def={}):
def open_subset(self, name, latex_name=None, coord_def={}, supersets=None):
r"""
Create an open subset of ``self``.
Expand All @@ -692,6 +692,8 @@ def open_subset(self, name, latex_name=None, coord_def={}):
terms of coordinates; ``coord_def`` must a be dictionary with keys
charts in the manifold's atlas and values the symbolic expressions
formed by the coordinates to define the subset.
- ``supersets`` -- (default: only ``self``) list of sets that the
new open subset is a subset of
OUTPUT:
Expand Down Expand Up @@ -745,22 +747,8 @@ def open_subset(self, name, latex_name=None, coord_def={}):
latex_name=latex_name,
metric_latex_name=self._metric_latex_name,
start_index=self._sindex)
resu._calculus_method = self._calculus_method
resu._supersets.update(self._supersets)
for sd in self._supersets:
sd._subsets.add(resu)
self._top_subsets.add(resu)
# Charts on the result from the coordinate definition:
for chart, restrictions in coord_def.items():
if chart not in self._atlas:
raise ValueError("the {} does not belong to ".format(chart) +
"the atlas of {}".format(self))
chart.restrict(resu, restrictions)
# Transition maps on the result inferred from those of self:
for chart1 in coord_def:
for chart2 in coord_def:
if chart2 != chart1 and (chart1, chart2) in self._coord_changes:
self._coord_changes[(chart1, chart2)].restrict(resu)
#!# update non-coordinate vector frames and change of frames
#
if supersets is None:
supersets = [self]
for superset in supersets:
superset._init_open_subset(resu, coord_def=coord_def)
return resu

0 comments on commit afe10a0

Please sign in to comment.