Skip to content

Commit

Permalink
Trac #31781: Improve handling of metrics on pseudo-Riemannian submani…
Browse files Browse the repository at this point in the history
…folds

In Sage 9.3.rc5, we have
{{{
sage: S2 = manifolds.Sphere(2)
sage: g = S2.metric()
sage: g
Riemannian metric g on the 2-sphere S^2 of radius 1 smoothly embedded
 in the Euclidean space E^3
}}}
So far so good, but then
{{{
sage: g.display()
...
ValueError: no basis could be found for computing the components
 in the Coordinate frame (A, (d/dtheta,d/dphi))
}}}
{{{
sage: g.ricci_scalar()
...
ValueError: no basis could be found for computing the components
 in the Coordinate frame (A, (d/dtheta,d/dphi))
}}}

URL: https://trac.sagemath.org/31781
Reported by: egourgoulhon
Ticket author(s): Eric Gourgoulhon
Reviewer(s): Michael Jung
  • Loading branch information
Release Manager committed Aug 29, 2021
2 parents 4ac9422 + dc15aff commit 8baa680
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 66 deletions.
14 changes: 8 additions & 6 deletions src/sage/manifolds/differentiable/degenerate.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class DegenerateManifold(DifferentiableManifold):
- ``n`` -- positive integer; dimension of the manifold
- ``name`` -- string; name (symbol) given to the manifold
- ``metric_name`` -- (default: ``'g'``) string; name (symbol) given to the
metric
- ``metric_name`` -- (default: ``None``) string; name (symbol) given to the
metric; if ``None``, ``'g'`` is used
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
tuple: `S = (n_+, n_-, n_0)`, where `n_+` (resp. `n_-`, resp. `n_0`) is the
number of positive terms (resp. negative terms, resp. zero tems) in any
Expand Down Expand Up @@ -98,12 +98,12 @@ class DegenerateManifold(DifferentiableManifold):
- [DB1996]_
- [DS2010]_
"""
def __init__(self, n, name, metric_name='g', signature=None, base_manifold=None,
diff_degree=infinity, latex_name=None,
def __init__(self, n, name, metric_name=None, signature=None,
base_manifold=None, diff_degree=infinity, latex_name=None,
metric_latex_name=None, start_index=0, category=None,
unique_tag=None):
r"""
Construct a pseudo-Riemannian manifold.
Construct a degenerate manifold.
TESTS::
Expand All @@ -130,7 +130,9 @@ def __init__(self, n, name, metric_name='g', signature=None, base_manifold=None,
category=category)
self._metric = None # to be initialized by metric()
self._metric_signature = signature
if not isinstance(metric_name, str):
if metric_name is None:
metric_name = 'g'
elif not isinstance(metric_name, str):
raise TypeError("{} is not a string".format(metric_name))
self._metric_name = metric_name
if metric_latex_name is None:
Expand Down
27 changes: 10 additions & 17 deletions src/sage/manifolds/differentiable/degenerate_submanifold.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,30 +182,24 @@ class DegenerateSubmanifold(DegenerateManifold, DifferentiableSubmanifold):
- ``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
:class:`~sage.categories.fields.Fields` and
:class:`~sage.categories.topological_spaces.TopologicalSpaces`)
for other types of manifolds
- ``ambient`` -- (default: ``None``) pseudo-Riemannian manifold `M` in
which the submanifold is embedded (or immersed). If ``None``, it is set
to ``self``
- ``metric_name`` -- (default: ``None``) string; name (symbol) given to the
metric; if ``None``, ``'g'`` is used
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
tuple: `S = (n_+, n_-, n_0)`, where `n_+` (resp. `n_-`, resp. `n_0`) is the
number of positive terms (resp. negative terms, resp. zero tems) in any
diagonal writing of the metric components; if ``signature`` is not
provided, `S` is set to `(ndim-1, 0, 1)`, being `ndim` the manifold's dimension
- ``ambient`` -- (default: ``None``) manifold of destination
of the immersion. If ``None``, set to ``self``
- ``base_manifold`` -- (default: ``None``) if not ``None``, must be a
topological manifold; the created object is then an open subset of
``base_manifold``
- ``diff_degree`` -- (default: ``infinity``) degree of differentiability
- ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
denote the manifold; if none are provided, it is set to ``name``
- ``metric_latex_name`` -- (default: ``None``) string; LaTeX symbol to
denote the metric; if none is provided, it is set to ``metric_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
Expand All @@ -227,12 +221,12 @@ class DegenerateSubmanifold(DegenerateManifold, DifferentiableSubmanifold):
:mod:`~sage.manifolds.differentiable.differentiable_submanifold`
"""
def __init__(self, n, name, ambient=None, metric_name='g', signature=None,
def __init__(self, n, name, ambient=None, metric_name=None, signature=None,
base_manifold=None, diff_degree=infinity, latex_name=None,
metric_latex_name=None, start_index=0, category=None,
unique_tag=None):
r"""
Construct a pseudo-Riemannian submanifold.
Construct a degenerate submanifold.
EXAMPLES:
Expand All @@ -245,7 +239,6 @@ def __init__(self, n, name, ambient=None, metric_name='g', signature=None,
differentiable manifold M
"""

DegenerateManifold.__init__(self, n, name=name,
metric_name=metric_name,
signature=signature,
Expand Down
21 changes: 11 additions & 10 deletions src/sage/manifolds/differentiable/examples/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
As a submanifold of a Riemannian manifold, namely the Euclidean space,
the 2-sphere admits an induced metric::
sage: h = S2_r.induced_metric()
sage: h.display()
gamma = r^2 dtheta⊗dtheta + r^2*sin(theta)^2 dphi⊗dphi
sage: g = S2_r.induced_metric()
sage: g.display()
g = r^2 dtheta⊗dtheta + r^2*sin(theta)^2 dphi⊗dphi
The induced metric is also known as the *first fundamental form* (see
:meth:`~sage.manifolds.differentiable.pseudo_riemannian_submanifold.PseudoRiemannianSubmanifold.first_fundamental_form`)::
sage: h is S2_r.first_fundamental_form()
sage: g is S2_r.first_fundamental_form()
True
The *second fundamental form* encodes the extrinsic curvature of the
Expand Down Expand Up @@ -157,12 +157,12 @@
vector field pointing outwards. Henceforth, the manifold admits
a volume form::
sage: h = S1c.induced_metric()
sage: h.display()
gamma = dchi⊗dchi
sage: eps = h.volume_form()
sage: g = S1c.induced_metric()
sage: g.display()
g = dchi⊗dchi
sage: eps = g.volume_form()
sage: eps.display()
eps_gamma = -dchi
eps_g = -dchi
"""

Expand Down Expand Up @@ -380,7 +380,8 @@ def __init__(self, n, radius=1, ambient_space=None, center=None, name=None,
PseudoRiemannianSubmanifold.__init__(self, n, name,
ambient=ambient_space,
signature=n, latex_name=latex_name,
start_index=1, category=category)
metric_name='g', start_index=1,
category=category)
# set attributes
self._radius = radius
self._center = center
Expand Down
12 changes: 7 additions & 5 deletions src/sage/manifolds/differentiable/pseudo_riemannian.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ class PseudoRiemannianManifold(DifferentiableManifold):
- ``n`` -- positive integer; dimension of the manifold
- ``name`` -- string; name (symbol) given to the manifold
- ``metric_name`` -- (default: ``'g'``) string; name (symbol) given to the
metric
- ``metric_name`` -- (default: ``None``) string; name (symbol) given to the
metric; if ``None``, ``'g'`` is used
- ``signature`` -- (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. number of negative terms) in any
Expand Down Expand Up @@ -412,8 +412,8 @@ class PseudoRiemannianManifold(DifferentiableManifold):
-2
"""
def __init__(self, n, name, metric_name='g', signature=None, base_manifold=None,
diff_degree=infinity, latex_name=None,
def __init__(self, n, name, metric_name=None, signature=None,
base_manifold=None, diff_degree=infinity, latex_name=None,
metric_latex_name=None, start_index=0, category=None,
unique_tag=None):
r"""
Expand Down Expand Up @@ -450,7 +450,9 @@ def __init__(self, n, name, metric_name='g', signature=None, base_manifold=None,
category=category)
self._metric = None # to be initialized by metric()
self._metric_signature = signature
if not isinstance(metric_name, str):
if metric_name is None:
metric_name = 'g'
elif not isinstance(metric_name, str):
raise TypeError("{} is not a string".format(metric_name))
self._metric_name = metric_name
if metric_latex_name is None:
Expand Down
115 changes: 104 additions & 11 deletions src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ class PseudoRiemannianSubmanifold(PseudoRiemannianManifold,
- ``ambient`` -- (default: ``None``) pseudo-Riemannian manifold `M` in
which the submanifold is embedded (or immersed). If ``None``, it is set
to ``self``
- ``metric_name`` -- (default: ``'g'``) string; name (symbol) given to the
submanifold's metric
- ``metric_name`` -- (default: ``None``) string; name (symbol) given to the
metric; if ``None``, ``'gamma'`` is used
- ``signature`` -- (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. number of negative terms) in any
Expand All @@ -236,7 +236,8 @@ class PseudoRiemannianSubmanifold(PseudoRiemannianManifold,
- ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
denote the submanifold; if none is provided, it is set to ``name``
- ``metric_latex_name`` -- (default: ``None``) string; LaTeX symbol to
denote the metric; if none is provided, it is set to ``metric_name``
denote the metric; if none is provided, it is set to ``metric_name`` if
the latter is not ``None`` and to ``r'\gamma'`` otherwise
- ``start_index`` -- (default: 0) integer; lower value of the range of
indices used for "indexed objects" on the submanifold, e.g. coordinates
in a chart
Expand Down Expand Up @@ -300,10 +301,10 @@ class PseudoRiemannianSubmanifold(PseudoRiemannianManifold,
:mod:`~sage.manifolds.differentiable.differentiable_submanifold`
"""
def __init__(self, n, name, ambient=None, metric_name='g', signature=None,
base_manifold=None, diff_degree=infinity, latex_name=None,
metric_latex_name=None, start_index=0, category=None,
unique_tag=None):
def __init__(self, n, name, ambient=None, metric_name=None,
signature=None, base_manifold=None, diff_degree=infinity,
latex_name=None, metric_latex_name=None, start_index=0,
category=None, unique_tag=None):
r"""
Construct a pseudo-Riemannian submanifold.
Expand Down Expand Up @@ -337,6 +338,9 @@ def __init__(self, n, name, ambient=None, metric_name='g', signature=None,
5-dimensional pseudo-Riemannian manifold M
"""
if metric_name is None:
metric_name = 'gamma'
metric_latex_name = r'\gamma'
PseudoRiemannianManifold.__init__(self, n, name=name,
metric_name=metric_name,
signature=signature,
Expand Down Expand Up @@ -513,7 +517,7 @@ def first_fundamental_form(self):
A sphere embedded in Euclidean space::
sage: M.<x,y,z> = EuclideanSpace()
sage: N = Manifold(2, 'N', ambient=M, structure="Riemannian")
sage: N = Manifold(2, 'N', ambient=M, structure='Riemannian')
sage: C.<th,ph> = N.chart(r'th:(0,pi):\theta ph:(-pi,pi):\phi')
sage: r = var('r', domain='real')
sage: assume(r>0)
Expand All @@ -535,16 +539,105 @@ def first_fundamental_form(self):
[ r^2 0]
[ 0 r^2*sin(th)^2]
By default, the first fundamental form is named ``gamma``, but this
can be customized by means of the argument ``metric_name`` when
declaring the submanifold::
sage: P = Manifold(1, 'P', ambient=M, structure='Riemannian',
....: metric_name='g')
sage: CP.<t> = P.chart()
sage: F = P.diff_map(M, [t, 2*t, 3*t])
sage: P.set_embedding(F)
sage: P.induced_metric()
Riemannian metric g on the 1-dimensional Riemannian submanifold P
embedded in the Euclidean space E^3
sage: P.induced_metric().display()
g = 14 dt⊗dt
"""
if self._first_fundamental_form is None:
self._first_fundamental_form = self.metric()
self._first_fundamental_form = super().metric()
self._first_fundamental_form.set(
self._immersion.pullback(self.ambient_metric()))
self._first_fundamental_form.set_name("gamma", r"\gamma")
return self._first_fundamental_form

induced_metric = first_fundamental_form

def metric(self, name=None, signature=None, latex_name=None,
dest_map=None):
r"""
Return the induced metric (first fundamental form) or define a new
metric tensor on the submanifold.
A new (uninitialzed) metric is returned only if the argument ``name``
is provided and differs from the metric name declared at the
construction of the submanifold; otherwise, the first fundamental
form is returned.
INPUT:
- ``name`` -- (default: ``None``) name given to the metric; if ``name``
is ``None`` or equals the metric name declared when constructing
the submanifold, the first fundamental form is returned (see
:meth:`first_fundamental_form`)
- ``signature`` -- (default: ``None``; ignored if ``name`` is ``None``)
signature `S` of the metric as a single integer: `S = n_+ - n_-`,
where `n_+` (resp. `n_-`) is the number of positive terms (resp.
number of negative terms) in any diagonal writing of the metric
components; if ``signature`` is not provided, `S` is set to the
submanifold's dimension (Riemannian signature)
- ``latex_name`` -- (default: ``None``; ignored if ``name`` is ``None``)
LaTeX symbol to denote the metric; if ``None``, it is formed from
``name``
- ``dest_map`` -- (default: ``None``; ignored if ``name`` is ``None``)
instance of
class :class:`~sage.manifolds.differentiable.diff_map.DiffMap`
representing the destination map `\Phi:\ U \rightarrow M`, where `U`
is the current submanifold; if ``None``, the identity map is assumed
(case of a metric tensor field *on* `U`)
OUTPUT:
- instance of
:class:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric`
EXAMPLES:
Induced metric on a straight line of the Euclidean plane::
sage: M.<x,y> = EuclideanSpace()
sage: N = Manifold(1, 'N', ambient=M, structure='Riemannian')
sage: CN.<t> = N.chart()
sage: F = N.diff_map(M, [t, 2*t])
sage: N.set_embedding(F)
sage: N.metric()
Riemannian metric gamma on the 1-dimensional Riemannian
submanifold N embedded in the Euclidean plane E^2
sage: N.metric().display()
gamma = 5 dt⊗dt
Setting the argument ``name`` to that declared while constructing
the submanifold (default = ``'gamma'``) yields the same result::
sage: N.metric(name='gamma') is N.metric()
True
while using a different name allows one to define a new metric on the
submanifold::
sage: h = N.metric(name='h'); h
Riemannian metric h on the 1-dimensional Riemannian submanifold N
embedded in the Euclidean plane E^2
sage: h[0, 0] = 1 # initialization
sage: h.display()
h = dt⊗dt
"""
if name is None or name == self._metric_name:
return self.first_fundamental_form()
return super().metric(name=name, signature=signature,
latex_name=latex_name, dest_map=dest_map)

@cached_method
def difft(self):
r"""
Expand Down Expand Up @@ -1162,7 +1255,7 @@ def second_fundamental_form(self):
+ " hypersurfaces")
if self._second_fundamental_form is None:
resu = self.vector_field_module().tensor((0, 2), name='K',
sym=[(0, 1)])
sym=[(0, 1)])
if self._dim_foliation != 0:
inverse_subs = {v: k for k, v in self._subs[0].items()}
asff = self.ambient_second_fundamental_form()
Expand Down
22 changes: 5 additions & 17 deletions src/sage/manifolds/manifold.py
Original file line number Diff line number Diff line change
Expand Up @@ -3008,27 +3008,15 @@ def Manifold(dim, name, latex_name=None, field='real', structure='smooth',
start_index=start_index,
unique_tag=unique_tag())
elif structure in ['pseudo-Riemannian', 'Riemannian', 'Lorentzian','degenerate_metric']:
if 'diff_degree' in extra_kwds:
diff_degree = extra_kwds['diff_degree']
else:
diff_degree = infinity
if 'metric_name' in extra_kwds:
metric_name = extra_kwds['metric_name']
else:
metric_name = 'g'
if 'metric_latex_name' in extra_kwds:
metric_latex_name = extra_kwds['metric_latex_name']
else:
metric_latex_name = None
diff_degree = extra_kwds.get('diff_degree', infinity)
metric_name = extra_kwds.get('metric_name', None)
metric_latex_name = extra_kwds.get('metric_latex_name', None)
if structure == 'pseudo-Riemannian':
if 'signature' in extra_kwds:
signature = extra_kwds['signature']
else:
signature = None
signature = extra_kwds.get('signature', None)
elif structure == 'Riemannian':
signature = dim
elif structure == 'degenerate_metric':
signature = (0,dim-1,1)
signature = (0, dim-1, 1)
elif structure == 'Lorentzian':
if 'signature' in extra_kwds:
signat = extra_kwds['signature']
Expand Down

0 comments on commit 8baa680

Please sign in to comment.