passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
|
@@ -0,0 +1,3032 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Pseudo-Riemannian Metrics and Degenerate Metrics
|
|
4
|
+
|
|
5
|
+
The class :class:`PseudoRiemannianMetric` implements pseudo-Riemannian metrics
|
|
6
|
+
on differentiable manifolds over `\RR`. The derived class
|
|
7
|
+
:class:`PseudoRiemannianMetricParal` is devoted to metrics with values on a
|
|
8
|
+
parallelizable manifold.
|
|
9
|
+
|
|
10
|
+
The class :class:`DegenerateMetric` implements degenerate (or null or lightlike)
|
|
11
|
+
metrics on differentiable manifolds over `\RR`. The derived class
|
|
12
|
+
:class:`DegenerateMetricParal` is devoted to metrics with values on a
|
|
13
|
+
parallelizable manifold.
|
|
14
|
+
|
|
15
|
+
AUTHORS:
|
|
16
|
+
|
|
17
|
+
- Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version
|
|
18
|
+
- Pablo Angulo (2016) : Schouten, Cotton and Cotton-York tensors
|
|
19
|
+
- Florentin Jaffredo (2018) : series expansion for the inverse metric
|
|
20
|
+
- Hans Fotsing Tetsing (2019) : degenerate metrics
|
|
21
|
+
- Marius Gerbershagen (2022) : compute volume forms with contravariant indices
|
|
22
|
+
only as needed
|
|
23
|
+
|
|
24
|
+
REFERENCES:
|
|
25
|
+
|
|
26
|
+
- [KN1963]_
|
|
27
|
+
- [Lee1997]_
|
|
28
|
+
- [ONe1983]_
|
|
29
|
+
- [DB1996]_
|
|
30
|
+
- [DS2010]_
|
|
31
|
+
"""
|
|
32
|
+
# *****************************************************************************
|
|
33
|
+
# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
|
|
34
|
+
# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
|
|
35
|
+
# Copyright (C) 2016 Pablo Angulo <pang@cancamusa.net>
|
|
36
|
+
# Copyright (C) 2018 Florentin Jaffredo <florentin.jaffredo@polytechnique.edu>
|
|
37
|
+
# Copyright (C) 2019 Hans Fotsing Tetsing <hans.fotsing@aims-cameroon.org>
|
|
38
|
+
#
|
|
39
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
40
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
41
|
+
# the License, or (at your option) any later version.
|
|
42
|
+
# https://www.gnu.org/licenses/
|
|
43
|
+
# *****************************************************************************
|
|
44
|
+
from __future__ import annotations
|
|
45
|
+
|
|
46
|
+
from typing import TYPE_CHECKING, overload
|
|
47
|
+
|
|
48
|
+
from sage.manifolds.differentiable.tensorfield import TensorField
|
|
49
|
+
from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
|
|
50
|
+
from sage.rings.integer import Integer
|
|
51
|
+
|
|
52
|
+
if TYPE_CHECKING:
|
|
53
|
+
from sage.manifolds.differentiable.diff_form import DiffForm
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PseudoRiemannianMetric(TensorField):
|
|
57
|
+
r"""
|
|
58
|
+
Pseudo-Riemannian metric with values on an open subset of a
|
|
59
|
+
differentiable manifold.
|
|
60
|
+
|
|
61
|
+
An instance of this class is a field of nondegenerate symmetric bilinear
|
|
62
|
+
forms (metric field) along a differentiable manifold `U` with
|
|
63
|
+
values on a differentiable manifold `M` over `\RR`, via a differentiable
|
|
64
|
+
mapping `\Phi: U \rightarrow M`.
|
|
65
|
+
The standard case of a metric field *on* a manifold corresponds to `U=M`
|
|
66
|
+
and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
67
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open interval
|
|
68
|
+
of `\RR`).
|
|
69
|
+
|
|
70
|
+
A *metric* `g` is a field on `U`, such that at each point `p\in U`, `g(p)`
|
|
71
|
+
is a bilinear map of the type:
|
|
72
|
+
|
|
73
|
+
.. MATH::
|
|
74
|
+
|
|
75
|
+
g(p):\ T_q M\times T_q M \longrightarrow \RR
|
|
76
|
+
|
|
77
|
+
where `T_q M` stands for the tangent space to the
|
|
78
|
+
manifold `M` at the point `q=\Phi(p)`, such that `g(p)` is symmetric:
|
|
79
|
+
`\forall (u,v)\in T_q M\times T_q M, \ g(p)(v,u) = g(p)(u,v)`
|
|
80
|
+
and nondegenerate:
|
|
81
|
+
`(\forall v\in T_q M,\ \ g(p)(u,v) = 0) \Longrightarrow u=0`.
|
|
82
|
+
|
|
83
|
+
.. NOTE::
|
|
84
|
+
|
|
85
|
+
If `M` is parallelizable, the class :class:`PseudoRiemannianMetricParal`
|
|
86
|
+
should be used instead.
|
|
87
|
+
|
|
88
|
+
INPUT:
|
|
89
|
+
|
|
90
|
+
- ``vector_field_module`` -- module `\mathfrak{X}(U,\Phi)` of vector
|
|
91
|
+
fields along `U` with values on `\Phi(U)\subset M`
|
|
92
|
+
- ``name`` -- name given to the metric
|
|
93
|
+
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
|
|
94
|
+
single integer: `S = n_+ - n_-`, where `n_+` (resp. `n_-`) is the number
|
|
95
|
+
of positive terms (resp. number of negative terms) in any diagonal
|
|
96
|
+
writing of the metric components; if ``signature`` is ``None``, `S` is
|
|
97
|
+
set to the dimension of manifold `M` (Riemannian signature)
|
|
98
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the metric;
|
|
99
|
+
if ``None``, it is formed from ``name``
|
|
100
|
+
|
|
101
|
+
EXAMPLES:
|
|
102
|
+
|
|
103
|
+
Let us construct the standard metric on the sphere `S^2`, described in
|
|
104
|
+
terms of stereographic coordinates, from the North pole (open subset `U`)
|
|
105
|
+
and from the South pole (open subset `V`)::
|
|
106
|
+
|
|
107
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
108
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
109
|
+
sage: M.declare_union(U,V) # S^2 is the union of U and V
|
|
110
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() # stereographic coord
|
|
111
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
112
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
113
|
+
....: restrictions2= u^2+v^2!=0)
|
|
114
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
115
|
+
sage: eU = c_xy.frame() ; eV = c_uv.frame()
|
|
116
|
+
sage: g = M.metric('g') ; g
|
|
117
|
+
Riemannian metric g on the 2-dimensional differentiable manifold S^2
|
|
118
|
+
|
|
119
|
+
The metric is considered as a tensor field of type (0,2) on `S^2`::
|
|
120
|
+
|
|
121
|
+
sage: g.parent()
|
|
122
|
+
Module T^(0,2)(S^2) of type-(0,2) tensors fields on the 2-dimensional
|
|
123
|
+
differentiable manifold S^2
|
|
124
|
+
|
|
125
|
+
We define `g` by its components on domain `U`::
|
|
126
|
+
|
|
127
|
+
sage: g[eU,1,1], g[eU,2,2] = 4/(1+x^2+y^2)^2, 4/(1+x^2+y^2)^2
|
|
128
|
+
sage: g.display(eU)
|
|
129
|
+
g = 4/(x^2 + y^2 + 1)^2 dx⊗dx + 4/(x^2 + y^2 + 1)^2 dy⊗dy
|
|
130
|
+
|
|
131
|
+
A matrix view of the components::
|
|
132
|
+
|
|
133
|
+
sage: g[eU,:]
|
|
134
|
+
[4/(x^2 + y^2 + 1)^2 0]
|
|
135
|
+
[ 0 4/(x^2 + y^2 + 1)^2]
|
|
136
|
+
|
|
137
|
+
The components of `g` on domain `V` expressed in terms of coordinates
|
|
138
|
+
`(u,v)` are obtained by applying (i) the tensor transformation law on
|
|
139
|
+
`W = U\cap V` and (ii) some analytical continuation::
|
|
140
|
+
|
|
141
|
+
sage: W = U.intersection(V)
|
|
142
|
+
sage: g.add_comp_by_continuation(eV, W, chart=c_uv)
|
|
143
|
+
sage: g.apply_map(factor, frame=eV, keep_other_components=True) # for a nicer display
|
|
144
|
+
sage: g.display(eV)
|
|
145
|
+
g = 4/(u^2 + v^2 + 1)^2 du⊗du + 4/(u^2 + v^2 + 1)^2 dv⊗dv
|
|
146
|
+
|
|
147
|
+
At this stage, the metric is fully defined on the whole sphere. Its
|
|
148
|
+
restriction to some subdomain is itself a metric (by default, it bears the
|
|
149
|
+
same symbol)::
|
|
150
|
+
|
|
151
|
+
sage: g.restrict(U)
|
|
152
|
+
Riemannian metric g on the Open subset U of the 2-dimensional
|
|
153
|
+
differentiable manifold S^2
|
|
154
|
+
sage: g.restrict(U).parent()
|
|
155
|
+
Free module T^(0,2)(U) of type-(0,2) tensors fields on the Open subset
|
|
156
|
+
U of the 2-dimensional differentiable manifold S^2
|
|
157
|
+
|
|
158
|
+
The parent of `g|_U` is a free module because is `U` is a parallelizable
|
|
159
|
+
domain, contrary to `S^2`. Actually, `g` and `g|_U` have different Python
|
|
160
|
+
type::
|
|
161
|
+
|
|
162
|
+
sage: type(g)
|
|
163
|
+
<class 'sage.manifolds.differentiable.metric.PseudoRiemannianMetric'>
|
|
164
|
+
sage: type(g.restrict(U))
|
|
165
|
+
<class 'sage.manifolds.differentiable.metric.PseudoRiemannianMetricParal'>
|
|
166
|
+
|
|
167
|
+
As a field of bilinear forms, the metric acts on pairs of vector fields,
|
|
168
|
+
yielding a scalar field::
|
|
169
|
+
|
|
170
|
+
sage: a = M.vector_field({eU: [x, 2+y]}, name='a')
|
|
171
|
+
sage: a.add_comp_by_continuation(eV, W, chart=c_uv)
|
|
172
|
+
sage: b = M.vector_field({eU: [-y, x]}, name='b')
|
|
173
|
+
sage: b.add_comp_by_continuation(eV, W, chart=c_uv)
|
|
174
|
+
sage: s = g(a,b) ; s
|
|
175
|
+
Scalar field g(a,b) on the 2-dimensional differentiable manifold S^2
|
|
176
|
+
sage: s.display()
|
|
177
|
+
g(a,b): S^2 → ℝ
|
|
178
|
+
on U: (x, y) ↦ 8*x/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1)
|
|
179
|
+
on V: (u, v) ↦ 8*(u^3 + u*v^2)/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1)
|
|
180
|
+
|
|
181
|
+
The inverse metric is::
|
|
182
|
+
|
|
183
|
+
sage: ginv = g.inverse() ; ginv
|
|
184
|
+
Tensor field inv_g of type (2,0) on the 2-dimensional differentiable
|
|
185
|
+
manifold S^2
|
|
186
|
+
sage: ginv.parent()
|
|
187
|
+
Module T^(2,0)(S^2) of type-(2,0) tensors fields on the 2-dimensional
|
|
188
|
+
differentiable manifold S^2
|
|
189
|
+
sage: latex(ginv)
|
|
190
|
+
g^{-1}
|
|
191
|
+
sage: ginv.display(eU)
|
|
192
|
+
inv_g = (1/4*x^4 + 1/4*y^4 + 1/2*(x^2 + 1)*y^2 + 1/2*x^2 + 1/4) ∂/∂x⊗∂/∂x
|
|
193
|
+
+ (1/4*x^4 + 1/4*y^4 + 1/2*(x^2 + 1)*y^2 + 1/2*x^2 + 1/4) ∂/∂y⊗∂/∂y
|
|
194
|
+
sage: ginv.display(eV)
|
|
195
|
+
inv_g = (1/4*u^4 + 1/4*v^4 + 1/2*(u^2 + 1)*v^2 + 1/2*u^2 + 1/4) ∂/∂u⊗∂/∂u
|
|
196
|
+
+ (1/4*u^4 + 1/4*v^4 + 1/2*(u^2 + 1)*v^2 + 1/2*u^2 + 1/4) ∂/∂v⊗∂/∂v
|
|
197
|
+
|
|
198
|
+
We have::
|
|
199
|
+
|
|
200
|
+
sage: ginv.restrict(U) is g.restrict(U).inverse()
|
|
201
|
+
True
|
|
202
|
+
sage: ginv.restrict(V) is g.restrict(V).inverse()
|
|
203
|
+
True
|
|
204
|
+
sage: ginv.restrict(W) is g.restrict(W).inverse()
|
|
205
|
+
True
|
|
206
|
+
|
|
207
|
+
To get the volume form (Levi-Civita tensor) associated with `g`, we have
|
|
208
|
+
first to define an orientation on `S^2`. The standard orientation is that
|
|
209
|
+
in which ``eV`` is right-handed; indeed, once supplemented by the outward
|
|
210
|
+
unit normal, ``eV`` give birth to a right-handed frame with respect to the
|
|
211
|
+
standard orientation of the ambient Euclidean space `E^3`. With such an
|
|
212
|
+
orientation, ``eU`` is then left-handed and in order to define an
|
|
213
|
+
orientation on the whole of `S^2`, we introduce a vector frame
|
|
214
|
+
on `U` by swapping ``eU``'s vectors::
|
|
215
|
+
|
|
216
|
+
sage: f = U.vector_frame('f', (eU[2], eU[1]))
|
|
217
|
+
sage: M.set_orientation([eV, f])
|
|
218
|
+
|
|
219
|
+
We have then, factorizing the components for a nicer display::
|
|
220
|
+
|
|
221
|
+
sage: eps = g.volume_form() ; eps
|
|
222
|
+
2-form eps_g on the 2-dimensional differentiable manifold S^2
|
|
223
|
+
sage: eps.apply_map(factor, frame=eU, keep_other_components=True)
|
|
224
|
+
sage: eps.apply_map(factor, frame=eV, keep_other_components=True)
|
|
225
|
+
sage: eps.display(eU)
|
|
226
|
+
eps_g = -4/(x^2 + y^2 + 1)^2 dx∧dy
|
|
227
|
+
sage: eps.display(eV)
|
|
228
|
+
eps_g = 4/(u^2 + v^2 + 1)^2 du∧dv
|
|
229
|
+
|
|
230
|
+
The unique non-trivial component of the volume form is, up to a sign
|
|
231
|
+
depending of the chosen orientation, nothing but the square root of the
|
|
232
|
+
determinant of `g` in the corresponding frame::
|
|
233
|
+
|
|
234
|
+
sage: eps[[eU,1,2]] == -g.sqrt_abs_det(eU)
|
|
235
|
+
True
|
|
236
|
+
sage: eps[[eV,1,2]] == g.sqrt_abs_det(eV)
|
|
237
|
+
True
|
|
238
|
+
|
|
239
|
+
The Levi-Civita connection associated with the metric `g`::
|
|
240
|
+
|
|
241
|
+
sage: nabla = g.connection() ; nabla
|
|
242
|
+
Levi-Civita connection nabla_g associated with the Riemannian metric g
|
|
243
|
+
on the 2-dimensional differentiable manifold S^2
|
|
244
|
+
sage: latex(nabla)
|
|
245
|
+
\nabla_{g}
|
|
246
|
+
|
|
247
|
+
The Christoffel symbols `\Gamma^i_{\ \, jk}` associated with some
|
|
248
|
+
coordinates::
|
|
249
|
+
|
|
250
|
+
sage: g.christoffel_symbols(c_xy)
|
|
251
|
+
3-indices components w.r.t. Coordinate frame (U, (∂/∂x,∂/∂y)), with
|
|
252
|
+
symmetry on the index positions (1, 2)
|
|
253
|
+
sage: g.christoffel_symbols(c_xy)[:]
|
|
254
|
+
[[[-2*x/(x^2 + y^2 + 1), -2*y/(x^2 + y^2 + 1)],
|
|
255
|
+
[-2*y/(x^2 + y^2 + 1), 2*x/(x^2 + y^2 + 1)]],
|
|
256
|
+
[[2*y/(x^2 + y^2 + 1), -2*x/(x^2 + y^2 + 1)],
|
|
257
|
+
[-2*x/(x^2 + y^2 + 1), -2*y/(x^2 + y^2 + 1)]]]
|
|
258
|
+
sage: g.christoffel_symbols(c_uv)[:]
|
|
259
|
+
[[[-2*u/(u^2 + v^2 + 1), -2*v/(u^2 + v^2 + 1)],
|
|
260
|
+
[-2*v/(u^2 + v^2 + 1), 2*u/(u^2 + v^2 + 1)]],
|
|
261
|
+
[[2*v/(u^2 + v^2 + 1), -2*u/(u^2 + v^2 + 1)],
|
|
262
|
+
[-2*u/(u^2 + v^2 + 1), -2*v/(u^2 + v^2 + 1)]]]
|
|
263
|
+
|
|
264
|
+
The Christoffel symbols are nothing but the connection coefficients w.r.t.
|
|
265
|
+
the coordinate frame::
|
|
266
|
+
|
|
267
|
+
sage: g.christoffel_symbols(c_xy) is nabla.coef(c_xy.frame())
|
|
268
|
+
True
|
|
269
|
+
sage: g.christoffel_symbols(c_uv) is nabla.coef(c_uv.frame())
|
|
270
|
+
True
|
|
271
|
+
|
|
272
|
+
Test that `\nabla` is the connection compatible with `g`::
|
|
273
|
+
|
|
274
|
+
sage: t = nabla(g) ; t
|
|
275
|
+
Tensor field nabla_g(g) of type (0,3) on the 2-dimensional
|
|
276
|
+
differentiable manifold S^2
|
|
277
|
+
sage: t.display(eU)
|
|
278
|
+
nabla_g(g) = 0
|
|
279
|
+
sage: t.display(eV)
|
|
280
|
+
nabla_g(g) = 0
|
|
281
|
+
sage: t == 0
|
|
282
|
+
True
|
|
283
|
+
|
|
284
|
+
The Riemann curvature tensor of `g`::
|
|
285
|
+
|
|
286
|
+
sage: riem = g.riemann() ; riem
|
|
287
|
+
Tensor field Riem(g) of type (1,3) on the 2-dimensional differentiable
|
|
288
|
+
manifold S^2
|
|
289
|
+
sage: riem.display(eU)
|
|
290
|
+
Riem(g) = 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) ∂/∂x⊗dy⊗dx⊗dy
|
|
291
|
+
- 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) ∂/∂x⊗dy⊗dy⊗dx
|
|
292
|
+
- 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) ∂/∂y⊗dx⊗dx⊗dy
|
|
293
|
+
+ 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) ∂/∂y⊗dx⊗dy⊗dx
|
|
294
|
+
sage: riem.display(eV)
|
|
295
|
+
Riem(g) = 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) ∂/∂u⊗dv⊗du⊗dv
|
|
296
|
+
- 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) ∂/∂u⊗dv⊗dv⊗du
|
|
297
|
+
- 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) ∂/∂v⊗du⊗du⊗dv
|
|
298
|
+
+ 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) ∂/∂v⊗du⊗dv⊗du
|
|
299
|
+
|
|
300
|
+
The Ricci tensor of `g`::
|
|
301
|
+
|
|
302
|
+
sage: ric = g.ricci() ; ric
|
|
303
|
+
Field of symmetric bilinear forms Ric(g) on the 2-dimensional
|
|
304
|
+
differentiable manifold S^2
|
|
305
|
+
sage: ric.display(eU)
|
|
306
|
+
Ric(g) = 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx⊗dx
|
|
307
|
+
+ 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dy⊗dy
|
|
308
|
+
sage: ric.display(eV)
|
|
309
|
+
Ric(g) = 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) du⊗du
|
|
310
|
+
+ 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) dv⊗dv
|
|
311
|
+
sage: ric == g
|
|
312
|
+
True
|
|
313
|
+
|
|
314
|
+
The Ricci scalar of `g`::
|
|
315
|
+
|
|
316
|
+
sage: r = g.ricci_scalar() ; r
|
|
317
|
+
Scalar field r(g) on the 2-dimensional differentiable manifold S^2
|
|
318
|
+
sage: r.display()
|
|
319
|
+
r(g): S^2 → ℝ
|
|
320
|
+
on U: (x, y) ↦ 2
|
|
321
|
+
on V: (u, v) ↦ 2
|
|
322
|
+
|
|
323
|
+
In dimension 2, the Riemann tensor can be expressed entirely in terms of
|
|
324
|
+
the Ricci scalar `r`:
|
|
325
|
+
|
|
326
|
+
.. MATH::
|
|
327
|
+
|
|
328
|
+
R^i_{\ \, jlk} = \frac{r}{2} \left( \delta^i_{\ \, k} g_{jl}
|
|
329
|
+
- \delta^i_{\ \, l} g_{jk} \right)
|
|
330
|
+
|
|
331
|
+
This formula can be checked here, with the r.h.s. rewritten as
|
|
332
|
+
`-r g_{j[k} \delta^i_{\ \, l]}`::
|
|
333
|
+
|
|
334
|
+
sage: delta = M.tangent_identity_field()
|
|
335
|
+
sage: riem == - r*(g*delta).antisymmetrize(2,3)
|
|
336
|
+
True
|
|
337
|
+
"""
|
|
338
|
+
_derived_objects = ('_connection', '_ricci_scalar', '_weyl',
|
|
339
|
+
'_schouten', '_cotton', '_cotton_york')
|
|
340
|
+
|
|
341
|
+
def __init__(self, vector_field_module, name, signature=None,
|
|
342
|
+
latex_name=None):
|
|
343
|
+
r"""
|
|
344
|
+
Construct a metric.
|
|
345
|
+
|
|
346
|
+
TESTS::
|
|
347
|
+
|
|
348
|
+
sage: M = Manifold(2, 'M')
|
|
349
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
350
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
351
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
352
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
353
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
354
|
+
....: restrictions2= u+v>0)
|
|
355
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
356
|
+
sage: W = U.intersection(V)
|
|
357
|
+
sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
|
|
358
|
+
sage: XM = M.vector_field_module()
|
|
359
|
+
sage: from sage.manifolds.differentiable.metric import \
|
|
360
|
+
....: PseudoRiemannianMetric
|
|
361
|
+
sage: g = PseudoRiemannianMetric(XM, 'g', signature=0); g
|
|
362
|
+
Lorentzian metric g on the 2-dimensional differentiable
|
|
363
|
+
manifold M
|
|
364
|
+
sage: g[e_xy,0,0], g[e_xy,1,1] = -(1+x^2), 1+y^2
|
|
365
|
+
sage: g.add_comp_by_continuation(e_uv, W, c_uv)
|
|
366
|
+
sage: TestSuite(g).run(skip=['_test_category', '_test_pickling'])
|
|
367
|
+
|
|
368
|
+
.. TODO::
|
|
369
|
+
|
|
370
|
+
- fix _test_pickling (in the superclass TensorField)
|
|
371
|
+
- add a specific parent to the metrics, to fit with the category
|
|
372
|
+
framework
|
|
373
|
+
"""
|
|
374
|
+
TensorField.__init__(self, vector_field_module, (0,2),
|
|
375
|
+
name=name, latex_name=latex_name, sym=(0,1))
|
|
376
|
+
# signature:
|
|
377
|
+
ndim = self._ambient_domain.dimension()
|
|
378
|
+
if signature is None:
|
|
379
|
+
signature = ndim
|
|
380
|
+
else:
|
|
381
|
+
if not isinstance(signature, (int, Integer)):
|
|
382
|
+
raise TypeError("the metric signature must be an integer")
|
|
383
|
+
if (signature < - ndim) or (signature > ndim):
|
|
384
|
+
raise ValueError("metric signature out of range")
|
|
385
|
+
if (signature+ndim) % 2 == 1:
|
|
386
|
+
if ndim % 2 == 0:
|
|
387
|
+
raise ValueError("the metric signature must be even")
|
|
388
|
+
else:
|
|
389
|
+
raise ValueError("the metric signature must be odd")
|
|
390
|
+
self._signature = signature
|
|
391
|
+
# the pair (n_+, n_-):
|
|
392
|
+
self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2)
|
|
393
|
+
self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_-
|
|
394
|
+
# Initialization of derived quantities:
|
|
395
|
+
PseudoRiemannianMetric._init_derived(self)
|
|
396
|
+
|
|
397
|
+
def _repr_(self):
|
|
398
|
+
r"""
|
|
399
|
+
String representation of the object.
|
|
400
|
+
|
|
401
|
+
TESTS::
|
|
402
|
+
|
|
403
|
+
sage: M = Manifold(5, 'M')
|
|
404
|
+
sage: g = M.metric('g')
|
|
405
|
+
sage: g._repr_()
|
|
406
|
+
'Riemannian metric g on the 5-dimensional differentiable manifold M'
|
|
407
|
+
sage: g = M.metric('g', signature=3)
|
|
408
|
+
sage: g._repr_()
|
|
409
|
+
'Lorentzian metric g on the 5-dimensional differentiable manifold M'
|
|
410
|
+
sage: g = M.metric('g', signature=1)
|
|
411
|
+
sage: g._repr_()
|
|
412
|
+
'Pseudo-Riemannian metric g on the 5-dimensional differentiable manifold M'
|
|
413
|
+
"""
|
|
414
|
+
n = self._ambient_domain.dimension()
|
|
415
|
+
s = self._signature
|
|
416
|
+
if s == n:
|
|
417
|
+
description = "Riemannian metric "
|
|
418
|
+
elif s == n-2 or s == 2-n:
|
|
419
|
+
description = "Lorentzian metric "
|
|
420
|
+
else:
|
|
421
|
+
description = "Pseudo-Riemannian metric "
|
|
422
|
+
description += self._name + " "
|
|
423
|
+
return self._final_repr(description)
|
|
424
|
+
|
|
425
|
+
def _new_instance(self):
|
|
426
|
+
r"""
|
|
427
|
+
Create an instance of the same class as ``self`` with the same
|
|
428
|
+
signature.
|
|
429
|
+
|
|
430
|
+
TESTS::
|
|
431
|
+
|
|
432
|
+
sage: M = Manifold(5, 'M')
|
|
433
|
+
sage: g = M.metric('g', signature=3)
|
|
434
|
+
sage: g1 = g._new_instance(); g1
|
|
435
|
+
Lorentzian metric unnamed metric on the 5-dimensional
|
|
436
|
+
differentiable manifold M
|
|
437
|
+
sage: type(g1) == type(g)
|
|
438
|
+
True
|
|
439
|
+
sage: g1.parent() is g.parent()
|
|
440
|
+
True
|
|
441
|
+
sage: g1.signature() == g.signature()
|
|
442
|
+
True
|
|
443
|
+
"""
|
|
444
|
+
return type(self)(self._vmodule, 'unnamed metric',
|
|
445
|
+
signature=self._signature,
|
|
446
|
+
latex_name=r'\text{unnamed metric}')
|
|
447
|
+
|
|
448
|
+
def _init_derived(self):
|
|
449
|
+
r"""
|
|
450
|
+
Initialize the derived quantities.
|
|
451
|
+
|
|
452
|
+
TESTS::
|
|
453
|
+
|
|
454
|
+
sage: M = Manifold(5, 'M')
|
|
455
|
+
sage: g = M.metric('g')
|
|
456
|
+
sage: g._init_derived()
|
|
457
|
+
"""
|
|
458
|
+
# Initialization of quantities pertaining to the mother class:
|
|
459
|
+
TensorField._init_derived(self)
|
|
460
|
+
# inverse metric:
|
|
461
|
+
inv_name = 'inv_' + self._name
|
|
462
|
+
inv_latex_name = self._latex_name + r'^{-1}'
|
|
463
|
+
self._inverse = self._vmodule.tensor((2,0), name=inv_name,
|
|
464
|
+
latex_name=inv_latex_name,
|
|
465
|
+
sym=(0,1))
|
|
466
|
+
for attr in self._derived_objects:
|
|
467
|
+
self.__setattr__(attr, None)
|
|
468
|
+
self._determinants = {} # determinants in various frames
|
|
469
|
+
self._sqrt_abs_dets = {} # sqrt(abs(det g)) in various frames
|
|
470
|
+
self._vol_forms = [] # volume form and associated tensors
|
|
471
|
+
|
|
472
|
+
def _del_derived(self):
|
|
473
|
+
r"""
|
|
474
|
+
Delete the derived quantities.
|
|
475
|
+
|
|
476
|
+
TESTS::
|
|
477
|
+
|
|
478
|
+
sage: M = Manifold(5, 'M')
|
|
479
|
+
sage: g = M.metric('g')
|
|
480
|
+
sage: g._del_derived()
|
|
481
|
+
"""
|
|
482
|
+
# First the derived quantities from the mother class are deleted:
|
|
483
|
+
TensorField._del_derived(self)
|
|
484
|
+
# The inverse metric is cleared:
|
|
485
|
+
self._del_inverse()
|
|
486
|
+
# The connection, Ricci scalar and Weyl tensor are reset to None:
|
|
487
|
+
# The Schouten, Cotton and Cotton-York tensors are reset to None:
|
|
488
|
+
for attr in self._derived_objects:
|
|
489
|
+
self.__setattr__(attr, None)
|
|
490
|
+
# The dictionary of determinants over the various frames is cleared:
|
|
491
|
+
self._determinants.clear()
|
|
492
|
+
self._sqrt_abs_dets.clear()
|
|
493
|
+
# The volume form and the associated tensors is deleted:
|
|
494
|
+
del self._vol_forms[:]
|
|
495
|
+
|
|
496
|
+
def _del_inverse(self):
|
|
497
|
+
r"""
|
|
498
|
+
Delete the inverse metric.
|
|
499
|
+
|
|
500
|
+
TESTS::
|
|
501
|
+
|
|
502
|
+
sage: M = Manifold(5, 'M')
|
|
503
|
+
sage: g = M.metric('g')
|
|
504
|
+
sage: g._del_inverse()
|
|
505
|
+
"""
|
|
506
|
+
self._inverse._restrictions.clear()
|
|
507
|
+
self._inverse._del_derived()
|
|
508
|
+
|
|
509
|
+
def signature(self):
|
|
510
|
+
r"""
|
|
511
|
+
Signature of the metric.
|
|
512
|
+
|
|
513
|
+
OUTPUT:
|
|
514
|
+
|
|
515
|
+
- signature `S` of the metric, defined as the integer
|
|
516
|
+
`S = n_+ - n_-`, where `n_+` (resp. `n_-`) is the number of
|
|
517
|
+
positive terms (resp. number of negative terms) in any diagonal
|
|
518
|
+
writing of the metric components
|
|
519
|
+
|
|
520
|
+
EXAMPLES:
|
|
521
|
+
|
|
522
|
+
Signatures on a 2-dimensional manifold::
|
|
523
|
+
|
|
524
|
+
sage: M = Manifold(2, 'M')
|
|
525
|
+
sage: g = M.metric('g') # if not specified, the signature is Riemannian
|
|
526
|
+
sage: g.signature()
|
|
527
|
+
2
|
|
528
|
+
sage: h = M.metric('h', signature=0)
|
|
529
|
+
sage: h.signature()
|
|
530
|
+
0
|
|
531
|
+
"""
|
|
532
|
+
return self._signature
|
|
533
|
+
|
|
534
|
+
def restrict(self, subdomain, dest_map=None):
|
|
535
|
+
r"""
|
|
536
|
+
Return the restriction of the metric to some subdomain.
|
|
537
|
+
|
|
538
|
+
If the restriction has not been defined yet, it is constructed here.
|
|
539
|
+
|
|
540
|
+
INPUT:
|
|
541
|
+
|
|
542
|
+
- ``subdomain`` -- open subset `U` of the metric's domain (must be an
|
|
543
|
+
instance of :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`)
|
|
544
|
+
- ``dest_map`` -- (default: ``None``) destination map
|
|
545
|
+
`\Phi:\ U \rightarrow V`, where `V` is a subdomain of
|
|
546
|
+
``self._codomain``
|
|
547
|
+
(type: :class:`~sage.manifolds.differentiable.diff_map.DiffMap`)
|
|
548
|
+
If ``None``, the restriction of ``self._vmodule._dest_map`` to `U` is
|
|
549
|
+
used.
|
|
550
|
+
|
|
551
|
+
OUTPUT:
|
|
552
|
+
|
|
553
|
+
- instance of :class:`PseudoRiemannianMetric` representing the
|
|
554
|
+
restriction.
|
|
555
|
+
|
|
556
|
+
EXAMPLES::
|
|
557
|
+
|
|
558
|
+
sage: M = Manifold(5, 'M')
|
|
559
|
+
sage: g = M.metric('g', signature=3)
|
|
560
|
+
sage: U = M.open_subset('U')
|
|
561
|
+
sage: g.restrict(U)
|
|
562
|
+
Lorentzian metric g on the Open subset U of the
|
|
563
|
+
5-dimensional differentiable manifold M
|
|
564
|
+
sage: g.restrict(U).signature()
|
|
565
|
+
3
|
|
566
|
+
|
|
567
|
+
See the top documentation of :class:`PseudoRiemannianMetric` for more
|
|
568
|
+
examples.
|
|
569
|
+
"""
|
|
570
|
+
if subdomain == self._domain:
|
|
571
|
+
return self
|
|
572
|
+
if subdomain not in self._restrictions:
|
|
573
|
+
# Construct the restriction at the tensor field level:
|
|
574
|
+
resu = TensorField.restrict(self, subdomain, dest_map=dest_map)
|
|
575
|
+
# the type is correctly handled by TensorField.restrict, i.e.
|
|
576
|
+
# resu is of type self.__class__, but the signature is not handled
|
|
577
|
+
# by TensorField.restrict; we have to set it here:
|
|
578
|
+
resu._signature = self._signature
|
|
579
|
+
resu._signature_pm = self._signature_pm
|
|
580
|
+
resu._indic_signat = self._indic_signat
|
|
581
|
+
# Restrictions of derived quantities:
|
|
582
|
+
resu._inverse = self.inverse().restrict(subdomain)
|
|
583
|
+
for attr in self._derived_objects:
|
|
584
|
+
derived = self.__getattribute__(attr)
|
|
585
|
+
if derived is not None:
|
|
586
|
+
resu.__setattr__(attr, derived.restrict(subdomain))
|
|
587
|
+
if self._vol_forms != []:
|
|
588
|
+
for eps in self._vol_forms:
|
|
589
|
+
resu._vol_forms.append(eps.restrict(subdomain))
|
|
590
|
+
# NB: no initialization of resu._determinants nor
|
|
591
|
+
# resu._sqrt_abs_dets
|
|
592
|
+
# The restriction is ready:
|
|
593
|
+
self._restrictions[subdomain] = resu
|
|
594
|
+
return self._restrictions[subdomain]
|
|
595
|
+
|
|
596
|
+
def set(self, symbiform):
|
|
597
|
+
r"""
|
|
598
|
+
Define the metric from a field of symmetric bilinear forms.
|
|
599
|
+
|
|
600
|
+
INPUT:
|
|
601
|
+
|
|
602
|
+
- ``symbiform`` -- instance of
|
|
603
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
604
|
+
representing a field of symmetric bilinear forms
|
|
605
|
+
|
|
606
|
+
EXAMPLES:
|
|
607
|
+
|
|
608
|
+
Metric defined from a field of symmetric bilinear forms on a
|
|
609
|
+
non-parallelizable 2-dimensional manifold::
|
|
610
|
+
|
|
611
|
+
sage: M = Manifold(2, 'M')
|
|
612
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
613
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
614
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
615
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W',
|
|
616
|
+
....: restrictions1= x>0, restrictions2= u+v>0)
|
|
617
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
618
|
+
sage: W = U.intersection(V)
|
|
619
|
+
sage: eU = c_xy.frame() ; eV = c_uv.frame()
|
|
620
|
+
sage: h = M.sym_bilin_form_field(name='h')
|
|
621
|
+
sage: h[eU,0,0], h[eU,0,1], h[eU,1,1] = 1+x, x*y, 1-y
|
|
622
|
+
sage: h.add_comp_by_continuation(eV, W, c_uv)
|
|
623
|
+
sage: h.display(eU)
|
|
624
|
+
h = (x + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (-y + 1) dy⊗dy
|
|
625
|
+
sage: h.display(eV)
|
|
626
|
+
h = (1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2) du⊗du + 1/4*u du⊗dv
|
|
627
|
+
+ 1/4*u dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2) dv⊗dv
|
|
628
|
+
sage: g = M.metric('g')
|
|
629
|
+
sage: g.set(h)
|
|
630
|
+
sage: g.display(eU)
|
|
631
|
+
g = (x + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (-y + 1) dy⊗dy
|
|
632
|
+
sage: g.display(eV)
|
|
633
|
+
g = (1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2) du⊗du + 1/4*u du⊗dv
|
|
634
|
+
+ 1/4*u dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2) dv⊗dv
|
|
635
|
+
"""
|
|
636
|
+
if not isinstance(symbiform, TensorField):
|
|
637
|
+
raise TypeError("the argument must be a tensor field")
|
|
638
|
+
if symbiform._tensor_type != (0,2):
|
|
639
|
+
raise TypeError("the argument must be of tensor type (0,2)")
|
|
640
|
+
if symbiform._sym != ((0,1),):
|
|
641
|
+
raise TypeError("the argument must be symmetric")
|
|
642
|
+
if not symbiform._domain.is_subset(self._domain):
|
|
643
|
+
raise TypeError("the symmetric bilinear form is not defined " +
|
|
644
|
+
"on the metric domain")
|
|
645
|
+
self._del_derived()
|
|
646
|
+
self._restrictions.clear()
|
|
647
|
+
if isinstance(symbiform, TensorFieldParal):
|
|
648
|
+
rst = self.restrict(symbiform._domain)
|
|
649
|
+
rst.set(symbiform)
|
|
650
|
+
else:
|
|
651
|
+
for dom, symbiform_rst in symbiform._restrictions.items():
|
|
652
|
+
rst = self.restrict(dom)
|
|
653
|
+
rst.set(symbiform_rst)
|
|
654
|
+
|
|
655
|
+
def inverse(self, expansion_symbol=None, order=1):
|
|
656
|
+
r"""
|
|
657
|
+
Return the inverse metric.
|
|
658
|
+
|
|
659
|
+
INPUT:
|
|
660
|
+
|
|
661
|
+
- ``expansion_symbol`` -- (default: ``None``) symbolic variable; if
|
|
662
|
+
specified, the inverse will be expanded in power series with respect
|
|
663
|
+
to this variable (around its zero value)
|
|
664
|
+
- ``order`` -- integer (default: 1); the order of the expansion
|
|
665
|
+
if ``expansion_symbol`` is not ``None``; the *order* is defined as
|
|
666
|
+
the degree of the polynomial representing the truncated power series
|
|
667
|
+
in ``expansion_symbol``; currently only first order inverse is
|
|
668
|
+
supported
|
|
669
|
+
|
|
670
|
+
If ``expansion_symbol`` is set, then the zeroth order metric must be
|
|
671
|
+
invertible. Moreover, subsequent calls to this method will return
|
|
672
|
+
a cached value, even when called with the default value (to enable
|
|
673
|
+
computation of derived quantities). To reset, use :meth:`_del_derived`.
|
|
674
|
+
|
|
675
|
+
OUTPUT:
|
|
676
|
+
|
|
677
|
+
- instance of
|
|
678
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
679
|
+
with ``tensor_type`` = (2,0) representing the inverse metric
|
|
680
|
+
|
|
681
|
+
EXAMPLES:
|
|
682
|
+
|
|
683
|
+
Inverse of the standard metric on the 2-sphere::
|
|
684
|
+
|
|
685
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
686
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
687
|
+
sage: M.declare_union(U,V) # S^2 is the union of U and V
|
|
688
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() # stereographic coord.
|
|
689
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
690
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
691
|
+
....: restrictions2= u^2+v^2!=0)
|
|
692
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
693
|
+
sage: W = U.intersection(V) # the complement of the two poles
|
|
694
|
+
sage: eU = c_xy.frame() ; eV = c_uv.frame()
|
|
695
|
+
sage: g = M.metric('g')
|
|
696
|
+
sage: g[eU,1,1], g[eU,2,2] = 4/(1+x^2+y^2)^2, 4/(1+x^2+y^2)^2
|
|
697
|
+
sage: g.add_comp_by_continuation(eV, W, c_uv)
|
|
698
|
+
sage: ginv = g.inverse(); ginv
|
|
699
|
+
Tensor field inv_g of type (2,0) on the 2-dimensional differentiable manifold S^2
|
|
700
|
+
sage: ginv.display(eU)
|
|
701
|
+
inv_g = (1/4*x^4 + 1/4*y^4 + 1/2*(x^2 + 1)*y^2 + 1/2*x^2 + 1/4) ∂/∂x⊗∂/∂x
|
|
702
|
+
+ (1/4*x^4 + 1/4*y^4 + 1/2*(x^2 + 1)*y^2 + 1/2*x^2 + 1/4) ∂/∂y⊗∂/∂y
|
|
703
|
+
sage: ginv.display(eV)
|
|
704
|
+
inv_g = (1/4*u^4 + 1/4*v^4 + 1/2*(u^2 + 1)*v^2 + 1/2*u^2 + 1/4) ∂/∂u⊗∂/∂u
|
|
705
|
+
+ (1/4*u^4 + 1/4*v^4 + 1/2*(u^2 + 1)*v^2 + 1/2*u^2 + 1/4) ∂/∂v⊗∂/∂v
|
|
706
|
+
|
|
707
|
+
Let us check that ``ginv`` is indeed the inverse of ``g``::
|
|
708
|
+
|
|
709
|
+
sage: s = g.contract(ginv); s # contraction of last index of g with first index of ginv
|
|
710
|
+
Tensor field of type (1,1) on the 2-dimensional differentiable manifold S^2
|
|
711
|
+
sage: s == M.tangent_identity_field()
|
|
712
|
+
True
|
|
713
|
+
"""
|
|
714
|
+
# Is the inverse metric up to date?
|
|
715
|
+
for dom, rst in self._restrictions.items():
|
|
716
|
+
self._inverse._restrictions[dom] = rst.inverse(
|
|
717
|
+
expansion_symbol=expansion_symbol,
|
|
718
|
+
order=order) # forces the update
|
|
719
|
+
# of the restriction
|
|
720
|
+
return self._inverse
|
|
721
|
+
|
|
722
|
+
def connection(self, name=None, latex_name=None, init_coef=True):
|
|
723
|
+
r"""
|
|
724
|
+
Return the unique torsion-free affine connection compatible with
|
|
725
|
+
``self``.
|
|
726
|
+
|
|
727
|
+
This is the so-called Levi-Civita connection.
|
|
728
|
+
|
|
729
|
+
INPUT:
|
|
730
|
+
|
|
731
|
+
- ``name`` -- (default: ``None``) name given to the Levi-Civita
|
|
732
|
+
connection; if ``None``, it is formed from the metric name
|
|
733
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
734
|
+
Levi-Civita connection; if ``None``, it is set to ``name``, or if the
|
|
735
|
+
latter is None as well, it formed from the symbol `\nabla` and the
|
|
736
|
+
metric symbol
|
|
737
|
+
- ``init_coef`` -- boolean (default: ``True``); determines whether the
|
|
738
|
+
connection coefficients are initialized, as Christoffel symbols
|
|
739
|
+
in the top charts of the domain of ``self`` (i.e. disregarding
|
|
740
|
+
the subcharts)
|
|
741
|
+
|
|
742
|
+
OUTPUT:
|
|
743
|
+
|
|
744
|
+
- the Levi-Civita connection, as an instance of
|
|
745
|
+
:class:`~sage.manifolds.differentiable.levi_civita_connection.LeviCivitaConnection`
|
|
746
|
+
|
|
747
|
+
EXAMPLES:
|
|
748
|
+
|
|
749
|
+
Levi-Civita connection associated with the Euclidean metric on
|
|
750
|
+
`\RR^3`::
|
|
751
|
+
|
|
752
|
+
sage: M = Manifold(3, 'R^3', start_index=1)
|
|
753
|
+
|
|
754
|
+
Let us use spherical coordinates on `\RR^3`::
|
|
755
|
+
|
|
756
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
757
|
+
sage: c_spher.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
758
|
+
sage: g = U.metric('g')
|
|
759
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2 , (r*sin(th))^2 # the Euclidean metric
|
|
760
|
+
sage: g.connection()
|
|
761
|
+
Levi-Civita connection nabla_g associated with the Riemannian
|
|
762
|
+
metric g on the Open subset U of the 3-dimensional differentiable
|
|
763
|
+
manifold R^3
|
|
764
|
+
sage: g.connection().display() # Nonzero connection coefficients
|
|
765
|
+
Gam^r_th,th = -r
|
|
766
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
767
|
+
Gam^th_r,th = 1/r
|
|
768
|
+
Gam^th_th,r = 1/r
|
|
769
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
770
|
+
Gam^ph_r,ph = 1/r
|
|
771
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
772
|
+
Gam^ph_ph,r = 1/r
|
|
773
|
+
Gam^ph_ph,th = cos(th)/sin(th)
|
|
774
|
+
|
|
775
|
+
Test of compatibility with the metric::
|
|
776
|
+
|
|
777
|
+
sage: Dg = g.connection()(g) ; Dg
|
|
778
|
+
Tensor field nabla_g(g) of type (0,3) on the Open subset U of the
|
|
779
|
+
3-dimensional differentiable manifold R^3
|
|
780
|
+
sage: Dg == 0
|
|
781
|
+
True
|
|
782
|
+
sage: Dig = g.connection()(g.inverse()) ; Dig
|
|
783
|
+
Tensor field nabla_g(inv_g) of type (2,1) on the Open subset U of
|
|
784
|
+
the 3-dimensional differentiable manifold R^3
|
|
785
|
+
sage: Dig == 0
|
|
786
|
+
True
|
|
787
|
+
"""
|
|
788
|
+
from sage.manifolds.differentiable.levi_civita_connection import (
|
|
789
|
+
LeviCivitaConnection,
|
|
790
|
+
)
|
|
791
|
+
if self._connection is None:
|
|
792
|
+
if latex_name is None:
|
|
793
|
+
if name is None:
|
|
794
|
+
latex_name = r'\nabla_{' + self._latex_name + '}'
|
|
795
|
+
else:
|
|
796
|
+
latex_name = name
|
|
797
|
+
if name is None:
|
|
798
|
+
name = 'nabla_' + self._name
|
|
799
|
+
self._connection = LeviCivitaConnection(self, name,
|
|
800
|
+
latex_name=latex_name,
|
|
801
|
+
init_coef=init_coef)
|
|
802
|
+
return self._connection
|
|
803
|
+
|
|
804
|
+
def christoffel_symbols(self, chart=None):
|
|
805
|
+
r"""
|
|
806
|
+
Christoffel symbols of ``self`` with respect to a chart.
|
|
807
|
+
|
|
808
|
+
INPUT:
|
|
809
|
+
|
|
810
|
+
- ``chart`` -- (default: ``None``) chart with respect to which the
|
|
811
|
+
Christoffel symbols are required; if none is provided, the
|
|
812
|
+
default chart of the metric's domain is assumed.
|
|
813
|
+
|
|
814
|
+
OUTPUT:
|
|
815
|
+
|
|
816
|
+
- the set of Christoffel symbols in the given chart, as an instance of
|
|
817
|
+
:class:`~sage.tensor.modules.comp.CompWithSym`
|
|
818
|
+
|
|
819
|
+
EXAMPLES:
|
|
820
|
+
|
|
821
|
+
Christoffel symbols of the flat metric on `\RR^3` with respect to
|
|
822
|
+
spherical coordinates::
|
|
823
|
+
|
|
824
|
+
sage: M = Manifold(3, 'R3', r'\RR^3', start_index=1)
|
|
825
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
826
|
+
sage: X.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
827
|
+
sage: g = U.metric('g')
|
|
828
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2, r^2*sin(th)^2
|
|
829
|
+
sage: g.display() # the standard flat metric expressed in spherical coordinates
|
|
830
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
831
|
+
sage: Gam = g.christoffel_symbols() ; Gam
|
|
832
|
+
3-indices components w.r.t. Coordinate frame (U, (∂/∂r,∂/∂th,∂/∂ph)),
|
|
833
|
+
with symmetry on the index positions (1, 2)
|
|
834
|
+
sage: type(Gam)
|
|
835
|
+
<class 'sage.tensor.modules.comp.CompWithSym'>
|
|
836
|
+
sage: Gam[:]
|
|
837
|
+
[[[0, 0, 0], [0, -r, 0], [0, 0, -r*sin(th)^2]],
|
|
838
|
+
[[0, 1/r, 0], [1/r, 0, 0], [0, 0, -cos(th)*sin(th)]],
|
|
839
|
+
[[0, 0, 1/r], [0, 0, cos(th)/sin(th)], [1/r, cos(th)/sin(th), 0]]]
|
|
840
|
+
sage: Gam[1,2,2]
|
|
841
|
+
-r
|
|
842
|
+
sage: Gam[2,1,2]
|
|
843
|
+
1/r
|
|
844
|
+
sage: Gam[3,1,3]
|
|
845
|
+
1/r
|
|
846
|
+
sage: Gam[3,2,3]
|
|
847
|
+
cos(th)/sin(th)
|
|
848
|
+
sage: Gam[2,3,3]
|
|
849
|
+
-cos(th)*sin(th)
|
|
850
|
+
|
|
851
|
+
Note that a better display of the Christoffel symbols is provided by
|
|
852
|
+
the method :meth:`christoffel_symbols_display`::
|
|
853
|
+
|
|
854
|
+
sage: g.christoffel_symbols_display()
|
|
855
|
+
Gam^r_th,th = -r
|
|
856
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
857
|
+
Gam^th_r,th = 1/r
|
|
858
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
859
|
+
Gam^ph_r,ph = 1/r
|
|
860
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
861
|
+
"""
|
|
862
|
+
if chart is None:
|
|
863
|
+
frame = self._domain._def_chart._frame
|
|
864
|
+
else:
|
|
865
|
+
frame = chart._frame
|
|
866
|
+
return self.connection().coef(frame)
|
|
867
|
+
|
|
868
|
+
def christoffel_symbols_display(self, chart=None, symbol=None,
|
|
869
|
+
latex_symbol=None, index_labels=None, index_latex_labels=None,
|
|
870
|
+
coordinate_labels=True, only_nonzero=True,
|
|
871
|
+
only_nonredundant=True):
|
|
872
|
+
r"""
|
|
873
|
+
Display the Christoffel symbols w.r.t. to a given chart, one
|
|
874
|
+
per line.
|
|
875
|
+
|
|
876
|
+
The output is either text-formatted (console mode) or LaTeX-formatted
|
|
877
|
+
(notebook mode).
|
|
878
|
+
|
|
879
|
+
INPUT:
|
|
880
|
+
|
|
881
|
+
- ``chart`` -- (default: ``None``) chart with respect to which the
|
|
882
|
+
Christoffel symbols are defined; if none is provided, the
|
|
883
|
+
default chart of the metric's domain is assumed.
|
|
884
|
+
- ``symbol`` -- (default: ``None``) string specifying the
|
|
885
|
+
symbol of the connection coefficients; if ``None``, 'Gam' is used
|
|
886
|
+
- ``latex_symbol`` -- (default: ``None``) string specifying the LaTeX
|
|
887
|
+
symbol for the components; if ``None``, '\\Gamma' is used
|
|
888
|
+
- ``index_labels`` -- (default: ``None``) list of strings representing
|
|
889
|
+
the labels of each index; if ``None``, coordinate symbols are used
|
|
890
|
+
except if ``coordinate_symbols`` is set to ``False``, in which case
|
|
891
|
+
integer labels are used
|
|
892
|
+
- ``index_latex_labels`` -- (default: ``None``) list of strings
|
|
893
|
+
representing the LaTeX labels of each index; if ``None``, coordinate
|
|
894
|
+
LaTeX symbols are used, except if ``coordinate_symbols`` is set to
|
|
895
|
+
``False``, in which case integer labels are used
|
|
896
|
+
- ``coordinate_labels`` -- boolean (default: ``True``); if ``True``,
|
|
897
|
+
coordinate symbols are used by default (instead of integers)
|
|
898
|
+
- ``only_nonzero`` -- boolean (default: ``True``); if ``True``, only
|
|
899
|
+
nonzero connection coefficients are displayed
|
|
900
|
+
- ``only_nonredundant`` -- boolean (default: ``True``); if ``True``,
|
|
901
|
+
only nonredundant (w.r.t. the symmetry of the last two indices)
|
|
902
|
+
connection coefficients are displayed
|
|
903
|
+
|
|
904
|
+
EXAMPLES:
|
|
905
|
+
|
|
906
|
+
Christoffel symbols of the flat metric on `\RR^3` with respect to
|
|
907
|
+
spherical coordinates::
|
|
908
|
+
|
|
909
|
+
sage: M = Manifold(3, 'R3', r'\RR^3', start_index=1)
|
|
910
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
911
|
+
sage: X.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
912
|
+
sage: g = U.metric('g')
|
|
913
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2, r^2*sin(th)^2
|
|
914
|
+
sage: g.display() # the standard flat metric expressed in spherical coordinates
|
|
915
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
916
|
+
sage: g.christoffel_symbols_display()
|
|
917
|
+
Gam^r_th,th = -r
|
|
918
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
919
|
+
Gam^th_r,th = 1/r
|
|
920
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
921
|
+
Gam^ph_r,ph = 1/r
|
|
922
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
923
|
+
|
|
924
|
+
To list all nonzero Christoffel symbols, including those that can be
|
|
925
|
+
deduced by symmetry, use ``only_nonredundant=False``::
|
|
926
|
+
|
|
927
|
+
sage: g.christoffel_symbols_display(only_nonredundant=False)
|
|
928
|
+
Gam^r_th,th = -r
|
|
929
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
930
|
+
Gam^th_r,th = 1/r
|
|
931
|
+
Gam^th_th,r = 1/r
|
|
932
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
933
|
+
Gam^ph_r,ph = 1/r
|
|
934
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
935
|
+
Gam^ph_ph,r = 1/r
|
|
936
|
+
Gam^ph_ph,th = cos(th)/sin(th)
|
|
937
|
+
|
|
938
|
+
Listing all Christoffel symbols (except those that can be deduced by
|
|
939
|
+
symmetry), including the vanishing one::
|
|
940
|
+
|
|
941
|
+
sage: g.christoffel_symbols_display(only_nonzero=False)
|
|
942
|
+
Gam^r_r,r = 0
|
|
943
|
+
Gam^r_r,th = 0
|
|
944
|
+
Gam^r_r,ph = 0
|
|
945
|
+
Gam^r_th,th = -r
|
|
946
|
+
Gam^r_th,ph = 0
|
|
947
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
948
|
+
Gam^th_r,r = 0
|
|
949
|
+
Gam^th_r,th = 1/r
|
|
950
|
+
Gam^th_r,ph = 0
|
|
951
|
+
Gam^th_th,th = 0
|
|
952
|
+
Gam^th_th,ph = 0
|
|
953
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
954
|
+
Gam^ph_r,r = 0
|
|
955
|
+
Gam^ph_r,th = 0
|
|
956
|
+
Gam^ph_r,ph = 1/r
|
|
957
|
+
Gam^ph_th,th = 0
|
|
958
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
959
|
+
Gam^ph_ph,ph = 0
|
|
960
|
+
|
|
961
|
+
Using integer labels::
|
|
962
|
+
|
|
963
|
+
sage: g.christoffel_symbols_display(coordinate_labels=False)
|
|
964
|
+
Gam^1_22 = -r
|
|
965
|
+
Gam^1_33 = -r*sin(th)^2
|
|
966
|
+
Gam^2_12 = 1/r
|
|
967
|
+
Gam^2_33 = -cos(th)*sin(th)
|
|
968
|
+
Gam^3_13 = 1/r
|
|
969
|
+
Gam^3_23 = cos(th)/sin(th)
|
|
970
|
+
"""
|
|
971
|
+
if chart is None:
|
|
972
|
+
chart = self._domain.default_chart()
|
|
973
|
+
return self.connection().display(frame=chart.frame(), chart=chart,
|
|
974
|
+
symbol=symbol, latex_symbol=latex_symbol,
|
|
975
|
+
index_labels=index_labels, index_latex_labels=index_latex_labels,
|
|
976
|
+
coordinate_labels=coordinate_labels, only_nonzero=only_nonzero,
|
|
977
|
+
only_nonredundant=only_nonredundant)
|
|
978
|
+
|
|
979
|
+
def riemann(self, name=None, latex_name=None):
|
|
980
|
+
r"""
|
|
981
|
+
Return the Riemann curvature tensor associated with the metric.
|
|
982
|
+
|
|
983
|
+
This method is actually a shortcut for ``self.connection().riemann()``
|
|
984
|
+
|
|
985
|
+
The Riemann curvature tensor is the tensor field `R` of type (1,3)
|
|
986
|
+
defined by
|
|
987
|
+
|
|
988
|
+
.. MATH::
|
|
989
|
+
|
|
990
|
+
R(\omega, u, v, w) = \left\langle \omega, \nabla_u \nabla_v w
|
|
991
|
+
- \nabla_v \nabla_u w - \nabla_{[u, v]} w \right\rangle
|
|
992
|
+
|
|
993
|
+
for any 1-form `\omega` and any vector fields `u`, `v` and `w`.
|
|
994
|
+
|
|
995
|
+
INPUT:
|
|
996
|
+
|
|
997
|
+
- ``name`` -- (default: ``None``) name given to the Riemann tensor;
|
|
998
|
+
if none, it is set to "Riem(g)", where "g" is the metric's name
|
|
999
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1000
|
+
Riemann tensor; if none, it is set to "\\mathrm{Riem}(g)", where "g"
|
|
1001
|
+
is the metric's name
|
|
1002
|
+
|
|
1003
|
+
OUTPUT:
|
|
1004
|
+
|
|
1005
|
+
- the Riemann curvature tensor `R`, as an instance of
|
|
1006
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
1007
|
+
|
|
1008
|
+
EXAMPLES:
|
|
1009
|
+
|
|
1010
|
+
Riemann tensor of the standard metric on the 2-sphere::
|
|
1011
|
+
|
|
1012
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
1013
|
+
sage: U = M.open_subset('U') # the complement of a meridian (domain of spherical coordinates)
|
|
1014
|
+
sage: c_spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1015
|
+
sage: a = var('a') # the sphere radius
|
|
1016
|
+
sage: g = U.metric('g')
|
|
1017
|
+
sage: g[1,1], g[2,2] = a^2, a^2*sin(th)^2
|
|
1018
|
+
sage: g.display() # standard metric on the 2-sphere of radius a:
|
|
1019
|
+
g = a^2 dth⊗dth + a^2*sin(th)^2 dph⊗dph
|
|
1020
|
+
sage: g.riemann()
|
|
1021
|
+
Tensor field Riem(g) of type (1,3) on the Open subset U of the
|
|
1022
|
+
2-dimensional differentiable manifold S^2
|
|
1023
|
+
sage: g.riemann()[:]
|
|
1024
|
+
[[[[0, 0], [0, 0]], [[0, sin(th)^2], [-sin(th)^2, 0]]],
|
|
1025
|
+
[[[0, -1], [1, 0]], [[0, 0], [0, 0]]]]
|
|
1026
|
+
|
|
1027
|
+
In dimension 2, the Riemann tensor can be expressed entirely in terms of
|
|
1028
|
+
the Ricci scalar `r`:
|
|
1029
|
+
|
|
1030
|
+
.. MATH::
|
|
1031
|
+
|
|
1032
|
+
R^i_{\ \, jlk} = \frac{r}{2} \left( \delta^i_{\ \, k} g_{jl}
|
|
1033
|
+
- \delta^i_{\ \, l} g_{jk} \right)
|
|
1034
|
+
|
|
1035
|
+
This formula can be checked here, with the r.h.s. rewritten as
|
|
1036
|
+
`-r g_{j[k} \delta^i_{\ \, l]}`::
|
|
1037
|
+
|
|
1038
|
+
sage: g.riemann() == \
|
|
1039
|
+
....: -g.ricci_scalar()*(g*U.tangent_identity_field()).antisymmetrize(2,3)
|
|
1040
|
+
True
|
|
1041
|
+
|
|
1042
|
+
Using SymPy as symbolic engine::
|
|
1043
|
+
|
|
1044
|
+
sage: M.set_calculus_method('sympy')
|
|
1045
|
+
sage: g = U.metric('g')
|
|
1046
|
+
sage: g[1,1], g[2,2] = a**2, a**2*sin(th)**2
|
|
1047
|
+
sage: g.riemann()[:]
|
|
1048
|
+
[[[[0, 0], [0, 0]],
|
|
1049
|
+
[[0, sin(2*th)/(2*tan(th)) - cos(2*th)],
|
|
1050
|
+
[-sin(2*th)/(2*tan(th)) + cos(2*th), 0]]],
|
|
1051
|
+
[[[0, -1], [1, 0]], [[0, 0], [0, 0]]]]
|
|
1052
|
+
"""
|
|
1053
|
+
return self.connection().riemann(name, latex_name)
|
|
1054
|
+
|
|
1055
|
+
def ricci(self, name=None, latex_name=None):
|
|
1056
|
+
r"""
|
|
1057
|
+
Return the Ricci tensor associated with the metric.
|
|
1058
|
+
|
|
1059
|
+
This method is actually a shortcut for ``self.connection().ricci()``
|
|
1060
|
+
|
|
1061
|
+
The Ricci tensor is the tensor field `Ric` of type (0,2)
|
|
1062
|
+
defined from the Riemann curvature tensor `R` by
|
|
1063
|
+
|
|
1064
|
+
.. MATH::
|
|
1065
|
+
|
|
1066
|
+
Ric(u, v) = R(e^i, u, e_i, v)
|
|
1067
|
+
|
|
1068
|
+
for any vector fields `u` and `v`, `(e_i)` being any vector frame and
|
|
1069
|
+
`(e^i)` the dual coframe.
|
|
1070
|
+
|
|
1071
|
+
INPUT:
|
|
1072
|
+
|
|
1073
|
+
- ``name`` -- (default: ``None``) name given to the Ricci tensor;
|
|
1074
|
+
if none, it is set to "Ric(g)", where "g" is the metric's name
|
|
1075
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1076
|
+
Ricci tensor; if none, it is set to "\\mathrm{Ric}(g)", where "g"
|
|
1077
|
+
is the metric's name
|
|
1078
|
+
|
|
1079
|
+
OUTPUT:
|
|
1080
|
+
|
|
1081
|
+
- the Ricci tensor `Ric`, as an instance of
|
|
1082
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField` of tensor
|
|
1083
|
+
type (0,2) and symmetric
|
|
1084
|
+
|
|
1085
|
+
EXAMPLES:
|
|
1086
|
+
|
|
1087
|
+
Ricci tensor of the standard metric on the 2-sphere::
|
|
1088
|
+
|
|
1089
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
1090
|
+
sage: U = M.open_subset('U') # the complement of a meridian (domain of spherical coordinates)
|
|
1091
|
+
sage: c_spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1092
|
+
sage: a = var('a') # the sphere radius
|
|
1093
|
+
sage: g = U.metric('g')
|
|
1094
|
+
sage: g[1,1], g[2,2] = a^2, a^2*sin(th)^2
|
|
1095
|
+
sage: g.display() # standard metric on the 2-sphere of radius a:
|
|
1096
|
+
g = a^2 dth⊗dth + a^2*sin(th)^2 dph⊗dph
|
|
1097
|
+
sage: g.ricci()
|
|
1098
|
+
Field of symmetric bilinear forms Ric(g) on the Open subset U of
|
|
1099
|
+
the 2-dimensional differentiable manifold S^2
|
|
1100
|
+
sage: g.ricci()[:]
|
|
1101
|
+
[ 1 0]
|
|
1102
|
+
[ 0 sin(th)^2]
|
|
1103
|
+
sage: g.ricci() == a^(-2) * g
|
|
1104
|
+
True
|
|
1105
|
+
"""
|
|
1106
|
+
return self.connection().ricci(name, latex_name)
|
|
1107
|
+
|
|
1108
|
+
def ricci_scalar(self, name=None, latex_name=None):
|
|
1109
|
+
r"""
|
|
1110
|
+
Return the Ricci scalar associated with the metric.
|
|
1111
|
+
|
|
1112
|
+
The Ricci scalar is the scalar field `r` defined from the Ricci tensor
|
|
1113
|
+
`Ric` and the metric tensor `g` by
|
|
1114
|
+
|
|
1115
|
+
.. MATH::
|
|
1116
|
+
|
|
1117
|
+
r = g^{ij} Ric_{ij}
|
|
1118
|
+
|
|
1119
|
+
INPUT:
|
|
1120
|
+
|
|
1121
|
+
- ``name`` -- (default: ``None``) name given to the Ricci scalar;
|
|
1122
|
+
if none, it is set to "r(g)", where "g" is the metric's name
|
|
1123
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1124
|
+
Ricci scalar; if none, it is set to "\\mathrm{r}(g)", where "g"
|
|
1125
|
+
is the metric's name
|
|
1126
|
+
|
|
1127
|
+
OUTPUT:
|
|
1128
|
+
|
|
1129
|
+
- the Ricci scalar `r`, as an instance of
|
|
1130
|
+
:class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES:
|
|
1133
|
+
|
|
1134
|
+
Ricci scalar of the standard metric on the 2-sphere::
|
|
1135
|
+
|
|
1136
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
1137
|
+
sage: U = M.open_subset('U') # the complement of a meridian (domain of spherical coordinates)
|
|
1138
|
+
sage: c_spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1139
|
+
sage: a = var('a') # the sphere radius
|
|
1140
|
+
sage: g = U.metric('g')
|
|
1141
|
+
sage: g[1,1], g[2,2] = a^2, a^2*sin(th)^2
|
|
1142
|
+
sage: g.display() # standard metric on the 2-sphere of radius a:
|
|
1143
|
+
g = a^2 dth⊗dth + a^2*sin(th)^2 dph⊗dph
|
|
1144
|
+
sage: g.ricci_scalar()
|
|
1145
|
+
Scalar field r(g) on the Open subset U of the 2-dimensional
|
|
1146
|
+
differentiable manifold S^2
|
|
1147
|
+
sage: g.ricci_scalar().display() # The Ricci scalar is constant:
|
|
1148
|
+
r(g): U → ℝ
|
|
1149
|
+
(th, ph) ↦ 2/a^2
|
|
1150
|
+
|
|
1151
|
+
"""
|
|
1152
|
+
if self._ricci_scalar is None:
|
|
1153
|
+
resu = self.inverse().contract(0, 1, self.ricci(), 0, 1)
|
|
1154
|
+
if name is None:
|
|
1155
|
+
name = "r(" + self._name + ")"
|
|
1156
|
+
if latex_name is None:
|
|
1157
|
+
latex_name = r"\mathrm{r}\left(" + self._latex_name + \
|
|
1158
|
+
r"\right)"
|
|
1159
|
+
resu._name = name
|
|
1160
|
+
resu._latex_name = latex_name
|
|
1161
|
+
self._ricci_scalar = resu
|
|
1162
|
+
return self._ricci_scalar
|
|
1163
|
+
|
|
1164
|
+
def weyl(self, name=None, latex_name=None):
|
|
1165
|
+
r"""
|
|
1166
|
+
Return the Weyl conformal tensor associated with the metric.
|
|
1167
|
+
|
|
1168
|
+
The Weyl conformal tensor is the tensor field `C` of type (1,3)
|
|
1169
|
+
defined as the trace-free part of the Riemann curvature tensor `R`
|
|
1170
|
+
|
|
1171
|
+
INPUT:
|
|
1172
|
+
|
|
1173
|
+
- ``name`` -- (default: ``None``) name given to the Weyl conformal
|
|
1174
|
+
tensor; if ``None``, it is set to "C(g)", where "g" is the metric's
|
|
1175
|
+
name
|
|
1176
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1177
|
+
Weyl conformal tensor; if ``None``, it is set to "\\mathrm{C}(g)",
|
|
1178
|
+
where "g" is the metric's name
|
|
1179
|
+
|
|
1180
|
+
OUTPUT:
|
|
1181
|
+
|
|
1182
|
+
- the Weyl conformal tensor `C`, as an instance of
|
|
1183
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
1184
|
+
|
|
1185
|
+
EXAMPLES:
|
|
1186
|
+
|
|
1187
|
+
Checking that the Weyl tensor identically vanishes on a 3-dimensional
|
|
1188
|
+
manifold, for instance the hyperbolic space `H^3`::
|
|
1189
|
+
|
|
1190
|
+
sage: M = Manifold(3, 'H^3', start_index=1)
|
|
1191
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
1192
|
+
sage: X.<rh,th,ph> = U.chart(r'rh:(0,+oo):\rho th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1193
|
+
sage: g = U.metric('g')
|
|
1194
|
+
sage: b = var('b')
|
|
1195
|
+
sage: g[1,1], g[2,2], g[3,3] = b^2, (b*sinh(rh))^2, (b*sinh(rh)*sin(th))^2
|
|
1196
|
+
sage: g.display() # standard metric on H^3:
|
|
1197
|
+
g = b^2 drh⊗drh + b^2*sinh(rh)^2 dth⊗dth
|
|
1198
|
+
+ b^2*sin(th)^2*sinh(rh)^2 dph⊗dph
|
|
1199
|
+
sage: C = g.weyl() ; C
|
|
1200
|
+
Tensor field C(g) of type (1,3) on the Open subset U of the
|
|
1201
|
+
3-dimensional differentiable manifold H^3
|
|
1202
|
+
sage: C == 0
|
|
1203
|
+
True
|
|
1204
|
+
"""
|
|
1205
|
+
if self._weyl is None:
|
|
1206
|
+
n = self._ambient_domain.dimension()
|
|
1207
|
+
if n < 3:
|
|
1208
|
+
raise ValueError("the Weyl tensor is not defined for a " +
|
|
1209
|
+
"manifold of dimension n <= 2")
|
|
1210
|
+
delta = self._domain.tangent_identity_field(dest_map=self._vmodule._dest_map)
|
|
1211
|
+
riem = self.riemann()
|
|
1212
|
+
ric = self.ricci()
|
|
1213
|
+
rscal = self.ricci_scalar()
|
|
1214
|
+
# First index of the Ricci tensor raised with the metric
|
|
1215
|
+
ricup = ric.up(self, 0)
|
|
1216
|
+
aux = self*ricup + ric*delta - rscal/(n-1) * self*delta
|
|
1217
|
+
self._weyl = riem + 2/(n-2) * aux.antisymmetrize(2,3)
|
|
1218
|
+
if name is None:
|
|
1219
|
+
name = "C(" + self._name + ")"
|
|
1220
|
+
if latex_name is None:
|
|
1221
|
+
latex_name = r"\mathrm{C}\left(" + self._latex_name + r"\right)"
|
|
1222
|
+
self._weyl.set_name(name=name, latex_name=latex_name)
|
|
1223
|
+
return self._weyl
|
|
1224
|
+
|
|
1225
|
+
def schouten(self, name=None, latex_name=None):
|
|
1226
|
+
r"""
|
|
1227
|
+
Return the Schouten tensor associated with the metric.
|
|
1228
|
+
|
|
1229
|
+
The Schouten tensor is the tensor field `Sc` of type (0,2) defined
|
|
1230
|
+
from the Ricci curvature tensor `Ric` (see :meth:`ricci`) and the
|
|
1231
|
+
scalar curvature `r` (see :meth:`ricci_scalar`) and the metric `g` by
|
|
1232
|
+
|
|
1233
|
+
.. MATH::
|
|
1234
|
+
|
|
1235
|
+
Sc(u, v) = \frac{1}{n-2}\left(Ric(u, v) + \frac{r}{2(n-1)}g(u,v)
|
|
1236
|
+
\right)
|
|
1237
|
+
|
|
1238
|
+
for any vector fields `u` and `v`.
|
|
1239
|
+
|
|
1240
|
+
INPUT:
|
|
1241
|
+
|
|
1242
|
+
- ``name`` -- (default: ``None``) name given to the Schouten tensor;
|
|
1243
|
+
if none, it is set to "Schouten(g)", where "g" is the metric's name
|
|
1244
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1245
|
+
Schouten tensor; if none, it is set to "\\mathrm{Schouten}(g)",
|
|
1246
|
+
where "g" is the metric's name
|
|
1247
|
+
|
|
1248
|
+
OUTPUT:
|
|
1249
|
+
|
|
1250
|
+
- the Schouten tensor `Sc`, as an instance of
|
|
1251
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField` of tensor
|
|
1252
|
+
type (0,2) and symmetric
|
|
1253
|
+
|
|
1254
|
+
EXAMPLES:
|
|
1255
|
+
|
|
1256
|
+
Schouten tensor of the left invariant metric of Heisenberg's
|
|
1257
|
+
Nil group::
|
|
1258
|
+
|
|
1259
|
+
sage: M = Manifold(3, 'Nil', start_index=1)
|
|
1260
|
+
sage: X.<x,y,z> = M.chart()
|
|
1261
|
+
sage: g = M.riemannian_metric('g')
|
|
1262
|
+
sage: g[1,1], g[2,2], g[2,3], g[3,3] = 1, 1+x^2, -x, 1
|
|
1263
|
+
sage: g.display()
|
|
1264
|
+
g = dx⊗dx + (x^2 + 1) dy⊗dy - x dy⊗dz - x dz⊗dy + dz⊗dz
|
|
1265
|
+
sage: g.schouten()
|
|
1266
|
+
Field of symmetric bilinear forms Schouten(g) on the 3-dimensional
|
|
1267
|
+
differentiable manifold Nil
|
|
1268
|
+
sage: g.schouten().display()
|
|
1269
|
+
Schouten(g) = -3/8 dx⊗dx + (5/8*x^2 - 3/8) dy⊗dy - 5/8*x dy⊗dz
|
|
1270
|
+
- 5/8*x dz⊗dy + 5/8 dz⊗dz
|
|
1271
|
+
"""
|
|
1272
|
+
n = self._ambient_domain.dimension()
|
|
1273
|
+
if n < 3:
|
|
1274
|
+
raise ValueError("the Schouten tensor is only defined for a " +
|
|
1275
|
+
"manifold of dimension >= 3")
|
|
1276
|
+
if self._schouten is None:
|
|
1277
|
+
s = (1/(n-2))*self.ricci() - (self.ricci_scalar()/(2*(n-1)*(n-2)))*self
|
|
1278
|
+
name = name or 'Schouten(' + self._name + ')'
|
|
1279
|
+
latex_name = latex_name or r'\mathrm{Schouten}(' + self._latex_name + ')'
|
|
1280
|
+
s.set_name(name=name, latex_name=latex_name)
|
|
1281
|
+
self._schouten = s
|
|
1282
|
+
return self._schouten
|
|
1283
|
+
|
|
1284
|
+
def cotton(self, name=None, latex_name=None):
|
|
1285
|
+
r"""
|
|
1286
|
+
Return the Cotton conformal tensor associated with the metric.
|
|
1287
|
+
The tensor has type (0,3) and is defined in terms of the Schouten
|
|
1288
|
+
tensor `S` (see :meth:`schouten`):
|
|
1289
|
+
|
|
1290
|
+
.. MATH::
|
|
1291
|
+
|
|
1292
|
+
C_{ijk} = (n-2) \left(\nabla_k S_{ij}
|
|
1293
|
+
- \nabla_j S_{ik}\right)
|
|
1294
|
+
|
|
1295
|
+
INPUT:
|
|
1296
|
+
|
|
1297
|
+
- ``name`` -- (default: ``None``) name given to the Cotton conformal
|
|
1298
|
+
tensor; if ``None``, it is set to "Cot(g)", where "g" is the metric's
|
|
1299
|
+
name
|
|
1300
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1301
|
+
Cotton conformal tensor; if ``None``, it is set to "\\mathrm{Cot}(g)",
|
|
1302
|
+
where "g" is the metric's name
|
|
1303
|
+
|
|
1304
|
+
OUTPUT:
|
|
1305
|
+
|
|
1306
|
+
- the Cotton conformal tensor `Cot`, as an instance of
|
|
1307
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
1308
|
+
|
|
1309
|
+
EXAMPLES:
|
|
1310
|
+
|
|
1311
|
+
Checking that the Cotton tensor identically vanishes on a conformally flat
|
|
1312
|
+
3-dimensional manifold, for instance the hyperbolic space `H^3`::
|
|
1313
|
+
|
|
1314
|
+
sage: M = Manifold(3, 'H^3', start_index=1)
|
|
1315
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
1316
|
+
sage: X.<rh,th,ph> = U.chart(r'rh:(0,+oo):\rho th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1317
|
+
sage: g = U.metric('g')
|
|
1318
|
+
sage: b = var('b')
|
|
1319
|
+
sage: g[1,1], g[2,2], g[3,3] = b^2, (b*sinh(rh))^2, (b*sinh(rh)*sin(th))^2
|
|
1320
|
+
sage: g.display() # standard metric on H^3:
|
|
1321
|
+
g = b^2 drh⊗drh + b^2*sinh(rh)^2 dth⊗dth
|
|
1322
|
+
+ b^2*sin(th)^2*sinh(rh)^2 dph⊗dph
|
|
1323
|
+
sage: Cot = g.cotton() ; Cot # long time
|
|
1324
|
+
Tensor field Cot(g) of type (0,3) on the Open subset U of the
|
|
1325
|
+
3-dimensional differentiable manifold H^3
|
|
1326
|
+
sage: Cot == 0 # long time
|
|
1327
|
+
True
|
|
1328
|
+
"""
|
|
1329
|
+
n = self._ambient_domain.dimension()
|
|
1330
|
+
if n < 3:
|
|
1331
|
+
raise ValueError("the Cotton tensor is only defined for a " +
|
|
1332
|
+
"manifold of dimension >= 3")
|
|
1333
|
+
if self._cotton is None:
|
|
1334
|
+
nabla = self.connection()
|
|
1335
|
+
s = self.schouten()
|
|
1336
|
+
cot = 2*(n-2)*nabla(s).antisymmetrize(1,2)
|
|
1337
|
+
name = name or 'Cot(' + self._name + ')'
|
|
1338
|
+
latex_name = latex_name or r'\mathrm{Cot}(' + self._latex_name + ')'
|
|
1339
|
+
cot.set_name(name=name, latex_name=latex_name)
|
|
1340
|
+
self._cotton = cot
|
|
1341
|
+
return self._cotton
|
|
1342
|
+
|
|
1343
|
+
def cotton_york(self, name=None, latex_name=None):
|
|
1344
|
+
r"""
|
|
1345
|
+
Return the Cotton-York conformal tensor associated with the metric.
|
|
1346
|
+
The tensor has type (0,2) and is only defined for manifolds of
|
|
1347
|
+
dimension 3. It is defined in terms of the Cotton tensor `C`
|
|
1348
|
+
(see :meth:`cotton`) or the Schouten tensor `S` (see :meth:`schouten`):
|
|
1349
|
+
|
|
1350
|
+
.. MATH::
|
|
1351
|
+
|
|
1352
|
+
CY_{ij} = \frac{1}{2} \epsilon^{kl}_{\ \ \, i} C_{jlk}
|
|
1353
|
+
= \epsilon^{kl}_{\ \ \, i} \nabla_k S_{lj}
|
|
1354
|
+
|
|
1355
|
+
INPUT:
|
|
1356
|
+
|
|
1357
|
+
- ``name`` -- (default: ``None``) name given to the Cotton-York
|
|
1358
|
+
tensor; if ``None``, it is set to "CY(g)", where "g" is the metric's
|
|
1359
|
+
name
|
|
1360
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1361
|
+
Cotton-York tensor; if ``None``, it is set to "\\mathrm{CY}(g)",
|
|
1362
|
+
where "g" is the metric's name
|
|
1363
|
+
|
|
1364
|
+
OUTPUT:
|
|
1365
|
+
|
|
1366
|
+
- the Cotton-York conformal tensor `CY`, as an instance of
|
|
1367
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
1368
|
+
|
|
1369
|
+
EXAMPLES:
|
|
1370
|
+
|
|
1371
|
+
Compute the determinant of the Cotton-York tensor for the Heisenberg
|
|
1372
|
+
group with the left invariant metric::
|
|
1373
|
+
|
|
1374
|
+
sage: M = Manifold(3, 'Nil', start_index=1)
|
|
1375
|
+
sage: X.<x,y,z> = M.chart()
|
|
1376
|
+
sage: g = M.riemannian_metric('g')
|
|
1377
|
+
sage: g[1,1], g[2,2], g[2,3], g[3,3] = 1, 1+x^2, -x, 1
|
|
1378
|
+
sage: g.display()
|
|
1379
|
+
g = dx⊗dx + (x^2 + 1) dy⊗dy - x dy⊗dz - x dz⊗dy + dz⊗dz
|
|
1380
|
+
sage: CY = g.cotton_york() ; CY # long time
|
|
1381
|
+
Tensor field CY(g) of type (0,2) on the 3-dimensional
|
|
1382
|
+
differentiable manifold Nil
|
|
1383
|
+
sage: CY.display() # long time
|
|
1384
|
+
CY(g) = 1/2 dx⊗dx + (-x^2 + 1/2) dy⊗dy + x dy⊗dz + x dz⊗dy - dz⊗dz
|
|
1385
|
+
sage: det(CY[:]) # long time
|
|
1386
|
+
-1/4
|
|
1387
|
+
"""
|
|
1388
|
+
n = self._ambient_domain.dimension()
|
|
1389
|
+
if n != 3:
|
|
1390
|
+
raise ValueError("the Cotton-York tensor is only defined for a " +
|
|
1391
|
+
"manifold of dimension 3")
|
|
1392
|
+
if self._cotton_york is None:
|
|
1393
|
+
cot = self.cotton()
|
|
1394
|
+
eps = self.volume_form(2)
|
|
1395
|
+
cy = eps.contract(0, 1, cot, 2, 1)/2
|
|
1396
|
+
name = name or 'CY(' + self._name + ')'
|
|
1397
|
+
latex_name = latex_name or r'\mathrm{CY}(' + self._latex_name + ')'
|
|
1398
|
+
cy.set_name(name=name, latex_name=latex_name)
|
|
1399
|
+
self._cotton_york = cy
|
|
1400
|
+
return self._cotton_york
|
|
1401
|
+
|
|
1402
|
+
def determinant(self, frame=None):
|
|
1403
|
+
r"""
|
|
1404
|
+
Determinant of the metric components in the specified frame.
|
|
1405
|
+
|
|
1406
|
+
INPUT:
|
|
1407
|
+
|
|
1408
|
+
- ``frame`` -- (default: ``None``) vector frame with
|
|
1409
|
+
respect to which the components `g_{ij}` of the metric are defined;
|
|
1410
|
+
if ``None``, the default frame of the metric's domain is used. If a
|
|
1411
|
+
chart is provided instead of a frame, the associated coordinate
|
|
1412
|
+
frame is used
|
|
1413
|
+
|
|
1414
|
+
OUTPUT:
|
|
1415
|
+
|
|
1416
|
+
- the determinant `\det (g_{ij})`, as an instance of
|
|
1417
|
+
:class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES:
|
|
1420
|
+
|
|
1421
|
+
Metric determinant on a 2-dimensional manifold::
|
|
1422
|
+
|
|
1423
|
+
sage: M = Manifold(2, 'M', start_index=1)
|
|
1424
|
+
sage: X.<x,y> = M.chart()
|
|
1425
|
+
sage: g = M.metric('g')
|
|
1426
|
+
sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
|
|
1427
|
+
sage: g[:]
|
|
1428
|
+
[ x + 1 x*y]
|
|
1429
|
+
[ x*y -y + 1]
|
|
1430
|
+
sage: s = g.determinant() # determinant in M's default frame
|
|
1431
|
+
sage: s.expr()
|
|
1432
|
+
-x^2*y^2 - (x + 1)*y + x + 1
|
|
1433
|
+
|
|
1434
|
+
A shortcut is ``det()``::
|
|
1435
|
+
|
|
1436
|
+
sage: g.det() == g.determinant()
|
|
1437
|
+
True
|
|
1438
|
+
|
|
1439
|
+
The notation ``det(g)`` can be used::
|
|
1440
|
+
|
|
1441
|
+
sage: det(g) == g.determinant()
|
|
1442
|
+
True
|
|
1443
|
+
|
|
1444
|
+
Determinant in a frame different from the default's one::
|
|
1445
|
+
|
|
1446
|
+
sage: Y.<u,v> = M.chart()
|
|
1447
|
+
sage: ch_X_Y = X.transition_map(Y, [x+y, x-y])
|
|
1448
|
+
sage: ch_X_Y.inverse()
|
|
1449
|
+
Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y))
|
|
1450
|
+
sage: g.comp(Y.frame())[:, Y]
|
|
1451
|
+
[ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2 1/4*u]
|
|
1452
|
+
[ 1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
|
|
1453
|
+
sage: g.determinant(Y.frame()).expr()
|
|
1454
|
+
-1/4*x^2*y^2 - 1/4*(x + 1)*y + 1/4*x + 1/4
|
|
1455
|
+
sage: g.determinant(Y.frame()).expr(Y)
|
|
1456
|
+
-1/64*u^4 - 1/64*v^4 + 1/32*(u^2 + 2)*v^2 - 1/16*u^2 + 1/4*v + 1/4
|
|
1457
|
+
|
|
1458
|
+
A chart can be passed instead of a frame::
|
|
1459
|
+
|
|
1460
|
+
sage: g.determinant(X) is g.determinant(X.frame())
|
|
1461
|
+
True
|
|
1462
|
+
sage: g.determinant(Y) is g.determinant(Y.frame())
|
|
1463
|
+
True
|
|
1464
|
+
|
|
1465
|
+
The metric determinant depends on the frame::
|
|
1466
|
+
|
|
1467
|
+
sage: g.determinant(X.frame()) == g.determinant(Y.frame())
|
|
1468
|
+
False
|
|
1469
|
+
|
|
1470
|
+
Using SymPy as symbolic engine::
|
|
1471
|
+
|
|
1472
|
+
sage: M.set_calculus_method('sympy')
|
|
1473
|
+
sage: g = M.metric('g')
|
|
1474
|
+
sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
|
|
1475
|
+
sage: s = g.determinant() # determinant in M's default frame
|
|
1476
|
+
sage: s.expr()
|
|
1477
|
+
-x**2*y**2 + x - y*(x + 1) + 1
|
|
1478
|
+
"""
|
|
1479
|
+
from sage.matrix.constructor import matrix
|
|
1480
|
+
dom = self._domain
|
|
1481
|
+
if frame is None:
|
|
1482
|
+
frame = dom._def_frame
|
|
1483
|
+
if frame in dom._atlas:
|
|
1484
|
+
# frame is actually a chart and is changed to the associated
|
|
1485
|
+
# coordinate frame:
|
|
1486
|
+
frame = frame._frame
|
|
1487
|
+
if frame not in self._determinants:
|
|
1488
|
+
# a new computation is necessary
|
|
1489
|
+
resu = frame._domain.scalar_field()
|
|
1490
|
+
manif = self._ambient_domain
|
|
1491
|
+
gg = self.comp(frame)
|
|
1492
|
+
i1 = manif.start_index()
|
|
1493
|
+
for chart in gg[[i1, i1]]._express:
|
|
1494
|
+
# TODO: do the computation without the 'SR' enforcement
|
|
1495
|
+
gm = matrix( [[ gg[i, j, chart].expr(method='SR')
|
|
1496
|
+
for j in manif.irange()] for i in manif.irange()] )
|
|
1497
|
+
detgm = chart.simplify(gm.det(), method='SR')
|
|
1498
|
+
resu.add_expr(detgm, chart=chart)
|
|
1499
|
+
self._determinants[frame] = resu
|
|
1500
|
+
return self._determinants[frame]
|
|
1501
|
+
|
|
1502
|
+
det = determinant
|
|
1503
|
+
|
|
1504
|
+
def sqrt_abs_det(self, frame=None):
|
|
1505
|
+
r"""
|
|
1506
|
+
Square root of the absolute value of the determinant of the metric
|
|
1507
|
+
components in the specified frame.
|
|
1508
|
+
|
|
1509
|
+
INPUT:
|
|
1510
|
+
|
|
1511
|
+
- ``frame`` -- (default: ``None``) vector frame with
|
|
1512
|
+
respect to which the components `g_{ij}` of ``self`` are defined;
|
|
1513
|
+
if ``None``, the domain's default frame is used. If a chart is
|
|
1514
|
+
provided, the associated coordinate frame is used
|
|
1515
|
+
|
|
1516
|
+
OUTPUT:
|
|
1517
|
+
|
|
1518
|
+
- `\sqrt{|\det (g_{ij})|}`, as an instance of
|
|
1519
|
+
:class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
|
|
1520
|
+
|
|
1521
|
+
EXAMPLES:
|
|
1522
|
+
|
|
1523
|
+
Standard metric in the Euclidean space `\RR^3` with spherical
|
|
1524
|
+
coordinates::
|
|
1525
|
+
|
|
1526
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
1527
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
1528
|
+
sage: c_spher.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1529
|
+
sage: g = U.metric('g')
|
|
1530
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2, (r*sin(th))^2
|
|
1531
|
+
sage: g.display()
|
|
1532
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
1533
|
+
sage: g.sqrt_abs_det().expr()
|
|
1534
|
+
r^2*sin(th)
|
|
1535
|
+
|
|
1536
|
+
Metric determinant on a 2-dimensional manifold::
|
|
1537
|
+
|
|
1538
|
+
sage: M = Manifold(2, 'M', start_index=1)
|
|
1539
|
+
sage: X.<x,y> = M.chart()
|
|
1540
|
+
sage: g = M.metric('g')
|
|
1541
|
+
sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
|
|
1542
|
+
sage: g[:]
|
|
1543
|
+
[ x + 1 x*y]
|
|
1544
|
+
[ x*y -y + 1]
|
|
1545
|
+
sage: s = g.sqrt_abs_det() ; s
|
|
1546
|
+
Scalar field on the 2-dimensional differentiable manifold M
|
|
1547
|
+
sage: s.expr()
|
|
1548
|
+
sqrt(-x^2*y^2 - (x + 1)*y + x + 1)
|
|
1549
|
+
|
|
1550
|
+
Determinant in a frame different from the default's one::
|
|
1551
|
+
|
|
1552
|
+
sage: Y.<u,v> = M.chart()
|
|
1553
|
+
sage: ch_X_Y = X.transition_map(Y, [x+y, x-y])
|
|
1554
|
+
sage: ch_X_Y.inverse()
|
|
1555
|
+
Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y))
|
|
1556
|
+
sage: g[Y.frame(),:,Y]
|
|
1557
|
+
[ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2 1/4*u]
|
|
1558
|
+
[ 1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
|
|
1559
|
+
sage: g.sqrt_abs_det(Y.frame()).expr()
|
|
1560
|
+
1/2*sqrt(-x^2*y^2 - (x + 1)*y + x + 1)
|
|
1561
|
+
sage: g.sqrt_abs_det(Y.frame()).expr(Y)
|
|
1562
|
+
1/8*sqrt(-u^4 - v^4 + 2*(u^2 + 2)*v^2 - 4*u^2 + 16*v + 16)
|
|
1563
|
+
|
|
1564
|
+
A chart can be passed instead of a frame::
|
|
1565
|
+
|
|
1566
|
+
sage: g.sqrt_abs_det(Y) is g.sqrt_abs_det(Y.frame())
|
|
1567
|
+
True
|
|
1568
|
+
|
|
1569
|
+
The metric determinant depends on the frame::
|
|
1570
|
+
|
|
1571
|
+
sage: g.sqrt_abs_det(X.frame()) == g.sqrt_abs_det(Y.frame())
|
|
1572
|
+
False
|
|
1573
|
+
|
|
1574
|
+
Using SymPy as symbolic engine::
|
|
1575
|
+
|
|
1576
|
+
sage: M.set_calculus_method('sympy')
|
|
1577
|
+
sage: g = M.metric('g')
|
|
1578
|
+
sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
|
|
1579
|
+
sage: g.sqrt_abs_det().expr()
|
|
1580
|
+
sqrt(-x**2*y**2 - x*y + x - y + 1)
|
|
1581
|
+
sage: g.sqrt_abs_det(Y.frame()).expr()
|
|
1582
|
+
sqrt(-x**2*y**2 - x*y + x - y + 1)/2
|
|
1583
|
+
sage: g.sqrt_abs_det(Y.frame()).expr(Y)
|
|
1584
|
+
sqrt(-u**4 + 2*u**2*v**2 - 4*u**2 - v**4 + 4*v**2 + 16*v + 16)/8
|
|
1585
|
+
"""
|
|
1586
|
+
dom = self._domain
|
|
1587
|
+
if frame is None:
|
|
1588
|
+
frame = dom._def_frame
|
|
1589
|
+
if frame in dom._atlas:
|
|
1590
|
+
# frame is actually a chart and is changed to the associated
|
|
1591
|
+
# coordinate frame:
|
|
1592
|
+
frame = frame._frame
|
|
1593
|
+
if frame not in self._sqrt_abs_dets:
|
|
1594
|
+
# a new computation is necessary
|
|
1595
|
+
detg = self.determinant(frame)
|
|
1596
|
+
resu = frame._domain.scalar_field()
|
|
1597
|
+
for chart, funct in detg._express.items():
|
|
1598
|
+
x = (self._indic_signat * funct).sqrt().expr()
|
|
1599
|
+
resu.add_expr(x, chart=chart)
|
|
1600
|
+
self._sqrt_abs_dets[frame] = resu
|
|
1601
|
+
return self._sqrt_abs_dets[frame]
|
|
1602
|
+
|
|
1603
|
+
@overload
|
|
1604
|
+
def volume_form(self) -> DiffForm: ...
|
|
1605
|
+
@overload
|
|
1606
|
+
def volume_form(self, contra: int) -> TensorField: ...
|
|
1607
|
+
def volume_form(self, contra=0):
|
|
1608
|
+
r"""
|
|
1609
|
+
Volume form (Levi-Civita tensor) `\epsilon` associated with the metric.
|
|
1610
|
+
|
|
1611
|
+
The volume form `\epsilon` is an `n`-form (`n` being the manifold's
|
|
1612
|
+
dimension) such that for any oriented vector basis `(e_i)` which is
|
|
1613
|
+
orthonormal with respect to the metric, the condition
|
|
1614
|
+
|
|
1615
|
+
.. MATH::
|
|
1616
|
+
|
|
1617
|
+
\epsilon(e_1,\ldots,e_n) = 1
|
|
1618
|
+
|
|
1619
|
+
holds.
|
|
1620
|
+
|
|
1621
|
+
Notice that a volume form requires an orientable manifold with
|
|
1622
|
+
a preferred orientation, see
|
|
1623
|
+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.orientation`
|
|
1624
|
+
for details.
|
|
1625
|
+
|
|
1626
|
+
INPUT:
|
|
1627
|
+
|
|
1628
|
+
- ``contra`` -- (default: 0) number of contravariant indices of the
|
|
1629
|
+
returned tensor
|
|
1630
|
+
|
|
1631
|
+
OUTPUT:
|
|
1632
|
+
|
|
1633
|
+
- if ``contra = 0`` (default value): the volume `n`-form `\epsilon`, as
|
|
1634
|
+
an instance of
|
|
1635
|
+
:class:`~sage.manifolds.differentiable.diff_form.DiffForm`
|
|
1636
|
+
- if ``contra = k``, with `1\leq k \leq n`, the tensor field of type
|
|
1637
|
+
(k,n-k) formed from `\epsilon` by raising the first k indices with
|
|
1638
|
+
the metric (see method
|
|
1639
|
+
:meth:`~sage.manifolds.differentiable.tensorfield.TensorField.up`);
|
|
1640
|
+
the output is then an instance of
|
|
1641
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`, with
|
|
1642
|
+
the appropriate antisymmetries, or of the subclass
|
|
1643
|
+
:class:`~sage.manifolds.differentiable.multivectorfield.MultivectorField`
|
|
1644
|
+
if `k=n`
|
|
1645
|
+
|
|
1646
|
+
EXAMPLES:
|
|
1647
|
+
|
|
1648
|
+
Volume form on `\RR^3` with spherical coordinates, using the standard
|
|
1649
|
+
orientation, which is predefined::
|
|
1650
|
+
|
|
1651
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
1652
|
+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
|
|
1653
|
+
sage: c_spher.<r,th,ph> = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1654
|
+
sage: g = U.metric('g')
|
|
1655
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2, (r*sin(th))^2
|
|
1656
|
+
sage: g.display()
|
|
1657
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
1658
|
+
sage: eps = g.volume_form() ; eps
|
|
1659
|
+
3-form eps_g on the Open subset U of the 3-dimensional
|
|
1660
|
+
differentiable manifold M
|
|
1661
|
+
sage: eps.display()
|
|
1662
|
+
eps_g = r^2*sin(th) dr∧dth∧dph
|
|
1663
|
+
sage: eps[[1,2,3]] == g.sqrt_abs_det()
|
|
1664
|
+
True
|
|
1665
|
+
sage: latex(eps)
|
|
1666
|
+
\epsilon_{g}
|
|
1667
|
+
|
|
1668
|
+
The tensor field of components `\epsilon^i_{\ \, jk}` (``contra=1``)::
|
|
1669
|
+
|
|
1670
|
+
sage: eps1 = g.volume_form(1) ; eps1
|
|
1671
|
+
Tensor field of type (1,2) on the Open subset U of the
|
|
1672
|
+
3-dimensional differentiable manifold M
|
|
1673
|
+
sage: eps1.symmetries()
|
|
1674
|
+
no symmetry; antisymmetry: (1, 2)
|
|
1675
|
+
sage: eps1[:]
|
|
1676
|
+
[[[0, 0, 0], [0, 0, r^2*sin(th)], [0, -r^2*sin(th), 0]],
|
|
1677
|
+
[[0, 0, -sin(th)], [0, 0, 0], [sin(th), 0, 0]],
|
|
1678
|
+
[[0, 1/sin(th), 0], [-1/sin(th), 0, 0], [0, 0, 0]]]
|
|
1679
|
+
|
|
1680
|
+
The tensor field of components `\epsilon^{ij}_{\ \ k}` (``contra=2``)::
|
|
1681
|
+
|
|
1682
|
+
sage: eps2 = g.volume_form(2) ; eps2
|
|
1683
|
+
Tensor field of type (2,1) on the Open subset U of the
|
|
1684
|
+
3-dimensional differentiable manifold M
|
|
1685
|
+
sage: eps2.symmetries()
|
|
1686
|
+
no symmetry; antisymmetry: (0, 1)
|
|
1687
|
+
sage: eps2[:]
|
|
1688
|
+
[[[0, 0, 0], [0, 0, sin(th)], [0, -1/sin(th), 0]],
|
|
1689
|
+
[[0, 0, -sin(th)], [0, 0, 0], [1/(r^2*sin(th)), 0, 0]],
|
|
1690
|
+
[[0, 1/sin(th), 0], [-1/(r^2*sin(th)), 0, 0], [0, 0, 0]]]
|
|
1691
|
+
|
|
1692
|
+
The tensor field of components `\epsilon^{ijk}` (``contra=3``)::
|
|
1693
|
+
|
|
1694
|
+
sage: eps3 = g.volume_form(3) ; eps3
|
|
1695
|
+
3-vector field on the Open subset U of the 3-dimensional
|
|
1696
|
+
differentiable manifold M
|
|
1697
|
+
sage: eps3.tensor_type()
|
|
1698
|
+
(3, 0)
|
|
1699
|
+
sage: eps3.symmetries()
|
|
1700
|
+
no symmetry; antisymmetry: (0, 1, 2)
|
|
1701
|
+
sage: eps3[:]
|
|
1702
|
+
[[[0, 0, 0], [0, 0, 1/(r^2*sin(th))], [0, -1/(r^2*sin(th)), 0]],
|
|
1703
|
+
[[0, 0, -1/(r^2*sin(th))], [0, 0, 0], [1/(r^2*sin(th)), 0, 0]],
|
|
1704
|
+
[[0, 1/(r^2*sin(th)), 0], [-1/(r^2*sin(th)), 0, 0], [0, 0, 0]]]
|
|
1705
|
+
sage: eps3[1,2,3]
|
|
1706
|
+
1/(r^2*sin(th))
|
|
1707
|
+
sage: eps3[[1,2,3]] * g.sqrt_abs_det() == 1
|
|
1708
|
+
True
|
|
1709
|
+
|
|
1710
|
+
If the manifold has no predefined orientation, an orientation must be
|
|
1711
|
+
set before invoking ``volume_form()``. For instance let consider the
|
|
1712
|
+
2-sphere described by the stereographic charts from the North and
|
|
1713
|
+
South pole::
|
|
1714
|
+
|
|
1715
|
+
sage: M = Manifold(2, 'M', structure='Riemannian')
|
|
1716
|
+
sage: U = M.open_subset('U'); V = M.open_subset('V')
|
|
1717
|
+
sage: M.declare_union(U, V)
|
|
1718
|
+
sage: c_xy.<x,y> = U.chart() # stereographic chart from the North pole
|
|
1719
|
+
sage: c_uv.<u,v> = V.chart() # stereographic chart from the South pole
|
|
1720
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
1721
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
1722
|
+
....: restrictions2= u^2+v^2!=0)
|
|
1723
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
1724
|
+
sage: eU = c_xy.frame(); eV = c_uv.frame()
|
|
1725
|
+
sage: g = M.metric()
|
|
1726
|
+
sage: g[eU,0,0], g[eU,1,1] = 4/(1+x^2+y^2)^2, 4/(1+x^2+y^2)^2
|
|
1727
|
+
sage: g.add_comp_by_continuation(eV, U.intersection(V), chart=c_uv)
|
|
1728
|
+
sage: eps = g.volume_form()
|
|
1729
|
+
Traceback (most recent call last):
|
|
1730
|
+
...
|
|
1731
|
+
ValueError: 2-dimensional Riemannian manifold M must admit an
|
|
1732
|
+
orientation
|
|
1733
|
+
|
|
1734
|
+
Let us define the orientation of ``M`` such that ``eU`` is
|
|
1735
|
+
right-handed; ``eV`` is then left-handed and in order to define an
|
|
1736
|
+
orientation on the whole of ``M``, we introduce a vector frame on ``V``
|
|
1737
|
+
by swapping ``eV``'s vectors::
|
|
1738
|
+
|
|
1739
|
+
sage: f = V.vector_frame('f', (eV[1], eV[0]))
|
|
1740
|
+
sage: M.set_orientation([eU, f])
|
|
1741
|
+
|
|
1742
|
+
We have then, factorizing the components for a nicer display::
|
|
1743
|
+
|
|
1744
|
+
sage: eps = g.volume_form()
|
|
1745
|
+
sage: eps.apply_map(factor, frame=eU, keep_other_components=True)
|
|
1746
|
+
sage: eps.apply_map(factor, frame=eV, keep_other_components=True)
|
|
1747
|
+
sage: eps.display(eU)
|
|
1748
|
+
eps_g = 4/(x^2 + y^2 + 1)^2 dx∧dy
|
|
1749
|
+
sage: eps.display(eV)
|
|
1750
|
+
eps_g = -4/(u^2 + v^2 + 1)^2 du∧dv
|
|
1751
|
+
|
|
1752
|
+
Note the minus sign in the above expression, reflecting the fact that
|
|
1753
|
+
``eV`` is left-handed with respect to the chosen orientation.
|
|
1754
|
+
"""
|
|
1755
|
+
dom = self._domain
|
|
1756
|
+
orient = dom.orientation()
|
|
1757
|
+
manif = self._ambient_domain
|
|
1758
|
+
ndim = manif.dimension()
|
|
1759
|
+
if not orient:
|
|
1760
|
+
raise ValueError('{} must admit an orientation'.format(dom))
|
|
1761
|
+
if contra > ndim:
|
|
1762
|
+
raise ValueError('The number of contravariant indices is greater '
|
|
1763
|
+
'than the manifold dimension')
|
|
1764
|
+
if self._vol_forms == []:
|
|
1765
|
+
# a new computation is necessary
|
|
1766
|
+
# The result is constructed on the vector field module,
|
|
1767
|
+
# so that dest_map is taken automatically into account:
|
|
1768
|
+
eps = self._vmodule.alternating_form(ndim, name='eps_'+self._name,
|
|
1769
|
+
latex_name=r'\epsilon_{'+self._latex_name+r'}')
|
|
1770
|
+
si = manif.start_index()
|
|
1771
|
+
ind = tuple(range(si, si+ndim))
|
|
1772
|
+
for frame in orient:
|
|
1773
|
+
if frame.destination_map() is frame.domain().identity_map():
|
|
1774
|
+
eps.add_comp(frame)[[ind]] = self.sqrt_abs_det(frame)
|
|
1775
|
+
self._vol_forms.append(eps) # Levi-Civita tensor constructed
|
|
1776
|
+
if contra >= len(self._vol_forms):
|
|
1777
|
+
# Tensors related to the Levi-Civita one by index rising:
|
|
1778
|
+
for k in range(len(self._vol_forms), contra+1):
|
|
1779
|
+
epskm1 = self._vol_forms[k-1]
|
|
1780
|
+
epsk = epskm1.up(self, k-1)
|
|
1781
|
+
if k > 1:
|
|
1782
|
+
# restoring the antisymmetry after the up operation:
|
|
1783
|
+
epsk = epsk.antisymmetrize(*range(k))
|
|
1784
|
+
self._vol_forms.append(epsk)
|
|
1785
|
+
return self._vol_forms[contra]
|
|
1786
|
+
|
|
1787
|
+
def hodge_star(self, pform: DiffForm) -> DiffForm:
|
|
1788
|
+
r"""
|
|
1789
|
+
Compute the Hodge dual of a differential form with respect to the
|
|
1790
|
+
metric.
|
|
1791
|
+
|
|
1792
|
+
If the differential form is a `p`-form `A`, its *Hodge dual* with
|
|
1793
|
+
respect to the metric `g` is the
|
|
1794
|
+
`(n-p)`-form `*A` defined by
|
|
1795
|
+
|
|
1796
|
+
.. MATH::
|
|
1797
|
+
|
|
1798
|
+
*A_{i_1\ldots i_{n-p}} = \frac{1}{p!} A_{k_1\ldots k_p}
|
|
1799
|
+
\epsilon^{k_1\ldots k_p}_{\qquad\ i_1\ldots i_{n-p}}
|
|
1800
|
+
|
|
1801
|
+
where `n` is the manifold's dimension, `\epsilon` is the volume
|
|
1802
|
+
`n`-form associated with `g` (see :meth:`volume_form`) and the indices
|
|
1803
|
+
`k_1,\ldots, k_p` are raised with `g`.
|
|
1804
|
+
|
|
1805
|
+
Notice that the Hodge star dual requires an orientable manifold
|
|
1806
|
+
with a preferred orientation, see
|
|
1807
|
+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.orientation`
|
|
1808
|
+
for details.
|
|
1809
|
+
|
|
1810
|
+
INPUT:
|
|
1811
|
+
|
|
1812
|
+
- ``pform`` -- a `p`-form `A`; must be an instance of
|
|
1813
|
+
:class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
|
|
1814
|
+
for `p=0` and of
|
|
1815
|
+
:class:`~sage.manifolds.differentiable.diff_form.DiffForm` or
|
|
1816
|
+
:class:`~sage.manifolds.differentiable.diff_form.DiffFormParal`
|
|
1817
|
+
for `p\geq 1`.
|
|
1818
|
+
|
|
1819
|
+
OUTPUT:
|
|
1820
|
+
|
|
1821
|
+
- the `(n-p)`-form `*A`
|
|
1822
|
+
|
|
1823
|
+
EXAMPLES:
|
|
1824
|
+
|
|
1825
|
+
Hodge dual of a 1-form in the Euclidean space `R^3`::
|
|
1826
|
+
|
|
1827
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
1828
|
+
sage: X.<x,y,z> = M.chart()
|
|
1829
|
+
sage: g = M.metric('g')
|
|
1830
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1
|
|
1831
|
+
sage: var('Ax Ay Az')
|
|
1832
|
+
(Ax, Ay, Az)
|
|
1833
|
+
sage: a = M.one_form(Ax, Ay, Az, name='A')
|
|
1834
|
+
sage: sa = g.hodge_star(a) ; sa
|
|
1835
|
+
2-form *A on the 3-dimensional differentiable manifold M
|
|
1836
|
+
sage: sa.display()
|
|
1837
|
+
*A = Az dx∧dy - Ay dx∧dz + Ax dy∧dz
|
|
1838
|
+
sage: ssa = g.hodge_star(sa) ; ssa
|
|
1839
|
+
1-form **A on the 3-dimensional differentiable manifold M
|
|
1840
|
+
sage: ssa.display()
|
|
1841
|
+
**A = Ax dx + Ay dy + Az dz
|
|
1842
|
+
sage: ssa == a # must hold for a Riemannian metric in dimension 3
|
|
1843
|
+
True
|
|
1844
|
+
|
|
1845
|
+
Hodge dual of a 0-form (scalar field) in `R^3`::
|
|
1846
|
+
|
|
1847
|
+
sage: f = M.scalar_field(function('F')(x,y,z), name='f')
|
|
1848
|
+
sage: sf = g.hodge_star(f) ; sf
|
|
1849
|
+
3-form *f on the 3-dimensional differentiable manifold M
|
|
1850
|
+
sage: sf.display()
|
|
1851
|
+
*f = F(x, y, z) dx∧dy∧dz
|
|
1852
|
+
sage: ssf = g.hodge_star(sf) ; ssf
|
|
1853
|
+
Scalar field **f on the 3-dimensional differentiable manifold M
|
|
1854
|
+
sage: ssf.display()
|
|
1855
|
+
**f: M → ℝ
|
|
1856
|
+
(x, y, z) ↦ F(x, y, z)
|
|
1857
|
+
sage: ssf == f # must hold for a Riemannian metric
|
|
1858
|
+
True
|
|
1859
|
+
|
|
1860
|
+
Hodge dual of a 0-form in Minkowski spacetime::
|
|
1861
|
+
|
|
1862
|
+
sage: M = Manifold(4, 'M')
|
|
1863
|
+
sage: X.<t,x,y,z> = M.chart()
|
|
1864
|
+
sage: g = M.lorentzian_metric('g')
|
|
1865
|
+
sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1
|
|
1866
|
+
sage: g.display() # Minkowski metric
|
|
1867
|
+
g = -dt⊗dt + dx⊗dx + dy⊗dy + dz⊗dz
|
|
1868
|
+
sage: var('f0')
|
|
1869
|
+
f0
|
|
1870
|
+
sage: f = M.scalar_field(f0, name='f')
|
|
1871
|
+
sage: sf = g.hodge_star(f) ; sf
|
|
1872
|
+
4-form *f on the 4-dimensional differentiable manifold M
|
|
1873
|
+
sage: sf.display()
|
|
1874
|
+
*f = f0 dt∧dx∧dy∧dz
|
|
1875
|
+
sage: ssf = g.hodge_star(sf) ; ssf
|
|
1876
|
+
Scalar field **f on the 4-dimensional differentiable manifold M
|
|
1877
|
+
sage: ssf.display()
|
|
1878
|
+
**f: M → ℝ
|
|
1879
|
+
(t, x, y, z) ↦ -f0
|
|
1880
|
+
sage: ssf == -f # must hold for a Lorentzian metric
|
|
1881
|
+
True
|
|
1882
|
+
|
|
1883
|
+
Hodge dual of a 1-form in Minkowski spacetime::
|
|
1884
|
+
|
|
1885
|
+
sage: var('At Ax Ay Az')
|
|
1886
|
+
(At, Ax, Ay, Az)
|
|
1887
|
+
sage: a = M.one_form(At, Ax, Ay, Az, name='A')
|
|
1888
|
+
sage: a.display()
|
|
1889
|
+
A = At dt + Ax dx + Ay dy + Az dz
|
|
1890
|
+
sage: sa = g.hodge_star(a) ; sa
|
|
1891
|
+
3-form *A on the 4-dimensional differentiable manifold M
|
|
1892
|
+
sage: sa.display()
|
|
1893
|
+
*A = -Az dt∧dx∧dy + Ay dt∧dx∧dz - Ax dt∧dy∧dz - At dx∧dy∧dz
|
|
1894
|
+
sage: ssa = g.hodge_star(sa) ; ssa
|
|
1895
|
+
1-form **A on the 4-dimensional differentiable manifold M
|
|
1896
|
+
sage: ssa.display()
|
|
1897
|
+
**A = At dt + Ax dx + Ay dy + Az dz
|
|
1898
|
+
sage: ssa == a # must hold for a Lorentzian metric in dimension 4
|
|
1899
|
+
True
|
|
1900
|
+
|
|
1901
|
+
Hodge dual of a 2-form in Minkowski spacetime::
|
|
1902
|
+
|
|
1903
|
+
sage: F = M.diff_form(2, name='F')
|
|
1904
|
+
sage: var('Ex Ey Ez Bx By Bz')
|
|
1905
|
+
(Ex, Ey, Ez, Bx, By, Bz)
|
|
1906
|
+
sage: F[0,1], F[0,2], F[0,3] = -Ex, -Ey, -Ez
|
|
1907
|
+
sage: F[1,2], F[1,3], F[2,3] = Bz, -By, Bx
|
|
1908
|
+
sage: F[:]
|
|
1909
|
+
[ 0 -Ex -Ey -Ez]
|
|
1910
|
+
[ Ex 0 Bz -By]
|
|
1911
|
+
[ Ey -Bz 0 Bx]
|
|
1912
|
+
[ Ez By -Bx 0]
|
|
1913
|
+
sage: sF = g.hodge_star(F) ; sF
|
|
1914
|
+
2-form *F on the 4-dimensional differentiable manifold M
|
|
1915
|
+
sage: sF[:]
|
|
1916
|
+
[ 0 Bx By Bz]
|
|
1917
|
+
[-Bx 0 Ez -Ey]
|
|
1918
|
+
[-By -Ez 0 Ex]
|
|
1919
|
+
[-Bz Ey -Ex 0]
|
|
1920
|
+
sage: ssF = g.hodge_star(sF) ; ssF
|
|
1921
|
+
2-form **F on the 4-dimensional differentiable manifold M
|
|
1922
|
+
sage: ssF[:]
|
|
1923
|
+
[ 0 Ex Ey Ez]
|
|
1924
|
+
[-Ex 0 -Bz By]
|
|
1925
|
+
[-Ey Bz 0 -Bx]
|
|
1926
|
+
[-Ez -By Bx 0]
|
|
1927
|
+
sage: ssF.display()
|
|
1928
|
+
**F = Ex dt∧dx + Ey dt∧dy + Ez dt∧dz - Bz dx∧dy + By dx∧dz
|
|
1929
|
+
- Bx dy∧dz
|
|
1930
|
+
sage: F.display()
|
|
1931
|
+
F = -Ex dt∧dx - Ey dt∧dy - Ez dt∧dz + Bz dx∧dy - By dx∧dz
|
|
1932
|
+
+ Bx dy∧dz
|
|
1933
|
+
sage: ssF == -F # must hold for a Lorentzian metric in dimension 4
|
|
1934
|
+
True
|
|
1935
|
+
|
|
1936
|
+
Test of the standard identity
|
|
1937
|
+
|
|
1938
|
+
.. MATH::
|
|
1939
|
+
|
|
1940
|
+
*(A\wedge B) = \epsilon(A^\sharp, B^\sharp, ., .)
|
|
1941
|
+
|
|
1942
|
+
where `A` and `B` are any 1-forms and `A^\sharp` and `B^\sharp` the
|
|
1943
|
+
vectors associated to them by the metric `g` (index raising)::
|
|
1944
|
+
|
|
1945
|
+
sage: var('Bt Bx By Bz')
|
|
1946
|
+
(Bt, Bx, By, Bz)
|
|
1947
|
+
sage: b = M.one_form(Bt, Bx, By, Bz, name='B')
|
|
1948
|
+
sage: b.display()
|
|
1949
|
+
B = Bt dt + Bx dx + By dy + Bz dz
|
|
1950
|
+
sage: epsilon = g.volume_form()
|
|
1951
|
+
sage: g.hodge_star(a.wedge(b)) == epsilon.contract(0,a.up(g)).contract(0,b.up(g))
|
|
1952
|
+
True
|
|
1953
|
+
"""
|
|
1954
|
+
return pform.hodge_dual(self)
|
|
1955
|
+
|
|
1956
|
+
|
|
1957
|
+
#******************************************************************************
|
|
1958
|
+
|
|
1959
|
+
class PseudoRiemannianMetricParal(PseudoRiemannianMetric, TensorFieldParal):
|
|
1960
|
+
r"""
|
|
1961
|
+
Pseudo-Riemannian metric with values on a parallelizable manifold.
|
|
1962
|
+
|
|
1963
|
+
An instance of this class is a field of nondegenerate symmetric bilinear
|
|
1964
|
+
forms (metric field) along a differentiable manifold `U` with values in a
|
|
1965
|
+
parallelizable manifold `M` over `\RR`, via a differentiable mapping
|
|
1966
|
+
`\Phi: U \rightarrow M`. The standard case of a metric field *on* a
|
|
1967
|
+
manifold corresponds to `U=M` and `\Phi = \mathrm{Id}_M`. Other common
|
|
1968
|
+
cases are `\Phi` being an immersion and `\Phi` being a curve in `M` (`U` is
|
|
1969
|
+
then an open interval of `\RR`).
|
|
1970
|
+
|
|
1971
|
+
A *metric* `g` is a field on `U`, such that at each
|
|
1972
|
+
point `p\in U`, `g(p)` is a bilinear map of the type:
|
|
1973
|
+
|
|
1974
|
+
.. MATH::
|
|
1975
|
+
|
|
1976
|
+
g(p):\ T_q M\times T_q M \longrightarrow \RR
|
|
1977
|
+
|
|
1978
|
+
where `T_q M` stands for the tangent space to manifold `M` at the point
|
|
1979
|
+
`q=\Phi(p)`, such that `g(p)` is symmetric:
|
|
1980
|
+
`\forall (u,v)\in T_q M\times T_q M, \ g(p)(v,u) = g(p)(u,v)`
|
|
1981
|
+
and nondegenerate:
|
|
1982
|
+
`(\forall v\in T_q M,\ \ g(p)(u,v) = 0) \Longrightarrow u=0`.
|
|
1983
|
+
|
|
1984
|
+
.. NOTE::
|
|
1985
|
+
|
|
1986
|
+
If `M` is not parallelizable, the class :class:`PseudoRiemannianMetric`
|
|
1987
|
+
should be used instead.
|
|
1988
|
+
|
|
1989
|
+
INPUT:
|
|
1990
|
+
|
|
1991
|
+
- ``vector_field_module`` -- free module `\mathfrak{X}(U,\Phi)` of vector
|
|
1992
|
+
fields along `U` with values on `\Phi(U)\subset M`
|
|
1993
|
+
- ``name`` -- name given to the metric
|
|
1994
|
+
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
|
|
1995
|
+
single integer: `S = n_+ - n_-`, where `n_+` (resp. `n_-`) is the number
|
|
1996
|
+
of positive terms (resp. number of negative terms) in any diagonal
|
|
1997
|
+
writing of the metric components; if ``signature`` is ``None``, `S` is
|
|
1998
|
+
set to the dimension of manifold `M` (Riemannian signature)
|
|
1999
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the metric;
|
|
2000
|
+
if ``None``, it is formed from ``name``
|
|
2001
|
+
|
|
2002
|
+
EXAMPLES:
|
|
2003
|
+
|
|
2004
|
+
Metric on a 2-dimensional manifold::
|
|
2005
|
+
|
|
2006
|
+
sage: M = Manifold(2, 'M', start_index=1)
|
|
2007
|
+
sage: c_xy.<x,y> = M.chart()
|
|
2008
|
+
sage: g = M.metric('g') ; g
|
|
2009
|
+
Riemannian metric g on the 2-dimensional differentiable manifold M
|
|
2010
|
+
sage: latex(g)
|
|
2011
|
+
g
|
|
2012
|
+
|
|
2013
|
+
A metric is a special kind of tensor field and therefore inheritates all the
|
|
2014
|
+
properties from class
|
|
2015
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`::
|
|
2016
|
+
|
|
2017
|
+
sage: g.parent()
|
|
2018
|
+
Free module T^(0,2)(M) of type-(0,2) tensors fields on the
|
|
2019
|
+
2-dimensional differentiable manifold M
|
|
2020
|
+
sage: g.tensor_type()
|
|
2021
|
+
(0, 2)
|
|
2022
|
+
sage: g.symmetries() # g is symmetric:
|
|
2023
|
+
symmetry: (0, 1); no antisymmetry
|
|
2024
|
+
|
|
2025
|
+
Setting the metric components in the manifold's default frame::
|
|
2026
|
+
|
|
2027
|
+
sage: g[1,1], g[1,2], g[2,2] = 1+x, x*y, 1-x
|
|
2028
|
+
sage: g[:]
|
|
2029
|
+
[ x + 1 x*y]
|
|
2030
|
+
[ x*y -x + 1]
|
|
2031
|
+
sage: g.display()
|
|
2032
|
+
g = (x + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (-x + 1) dy⊗dy
|
|
2033
|
+
|
|
2034
|
+
Metric components in a frame different from the manifold's default one::
|
|
2035
|
+
|
|
2036
|
+
sage: c_uv.<u,v> = M.chart() # new chart on M
|
|
2037
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, [x+y, x-y]) ; xy_to_uv
|
|
2038
|
+
Change of coordinates from Chart (M, (x, y)) to Chart (M, (u, v))
|
|
2039
|
+
sage: uv_to_xy = xy_to_uv.inverse() ; uv_to_xy
|
|
2040
|
+
Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y))
|
|
2041
|
+
sage: M.atlas()
|
|
2042
|
+
[Chart (M, (x, y)), Chart (M, (u, v))]
|
|
2043
|
+
sage: M.frames()
|
|
2044
|
+
[Coordinate frame (M, (∂/∂x,∂/∂y)), Coordinate frame (M, (∂/∂u,∂/∂v))]
|
|
2045
|
+
sage: g[c_uv.frame(),:] # metric components in frame c_uv.frame() expressed in M's default chart (x,y)
|
|
2046
|
+
[ 1/2*x*y + 1/2 1/2*x]
|
|
2047
|
+
[ 1/2*x -1/2*x*y + 1/2]
|
|
2048
|
+
sage: g.display(c_uv.frame())
|
|
2049
|
+
g = (1/2*x*y + 1/2) du⊗du + 1/2*x du⊗dv + 1/2*x dv⊗du
|
|
2050
|
+
+ (-1/2*x*y + 1/2) dv⊗dv
|
|
2051
|
+
sage: g[c_uv.frame(),:,c_uv] # metric components in frame c_uv.frame() expressed in chart (u,v)
|
|
2052
|
+
[ 1/8*u^2 - 1/8*v^2 + 1/2 1/4*u + 1/4*v]
|
|
2053
|
+
[ 1/4*u + 1/4*v -1/8*u^2 + 1/8*v^2 + 1/2]
|
|
2054
|
+
sage: g.display(c_uv.frame(), c_uv)
|
|
2055
|
+
g = (1/8*u^2 - 1/8*v^2 + 1/2) du⊗du + (1/4*u + 1/4*v) du⊗dv
|
|
2056
|
+
+ (1/4*u + 1/4*v) dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/2) dv⊗dv
|
|
2057
|
+
|
|
2058
|
+
As a shortcut of the above command, on can pass just the chart ``c_uv``
|
|
2059
|
+
to ``display``, the vector frame being then assumed to be the coordinate
|
|
2060
|
+
frame associated with the chart::
|
|
2061
|
+
|
|
2062
|
+
sage: g.display(c_uv)
|
|
2063
|
+
g = (1/8*u^2 - 1/8*v^2 + 1/2) du⊗du + (1/4*u + 1/4*v) du⊗dv
|
|
2064
|
+
+ (1/4*u + 1/4*v) dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/2) dv⊗dv
|
|
2065
|
+
|
|
2066
|
+
The inverse metric is obtained via :meth:`inverse`::
|
|
2067
|
+
|
|
2068
|
+
sage: ig = g.inverse() ; ig
|
|
2069
|
+
Tensor field inv_g of type (2,0) on the 2-dimensional differentiable
|
|
2070
|
+
manifold M
|
|
2071
|
+
sage: ig[:]
|
|
2072
|
+
[ (x - 1)/(x^2*y^2 + x^2 - 1) x*y/(x^2*y^2 + x^2 - 1)]
|
|
2073
|
+
[ x*y/(x^2*y^2 + x^2 - 1) -(x + 1)/(x^2*y^2 + x^2 - 1)]
|
|
2074
|
+
sage: ig.display()
|
|
2075
|
+
inv_g = (x - 1)/(x^2*y^2 + x^2 - 1) ∂/∂x⊗∂/∂x
|
|
2076
|
+
+ x*y/(x^2*y^2 + x^2 - 1) ∂/∂x⊗∂/∂y + x*y/(x^2*y^2 + x^2 - 1) ∂/∂y⊗∂/∂x
|
|
2077
|
+
- (x + 1)/(x^2*y^2 + x^2 - 1) ∂/∂y⊗∂/∂y
|
|
2078
|
+
"""
|
|
2079
|
+
def __init__(self, vector_field_module, name, signature=None,
|
|
2080
|
+
latex_name=None):
|
|
2081
|
+
r"""
|
|
2082
|
+
Construct a metric on a parallelizable manifold.
|
|
2083
|
+
|
|
2084
|
+
TESTS::
|
|
2085
|
+
|
|
2086
|
+
sage: M = Manifold(2, 'M')
|
|
2087
|
+
sage: X.<x,y> = M.chart() # makes M parallelizable
|
|
2088
|
+
sage: XM = M.vector_field_module()
|
|
2089
|
+
sage: from sage.manifolds.differentiable.metric import \
|
|
2090
|
+
....: PseudoRiemannianMetricParal
|
|
2091
|
+
sage: g = PseudoRiemannianMetricParal(XM, 'g', signature=0); g
|
|
2092
|
+
Lorentzian metric g on the 2-dimensional differentiable manifold M
|
|
2093
|
+
sage: g[0,0], g[1,1] = -(1+x^2), 1+y^2
|
|
2094
|
+
sage: TestSuite(g).run(skip='_test_category')
|
|
2095
|
+
|
|
2096
|
+
.. TODO::
|
|
2097
|
+
|
|
2098
|
+
- add a specific parent to the metrics, to fit with the category
|
|
2099
|
+
framework
|
|
2100
|
+
"""
|
|
2101
|
+
TensorFieldParal.__init__(self, vector_field_module, (0,2),
|
|
2102
|
+
name=name, latex_name=latex_name, sym=(0,1))
|
|
2103
|
+
# signature:
|
|
2104
|
+
ndim = self._ambient_domain.dimension()
|
|
2105
|
+
if signature is None:
|
|
2106
|
+
signature = ndim
|
|
2107
|
+
else:
|
|
2108
|
+
if not isinstance(signature, (int, Integer)):
|
|
2109
|
+
raise TypeError("the metric signature must be an integer")
|
|
2110
|
+
if (signature < - ndim) or (signature > ndim):
|
|
2111
|
+
raise ValueError("metric signature out of range")
|
|
2112
|
+
if (signature+ndim) % 2 == 1:
|
|
2113
|
+
if ndim % 2 == 0:
|
|
2114
|
+
raise ValueError("the metric signature must be even")
|
|
2115
|
+
else:
|
|
2116
|
+
raise ValueError("the metric signature must be odd")
|
|
2117
|
+
self._signature = signature
|
|
2118
|
+
# the pair (n_+, n_-):
|
|
2119
|
+
self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2)
|
|
2120
|
+
self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_-
|
|
2121
|
+
# Initialization of derived quantities:
|
|
2122
|
+
PseudoRiemannianMetricParal._init_derived(self)
|
|
2123
|
+
|
|
2124
|
+
def _init_derived(self):
|
|
2125
|
+
r"""
|
|
2126
|
+
Initialize the derived quantities.
|
|
2127
|
+
|
|
2128
|
+
TESTS::
|
|
2129
|
+
|
|
2130
|
+
sage: M = Manifold(3, 'M')
|
|
2131
|
+
sage: X.<x,y,z> = M.chart() # makes M parallelizable
|
|
2132
|
+
sage: g = M.metric('g')
|
|
2133
|
+
sage: g._init_derived()
|
|
2134
|
+
"""
|
|
2135
|
+
# Initialization of quantities pertaining to the mother classes:
|
|
2136
|
+
TensorFieldParal._init_derived(self)
|
|
2137
|
+
PseudoRiemannianMetric._init_derived(self)
|
|
2138
|
+
|
|
2139
|
+
def _del_derived(self, del_restrictions=True):
|
|
2140
|
+
r"""
|
|
2141
|
+
Delete the derived quantities.
|
|
2142
|
+
|
|
2143
|
+
INPUT:
|
|
2144
|
+
|
|
2145
|
+
- ``del_restrictions`` -- boolean (default: ``True``); determines whether the
|
|
2146
|
+
restrictions of ``self`` to subdomains are deleted
|
|
2147
|
+
|
|
2148
|
+
TESTS::
|
|
2149
|
+
|
|
2150
|
+
sage: M = Manifold(3, 'M')
|
|
2151
|
+
sage: X.<x,y,z> = M.chart() # makes M parallelizable
|
|
2152
|
+
sage: g = M.metric('g')
|
|
2153
|
+
sage: g._del_derived(del_restrictions=False)
|
|
2154
|
+
sage: g._del_derived()
|
|
2155
|
+
"""
|
|
2156
|
+
# The derived quantities from the mother classes are deleted:
|
|
2157
|
+
TensorFieldParal._del_derived(self, del_restrictions=del_restrictions)
|
|
2158
|
+
PseudoRiemannianMetric._del_derived(self)
|
|
2159
|
+
|
|
2160
|
+
def _del_inverse(self):
|
|
2161
|
+
r"""
|
|
2162
|
+
Delete the inverse metric.
|
|
2163
|
+
|
|
2164
|
+
TESTS::
|
|
2165
|
+
|
|
2166
|
+
sage: M = Manifold(3, 'M')
|
|
2167
|
+
sage: X.<x,y,z> = M.chart() # makes M parallelizable
|
|
2168
|
+
sage: g = M.metric('g')
|
|
2169
|
+
sage: g._del_inverse()
|
|
2170
|
+
"""
|
|
2171
|
+
self._inverse._components.clear()
|
|
2172
|
+
self._inverse._del_derived()
|
|
2173
|
+
|
|
2174
|
+
def restrict(self, subdomain, dest_map=None):
|
|
2175
|
+
r"""
|
|
2176
|
+
Return the restriction of the metric to some subdomain.
|
|
2177
|
+
|
|
2178
|
+
If the restriction has not been defined yet, it is constructed here.
|
|
2179
|
+
|
|
2180
|
+
INPUT:
|
|
2181
|
+
|
|
2182
|
+
- ``subdomain`` -- open subset `U` of ``self._domain`` (must be an
|
|
2183
|
+
instance of
|
|
2184
|
+
:class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`)
|
|
2185
|
+
- ``dest_map`` -- (default: ``None``) destination map
|
|
2186
|
+
`\Phi:\ U \rightarrow V`, where `V` is a subdomain of
|
|
2187
|
+
``self._codomain``
|
|
2188
|
+
(type: :class:`~sage.manifolds.differentiable.diff_map.DiffMap`)
|
|
2189
|
+
If ``None``, the restriction of ``self._vmodule._dest_map`` to `U` is
|
|
2190
|
+
used.
|
|
2191
|
+
|
|
2192
|
+
OUTPUT:
|
|
2193
|
+
|
|
2194
|
+
- instance of :class:`PseudoRiemannianMetricParal` representing the
|
|
2195
|
+
restriction.
|
|
2196
|
+
|
|
2197
|
+
EXAMPLES:
|
|
2198
|
+
|
|
2199
|
+
Restriction of a Lorentzian metric on `\RR^2` to the upper half plane::
|
|
2200
|
+
|
|
2201
|
+
sage: M = Manifold(2, 'M')
|
|
2202
|
+
sage: X.<x,y> = M.chart()
|
|
2203
|
+
sage: g = M.lorentzian_metric('g')
|
|
2204
|
+
sage: g[0,0], g[1,1] = -1, 1
|
|
2205
|
+
sage: U = M.open_subset('U', coord_def={X: y>0})
|
|
2206
|
+
sage: gU = g.restrict(U); gU
|
|
2207
|
+
Lorentzian metric g on the Open subset U of the 2-dimensional
|
|
2208
|
+
differentiable manifold M
|
|
2209
|
+
sage: gU.signature()
|
|
2210
|
+
0
|
|
2211
|
+
sage: gU.display()
|
|
2212
|
+
g = -dx⊗dx + dy⊗dy
|
|
2213
|
+
"""
|
|
2214
|
+
if subdomain == self._domain:
|
|
2215
|
+
return self
|
|
2216
|
+
if subdomain not in self._restrictions:
|
|
2217
|
+
# Construct the restriction at the tensor field level:
|
|
2218
|
+
resu = TensorFieldParal.restrict(self, subdomain, dest_map=dest_map)
|
|
2219
|
+
# the type is correctly handled by TensorFieldParal.restrict, i.e.
|
|
2220
|
+
# resu is of type self.__class__, but the signature is not handled
|
|
2221
|
+
# by TensorFieldParal.restrict; we have to set it here:
|
|
2222
|
+
resu._signature = self._signature
|
|
2223
|
+
resu._signature_pm = self._signature_pm
|
|
2224
|
+
resu._indic_signat = self._indic_signat
|
|
2225
|
+
# Restrictions of derived quantities:
|
|
2226
|
+
resu._inverse = self.inverse().restrict(subdomain)
|
|
2227
|
+
if self._connection is not None:
|
|
2228
|
+
resu._connection = self._connection.restrict(subdomain)
|
|
2229
|
+
if self._ricci_scalar is not None:
|
|
2230
|
+
resu._ricci_scalar = self._ricci_scalar.restrict(subdomain)
|
|
2231
|
+
if self._weyl is not None:
|
|
2232
|
+
resu._weyl = self._weyl.restrict(subdomain)
|
|
2233
|
+
if self._vol_forms != []:
|
|
2234
|
+
for eps in self._vol_forms:
|
|
2235
|
+
resu._vol_forms.append(eps.restrict(subdomain))
|
|
2236
|
+
# NB: no initialization of resu._determinants nor
|
|
2237
|
+
# resu._sqrt_abs_dets
|
|
2238
|
+
# The restriction is ready:
|
|
2239
|
+
self._restrictions[subdomain] = resu
|
|
2240
|
+
return self._restrictions[subdomain]
|
|
2241
|
+
|
|
2242
|
+
def set(self, symbiform):
|
|
2243
|
+
r"""
|
|
2244
|
+
Define the metric from a field of symmetric bilinear forms.
|
|
2245
|
+
|
|
2246
|
+
INPUT:
|
|
2247
|
+
|
|
2248
|
+
- ``symbiform`` -- instance of
|
|
2249
|
+
:class:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal`
|
|
2250
|
+
representing a field of symmetric bilinear forms
|
|
2251
|
+
|
|
2252
|
+
EXAMPLES::
|
|
2253
|
+
|
|
2254
|
+
sage: M = Manifold(2, 'M')
|
|
2255
|
+
sage: X.<x,y> = M.chart()
|
|
2256
|
+
sage: s = M.sym_bilin_form_field(name='s')
|
|
2257
|
+
sage: s[0,0], s[0,1], s[1,1] = 1+x^2, x*y, 1+y^2
|
|
2258
|
+
sage: g = M.metric('g')
|
|
2259
|
+
sage: g.set(s)
|
|
2260
|
+
sage: g.display()
|
|
2261
|
+
g = (x^2 + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (y^2 + 1) dy⊗dy
|
|
2262
|
+
"""
|
|
2263
|
+
if not isinstance(symbiform, TensorFieldParal):
|
|
2264
|
+
raise TypeError("the argument must be a tensor field with " +
|
|
2265
|
+
"values on a parallelizable domain")
|
|
2266
|
+
if symbiform._tensor_type != (0,2):
|
|
2267
|
+
raise TypeError("the argument must be of tensor type (0,2)")
|
|
2268
|
+
if symbiform._sym != ((0,1),):
|
|
2269
|
+
raise TypeError("the argument must be symmetric")
|
|
2270
|
+
if symbiform._vmodule is not self._vmodule:
|
|
2271
|
+
raise TypeError("the symmetric bilinear form and the metric are " +
|
|
2272
|
+
"not defined on the same vector field module")
|
|
2273
|
+
self._del_derived()
|
|
2274
|
+
self._components.clear()
|
|
2275
|
+
for frame in symbiform._components:
|
|
2276
|
+
self._components[frame] = symbiform._components[frame].copy()
|
|
2277
|
+
for dom, symbiform_rst in symbiform._restrictions.items():
|
|
2278
|
+
rst = self.restrict(dom)
|
|
2279
|
+
rst.set(symbiform_rst)
|
|
2280
|
+
|
|
2281
|
+
def inverse(self, expansion_symbol=None, order=1):
|
|
2282
|
+
r"""
|
|
2283
|
+
Return the inverse metric.
|
|
2284
|
+
|
|
2285
|
+
INPUT:
|
|
2286
|
+
|
|
2287
|
+
- ``expansion_symbol`` -- (default: ``None``) symbolic variable; if
|
|
2288
|
+
specified, the inverse will be expanded in power series with respect
|
|
2289
|
+
to this variable (around its zero value)
|
|
2290
|
+
- ``order`` -- integer (default: 1); the order of the expansion
|
|
2291
|
+
if ``expansion_symbol`` is not ``None``; the *order* is defined as
|
|
2292
|
+
the degree of the polynomial representing the truncated power series
|
|
2293
|
+
in ``expansion_symbol``; currently only first order inverse is
|
|
2294
|
+
supported
|
|
2295
|
+
|
|
2296
|
+
If ``expansion_symbol`` is set, then the zeroth order metric must be
|
|
2297
|
+
invertible. Moreover, subsequent calls to this method will return
|
|
2298
|
+
a cached value, even when called with the default value (to enable
|
|
2299
|
+
computation of derived quantities). To reset, use :meth:`_del_derived`.
|
|
2300
|
+
|
|
2301
|
+
OUTPUT:
|
|
2302
|
+
|
|
2303
|
+
- instance of
|
|
2304
|
+
:class:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal`
|
|
2305
|
+
with ``tensor_type`` = (2,0) representing the inverse metric
|
|
2306
|
+
|
|
2307
|
+
EXAMPLES:
|
|
2308
|
+
|
|
2309
|
+
Inverse metric on a 2-dimensional manifold::
|
|
2310
|
+
|
|
2311
|
+
sage: M = Manifold(2, 'M', start_index=1)
|
|
2312
|
+
sage: c_xy.<x,y> = M.chart()
|
|
2313
|
+
sage: g = M.metric('g')
|
|
2314
|
+
sage: g[1,1], g[1,2], g[2,2] = 1+x, x*y, 1-x
|
|
2315
|
+
sage: g[:] # components in the manifold's default frame
|
|
2316
|
+
[ x + 1 x*y]
|
|
2317
|
+
[ x*y -x + 1]
|
|
2318
|
+
sage: ig = g.inverse() ; ig
|
|
2319
|
+
Tensor field inv_g of type (2,0) on the 2-dimensional
|
|
2320
|
+
differentiable manifold M
|
|
2321
|
+
sage: ig[:]
|
|
2322
|
+
[ (x - 1)/(x^2*y^2 + x^2 - 1) x*y/(x^2*y^2 + x^2 - 1)]
|
|
2323
|
+
[ x*y/(x^2*y^2 + x^2 - 1) -(x + 1)/(x^2*y^2 + x^2 - 1)]
|
|
2324
|
+
|
|
2325
|
+
If the metric is modified, the inverse metric is automatically updated::
|
|
2326
|
+
|
|
2327
|
+
sage: g[1,2] = 0 ; g[:]
|
|
2328
|
+
[ x + 1 0]
|
|
2329
|
+
[ 0 -x + 1]
|
|
2330
|
+
sage: g.inverse()[:]
|
|
2331
|
+
[ 1/(x + 1) 0]
|
|
2332
|
+
[ 0 -1/(x - 1)]
|
|
2333
|
+
|
|
2334
|
+
Using SymPy as symbolic engine::
|
|
2335
|
+
|
|
2336
|
+
sage: M.set_calculus_method('sympy')
|
|
2337
|
+
sage: g[1,1], g[1,2], g[2,2] = 1+x, x*y, 1-x
|
|
2338
|
+
sage: g[:] # components in the manifold's default frame
|
|
2339
|
+
[x + 1 x*y]
|
|
2340
|
+
[ x*y 1 - x]
|
|
2341
|
+
sage: g.inverse()[:]
|
|
2342
|
+
[ (x - 1)/(x**2*y**2 + x**2 - 1) x*y/(x**2*y**2 + x**2 - 1)]
|
|
2343
|
+
[ x*y/(x**2*y**2 + x**2 - 1) -(x + 1)/(x**2*y**2 + x**2 - 1)]
|
|
2344
|
+
|
|
2345
|
+
Demonstration of the series expansion capabilities::
|
|
2346
|
+
|
|
2347
|
+
sage: M = Manifold(4, 'M', structure='Lorentzian')
|
|
2348
|
+
sage: C.<t,x,y,z> = M.chart()
|
|
2349
|
+
sage: e = var('e')
|
|
2350
|
+
sage: g = M.metric()
|
|
2351
|
+
sage: h = M.tensor_field(0, 2, sym=(0,1))
|
|
2352
|
+
sage: g[0, 0], g[1, 1], g[2, 2], g[3, 3] = -1, 1, 1, 1
|
|
2353
|
+
sage: h[0, 1], h[1, 2], h[2, 3] = 1, 1, 1
|
|
2354
|
+
sage: g.set(g + e*h)
|
|
2355
|
+
|
|
2356
|
+
If ``e`` is a small parameter, ``g`` is a tridiagonal approximation of
|
|
2357
|
+
the Minkowski metric::
|
|
2358
|
+
|
|
2359
|
+
sage: g[:]
|
|
2360
|
+
[-1 e 0 0]
|
|
2361
|
+
[ e 1 e 0]
|
|
2362
|
+
[ 0 e 1 e]
|
|
2363
|
+
[ 0 0 e 1]
|
|
2364
|
+
|
|
2365
|
+
The inverse, truncated to first order in ``e``, is::
|
|
2366
|
+
|
|
2367
|
+
sage: g.inverse(expansion_symbol=e)[:]
|
|
2368
|
+
[-1 e 0 0]
|
|
2369
|
+
[ e 1 -e 0]
|
|
2370
|
+
[ 0 -e 1 -e]
|
|
2371
|
+
[ 0 0 -e 1]
|
|
2372
|
+
|
|
2373
|
+
If ``inverse()`` is called subsequently, the result will be the same.
|
|
2374
|
+
This allows for all computations to be made to first order::
|
|
2375
|
+
|
|
2376
|
+
sage: g.inverse()[:]
|
|
2377
|
+
[-1 e 0 0]
|
|
2378
|
+
[ e 1 -e 0]
|
|
2379
|
+
[ 0 -e 1 -e]
|
|
2380
|
+
[ 0 0 -e 1]
|
|
2381
|
+
"""
|
|
2382
|
+
if expansion_symbol is not None:
|
|
2383
|
+
if (self._inverse is not None and bool(self._inverse._components)
|
|
2384
|
+
and self._inverse._components.values()[0][0,0]._expansion_symbol
|
|
2385
|
+
== expansion_symbol
|
|
2386
|
+
and self._inverse._components.values()[0][0,0]._order == order):
|
|
2387
|
+
return self._inverse
|
|
2388
|
+
|
|
2389
|
+
if order != 1:
|
|
2390
|
+
raise NotImplementedError("only first order inverse is implemented")
|
|
2391
|
+
decompo = self.series_expansion(expansion_symbol, order)
|
|
2392
|
+
g0 = decompo[0]
|
|
2393
|
+
g1 = decompo[1]
|
|
2394
|
+
|
|
2395
|
+
g0m = self._new_instance() # needed because only metrics have
|
|
2396
|
+
g0m.set_comp()[:] = g0[:] # an "inverse" method.
|
|
2397
|
+
|
|
2398
|
+
contraction = g1.contract(0, g0m.inverse(), 0)
|
|
2399
|
+
contraction = contraction.contract(1, g0m.inverse(), 1)
|
|
2400
|
+
self._inverse = g0m.inverse() - expansion_symbol * contraction
|
|
2401
|
+
self._inverse.set_calc_order(expansion_symbol, order)
|
|
2402
|
+
return self._inverse
|
|
2403
|
+
|
|
2404
|
+
from sage.matrix.constructor import matrix
|
|
2405
|
+
from sage.tensor.modules.comp import CompFullySym
|
|
2406
|
+
# Is the inverse metric up to date ?
|
|
2407
|
+
for frame in self._components:
|
|
2408
|
+
if frame not in self._inverse._components:
|
|
2409
|
+
# the computation is necessary
|
|
2410
|
+
fmodule = self._fmodule
|
|
2411
|
+
si = fmodule._sindex
|
|
2412
|
+
nsi = fmodule._rank + si
|
|
2413
|
+
dom = self._domain
|
|
2414
|
+
cinv = CompFullySym(fmodule._ring, frame, 2, start_index=si,
|
|
2415
|
+
output_formatter=fmodule._output_formatter)
|
|
2416
|
+
cinv_scal = {} # dict. of scalars representing the components
|
|
2417
|
+
# of the inverse (keys: comp. indices)
|
|
2418
|
+
for i in range(si, nsi):
|
|
2419
|
+
for j in range(i, nsi): # symmetry taken into account
|
|
2420
|
+
cinv_scal[(i,j)] = dom.scalar_field()
|
|
2421
|
+
for chart in dom.top_charts():
|
|
2422
|
+
# TODO: do the computation without the 'SR' enforcement
|
|
2423
|
+
try:
|
|
2424
|
+
gmat = matrix(
|
|
2425
|
+
[[self.comp(frame)[i, j, chart].expr(method='SR')
|
|
2426
|
+
for j in range(si, nsi)] for i in range(si, nsi)])
|
|
2427
|
+
gmat_inv = gmat.inverse()
|
|
2428
|
+
except (KeyError, ValueError):
|
|
2429
|
+
continue
|
|
2430
|
+
for i in range(si, nsi):
|
|
2431
|
+
for j in range(i, nsi):
|
|
2432
|
+
val = chart.simplify(gmat_inv[i-si,j-si], method='SR')
|
|
2433
|
+
cinv_scal[(i,j)].add_expr(val, chart=chart)
|
|
2434
|
+
for i in range(si, nsi):
|
|
2435
|
+
for j in range(i, nsi):
|
|
2436
|
+
cinv[i,j] = cinv_scal[(i,j)]
|
|
2437
|
+
self._inverse._components[frame] = cinv
|
|
2438
|
+
return self._inverse
|
|
2439
|
+
|
|
2440
|
+
def ricci_scalar(self, name=None, latex_name=None):
|
|
2441
|
+
r"""
|
|
2442
|
+
Return the metric's Ricci scalar.
|
|
2443
|
+
|
|
2444
|
+
The Ricci scalar is the scalar field `r` defined from the Ricci tensor
|
|
2445
|
+
`Ric` and the metric tensor `g` by
|
|
2446
|
+
|
|
2447
|
+
.. MATH::
|
|
2448
|
+
|
|
2449
|
+
r = g^{ij} Ric_{ij}
|
|
2450
|
+
|
|
2451
|
+
INPUT:
|
|
2452
|
+
|
|
2453
|
+
- ``name`` -- (default: ``None``) name given to the Ricci scalar;
|
|
2454
|
+
if none, it is set to "r(g)", where "g" is the metric's name
|
|
2455
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
2456
|
+
Ricci scalar; if none, it is set to "\\mathrm{r}(g)", where "g"
|
|
2457
|
+
is the metric's name
|
|
2458
|
+
|
|
2459
|
+
OUTPUT:
|
|
2460
|
+
|
|
2461
|
+
- the Ricci scalar `r`, as an instance of
|
|
2462
|
+
:class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
|
|
2463
|
+
|
|
2464
|
+
EXAMPLES:
|
|
2465
|
+
|
|
2466
|
+
Ricci scalar of the standard metric on the 2-sphere::
|
|
2467
|
+
|
|
2468
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
2469
|
+
sage: U = M.open_subset('U') # the complement of a meridian (domain of spherical coordinates)
|
|
2470
|
+
sage: c_spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
2471
|
+
sage: a = var('a') # the sphere radius
|
|
2472
|
+
sage: g = U.metric('g')
|
|
2473
|
+
sage: g[1,1], g[2,2] = a^2, a^2*sin(th)^2
|
|
2474
|
+
sage: g.display() # standard metric on the 2-sphere of radius a:
|
|
2475
|
+
g = a^2 dth⊗dth + a^2*sin(th)^2 dph⊗dph
|
|
2476
|
+
sage: g.ricci_scalar()
|
|
2477
|
+
Scalar field r(g) on the Open subset U of the 2-dimensional
|
|
2478
|
+
differentiable manifold S^2
|
|
2479
|
+
sage: g.ricci_scalar().display() # The Ricci scalar is constant:
|
|
2480
|
+
r(g): U → ℝ
|
|
2481
|
+
(th, ph) ↦ 2/a^2
|
|
2482
|
+
|
|
2483
|
+
"""
|
|
2484
|
+
if self._ricci_scalar is None:
|
|
2485
|
+
manif = self._ambient_domain
|
|
2486
|
+
ric = self.ricci()
|
|
2487
|
+
ig = self.inverse()
|
|
2488
|
+
frame = ig.common_basis(ric)
|
|
2489
|
+
cric = ric._components[frame]
|
|
2490
|
+
cig = ig._components[frame]
|
|
2491
|
+
rsum1 = 0
|
|
2492
|
+
for i in manif.irange():
|
|
2493
|
+
rsum1 += cig[[i,i]] * cric[[i,i]]
|
|
2494
|
+
rsum2 = 0
|
|
2495
|
+
for i in manif.irange():
|
|
2496
|
+
for j in manif.irange(start=i+1):
|
|
2497
|
+
rsum2 += cig[[i,j]] * cric[[i,j]]
|
|
2498
|
+
self._ricci_scalar = rsum1 + 2*rsum2
|
|
2499
|
+
if name is None:
|
|
2500
|
+
self._ricci_scalar._name = "r(" + self._name + ")"
|
|
2501
|
+
else:
|
|
2502
|
+
self._ricci_scalar._name = name
|
|
2503
|
+
if latex_name is None:
|
|
2504
|
+
self._ricci_scalar._latex_name = r"\mathrm{r}\left(" + \
|
|
2505
|
+
self._latex_name + r"\right)"
|
|
2506
|
+
else:
|
|
2507
|
+
self._ricci_scalar._latex_name = latex_name
|
|
2508
|
+
return self._ricci_scalar
|
|
2509
|
+
|
|
2510
|
+
|
|
2511
|
+
#****************************************************************************************************
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
class DegenerateMetric(TensorField):
|
|
2515
|
+
r"""
|
|
2516
|
+
Degenerate (or null or lightlike) metric with values on an open subset of a
|
|
2517
|
+
differentiable manifold.
|
|
2518
|
+
|
|
2519
|
+
An instance of this class is a field of degenerate symmetric bilinear
|
|
2520
|
+
forms (metric field) along a differentiable manifold `U` with
|
|
2521
|
+
values on a differentiable manifold `M` over `\RR`, via a differentiable
|
|
2522
|
+
mapping `\Phi: U \rightarrow M`.
|
|
2523
|
+
The standard case of a degenerate metric field *on* a manifold corresponds to `U=M`
|
|
2524
|
+
and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
2525
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open interval
|
|
2526
|
+
of `\RR`).
|
|
2527
|
+
|
|
2528
|
+
A *degenerate metric* `g` is a field on `U`, such that at each point `p\in U`, `g(p)`
|
|
2529
|
+
is a bilinear map of the type:
|
|
2530
|
+
|
|
2531
|
+
.. MATH::
|
|
2532
|
+
|
|
2533
|
+
g(p):\ T_q M\times T_q M \longrightarrow \RR
|
|
2534
|
+
|
|
2535
|
+
where `T_q M` stands for the tangent space to the
|
|
2536
|
+
manifold `M` at the point `q=\Phi(p)`, such that `g(p)` is symmetric:
|
|
2537
|
+
`\forall (u,v)\in T_q M\times T_q M, \ g(p)(v,u) = g(p)(u,v)`
|
|
2538
|
+
and degenerate:
|
|
2539
|
+
`\exists v\in T_q M;\ \ g(p)(u,v) = 0\ \ \forall u\in T_qM`.
|
|
2540
|
+
|
|
2541
|
+
.. NOTE::
|
|
2542
|
+
|
|
2543
|
+
If `M` is parallelizable, the class :class:`DegenerateMetricParal`
|
|
2544
|
+
should be used instead.
|
|
2545
|
+
|
|
2546
|
+
INPUT:
|
|
2547
|
+
|
|
2548
|
+
- ``vector_field_module`` -- module `\mathfrak{X}(U,\Phi)` of vector
|
|
2549
|
+
fields along `U` with values on `\Phi(U)\subset M`
|
|
2550
|
+
- ``name`` -- name given to the metric
|
|
2551
|
+
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
|
|
2552
|
+
tuple: `S = (n_+, n_-, n_0)`, where `n_+` (resp. `n_-`, resp. `n_0`) is the
|
|
2553
|
+
number of positive terms (resp. negative terms, resp. zero tems) in any
|
|
2554
|
+
diagonal writing of the metric components; if ``signature`` is not
|
|
2555
|
+
provided, `S` is set to `(ndim-1, 0, 1)`, being `ndim` the manifold's dimension
|
|
2556
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the metric;
|
|
2557
|
+
if ``None``, it is formed from ``name``
|
|
2558
|
+
|
|
2559
|
+
EXAMPLES:
|
|
2560
|
+
|
|
2561
|
+
Lightlike cone::
|
|
2562
|
+
|
|
2563
|
+
sage: M = Manifold(3, 'M'); X.<x,y,z> = M.chart()
|
|
2564
|
+
sage: g = M.metric('g', signature=(2,0,1)); g
|
|
2565
|
+
degenerate metric g on the 3-dimensional differentiable manifold M
|
|
2566
|
+
sage: det(g)
|
|
2567
|
+
Scalar field zero on the 3-dimensional differentiable manifold M
|
|
2568
|
+
sage: g.parent()
|
|
2569
|
+
Free module T^(0,2)(M) of type-(0,2) tensors fields on the
|
|
2570
|
+
3-dimensional differentiable manifold M
|
|
2571
|
+
sage: g[0,0], g[0,1], g[0,2] = (y^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2572
|
+
....: - x*y/(x^2 + y^2 + z^2), - x*z/(x^2 + y^2 + z^2)
|
|
2573
|
+
sage: g[1,1], g[1,2], g[2,2] = (x^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2574
|
+
....: - y*z/(x^2 + y^2 + z^2), (x^2 + y^2)/(x^2 + y^2 + z^2)
|
|
2575
|
+
sage: g.disp()
|
|
2576
|
+
g = (y^2 + z^2)/(x^2 + y^2 + z^2) dx⊗dx - x*y/(x^2 + y^2 + z^2) dx⊗dy
|
|
2577
|
+
- x*z/(x^2 + y^2 + z^2) dx⊗dz - x*y/(x^2 + y^2 + z^2) dy⊗dx
|
|
2578
|
+
+ (x^2 + z^2)/(x^2 + y^2 + z^2) dy⊗dy - y*z/(x^2 + y^2 + z^2) dy⊗dz
|
|
2579
|
+
- x*z/(x^2 + y^2 + z^2) dz⊗dx - y*z/(x^2 + y^2 + z^2) dz⊗dy
|
|
2580
|
+
+ (x^2 + y^2)/(x^2 + y^2 + z^2) dz⊗dz
|
|
2581
|
+
|
|
2582
|
+
The position vector is a lightlike vector field::
|
|
2583
|
+
|
|
2584
|
+
sage: v = M.vector_field()
|
|
2585
|
+
sage: v[0], v[1], v[2] = x , y, z
|
|
2586
|
+
sage: g(v, v).disp()
|
|
2587
|
+
M → ℝ
|
|
2588
|
+
(x, y, z) ↦ 0
|
|
2589
|
+
"""
|
|
2590
|
+
|
|
2591
|
+
def __init__(self, vector_field_module, name, signature=None,
|
|
2592
|
+
latex_name=None):
|
|
2593
|
+
r"""
|
|
2594
|
+
Construct a metric.
|
|
2595
|
+
|
|
2596
|
+
TESTS::
|
|
2597
|
+
|
|
2598
|
+
sage: M = Manifold(4, 'M', structure='Lorentzian')
|
|
2599
|
+
sage: var('m'); assume(m>0)
|
|
2600
|
+
m
|
|
2601
|
+
sage: Int = M.open_subset('Int')
|
|
2602
|
+
sage: X.<t,r,th,ph>=Int.chart(r"t r:(0,2*m) th:(0,pi):\theta ph:(0,2*pi):\phi")
|
|
2603
|
+
sage: XM = M.vector_field_module(); e = X.frame()
|
|
2604
|
+
sage: from sage.manifolds.differentiable.metric import \
|
|
2605
|
+
....: DegenerateMetric
|
|
2606
|
+
sage: g = DegenerateMetric(XM, 'g', signature=(2,1,1)); g
|
|
2607
|
+
degenerate metric g on the 4-dimensional Lorentzian manifold M
|
|
2608
|
+
sage: g[e, 0,0], g[e, 0,1], g[e, 1,1], g[e, 2,2], \
|
|
2609
|
+
....: g[e, 3,3] = -1+2*m/r, 2*m/r, 1+2*m/r, r^2, r^2*sin(th)^2
|
|
2610
|
+
sage: g.disp(e)
|
|
2611
|
+
g = (2*m/r - 1) dt⊗dt + 2*m/r dt⊗dr + 2*m/r dr⊗dt + (2*m/r + 1) dr⊗dr
|
|
2612
|
+
+ r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
2613
|
+
"""
|
|
2614
|
+
TensorField.__init__(self, vector_field_module, (0,2),
|
|
2615
|
+
name=name, latex_name=latex_name, sym=(0,1))
|
|
2616
|
+
# signature:
|
|
2617
|
+
ndim = self._ambient_domain.dimension()
|
|
2618
|
+
if signature is None:
|
|
2619
|
+
signature = (ndim-1,0,1)
|
|
2620
|
+
else:
|
|
2621
|
+
try:
|
|
2622
|
+
for elt in signature:
|
|
2623
|
+
if (elt < 0) or (not isinstance(elt, (int, Integer))):
|
|
2624
|
+
raise ValueError("{} must be a positive integer".format(elt))
|
|
2625
|
+
if elt > ndim:
|
|
2626
|
+
raise ValueError("{} must be less than {}".format(elt,ndim))
|
|
2627
|
+
sign = signature[0]+signature[1]+signature[2]
|
|
2628
|
+
if sign != ndim:
|
|
2629
|
+
raise ValueError("{} is different from {}".format(sign, ndim))
|
|
2630
|
+
except TypeError:
|
|
2631
|
+
raise TypeError("signature must be an iterable")
|
|
2632
|
+
self._signature = (signature[0],signature[1],signature[2])
|
|
2633
|
+
# the tuple (n_+, n_-, n_0):
|
|
2634
|
+
self._signature_pm = self._signature
|
|
2635
|
+
|
|
2636
|
+
def _repr_(self):
|
|
2637
|
+
r"""
|
|
2638
|
+
String representation of the object.
|
|
2639
|
+
|
|
2640
|
+
TESTS::
|
|
2641
|
+
|
|
2642
|
+
sage: M = Manifold(3, 'M')
|
|
2643
|
+
sage: g = M.metric('g', signature=(1,1,1))
|
|
2644
|
+
sage: g._repr_()
|
|
2645
|
+
'degenerate metric g on the 3-dimensional differentiable manifold M'
|
|
2646
|
+
"""
|
|
2647
|
+
return self._final_repr("degenerate metric "+self._name + " ")
|
|
2648
|
+
|
|
2649
|
+
def _new_instance(self):
|
|
2650
|
+
r"""
|
|
2651
|
+
Create an instance of the same class as ``self`` with the same
|
|
2652
|
+
signature.
|
|
2653
|
+
|
|
2654
|
+
TESTS::
|
|
2655
|
+
|
|
2656
|
+
sage: M = Manifold(3, 'M')
|
|
2657
|
+
sage: g = M.metric('g', signature=(1,1,1))
|
|
2658
|
+
sage: g1 = g._new_instance(); g1
|
|
2659
|
+
degenerate metric unnamed metric on the 3-dimensional differentiable manifold M
|
|
2660
|
+
sage: type(g1) == type(g)
|
|
2661
|
+
True
|
|
2662
|
+
sage: g1.parent() is g.parent()
|
|
2663
|
+
True
|
|
2664
|
+
sage: g1.signature() == g.signature()
|
|
2665
|
+
True
|
|
2666
|
+
"""
|
|
2667
|
+
return type(self)(self._vmodule, 'unnamed metric',
|
|
2668
|
+
signature=self._signature,
|
|
2669
|
+
latex_name=r'\text{unnamed metric}')
|
|
2670
|
+
|
|
2671
|
+
def signature(self):
|
|
2672
|
+
r"""
|
|
2673
|
+
Signature of the metric.
|
|
2674
|
+
|
|
2675
|
+
OUTPUT:
|
|
2676
|
+
|
|
2677
|
+
- signature of a degenerate metric is defined as the tuple
|
|
2678
|
+
`(n_+,n_-,n_0)`, where `n_+` (resp. `n_-`, resp. `n_0`) is the number of
|
|
2679
|
+
positive terms (resp. negative terms, resp. zero terms) eigenvalues
|
|
2680
|
+
|
|
2681
|
+
EXAMPLES:
|
|
2682
|
+
|
|
2683
|
+
Signatures on a 3-dimensional manifold::
|
|
2684
|
+
|
|
2685
|
+
sage: M = Manifold(3, 'M')
|
|
2686
|
+
sage: g = M.metric('g', signature=(1,1,1))
|
|
2687
|
+
sage: g.signature()
|
|
2688
|
+
(1, 1, 1)
|
|
2689
|
+
sage: M = Manifold(3, 'M', structure='degenerate_metric')
|
|
2690
|
+
sage: g = M.metric()
|
|
2691
|
+
sage: g.signature()
|
|
2692
|
+
(0, 2, 1)
|
|
2693
|
+
"""
|
|
2694
|
+
return self._signature
|
|
2695
|
+
|
|
2696
|
+
def set(self, symbiform):
|
|
2697
|
+
r"""
|
|
2698
|
+
Define the metric from a field of symmetric bilinear forms.
|
|
2699
|
+
|
|
2700
|
+
INPUT:
|
|
2701
|
+
|
|
2702
|
+
- ``symbiform`` -- instance of
|
|
2703
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
2704
|
+
representing a field of symmetric bilinear forms
|
|
2705
|
+
|
|
2706
|
+
EXAMPLES:
|
|
2707
|
+
|
|
2708
|
+
Metric defined from a field of symmetric bilinear forms on a
|
|
2709
|
+
non-parallelizable 2-dimensional manifold::
|
|
2710
|
+
|
|
2711
|
+
sage: M = Manifold(2, 'M')
|
|
2712
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
2713
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
2714
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
2715
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W',
|
|
2716
|
+
....: restrictions1= x>0, restrictions2= u+v>0)
|
|
2717
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
2718
|
+
sage: W = U.intersection(V)
|
|
2719
|
+
sage: eU = c_xy.frame() ; eV = c_uv.frame()
|
|
2720
|
+
sage: h = M.sym_bilin_form_field(name='h')
|
|
2721
|
+
sage: h[eU,0,0], h[eU,0,1], h[eU,1,1] = 1+x, x*y, 1-y
|
|
2722
|
+
sage: h.add_comp_by_continuation(eV, W, c_uv)
|
|
2723
|
+
sage: h.display(eU)
|
|
2724
|
+
h = (x + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (-y + 1) dy⊗dy
|
|
2725
|
+
sage: h.display(eV)
|
|
2726
|
+
h = (1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2) du⊗du + 1/4*u du⊗dv
|
|
2727
|
+
+ 1/4*u dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2) dv⊗dv
|
|
2728
|
+
sage: g = M.metric('g')
|
|
2729
|
+
sage: g.set(h)
|
|
2730
|
+
sage: g.display(eU)
|
|
2731
|
+
g = (x + 1) dx⊗dx + x*y dx⊗dy + x*y dy⊗dx + (-y + 1) dy⊗dy
|
|
2732
|
+
sage: g.display(eV)
|
|
2733
|
+
g = (1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2) du⊗du + 1/4*u du⊗dv
|
|
2734
|
+
+ 1/4*u dv⊗du + (-1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2) dv⊗dv
|
|
2735
|
+
"""
|
|
2736
|
+
if not isinstance(symbiform, TensorField):
|
|
2737
|
+
raise TypeError("the argument must be a tensor field")
|
|
2738
|
+
if symbiform._tensor_type != (0,2):
|
|
2739
|
+
raise TypeError("the argument must be of tensor type (0,2)")
|
|
2740
|
+
if symbiform._sym != ((0,1),):
|
|
2741
|
+
raise TypeError("the argument must be symmetric")
|
|
2742
|
+
if not symbiform._domain.is_subset(self._domain):
|
|
2743
|
+
raise TypeError("the symmetric bilinear form is not defined " +
|
|
2744
|
+
"on the metric domain")
|
|
2745
|
+
self._restrictions.clear()
|
|
2746
|
+
if isinstance(symbiform, TensorFieldParal):
|
|
2747
|
+
rst = self.restrict(symbiform._domain)
|
|
2748
|
+
rst.set(symbiform)
|
|
2749
|
+
else:
|
|
2750
|
+
for dom, symbiform_rst in symbiform._restrictions.items():
|
|
2751
|
+
rst = self.restrict(dom)
|
|
2752
|
+
rst.set(symbiform_rst)
|
|
2753
|
+
|
|
2754
|
+
def restrict(self, subdomain, dest_map=None):
|
|
2755
|
+
r"""
|
|
2756
|
+
Return the restriction of the metric to some subdomain.
|
|
2757
|
+
|
|
2758
|
+
If the restriction has not been defined yet, it is constructed here.
|
|
2759
|
+
|
|
2760
|
+
INPUT:
|
|
2761
|
+
|
|
2762
|
+
- ``subdomain`` -- open subset `U` of the metric's domain (must be an
|
|
2763
|
+
instance of :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`)
|
|
2764
|
+
- ``dest_map`` -- (default: ``None``) destination map
|
|
2765
|
+
`\Phi:\ U \rightarrow V`, where `V` is a subdomain of
|
|
2766
|
+
``self._codomain``
|
|
2767
|
+
(type: :class:`~sage.manifolds.differentiable.diff_map.DiffMap`)
|
|
2768
|
+
If ``None``, the restriction of ``self._vmodule._dest_map`` to `U` is
|
|
2769
|
+
used.
|
|
2770
|
+
|
|
2771
|
+
OUTPUT:
|
|
2772
|
+
|
|
2773
|
+
- instance of :class:`DegenerateMetric` representing the
|
|
2774
|
+
restriction.
|
|
2775
|
+
|
|
2776
|
+
EXAMPLES::
|
|
2777
|
+
|
|
2778
|
+
sage: M = Manifold(5, 'M')
|
|
2779
|
+
sage: g = M.metric('g', signature=(3,1,1))
|
|
2780
|
+
sage: U = M.open_subset('U')
|
|
2781
|
+
sage: g.restrict(U)
|
|
2782
|
+
degenerate metric g on the Open subset U of the 5-dimensional
|
|
2783
|
+
differentiable manifold M
|
|
2784
|
+
sage: g.restrict(U).signature()
|
|
2785
|
+
(3, 1, 1)
|
|
2786
|
+
|
|
2787
|
+
See the top documentation of :class:`DegenerateMetric` for more
|
|
2788
|
+
examples.
|
|
2789
|
+
"""
|
|
2790
|
+
if subdomain == self._domain:
|
|
2791
|
+
return self
|
|
2792
|
+
if subdomain not in self._restrictions:
|
|
2793
|
+
# Construct the restriction at the tensor field level:
|
|
2794
|
+
resu = TensorField.restrict(self, subdomain, dest_map=dest_map)
|
|
2795
|
+
# the type is correctly handled by TensorField.restrict, i.e.
|
|
2796
|
+
# resu is of type self.__class__, but the signature is not handled
|
|
2797
|
+
# by TensorField.restrict; we have to set it here:
|
|
2798
|
+
resu._signature = self._signature
|
|
2799
|
+
resu._signature_pm = self._signature_pm
|
|
2800
|
+
self._restrictions[subdomain] = resu
|
|
2801
|
+
return self._restrictions[subdomain]
|
|
2802
|
+
|
|
2803
|
+
def determinant(self):
|
|
2804
|
+
r"""
|
|
2805
|
+
Determinant of a degenerate metric is always '0'.
|
|
2806
|
+
|
|
2807
|
+
EXAMPLES::
|
|
2808
|
+
|
|
2809
|
+
sage: S = Manifold(2, 'S')
|
|
2810
|
+
sage: g = S.metric('g', signature=([0,1,1]))
|
|
2811
|
+
sage: g.determinant()
|
|
2812
|
+
Scalar field zero on the 2-dimensional differentiable manifold S
|
|
2813
|
+
"""
|
|
2814
|
+
return self._domain.zero_scalar_field()
|
|
2815
|
+
|
|
2816
|
+
det = determinant
|
|
2817
|
+
|
|
2818
|
+
#****************************************************************************************
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
class DegenerateMetricParal(DegenerateMetric, TensorFieldParal):
|
|
2822
|
+
r"""
|
|
2823
|
+
Degenerate (or null or lightlike) metric with values on an open subset of a
|
|
2824
|
+
differentiable manifold.
|
|
2825
|
+
|
|
2826
|
+
An instance of this class is a field of degenerate symmetric bilinear
|
|
2827
|
+
forms (metric field) along a differentiable manifold `U` with
|
|
2828
|
+
values on a differentiable manifold `M` over `\RR`, via a differentiable
|
|
2829
|
+
mapping `\Phi: U \rightarrow M`.
|
|
2830
|
+
The standard case of a degenerate metric field *on* a manifold corresponds
|
|
2831
|
+
to `U=M` and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
2832
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open interval
|
|
2833
|
+
of `\RR`).
|
|
2834
|
+
|
|
2835
|
+
A *degenerate metric* `g` is a field on `U`, such that at each point
|
|
2836
|
+
`p\in U`, `g(p)` is a bilinear map of the type:
|
|
2837
|
+
|
|
2838
|
+
.. MATH::
|
|
2839
|
+
|
|
2840
|
+
g(p):\ T_q M\times T_q M \longrightarrow \RR
|
|
2841
|
+
|
|
2842
|
+
where `T_q M` stands for the tangent space to the
|
|
2843
|
+
manifold `M` at the point `q=\Phi(p)`, such that `g(p)` is symmetric:
|
|
2844
|
+
`\forall (u,v)\in T_q M\times T_q M, \ g(p)(v,u) = g(p)(u,v)`
|
|
2845
|
+
and degenerate:
|
|
2846
|
+
`\exists v\in T_q M;\ \ g(p)(u,v) = 0\ \ \forall u\in T_qM`.
|
|
2847
|
+
|
|
2848
|
+
.. NOTE::
|
|
2849
|
+
|
|
2850
|
+
If `M` is not parallelizable, the class :class:`DegenerateMetric`
|
|
2851
|
+
should be used instead.
|
|
2852
|
+
|
|
2853
|
+
INPUT:
|
|
2854
|
+
|
|
2855
|
+
- ``vector_field_module`` -- module `\mathfrak{X}(U,\Phi)` of vector
|
|
2856
|
+
fields along `U` with values on `\Phi(U)\subset M`
|
|
2857
|
+
- ``name`` -- name given to the metric
|
|
2858
|
+
- ``signature`` -- (default: ``None``) signature `S` of the metric as a
|
|
2859
|
+
tuple: `S = (n_+, n_-, n_0)`, where `n_+` (resp. `n_-`, resp. `n_0`) is the
|
|
2860
|
+
number of positive terms (resp. negative terms, resp. zero tems) in any
|
|
2861
|
+
diagonal writing of the metric components; if ``signature`` is not
|
|
2862
|
+
provided, `S` is set to `(ndim-1, 0, 1)`, being `ndim` the manifold's dimension
|
|
2863
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the metric;
|
|
2864
|
+
if ``None``, it is formed from ``name``
|
|
2865
|
+
|
|
2866
|
+
EXAMPLES:
|
|
2867
|
+
|
|
2868
|
+
Lightlike cone::
|
|
2869
|
+
|
|
2870
|
+
sage: M = Manifold(3, 'M'); X.<x,y,z> = M.chart()
|
|
2871
|
+
sage: g = M.metric('g', signature=(2,0,1)); g
|
|
2872
|
+
degenerate metric g on the 3-dimensional differentiable manifold M
|
|
2873
|
+
sage: det(g)
|
|
2874
|
+
Scalar field zero on the 3-dimensional differentiable manifold M
|
|
2875
|
+
sage: g.parent()
|
|
2876
|
+
Free module T^(0,2)(M) of type-(0,2) tensors fields on the
|
|
2877
|
+
3-dimensional differentiable manifold M
|
|
2878
|
+
sage: g[0,0], g[0,1], g[0,2] = (y^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2879
|
+
....: - x*y/(x^2 + y^2 + z^2), - x*z/(x^2 + y^2 + z^2)
|
|
2880
|
+
sage: g[1,1], g[1,2], g[2,2] = (x^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2881
|
+
....: - y*z/(x^2 + y^2 + z^2), (x^2 + y^2)/(x^2 + y^2 + z^2)
|
|
2882
|
+
sage: g.disp()
|
|
2883
|
+
g = (y^2 + z^2)/(x^2 + y^2 + z^2) dx⊗dx - x*y/(x^2 + y^2 + z^2) dx⊗dy
|
|
2884
|
+
- x*z/(x^2 + y^2 + z^2) dx⊗dz - x*y/(x^2 + y^2 + z^2) dy⊗dx
|
|
2885
|
+
+ (x^2 + z^2)/(x^2 + y^2 + z^2) dy⊗dy - y*z/(x^2 + y^2 + z^2) dy⊗dz
|
|
2886
|
+
- x*z/(x^2 + y^2 + z^2) dz⊗dx - y*z/(x^2 + y^2 + z^2) dz⊗dy
|
|
2887
|
+
+ (x^2 + y^2)/(x^2 + y^2 + z^2) dz⊗dz
|
|
2888
|
+
|
|
2889
|
+
The position vector is a lightlike vector field::
|
|
2890
|
+
|
|
2891
|
+
sage: v = M.vector_field()
|
|
2892
|
+
sage: v[0], v[1], v[2] = x , y, z
|
|
2893
|
+
sage: g(v, v).disp()
|
|
2894
|
+
M → ℝ
|
|
2895
|
+
(x, y, z) ↦ 0
|
|
2896
|
+
"""
|
|
2897
|
+
|
|
2898
|
+
def __init__(self, vector_field_module, name, signature=None,
|
|
2899
|
+
latex_name=None):
|
|
2900
|
+
r"""
|
|
2901
|
+
Construct a metric.
|
|
2902
|
+
|
|
2903
|
+
TESTS::
|
|
2904
|
+
|
|
2905
|
+
sage: M = Manifold(3, 'M'); X.<x,y,z> = M.chart()
|
|
2906
|
+
sage: XM = M.vector_field_module()
|
|
2907
|
+
sage: from sage.manifolds.differentiable.metric import \
|
|
2908
|
+
....: DegenerateMetricParal
|
|
2909
|
+
sage: g = DegenerateMetricParal(XM, 'g', signature=(2,0,1)); g
|
|
2910
|
+
degenerate metric g on the 3-dimensional differentiable manifold M
|
|
2911
|
+
sage: g[0,0], g[0,1], g[0,2] = (y^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2912
|
+
....: - x*y/(x^2 + y^2 + z^2), - x*z/(x^2 + y^2 + z^2)
|
|
2913
|
+
sage: g[1,1], g[1,2], g[2,2] = (x^2 + z^2)/(x^2 + y^2 + z^2), \
|
|
2914
|
+
....: - y*z/(x^2 + y^2 + z^2), (x^2 + y^2)/(x^2 + y^2 + z^2)
|
|
2915
|
+
sage: g.disp()
|
|
2916
|
+
g = (y^2 + z^2)/(x^2 + y^2 + z^2) dx⊗dx - x*y/(x^2 + y^2 + z^2) dx⊗dy
|
|
2917
|
+
- x*z/(x^2 + y^2 + z^2) dx⊗dz - x*y/(x^2 + y^2 + z^2) dy⊗dx
|
|
2918
|
+
+ (x^2 + z^2)/(x^2 + y^2 + z^2) dy⊗dy - y*z/(x^2 + y^2 + z^2) dy⊗dz
|
|
2919
|
+
- x*z/(x^2 + y^2 + z^2) dz⊗dx - y*z/(x^2 + y^2 + z^2) dz⊗dy
|
|
2920
|
+
+ (x^2 + y^2)/(x^2 + y^2 + z^2) dz⊗dz
|
|
2921
|
+
"""
|
|
2922
|
+
TensorFieldParal.__init__(self, vector_field_module, (0,2),
|
|
2923
|
+
name=name, latex_name=latex_name, sym=(0,1))
|
|
2924
|
+
# signature:
|
|
2925
|
+
ndim = self._ambient_domain.dimension()
|
|
2926
|
+
if signature is None:
|
|
2927
|
+
signature = (ndim-1,0,1)
|
|
2928
|
+
else:
|
|
2929
|
+
try:
|
|
2930
|
+
for elt in signature:
|
|
2931
|
+
if (elt < 0) or (not isinstance(elt, (int, Integer))):
|
|
2932
|
+
raise ValueError("{} must be a positive integer".format(elt))
|
|
2933
|
+
sign = signature[0]+signature[1]+signature[2]
|
|
2934
|
+
if sign != ndim:
|
|
2935
|
+
raise ValueError("{} is different from {}".format(sign, ndim))
|
|
2936
|
+
except TypeError:
|
|
2937
|
+
raise TypeError("signature must be an iterable")
|
|
2938
|
+
self._signature = (signature[0],signature[1],signature[2])
|
|
2939
|
+
# the tuple (n_+, n_-, n_0):
|
|
2940
|
+
self._signature_pm = self._signature
|
|
2941
|
+
|
|
2942
|
+
def set(self, symbiform):
|
|
2943
|
+
r"""
|
|
2944
|
+
Define the metric from a field of symmetric bilinear forms.
|
|
2945
|
+
|
|
2946
|
+
INPUT:
|
|
2947
|
+
|
|
2948
|
+
- ``symbiform`` -- instance of
|
|
2949
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
2950
|
+
representing a field of symmetric bilinear forms
|
|
2951
|
+
|
|
2952
|
+
EXAMPLES:
|
|
2953
|
+
|
|
2954
|
+
Metric defined from a field of symmetric bilinear forms on a
|
|
2955
|
+
parallelizable 3-dimensional manifold::
|
|
2956
|
+
|
|
2957
|
+
sage: M = Manifold(3, 'M', start_index=1);
|
|
2958
|
+
sage: X.<x,y,z> = M.chart()
|
|
2959
|
+
sage: dx, dy = X.coframe()[1], X.coframe()[2]
|
|
2960
|
+
sage: b = dx*dx + dy*dy
|
|
2961
|
+
sage: g = M.metric('g', signature=(1,1,1)); g
|
|
2962
|
+
degenerate metric g on the 3-dimensional differentiable manifold M
|
|
2963
|
+
sage: g.set(b)
|
|
2964
|
+
sage: g.display()
|
|
2965
|
+
g = dx⊗dx + dy⊗dy
|
|
2966
|
+
"""
|
|
2967
|
+
if not isinstance(symbiform, TensorFieldParal):
|
|
2968
|
+
raise TypeError("the argument must be a tensor field with " +
|
|
2969
|
+
"values on a parallelizable domain")
|
|
2970
|
+
if symbiform._tensor_type != (0,2):
|
|
2971
|
+
raise TypeError("the argument must be of tensor type (0,2)")
|
|
2972
|
+
if symbiform._sym != ((0,1),):
|
|
2973
|
+
raise TypeError("the argument must be symmetric")
|
|
2974
|
+
if symbiform._vmodule is not self._vmodule:
|
|
2975
|
+
raise TypeError("the symmetric bilinear form and the metric are " +
|
|
2976
|
+
"not defined on the same vector field module")
|
|
2977
|
+
self._components.clear()
|
|
2978
|
+
for frame in symbiform._components:
|
|
2979
|
+
self._components[frame] = symbiform._components[frame].copy()
|
|
2980
|
+
for dom, symbiform_rst in symbiform._restrictions.items():
|
|
2981
|
+
rst = self.restrict(dom)
|
|
2982
|
+
rst.set(symbiform_rst)
|
|
2983
|
+
|
|
2984
|
+
def restrict(self, subdomain, dest_map=None):
|
|
2985
|
+
r"""
|
|
2986
|
+
Return the restriction of the metric to some subdomain.
|
|
2987
|
+
|
|
2988
|
+
If the restriction has not been defined yet, it is constructed here.
|
|
2989
|
+
|
|
2990
|
+
INPUT:
|
|
2991
|
+
|
|
2992
|
+
- ``subdomain`` -- open subset `U` of the metric's domain (must be an
|
|
2993
|
+
instance of :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`)
|
|
2994
|
+
- ``dest_map`` -- (default: ``None``) destination map
|
|
2995
|
+
`\Phi:\ U \rightarrow V`, where `V` is a subdomain of
|
|
2996
|
+
``self._codomain``
|
|
2997
|
+
(type: :class:`~sage.manifolds.differentiable.diff_map.DiffMap`)
|
|
2998
|
+
If ``None``, the restriction of ``self._vmodule._dest_map`` to `U` is
|
|
2999
|
+
used.
|
|
3000
|
+
|
|
3001
|
+
OUTPUT:
|
|
3002
|
+
|
|
3003
|
+
- instance of :class:`DegenerateMetric` representing the
|
|
3004
|
+
restriction.
|
|
3005
|
+
|
|
3006
|
+
EXAMPLES::
|
|
3007
|
+
|
|
3008
|
+
sage: M = Manifold(5, 'M')
|
|
3009
|
+
sage: g = M.metric('g', signature=(3,1,1))
|
|
3010
|
+
sage: U = M.open_subset('U')
|
|
3011
|
+
sage: g.restrict(U)
|
|
3012
|
+
degenerate metric g on the Open subset U of the 5-dimensional differentiable manifold M
|
|
3013
|
+
sage: g.restrict(U).signature()
|
|
3014
|
+
(3, 1, 1)
|
|
3015
|
+
|
|
3016
|
+
See the top documentation of :class:`DegenerateMetric` for more
|
|
3017
|
+
examples.
|
|
3018
|
+
"""
|
|
3019
|
+
if subdomain == self._domain:
|
|
3020
|
+
return self
|
|
3021
|
+
if subdomain not in self._restrictions:
|
|
3022
|
+
# Construct the restriction at the tensor field level:
|
|
3023
|
+
resu = TensorFieldParal.restrict(self, subdomain, dest_map=dest_map)
|
|
3024
|
+
# the type is correctly handled by TensorField.restrict, i.e.
|
|
3025
|
+
# resu is of type self.__class__, but the signature is not handled
|
|
3026
|
+
# by TensorField.restrict; we have to set it here:
|
|
3027
|
+
resu._signature = self._signature
|
|
3028
|
+
resu._signature_pm = self._signature_pm
|
|
3029
|
+
self._restrictions[subdomain] = resu
|
|
3030
|
+
return self._restrictions[subdomain]
|
|
3031
|
+
|
|
3032
|
+
#****************************************************************************************
|