passagemath-symbolics 10.6.43__cp314-cp314t-musllinux_1_2_x86_64.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.
Potentially problematic release.
This version of passagemath-symbolics might be problematic. Click here for more details.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.43.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.43.dist-info/RECORD +171 -0
- passagemath_symbolics-10.6.43.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.6.43.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -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 +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -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 +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -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 +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -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 +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -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 +1520 -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 +910 -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 +1728 -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 +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -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 +1342 -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-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -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 +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -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 +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-x86_64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,841 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Levi-Civita Connections
|
|
4
|
+
|
|
5
|
+
The class :class:`LeviCivitaConnection` implements the Levi-Civita
|
|
6
|
+
connection associated with some pseudo-Riemannian metric on a smooth
|
|
7
|
+
manifold.
|
|
8
|
+
|
|
9
|
+
AUTHORS:
|
|
10
|
+
|
|
11
|
+
- Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version
|
|
12
|
+
- Marco Mancini (2015) : parallelization of some computations
|
|
13
|
+
- Marius Gerbershagen (2022) : use the first Bianchi identity in the
|
|
14
|
+
computation of the Riemann tensor
|
|
15
|
+
|
|
16
|
+
REFERENCES:
|
|
17
|
+
|
|
18
|
+
- [KN1963]_
|
|
19
|
+
- [Lee1997]_
|
|
20
|
+
- [ONe1983]_
|
|
21
|
+
"""
|
|
22
|
+
#******************************************************************************
|
|
23
|
+
# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
|
|
24
|
+
# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
|
|
25
|
+
# Copyright (C) 2015 Marco Mancini <marco.mancini@obspm.fr>
|
|
26
|
+
#
|
|
27
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
28
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
29
|
+
# the License, or (at your option) any later version.
|
|
30
|
+
# http://www.gnu.org/licenses/
|
|
31
|
+
#******************************************************************************
|
|
32
|
+
|
|
33
|
+
from sage.manifolds.differentiable.affine_connection import AffineConnection
|
|
34
|
+
from sage.manifolds.differentiable.vectorframe import CoordFrame
|
|
35
|
+
from sage.parallel.decorate import parallel
|
|
36
|
+
from sage.parallel.parallelism import Parallelism
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class LeviCivitaConnection(AffineConnection):
|
|
40
|
+
r"""
|
|
41
|
+
Levi-Civita connection on a pseudo-Riemannian manifold.
|
|
42
|
+
|
|
43
|
+
Let `M` be a differentiable manifold of class `C^\infty` (smooth manifold)
|
|
44
|
+
over `\RR` endowed with a pseudo-Riemannian metric `g`.
|
|
45
|
+
Let `C^\infty(M)` be the algebra of smooth functions
|
|
46
|
+
`M\rightarrow \RR` (cf.
|
|
47
|
+
:class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`)
|
|
48
|
+
and let `\mathfrak{X}(M)` be the `C^\infty(M)`-module of vector fields on
|
|
49
|
+
`M` (cf.
|
|
50
|
+
:class:`~sage.manifolds.differentiable.vectorfield_module.VectorFieldModule`).
|
|
51
|
+
The *Levi-Civita connection associated with* `g` is the unique operator
|
|
52
|
+
|
|
53
|
+
.. MATH::
|
|
54
|
+
|
|
55
|
+
\begin{array}{cccc}
|
|
56
|
+
\nabla: & \mathfrak{X}(M)\times \mathfrak{X}(M) & \longrightarrow &
|
|
57
|
+
\mathfrak{X}(M) \\
|
|
58
|
+
& (u,v) & \longmapsto & \nabla_u v
|
|
59
|
+
\end{array}
|
|
60
|
+
|
|
61
|
+
that
|
|
62
|
+
|
|
63
|
+
- is `\RR`-bilinear, i.e. is bilinear when considering `\mathfrak{X}(M)` as
|
|
64
|
+
a vector space over `\RR`
|
|
65
|
+
- is `C^\infty(M)`-linear w.r.t. the first argument:
|
|
66
|
+
`\forall f\in C^\infty(M),\ \nabla_{fu} v = f\nabla_u v`
|
|
67
|
+
- obeys Leibniz rule w.r.t. the second argument:
|
|
68
|
+
`\forall f\in C^\infty(M),\ \nabla_u (f v) = \mathrm{d}f(u)\, v + f \nabla_u v`
|
|
69
|
+
- is torsion-free
|
|
70
|
+
- is compatible with `g`:
|
|
71
|
+
`\forall (u,v,w)\in \mathfrak{X}(M)^3,\ u(g(v,w)) = g(\nabla_u v, w) + g(v, \nabla_u w)`
|
|
72
|
+
|
|
73
|
+
The Levi-Civita connection `\nabla` gives birth to the *covariant derivative
|
|
74
|
+
operator* acting on tensor fields, denoted by the same symbol:
|
|
75
|
+
|
|
76
|
+
.. MATH::
|
|
77
|
+
|
|
78
|
+
\begin{array}{cccc}
|
|
79
|
+
\nabla: & T^{(k,l)}(M) & \longrightarrow & T^{(k,l+1)}(M)\\
|
|
80
|
+
& t & \longmapsto & \nabla t
|
|
81
|
+
\end{array}
|
|
82
|
+
|
|
83
|
+
where `T^{(k,l)}(M)` stands for the `C^\infty(M)`-module of tensor fields
|
|
84
|
+
of type `(k,l)` on `M` (cf.
|
|
85
|
+
:class:`~sage.manifolds.differentiable.tensorfield_module.TensorFieldModule`),
|
|
86
|
+
with the convention `T^{(0,0)}(M):=C^\infty(M)`.
|
|
87
|
+
For a vector field `v`, the covariant derivative `\nabla v` is a
|
|
88
|
+
type-(1,1) tensor field such that
|
|
89
|
+
|
|
90
|
+
.. MATH::
|
|
91
|
+
|
|
92
|
+
\forall u \in\mathfrak{X}(M), \ \nabla_u v = \nabla v(., u)
|
|
93
|
+
|
|
94
|
+
More generally for any tensor field `t\in T^{(k,l)}(M)`, we have
|
|
95
|
+
|
|
96
|
+
.. MATH::
|
|
97
|
+
|
|
98
|
+
\forall u \in\mathfrak{X}(M), \ \nabla_u t = \nabla t(\ldots, u)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
.. NOTE::
|
|
102
|
+
|
|
103
|
+
The above convention means that, in terms of index notation,
|
|
104
|
+
the "derivation index" in `\nabla t` is the *last* one:
|
|
105
|
+
|
|
106
|
+
.. MATH::
|
|
107
|
+
|
|
108
|
+
\nabla_c t^{a_1\ldots a_k}_{\quad\quad b_1\ldots b_l} =
|
|
109
|
+
(\nabla t)^{a_1\ldots a_k}_{\quad\quad b_1\ldots b_l c}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
INPUT:
|
|
113
|
+
|
|
114
|
+
- ``metric`` -- the metric `g` defining the Levi-Civita connection, as an
|
|
115
|
+
instance of class
|
|
116
|
+
:class:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric`
|
|
117
|
+
- ``name`` -- name given to the connection
|
|
118
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
119
|
+
connection
|
|
120
|
+
- ``init_coef`` -- boolean (default: ``True``); determines whether the Christoffel
|
|
121
|
+
symbols are initialized (in the top charts on the domain, i.e.
|
|
122
|
+
disregarding the subcharts)
|
|
123
|
+
|
|
124
|
+
EXAMPLES:
|
|
125
|
+
|
|
126
|
+
Levi-Civita connection associated with the Euclidean metric on `\RR^3`
|
|
127
|
+
expressed in spherical coordinates::
|
|
128
|
+
|
|
129
|
+
sage: forget() # for doctests only
|
|
130
|
+
sage: M = Manifold(3, 'R^3', start_index=1)
|
|
131
|
+
sage: c_spher.<r,th,ph> = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
132
|
+
sage: g = M.metric('g')
|
|
133
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2 , (r*sin(th))^2
|
|
134
|
+
sage: g.display()
|
|
135
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
136
|
+
sage: nab = g.connection(name='nabla', latex_name=r'\nabla') ; nab
|
|
137
|
+
Levi-Civita connection nabla associated with the Riemannian metric g on
|
|
138
|
+
the 3-dimensional differentiable manifold R^3
|
|
139
|
+
|
|
140
|
+
Let us check that the connection is compatible with the metric::
|
|
141
|
+
|
|
142
|
+
sage: Dg = nab(g) ; Dg
|
|
143
|
+
Tensor field nabla(g) of type (0,3) on the 3-dimensional
|
|
144
|
+
differentiable manifold R^3
|
|
145
|
+
sage: Dg == 0
|
|
146
|
+
True
|
|
147
|
+
|
|
148
|
+
and that it is torsionless::
|
|
149
|
+
|
|
150
|
+
sage: nab.torsion() == 0
|
|
151
|
+
True
|
|
152
|
+
|
|
153
|
+
As a check, let us enforce the computation of the torsion::
|
|
154
|
+
|
|
155
|
+
sage: sage.manifolds.differentiable.affine_connection.AffineConnection.torsion(nab) == 0
|
|
156
|
+
True
|
|
157
|
+
|
|
158
|
+
The connection coefficients in the manifold's default frame are Christoffel
|
|
159
|
+
symbols, since the default frame is a coordinate frame::
|
|
160
|
+
|
|
161
|
+
sage: M.default_frame()
|
|
162
|
+
Coordinate frame (R^3, (∂/∂r,∂/∂th,∂/∂ph))
|
|
163
|
+
sage: nab.coef()
|
|
164
|
+
3-indices components w.r.t. Coordinate frame (R^3, (∂/∂r,∂/∂th,∂/∂ph)),
|
|
165
|
+
with symmetry on the index positions (1, 2)
|
|
166
|
+
|
|
167
|
+
We note that the Christoffel symbols are symmetric with respect to their
|
|
168
|
+
last two indices (positions (1,2)); their expression is::
|
|
169
|
+
|
|
170
|
+
sage: nab.coef()[:] # display as a array
|
|
171
|
+
[[[0, 0, 0], [0, -r, 0], [0, 0, -r*sin(th)^2]],
|
|
172
|
+
[[0, 1/r, 0], [1/r, 0, 0], [0, 0, -cos(th)*sin(th)]],
|
|
173
|
+
[[0, 0, 1/r], [0, 0, cos(th)/sin(th)], [1/r, cos(th)/sin(th), 0]]]
|
|
174
|
+
sage: nab.display() # display only the non-vanishing symbols
|
|
175
|
+
Gam^r_th,th = -r
|
|
176
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
177
|
+
Gam^th_r,th = 1/r
|
|
178
|
+
Gam^th_th,r = 1/r
|
|
179
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
180
|
+
Gam^ph_r,ph = 1/r
|
|
181
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
182
|
+
Gam^ph_ph,r = 1/r
|
|
183
|
+
Gam^ph_ph,th = cos(th)/sin(th)
|
|
184
|
+
sage: nab.display(only_nonredundant=True) # skip redundancy due to symmetry
|
|
185
|
+
Gam^r_th,th = -r
|
|
186
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
187
|
+
Gam^th_r,th = 1/r
|
|
188
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
189
|
+
Gam^ph_r,ph = 1/r
|
|
190
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
191
|
+
|
|
192
|
+
The same display can be obtained via the function
|
|
193
|
+
:meth:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric.christoffel_symbols_display`
|
|
194
|
+
acting on the metric::
|
|
195
|
+
|
|
196
|
+
sage: g.christoffel_symbols_display(chart=c_spher)
|
|
197
|
+
Gam^r_th,th = -r
|
|
198
|
+
Gam^r_ph,ph = -r*sin(th)^2
|
|
199
|
+
Gam^th_r,th = 1/r
|
|
200
|
+
Gam^th_ph,ph = -cos(th)*sin(th)
|
|
201
|
+
Gam^ph_r,ph = 1/r
|
|
202
|
+
Gam^ph_th,ph = cos(th)/sin(th)
|
|
203
|
+
"""
|
|
204
|
+
def __init__(self, metric, name, latex_name=None, init_coef=True):
|
|
205
|
+
r"""
|
|
206
|
+
Construct a Levi-Civita connection.
|
|
207
|
+
|
|
208
|
+
TESTS:
|
|
209
|
+
|
|
210
|
+
Levi-Civita connection of the hyperbolic plane::
|
|
211
|
+
|
|
212
|
+
sage: M = Manifold(2, 'M')
|
|
213
|
+
sage: X.<r,ph> = M.chart(r'r:(0,+oo) ph:(0,2*pi)')
|
|
214
|
+
sage: g = M.metric('g')
|
|
215
|
+
sage: g[0,0], g[1,1] = 1/(1+r^2), r^2
|
|
216
|
+
sage: from sage.manifolds.differentiable.levi_civita_connection \
|
|
217
|
+
....: import LeviCivitaConnection
|
|
218
|
+
sage: nab = LeviCivitaConnection(g, 'nabla', latex_name=r'\nabla')
|
|
219
|
+
sage: nab
|
|
220
|
+
Levi-Civita connection nabla associated with the Riemannian metric
|
|
221
|
+
g on the 2-dimensional differentiable manifold M
|
|
222
|
+
sage: TestSuite(nab).run()
|
|
223
|
+
"""
|
|
224
|
+
AffineConnection.__init__(self, metric.domain(), name, latex_name)
|
|
225
|
+
self._metric = metric
|
|
226
|
+
# Initialization of the derived quantities:
|
|
227
|
+
LeviCivitaConnection._init_derived(self)
|
|
228
|
+
if init_coef:
|
|
229
|
+
# Initialization of the Christoffel symbols in the top charts on
|
|
230
|
+
# the domain (i.e. disregarding the subcharts)
|
|
231
|
+
for chart in self._domain.top_charts():
|
|
232
|
+
self.coef(chart._frame)
|
|
233
|
+
|
|
234
|
+
def _repr_(self):
|
|
235
|
+
r"""
|
|
236
|
+
String representation of the object.
|
|
237
|
+
|
|
238
|
+
TESTS::
|
|
239
|
+
|
|
240
|
+
sage: M = Manifold(5, 'M')
|
|
241
|
+
sage: g = M.metric('g')
|
|
242
|
+
sage: nab = g.connection()
|
|
243
|
+
sage: nab._repr_()
|
|
244
|
+
'Levi-Civita connection nabla_g associated with the Riemannian metric g on the 5-dimensional differentiable manifold M'
|
|
245
|
+
sage: repr(nab) # indirect doctest
|
|
246
|
+
'Levi-Civita connection nabla_g associated with the Riemannian metric g on the 5-dimensional differentiable manifold M'
|
|
247
|
+
"""
|
|
248
|
+
description = "Levi-Civita connection"
|
|
249
|
+
if self._name is not None:
|
|
250
|
+
description += " " + self._name
|
|
251
|
+
description += " associated with the {}".format(self._metric)
|
|
252
|
+
return description
|
|
253
|
+
|
|
254
|
+
def _init_derived(self):
|
|
255
|
+
r"""
|
|
256
|
+
Initialize the derived quantities.
|
|
257
|
+
|
|
258
|
+
TESTS::
|
|
259
|
+
|
|
260
|
+
sage: M = Manifold(5, 'M')
|
|
261
|
+
sage: g = M.metric('g')
|
|
262
|
+
sage: nab = g.connection()
|
|
263
|
+
sage: nab._init_derived()
|
|
264
|
+
"""
|
|
265
|
+
AffineConnection._init_derived(self)
|
|
266
|
+
|
|
267
|
+
def _del_derived(self):
|
|
268
|
+
r"""
|
|
269
|
+
Delete the derived quantities.
|
|
270
|
+
|
|
271
|
+
TESTS::
|
|
272
|
+
|
|
273
|
+
sage: M = Manifold(5, 'M')
|
|
274
|
+
sage: g = M.metric('g')
|
|
275
|
+
sage: nab = g.connection()
|
|
276
|
+
sage: nab._del_derived()
|
|
277
|
+
"""
|
|
278
|
+
AffineConnection._del_derived(self)
|
|
279
|
+
|
|
280
|
+
def restrict(self, subdomain):
|
|
281
|
+
r"""
|
|
282
|
+
Return the restriction of the connection to some subdomain.
|
|
283
|
+
|
|
284
|
+
If such restriction has not been defined yet, it is constructed here.
|
|
285
|
+
|
|
286
|
+
INPUT:
|
|
287
|
+
|
|
288
|
+
- ``subdomain`` -- open subset `U` of the connection's domain (must be
|
|
289
|
+
an instance of
|
|
290
|
+
:class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`)
|
|
291
|
+
|
|
292
|
+
OUTPUT:
|
|
293
|
+
|
|
294
|
+
- instance of :class:`LeviCivitaConnection` representing the
|
|
295
|
+
restriction.
|
|
296
|
+
|
|
297
|
+
EXAMPLES::
|
|
298
|
+
|
|
299
|
+
sage: M = Manifold(2, 'M')
|
|
300
|
+
sage: X.<x,y> = M.chart()
|
|
301
|
+
sage: g = M.metric('g')
|
|
302
|
+
sage: g[0,0], g[1,1] = 1+y^2, 1+x^2
|
|
303
|
+
sage: nab = g.connection()
|
|
304
|
+
sage: nab[:]
|
|
305
|
+
[[[0, y/(y^2 + 1)], [y/(y^2 + 1), -x/(y^2 + 1)]],
|
|
306
|
+
[[-y/(x^2 + 1), x/(x^2 + 1)], [x/(x^2 + 1), 0]]]
|
|
307
|
+
sage: U = M.open_subset('U', coord_def={X: x>0})
|
|
308
|
+
sage: nabU = nab.restrict(U); nabU
|
|
309
|
+
Levi-Civita connection nabla_g associated with the Riemannian
|
|
310
|
+
metric g on the Open subset U of the 2-dimensional differentiable
|
|
311
|
+
manifold M
|
|
312
|
+
sage: nabU[:]
|
|
313
|
+
[[[0, y/(y^2 + 1)], [y/(y^2 + 1), -x/(y^2 + 1)]],
|
|
314
|
+
[[-y/(x^2 + 1), x/(x^2 + 1)], [x/(x^2 + 1), 0]]]
|
|
315
|
+
|
|
316
|
+
Let us check that the restriction is the connection compatible with the
|
|
317
|
+
restriction of the metric::
|
|
318
|
+
|
|
319
|
+
sage: nabU(g.restrict(U)).display()
|
|
320
|
+
nabla_g(g) = 0
|
|
321
|
+
"""
|
|
322
|
+
if subdomain == self._domain:
|
|
323
|
+
return self
|
|
324
|
+
if subdomain not in self._restrictions:
|
|
325
|
+
if not subdomain.is_subset(self._domain):
|
|
326
|
+
raise ValueError("the provided domain is not a subdomain of " +
|
|
327
|
+
"the current connection's domain")
|
|
328
|
+
resu = LeviCivitaConnection(self._metric.restrict(subdomain),
|
|
329
|
+
name=self._name,
|
|
330
|
+
latex_name=self._latex_name,
|
|
331
|
+
init_coef=False)
|
|
332
|
+
for frame in self._coefficients:
|
|
333
|
+
for sframe in subdomain._top_frames:
|
|
334
|
+
if sframe in frame._subframes:
|
|
335
|
+
comp_store = self._coefficients[frame]._comp
|
|
336
|
+
scoef = resu._new_coef(sframe)
|
|
337
|
+
scomp_store = scoef._comp
|
|
338
|
+
# the coefficients of the restriction are evaluated
|
|
339
|
+
# index by index:
|
|
340
|
+
for ind, value in comp_store.items():
|
|
341
|
+
scomp_store[ind] = value.restrict(sframe._domain)
|
|
342
|
+
resu._coefficients[sframe] = scoef
|
|
343
|
+
if self._riemann is not None:
|
|
344
|
+
resu._riemann = self._riemann.restrict(subdomain)
|
|
345
|
+
if self._ricci is not None:
|
|
346
|
+
resu._ricci = self._ricci.restrict(subdomain)
|
|
347
|
+
self._restrictions[subdomain] = resu
|
|
348
|
+
return self._restrictions[subdomain]
|
|
349
|
+
|
|
350
|
+
def _new_coef(self, frame):
|
|
351
|
+
r"""
|
|
352
|
+
Create the connection coefficients w.r.t. the given frame.
|
|
353
|
+
|
|
354
|
+
TESTS::
|
|
355
|
+
|
|
356
|
+
sage: M = Manifold(2, 'M')
|
|
357
|
+
sage: X.<x,y> = M.chart()
|
|
358
|
+
sage: g = M.metric('g')
|
|
359
|
+
sage: g[0,0], g[1,1] = 1, 1
|
|
360
|
+
sage: nab = g.connection()
|
|
361
|
+
sage: nab._new_coef(X.frame())
|
|
362
|
+
3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)), with
|
|
363
|
+
symmetry on the index positions (1, 2)
|
|
364
|
+
sage: e = M.vector_frame('e')
|
|
365
|
+
sage: nab._new_coef(e)
|
|
366
|
+
3-indices components w.r.t. Vector frame (M, (e_0,e_1))
|
|
367
|
+
"""
|
|
368
|
+
from sage.manifolds.differentiable.scalarfield import DiffScalarField
|
|
369
|
+
from sage.manifolds.differentiable.vectorframe import CoordFrame
|
|
370
|
+
from sage.tensor.modules.comp import Components, CompWithSym
|
|
371
|
+
if isinstance(frame, CoordFrame):
|
|
372
|
+
# the Christoffel symbols are symmetric:
|
|
373
|
+
return CompWithSym(frame._domain.scalar_field_algebra(), frame, 3,
|
|
374
|
+
start_index=self._domain._sindex,
|
|
375
|
+
output_formatter=DiffScalarField.coord_function,
|
|
376
|
+
sym=(1,2))
|
|
377
|
+
else:
|
|
378
|
+
# a priori no symmetry in a generic frame:
|
|
379
|
+
return Components(frame._domain.scalar_field_algebra(), frame, 3,
|
|
380
|
+
start_index=self._domain._sindex,
|
|
381
|
+
output_formatter=DiffScalarField.coord_function)
|
|
382
|
+
|
|
383
|
+
def coef(self, frame=None):
|
|
384
|
+
r"""
|
|
385
|
+
Return the connection coefficients relative to the given frame.
|
|
386
|
+
|
|
387
|
+
`n` being the manifold's dimension, the connection coefficients
|
|
388
|
+
relative to the vector frame `(e_i)` are the `n^3` scalar fields
|
|
389
|
+
`\Gamma^k_{\ \, ij}` defined by
|
|
390
|
+
|
|
391
|
+
.. MATH::
|
|
392
|
+
|
|
393
|
+
\nabla_{e_j} e_i = \Gamma^k_{\ \, ij} e_k
|
|
394
|
+
|
|
395
|
+
If the connection coefficients are not known already, they are computed
|
|
396
|
+
|
|
397
|
+
* as Christoffel symbols if the frame `(e_i)` is a coordinate frame
|
|
398
|
+
* from the above formula otherwise
|
|
399
|
+
|
|
400
|
+
INPUT:
|
|
401
|
+
|
|
402
|
+
- ``frame`` -- (default: ``None``) vector frame relative to which the
|
|
403
|
+
connection coefficients are required; if none is provided, the
|
|
404
|
+
domain's default frame is assumed
|
|
405
|
+
|
|
406
|
+
OUTPUT:
|
|
407
|
+
|
|
408
|
+
- connection coefficients relative to the frame ``frame``, as an
|
|
409
|
+
instance of the class :class:`~sage.tensor.modules.comp.Components`
|
|
410
|
+
with 3 indices ordered as `(k,i,j)`; for Christoffel symbols,
|
|
411
|
+
an instance of the subclass
|
|
412
|
+
:class:`~sage.tensor.modules.comp.CompWithSym` is returned.
|
|
413
|
+
|
|
414
|
+
EXAMPLES:
|
|
415
|
+
|
|
416
|
+
Christoffel symbols of the Levi-Civita connection associated to
|
|
417
|
+
the Euclidean metric on `\RR^3` expressed in spherical coordinates::
|
|
418
|
+
|
|
419
|
+
sage: M = Manifold(3, 'R^3', start_index=1)
|
|
420
|
+
sage: c_spher.<r,th,ph> = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
421
|
+
sage: g = M.metric('g')
|
|
422
|
+
sage: g[1,1], g[2,2], g[3,3] = 1, r^2 , (r*sin(th))^2
|
|
423
|
+
sage: g.display()
|
|
424
|
+
g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph
|
|
425
|
+
sage: nab = g.connection()
|
|
426
|
+
sage: gam = nab.coef() ; gam
|
|
427
|
+
3-indices components w.r.t. Coordinate frame (R^3, (∂/∂r,∂/∂th,∂/∂ph)),
|
|
428
|
+
with symmetry on the index positions (1, 2)
|
|
429
|
+
sage: gam[:]
|
|
430
|
+
[[[0, 0, 0], [0, -r, 0], [0, 0, -r*sin(th)^2]],
|
|
431
|
+
[[0, 1/r, 0], [1/r, 0, 0], [0, 0, -cos(th)*sin(th)]],
|
|
432
|
+
[[0, 0, 1/r], [0, 0, cos(th)/sin(th)], [1/r, cos(th)/sin(th), 0]]]
|
|
433
|
+
|
|
434
|
+
The only nonzero Christoffel symbols::
|
|
435
|
+
|
|
436
|
+
sage: gam[1,2,2], gam[1,3,3]
|
|
437
|
+
(-r, -r*sin(th)^2)
|
|
438
|
+
sage: gam[2,1,2], gam[2,3,3]
|
|
439
|
+
(1/r, -cos(th)*sin(th))
|
|
440
|
+
sage: gam[3,1,3], gam[3,2,3]
|
|
441
|
+
(1/r, cos(th)/sin(th))
|
|
442
|
+
|
|
443
|
+
Connection coefficients of the same connection with respect to the
|
|
444
|
+
orthonormal frame associated to spherical coordinates::
|
|
445
|
+
|
|
446
|
+
sage: ch_basis = M.automorphism_field()
|
|
447
|
+
sage: ch_basis[1,1], ch_basis[2,2], ch_basis[3,3] = 1, 1/r, 1/(r*sin(th))
|
|
448
|
+
sage: e = c_spher.frame().new_frame(ch_basis, 'e')
|
|
449
|
+
sage: gam_e = nab.coef(e) ; gam_e
|
|
450
|
+
3-indices components w.r.t. Vector frame (R^3, (e_1,e_2,e_3))
|
|
451
|
+
sage: gam_e[:]
|
|
452
|
+
[[[0, 0, 0], [0, -1/r, 0], [0, 0, -1/r]],
|
|
453
|
+
[[0, 1/r, 0], [0, 0, 0], [0, 0, -cos(th)/(r*sin(th))]],
|
|
454
|
+
[[0, 0, 1/r], [0, 0, cos(th)/(r*sin(th))], [0, 0, 0]]]
|
|
455
|
+
|
|
456
|
+
The only nonzero connection coefficients::
|
|
457
|
+
|
|
458
|
+
sage: gam_e[1,2,2], gam_e[2,1,2]
|
|
459
|
+
(-1/r, 1/r)
|
|
460
|
+
sage: gam_e[1,3,3], gam_e[3,1,3]
|
|
461
|
+
(-1/r, 1/r)
|
|
462
|
+
sage: gam_e[2,3,3], gam_e[3,2,3]
|
|
463
|
+
(-cos(th)/(r*sin(th)), cos(th)/(r*sin(th)))
|
|
464
|
+
"""
|
|
465
|
+
from sage.manifolds.differentiable.vectorframe import CoordFrame
|
|
466
|
+
if frame is None:
|
|
467
|
+
frame = self._domain._def_frame
|
|
468
|
+
if frame not in self._coefficients:
|
|
469
|
+
# the coefficients must be computed
|
|
470
|
+
#
|
|
471
|
+
# Check whether frame is a subframe of a frame in which the
|
|
472
|
+
# coefficients are already known:
|
|
473
|
+
for oframe in self._coefficients:
|
|
474
|
+
if frame in oframe._subframes:
|
|
475
|
+
self._coefficients[frame] = self._new_coef(frame)
|
|
476
|
+
comp_store = self._coefficients[frame]._comp
|
|
477
|
+
ocomp_store = self._coefficients[oframe]._comp
|
|
478
|
+
for ind, value in ocomp_store.items():
|
|
479
|
+
comp_store[ind] = value.restrict(frame._domain)
|
|
480
|
+
break
|
|
481
|
+
else:
|
|
482
|
+
# If not, the coefficients must be computed from scratch:
|
|
483
|
+
manif = self._domain
|
|
484
|
+
if isinstance(frame, CoordFrame):
|
|
485
|
+
# Christoffel symbols
|
|
486
|
+
chart = frame._chart
|
|
487
|
+
gam = self._new_coef(frame)
|
|
488
|
+
gg = self._metric.comp(frame)
|
|
489
|
+
ginv = self._metric.inverse().comp(frame)
|
|
490
|
+
|
|
491
|
+
if Parallelism().get('tensor') != 1:
|
|
492
|
+
# parallel computation
|
|
493
|
+
nproc = Parallelism().get('tensor')
|
|
494
|
+
lol = lambda lst, sz: [lst[i:i+sz] for i in
|
|
495
|
+
range(0, len(lst), sz)]
|
|
496
|
+
|
|
497
|
+
ind_list = []
|
|
498
|
+
for ind in gam.non_redundant_index_generator():
|
|
499
|
+
i, j, k = ind
|
|
500
|
+
ind_list.append((i,j,k))
|
|
501
|
+
ind_step = max(1,int(len(ind_list)/nproc/2))
|
|
502
|
+
local_list = lol(ind_list,ind_step)
|
|
503
|
+
|
|
504
|
+
# definition of the list of input parameters
|
|
505
|
+
listParalInput = []
|
|
506
|
+
for ind_part in local_list:
|
|
507
|
+
listParalInput.append((ind_part,chart,ginv,gg,manif))
|
|
508
|
+
|
|
509
|
+
# definition of the parallel function
|
|
510
|
+
@parallel(p_iter='multiprocessing',ncpus=nproc)
|
|
511
|
+
def make_Connect(local_list_ijk, chart, ginv, gg, manif):
|
|
512
|
+
partial = []
|
|
513
|
+
for i,j,k in local_list_ijk:
|
|
514
|
+
rsum = 0
|
|
515
|
+
for s in manif.irange():
|
|
516
|
+
if ginv[i,s, chart] != 0:
|
|
517
|
+
rsum += ginv[i,s, chart] * (
|
|
518
|
+
gg[s,k, chart].diff(j)
|
|
519
|
+
+ gg[j,s, chart].diff(k)
|
|
520
|
+
- gg[j,k, chart].diff(s) )
|
|
521
|
+
partial.append([i,j,k,rsum / 2])
|
|
522
|
+
return partial
|
|
523
|
+
|
|
524
|
+
# Computation and Assignation of values
|
|
525
|
+
for ii, val in make_Connect(listParalInput):
|
|
526
|
+
for jj in val:
|
|
527
|
+
gam[jj[0],jj[1],jj[2],ii[0][1]] = jj[3]
|
|
528
|
+
|
|
529
|
+
else:
|
|
530
|
+
# sequential
|
|
531
|
+
for ind in gam.non_redundant_index_generator():
|
|
532
|
+
i, j, k = ind
|
|
533
|
+
# The computation is performed at the ChartFunction level:
|
|
534
|
+
rsum = 0
|
|
535
|
+
for s in manif.irange():
|
|
536
|
+
rsum += ginv[i,s, chart] * (
|
|
537
|
+
gg[s,k, chart].diff(j)
|
|
538
|
+
+ gg[j,s, chart].diff(k)
|
|
539
|
+
- gg[j,k, chart].diff(s) )
|
|
540
|
+
gam[i,j,k, chart] = rsum / 2
|
|
541
|
+
|
|
542
|
+
# Assignation of results
|
|
543
|
+
self._coefficients[frame] = gam
|
|
544
|
+
|
|
545
|
+
else:
|
|
546
|
+
# Computation from the formula defining the connection coef.
|
|
547
|
+
return AffineConnection.coef(self, frame)
|
|
548
|
+
return self._coefficients[frame]
|
|
549
|
+
|
|
550
|
+
def torsion(self):
|
|
551
|
+
r"""
|
|
552
|
+
Return the connection's torsion tensor (identically zero for a
|
|
553
|
+
Levi-Civita connection).
|
|
554
|
+
|
|
555
|
+
See
|
|
556
|
+
:meth:`sage.manifolds.differentiable.affine_connection.AffineConnection.torsion`
|
|
557
|
+
for the general definition of the torsion tensor.
|
|
558
|
+
|
|
559
|
+
OUTPUT:
|
|
560
|
+
|
|
561
|
+
- the torsion tensor `T`, as a vanishing instance of
|
|
562
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
563
|
+
|
|
564
|
+
EXAMPLES::
|
|
565
|
+
|
|
566
|
+
sage: M = Manifold(2, 'M')
|
|
567
|
+
sage: X.<x,y> = M.chart()
|
|
568
|
+
sage: g = M.metric('g')
|
|
569
|
+
sage: g[0,0], g[1,1] = 1+y^2, 1+x^2
|
|
570
|
+
sage: nab = g.connection()
|
|
571
|
+
sage: t = nab.torsion(); t
|
|
572
|
+
Tensor field of type (1,2) on the 2-dimensional differentiable
|
|
573
|
+
manifold M
|
|
574
|
+
|
|
575
|
+
The torsion of a Levi-Civita connection is always zero::
|
|
576
|
+
|
|
577
|
+
sage: t.display()
|
|
578
|
+
0
|
|
579
|
+
"""
|
|
580
|
+
if self._torsion is None:
|
|
581
|
+
resu = self._domain.tensor_field(1, 2, antisym=(1,2))
|
|
582
|
+
for frame in self._coefficients:
|
|
583
|
+
# Initialization of the frame components to zero:
|
|
584
|
+
resu.add_comp(frame)
|
|
585
|
+
self._torsion = resu
|
|
586
|
+
return self._torsion
|
|
587
|
+
|
|
588
|
+
def riemann(self, name=None, latex_name=None):
|
|
589
|
+
r"""
|
|
590
|
+
Return the Riemann curvature tensor of the connection.
|
|
591
|
+
|
|
592
|
+
This method redefines
|
|
593
|
+
:meth:`sage.manifolds.differentiable.affine_connection.AffineConnection.riemann`
|
|
594
|
+
to take into account the symmetry of the Riemann tensor for a
|
|
595
|
+
Levi-Civita connection.
|
|
596
|
+
|
|
597
|
+
The Riemann curvature tensor is the tensor field `R` of type (1,3)
|
|
598
|
+
defined by
|
|
599
|
+
|
|
600
|
+
.. MATH::
|
|
601
|
+
|
|
602
|
+
R(\omega, w, u, v) = \left\langle \omega, \nabla_u \nabla_v w
|
|
603
|
+
- \nabla_v \nabla_u w - \nabla_{[u, v]} w \right\rangle
|
|
604
|
+
|
|
605
|
+
for any 1-form `\omega` and any vector fields `u`, `v` and `w`.
|
|
606
|
+
|
|
607
|
+
INPUT:
|
|
608
|
+
|
|
609
|
+
- ``name`` -- (default: ``None``) name given to the Riemann tensor;
|
|
610
|
+
if none, it is set to "Riem(g)", where "g" is the metric's name
|
|
611
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
612
|
+
Riemann tensor; if none, it is set to "\\mathrm{Riem}(g)", where "g"
|
|
613
|
+
is the metric's name
|
|
614
|
+
|
|
615
|
+
OUTPUT:
|
|
616
|
+
|
|
617
|
+
- the Riemann curvature tensor `R`, as an instance of
|
|
618
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
|
|
619
|
+
|
|
620
|
+
EXAMPLES:
|
|
621
|
+
|
|
622
|
+
Riemann tensor of the Levi-Civita connection associated with the
|
|
623
|
+
metric of the hyperbolic plane (Poincaré disk model)::
|
|
624
|
+
|
|
625
|
+
sage: M = Manifold(2, 'M', start_index=1)
|
|
626
|
+
sage: X.<x,y> = M.chart('x:(-1,1) y:(-1,1)', coord_restrictions=lambda x,y: x^2+y^2<1)
|
|
627
|
+
....: # Cartesian coord. on the Poincaré disk
|
|
628
|
+
sage: g = M.metric('g')
|
|
629
|
+
sage: g[1,1], g[2,2] = 4/(1-x^2-y^2)^2, 4/(1-x^2-y^2)^2
|
|
630
|
+
sage: nab = g.connection()
|
|
631
|
+
sage: riem = nab.riemann(); riem
|
|
632
|
+
Tensor field Riem(g) of type (1,3) on the 2-dimensional
|
|
633
|
+
differentiable manifold M
|
|
634
|
+
sage: riem.display_comp()
|
|
635
|
+
Riem(g)^x_yxy = -4/(x^4 + y^4 + 2*(x^2 - 1)*y^2 - 2*x^2 + 1)
|
|
636
|
+
Riem(g)^x_yyx = 4/(x^4 + y^4 + 2*(x^2 - 1)*y^2 - 2*x^2 + 1)
|
|
637
|
+
Riem(g)^y_xxy = 4/(x^4 + y^4 + 2*(x^2 - 1)*y^2 - 2*x^2 + 1)
|
|
638
|
+
Riem(g)^y_xyx = -4/(x^4 + y^4 + 2*(x^2 - 1)*y^2 - 2*x^2 + 1)
|
|
639
|
+
|
|
640
|
+
The same computation parallelized on 2 cores::
|
|
641
|
+
|
|
642
|
+
sage: Parallelism().set(nproc=2)
|
|
643
|
+
sage: riem_backup = riem
|
|
644
|
+
sage: g = M.metric('g')
|
|
645
|
+
sage: g[1,1], g[2,2] = 4/(1-x^2-y^2)^2, 4/(1-x^2-y^2)^2
|
|
646
|
+
sage: nab = g.connection()
|
|
647
|
+
sage: riem = nab.riemann(); riem
|
|
648
|
+
Tensor field Riem(g) of type (1,3) on the 2-dimensional
|
|
649
|
+
differentiable manifold M
|
|
650
|
+
sage: riem == riem_backup
|
|
651
|
+
True
|
|
652
|
+
sage: Parallelism().set(nproc=1) # switch off parallelization
|
|
653
|
+
"""
|
|
654
|
+
if self._riemann is None:
|
|
655
|
+
if name is None:
|
|
656
|
+
name = "Riem(" + self._metric._name + ")"
|
|
657
|
+
if latex_name is None:
|
|
658
|
+
latex_name = (r"\mathrm{Riem}\left(" + self._metric._latex_name
|
|
659
|
+
+ r"\right)")
|
|
660
|
+
manif = self._domain
|
|
661
|
+
resu = manif.tensor_field(1, 3, antisym=(2,3), name=name,
|
|
662
|
+
latex_name=latex_name)
|
|
663
|
+
for frame, gam in self._coefficients.items():
|
|
664
|
+
# The computation is performed only on the top frames:
|
|
665
|
+
for oframe in self._coefficients:
|
|
666
|
+
if frame in oframe._subframes and frame is not oframe:
|
|
667
|
+
break
|
|
668
|
+
else:
|
|
669
|
+
# frame in not a subframe and the computation is performed:
|
|
670
|
+
sc = frame.structure_coeff()
|
|
671
|
+
gam_gam = gam.contract(1, gam, 0)
|
|
672
|
+
gam_sc = gam.contract(2, sc, 0)
|
|
673
|
+
res = resu.add_comp(frame)
|
|
674
|
+
use_Bianchi = isinstance(frame,CoordFrame)
|
|
675
|
+
if Parallelism().get('tensor') != 1:
|
|
676
|
+
# parallel computation
|
|
677
|
+
nproc = Parallelism().get('tensor')
|
|
678
|
+
lol = lambda lst, sz: [lst[i:i+sz] for i in range(0,
|
|
679
|
+
len(lst), sz)]
|
|
680
|
+
ind_list = []
|
|
681
|
+
for i in manif.irange():
|
|
682
|
+
for j in manif.irange():
|
|
683
|
+
for k in manif.irange(start=j):
|
|
684
|
+
for l in manif.irange(start=k+1):
|
|
685
|
+
ind_list.append((i,j,k,l))
|
|
686
|
+
ind_step = max(1, int(len(ind_list)/nproc/2))
|
|
687
|
+
local_list = lol(ind_list, ind_step)
|
|
688
|
+
# definition of the list of input parameters
|
|
689
|
+
listParalInput = []
|
|
690
|
+
for ind_part in local_list:
|
|
691
|
+
listParalInput.append((frame, gam, gam_gam, gam_sc,
|
|
692
|
+
use_Bianchi, ind_part))
|
|
693
|
+
|
|
694
|
+
# definition of the parallel function
|
|
695
|
+
@parallel(p_iter='multiprocessing', ncpus=nproc)
|
|
696
|
+
def make_Riem(frame, gam, gam_gam, gam_sc, use_Bianchi,
|
|
697
|
+
local_list_ijkl):
|
|
698
|
+
def compute_component(i,j,k,l, frame, gam, gam_gam, gam_sc):
|
|
699
|
+
return frame[k](gam[[i,j,l]]) - frame[l](gam[[i,j,k]]) + \
|
|
700
|
+
gam_gam[[i,k,j,l]] - gam_gam[[i,l,j,k]] - gam_sc[[i,j,k,l]]
|
|
701
|
+
partial = []
|
|
702
|
+
for i,j,k,l in local_list_ijkl:
|
|
703
|
+
R_ijkl = compute_component(i,j,k,l, frame, gam, gam_gam, gam_sc)
|
|
704
|
+
partial.append([i,j,k,l, R_ijkl])
|
|
705
|
+
if j == k:
|
|
706
|
+
partial.append([i,l,k,l, compute_component(i,l,k,l, frame,
|
|
707
|
+
gam, gam_gam, gam_sc)])
|
|
708
|
+
else:
|
|
709
|
+
R_ikjl = compute_component(i,k,j,l, frame, gam, gam_gam, gam_sc)
|
|
710
|
+
partial.append([i,k,j,l, R_ikjl])
|
|
711
|
+
if use_Bianchi:
|
|
712
|
+
partial.append([i,l,j,k, R_ikjl - R_ijkl])
|
|
713
|
+
else:
|
|
714
|
+
partial.append([i,l,j,k, compute_component(i,l,j,k, frame,
|
|
715
|
+
gam, gam_gam, gam_sc)])
|
|
716
|
+
return partial
|
|
717
|
+
# Computation and assignation of values
|
|
718
|
+
for ii,val in make_Riem(listParalInput):
|
|
719
|
+
for jj in val:
|
|
720
|
+
res[jj[0], jj[1], jj[2], jj[3]] = jj[4]
|
|
721
|
+
|
|
722
|
+
else:
|
|
723
|
+
# sequential
|
|
724
|
+
for i in manif.irange():
|
|
725
|
+
for j in manif.irange():
|
|
726
|
+
for k in manif.irange():
|
|
727
|
+
# antisymmetry of the Riemann tensor taken
|
|
728
|
+
# into account by l>k:
|
|
729
|
+
for l in manif.irange(start=k+1):
|
|
730
|
+
if not use_Bianchi or (j <= k or j <= l):
|
|
731
|
+
res[i,j,k,l] = frame[k](gam[[i,j,l]]) - \
|
|
732
|
+
frame[l](gam[[i,j,k]]) + \
|
|
733
|
+
gam_gam[[i,k,j,l]] - \
|
|
734
|
+
gam_gam[[i,l,j,k]] - \
|
|
735
|
+
gam_sc[[i,j,k,l]]
|
|
736
|
+
if use_Bianchi:
|
|
737
|
+
# first Bianchi identity
|
|
738
|
+
for j in manif.irange():
|
|
739
|
+
for k in manif.irange(end=j-1):
|
|
740
|
+
for l in manif.irange(start=k+1,end=j-1):
|
|
741
|
+
# j > k and j > l:
|
|
742
|
+
res[i,j,k,l] = res[i,l,k,j] - res[i,k,l,j]
|
|
743
|
+
self._riemann = resu
|
|
744
|
+
return self._riemann
|
|
745
|
+
|
|
746
|
+
def ricci(self, name=None, latex_name=None):
|
|
747
|
+
r"""
|
|
748
|
+
Return the connection's Ricci tensor.
|
|
749
|
+
|
|
750
|
+
This method redefines
|
|
751
|
+
:meth:`sage.manifolds.differentiable.affine_connection.AffineConnection.ricci`
|
|
752
|
+
to take into account the symmetry of the Ricci tensor for a
|
|
753
|
+
Levi-Civita connection.
|
|
754
|
+
|
|
755
|
+
The Ricci tensor is the tensor field `Ric` of type (0,2)
|
|
756
|
+
defined from the Riemann curvature tensor `R` by
|
|
757
|
+
|
|
758
|
+
.. MATH::
|
|
759
|
+
|
|
760
|
+
Ric(u, v) = R(e^i, u, e_i, v)
|
|
761
|
+
|
|
762
|
+
for any vector fields `u` and `v`, `(e_i)` being any vector frame and
|
|
763
|
+
`(e^i)` the dual coframe.
|
|
764
|
+
|
|
765
|
+
INPUT:
|
|
766
|
+
|
|
767
|
+
- ``name`` -- (default: ``None``) name given to the Ricci tensor;
|
|
768
|
+
if none, it is set to "Ric(g)", where "g" is the metric's name
|
|
769
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
770
|
+
Ricci tensor; if none, it is set to "\\mathrm{Ric}(g)", where "g"
|
|
771
|
+
is the metric's name
|
|
772
|
+
|
|
773
|
+
OUTPUT:
|
|
774
|
+
|
|
775
|
+
- the Ricci tensor `Ric`, as an instance of
|
|
776
|
+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField` of tensor
|
|
777
|
+
type (0,2) and symmetric
|
|
778
|
+
|
|
779
|
+
EXAMPLES:
|
|
780
|
+
|
|
781
|
+
Ricci tensor of the standard connection on the 2-dimensional sphere::
|
|
782
|
+
|
|
783
|
+
sage: M = Manifold(2, 'S^2', start_index=1)
|
|
784
|
+
sage: c_spher.<th,ph> = M.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
785
|
+
sage: g = M.metric('g')
|
|
786
|
+
sage: g[1,1], g[2,2] = 1, sin(th)^2
|
|
787
|
+
sage: g.display() # standard metric on S^2:
|
|
788
|
+
g = dth⊗dth + sin(th)^2 dph⊗dph
|
|
789
|
+
sage: nab = g.connection() ; nab
|
|
790
|
+
Levi-Civita connection nabla_g associated with the Riemannian
|
|
791
|
+
metric g on the 2-dimensional differentiable manifold S^2
|
|
792
|
+
sage: ric = nab.ricci() ; ric
|
|
793
|
+
Field of symmetric bilinear forms Ric(g) on the 2-dimensional
|
|
794
|
+
differentiable manifold S^2
|
|
795
|
+
sage: ric.display()
|
|
796
|
+
Ric(g) = dth⊗dth + sin(th)^2 dph⊗dph
|
|
797
|
+
|
|
798
|
+
Checking that the Ricci tensor of the Levi-Civita connection associated
|
|
799
|
+
to Schwarzschild metric is identically zero (as a solution of the
|
|
800
|
+
Einstein equation)::
|
|
801
|
+
|
|
802
|
+
sage: M = Manifold(4, 'M')
|
|
803
|
+
sage: c_BL.<t,r,th,ph> = M.chart(r't r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') # Schwarzschild-Droste coordinates
|
|
804
|
+
sage: g = M.lorentzian_metric('g')
|
|
805
|
+
sage: m = var('m') # mass in Schwarzschild metric
|
|
806
|
+
sage: g[0,0], g[1,1] = -(1-2*m/r), 1/(1-2*m/r)
|
|
807
|
+
sage: g[2,2], g[3,3] = r^2, (r*sin(th))^2
|
|
808
|
+
sage: g.display()
|
|
809
|
+
g = (2*m/r - 1) dt⊗dt - 1/(2*m/r - 1) dr⊗dr + r^2 dth⊗dth
|
|
810
|
+
+ r^2*sin(th)^2 dph⊗dph
|
|
811
|
+
sage: nab = g.connection() ; nab
|
|
812
|
+
Levi-Civita connection nabla_g associated with the Lorentzian
|
|
813
|
+
metric g on the 4-dimensional differentiable manifold M
|
|
814
|
+
sage: ric = nab.ricci() ; ric
|
|
815
|
+
Field of symmetric bilinear forms Ric(g) on the 4-dimensional
|
|
816
|
+
differentiable manifold M
|
|
817
|
+
sage: ric == 0
|
|
818
|
+
True
|
|
819
|
+
"""
|
|
820
|
+
if self._ricci is None:
|
|
821
|
+
if name is None:
|
|
822
|
+
name = "Ric(" + self._metric._name + ")"
|
|
823
|
+
if latex_name is None:
|
|
824
|
+
latex_name = r"\mathrm{Ric}\left(" + \
|
|
825
|
+
self._metric._latex_name + r"\right)"
|
|
826
|
+
manif = self._domain
|
|
827
|
+
riem = self.riemann()
|
|
828
|
+
resu = manif.tensor_field(0, 2, sym=(0,1), name=name,
|
|
829
|
+
latex_name=latex_name)
|
|
830
|
+
for frame in self._coefficients:
|
|
831
|
+
cric = resu.add_comp(frame)
|
|
832
|
+
criem = riem.comp(frame)
|
|
833
|
+
for i in manif.irange():
|
|
834
|
+
# symmetry of the Ricci tensor taken into account by j>=i:
|
|
835
|
+
for j in manif.irange(start=i):
|
|
836
|
+
rsum = 0
|
|
837
|
+
for k in manif.irange():
|
|
838
|
+
rsum += criem[[k,i,k,j]]
|
|
839
|
+
cric[i,j] = rsum
|
|
840
|
+
self._ricci = resu
|
|
841
|
+
return self._ricci
|