passagemath-symbolics 10.8.1a1__cp311-cp311-macosx_13_0_arm64.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.
Files changed (182) hide show
  1. passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_symbolics/__init__.py +3 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/RECORD +182 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +6 -0
  6. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_symbolics.py +17 -0
  8. sage/calculus/all.py +14 -0
  9. sage/calculus/calculus.py +2838 -0
  10. sage/calculus/desolvers.py +1864 -0
  11. sage/calculus/predefined.py +51 -0
  12. sage/calculus/tests.py +225 -0
  13. sage/calculus/var.cpython-311-darwin.so +0 -0
  14. sage/calculus/var.pyx +401 -0
  15. sage/dynamics/all__sagemath_symbolics.py +6 -0
  16. sage/dynamics/complex_dynamics/all.py +5 -0
  17. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-311-darwin.so +0 -0
  19. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  20. sage/ext/all__sagemath_symbolics.py +1 -0
  21. sage/ext_data/kenzo/CP2.txt +45 -0
  22. sage/ext_data/kenzo/CP3.txt +349 -0
  23. sage/ext_data/kenzo/CP4.txt +4774 -0
  24. sage/ext_data/kenzo/README.txt +49 -0
  25. sage/ext_data/kenzo/S4.txt +20 -0
  26. sage/ext_data/magma/latex/latex.m +1021 -0
  27. sage/ext_data/magma/latex/latex.spec +1 -0
  28. sage/ext_data/magma/sage/basic.m +356 -0
  29. sage/ext_data/magma/sage/sage.spec +1 -0
  30. sage/ext_data/magma/spec +9 -0
  31. sage/geometry/all__sagemath_symbolics.py +8 -0
  32. sage/geometry/hyperbolic_space/all.py +5 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  39. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  40. sage/geometry/riemannian_manifolds/all.py +7 -0
  41. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  42. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  43. sage/interfaces/all__sagemath_symbolics.py +1 -0
  44. sage/interfaces/magma.py +2991 -0
  45. sage/interfaces/magma_free.py +90 -0
  46. sage/interfaces/maple.py +1402 -0
  47. sage/interfaces/mathematica.py +1345 -0
  48. sage/interfaces/mathics.py +1312 -0
  49. sage/interfaces/sympy.py +1398 -0
  50. sage/interfaces/sympy_wrapper.py +197 -0
  51. sage/interfaces/tides.py +938 -0
  52. sage/libs/all__sagemath_symbolics.py +6 -0
  53. sage/manifolds/all.py +7 -0
  54. sage/manifolds/calculus_method.py +553 -0
  55. sage/manifolds/catalog.py +437 -0
  56. sage/manifolds/chart.py +4010 -0
  57. sage/manifolds/chart_func.py +3416 -0
  58. sage/manifolds/continuous_map.py +2183 -0
  59. sage/manifolds/continuous_map_image.py +155 -0
  60. sage/manifolds/differentiable/affine_connection.py +2475 -0
  61. sage/manifolds/differentiable/all.py +1 -0
  62. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  63. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  64. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  65. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  66. sage/manifolds/differentiable/chart.py +1241 -0
  67. sage/manifolds/differentiable/curve.py +1028 -0
  68. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  69. sage/manifolds/differentiable/degenerate.py +559 -0
  70. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  71. sage/manifolds/differentiable/diff_form.py +1660 -0
  72. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  73. sage/manifolds/differentiable/diff_map.py +1315 -0
  74. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  75. sage/manifolds/differentiable/examples/all.py +1 -0
  76. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  77. sage/manifolds/differentiable/examples/real_line.py +897 -0
  78. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  79. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  80. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  81. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  82. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  83. sage/manifolds/differentiable/manifold.py +4254 -0
  84. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  85. sage/manifolds/differentiable/metric.py +3032 -0
  86. sage/manifolds/differentiable/mixed_form.py +1507 -0
  87. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  88. sage/manifolds/differentiable/multivector_module.py +800 -0
  89. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  90. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  91. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  92. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  93. sage/manifolds/differentiable/scalarfield.py +1343 -0
  94. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  95. sage/manifolds/differentiable/symplectic_form.py +912 -0
  96. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  97. sage/manifolds/differentiable/tangent_space.py +412 -0
  98. sage/manifolds/differentiable/tangent_vector.py +616 -0
  99. sage/manifolds/differentiable/tensorfield.py +4665 -0
  100. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  101. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  102. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  103. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  104. sage/manifolds/differentiable/vectorfield.py +1717 -0
  105. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  106. sage/manifolds/differentiable/vectorframe.py +1832 -0
  107. sage/manifolds/family.py +270 -0
  108. sage/manifolds/local_frame.py +1490 -0
  109. sage/manifolds/manifold.py +3090 -0
  110. sage/manifolds/manifold_homset.py +452 -0
  111. sage/manifolds/operators.py +359 -0
  112. sage/manifolds/point.py +994 -0
  113. sage/manifolds/scalarfield.py +3718 -0
  114. sage/manifolds/scalarfield_algebra.py +629 -0
  115. sage/manifolds/section.py +3111 -0
  116. sage/manifolds/section_module.py +831 -0
  117. sage/manifolds/structure.py +229 -0
  118. sage/manifolds/subset.py +2721 -0
  119. sage/manifolds/subsets/all.py +1 -0
  120. sage/manifolds/subsets/closure.py +131 -0
  121. sage/manifolds/subsets/pullback.py +883 -0
  122. sage/manifolds/topological_submanifold.py +891 -0
  123. sage/manifolds/trivialization.py +733 -0
  124. sage/manifolds/utilities.py +1348 -0
  125. sage/manifolds/vector_bundle.py +1347 -0
  126. sage/manifolds/vector_bundle_fiber.py +332 -0
  127. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  128. sage/matrix/all__sagemath_symbolics.py +1 -0
  129. sage/matrix/matrix_symbolic_dense.cpython-311-darwin.so +0 -0
  130. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  131. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  132. sage/matrix/matrix_symbolic_sparse.cpython-311-darwin.so +0 -0
  133. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  134. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  135. sage/modules/all__sagemath_symbolics.py +1 -0
  136. sage/modules/vector_callable_symbolic_dense.py +105 -0
  137. sage/modules/vector_symbolic_dense.py +116 -0
  138. sage/modules/vector_symbolic_sparse.py +118 -0
  139. sage/rings/all__sagemath_symbolics.py +4 -0
  140. sage/rings/asymptotic/all.py +6 -0
  141. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  142. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  143. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  144. sage/rings/asymptotic/growth_group.py +5373 -0
  145. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  146. sage/rings/asymptotic/term_monoid.py +5205 -0
  147. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  148. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  149. sage/symbolic/all.py +15 -0
  150. sage/symbolic/assumptions.py +987 -0
  151. sage/symbolic/benchmark.py +93 -0
  152. sage/symbolic/callable.py +456 -0
  153. sage/symbolic/callable.pyi +66 -0
  154. sage/symbolic/comparison_impl.pyi +38 -0
  155. sage/symbolic/complexity_measures.py +35 -0
  156. sage/symbolic/constants.py +1286 -0
  157. sage/symbolic/constants_c_impl.pyi +10 -0
  158. sage/symbolic/expression_conversion_algebraic.py +310 -0
  159. sage/symbolic/expression_conversion_sympy.py +317 -0
  160. sage/symbolic/expression_conversions.py +1727 -0
  161. sage/symbolic/function_factory.py +355 -0
  162. sage/symbolic/function_factory.pyi +41 -0
  163. sage/symbolic/getitem_impl.pyi +24 -0
  164. sage/symbolic/integration/all.py +1 -0
  165. sage/symbolic/integration/external.py +271 -0
  166. sage/symbolic/integration/integral.py +1075 -0
  167. sage/symbolic/maxima_wrapper.py +162 -0
  168. sage/symbolic/operators.py +267 -0
  169. sage/symbolic/operators.pyi +61 -0
  170. sage/symbolic/pynac_constant_impl.pyi +13 -0
  171. sage/symbolic/pynac_function_impl.pyi +8 -0
  172. sage/symbolic/random_tests.py +461 -0
  173. sage/symbolic/relation.py +2062 -0
  174. sage/symbolic/ring.cpython-311-darwin.so +0 -0
  175. sage/symbolic/ring.pxd +5 -0
  176. sage/symbolic/ring.pyi +110 -0
  177. sage/symbolic/ring.pyx +1393 -0
  178. sage/symbolic/series_impl.pyi +10 -0
  179. sage/symbolic/subring.py +1025 -0
  180. sage/symbolic/symengine.py +19 -0
  181. sage/symbolic/tests.py +40 -0
  182. sage/symbolic/units.py +1468 -0
@@ -0,0 +1,1522 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Multivector Fields
4
+
5
+ Let `U` and `M` be two differentiable manifolds.
6
+ Given a positive integer `p` and a differentiable map `\Phi: U \rightarrow M`,
7
+ a *multivector field of degree* `p`, or `p`-*vector field*,
8
+ *along* `U` *with values on* `M` is a field along `U` of alternating
9
+ contravariant tensors of rank `p` in the tangent spaces to `M`.
10
+ The standard case of a multivector field *on* a differentiable manifold
11
+ corresponds to `U = M` and `\Phi = \mathrm{Id}_M`. Other common cases are
12
+ `\Phi` being an immersion and `\Phi` being a curve in `M` (`U` is then an open
13
+ interval of `\RR`).
14
+
15
+ Two classes implement multivector fields, depending whether the manifold
16
+ `M` is parallelizable:
17
+
18
+ * :class:`MultivectorFieldParal` when `M` is parallelizable
19
+ * :class:`MultivectorField` when `M` is not assumed parallelizable.
20
+
21
+ AUTHORS:
22
+
23
+ - Eric Gourgoulhon (2017): initial version
24
+
25
+ REFERENCES:
26
+
27
+ - \R. L. Bishop and S. L. Goldberg (1980) [BG1980]_
28
+ - \C.-M. Marle (1997) [Mar1997]_
29
+ """
30
+
31
+ # *****************************************************************************
32
+ # Copyright (C) 2017 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
33
+ #
34
+ # Distributed under the terms of the GNU General Public License (GPL)
35
+ # as published by the Free Software Foundation; either version 2 of
36
+ # the License, or (at your option) any later version.
37
+ # https://www.gnu.org/licenses/
38
+ # *****************************************************************************
39
+
40
+ from sage.manifolds.differentiable.tensorfield import TensorField
41
+ from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
42
+ from sage.tensor.modules.alternating_contr_tensor import AlternatingContrTensor
43
+
44
+
45
+ class MultivectorField(TensorField):
46
+ r"""
47
+ Multivector field with values on a generic (i.e. a priori not
48
+ parallelizable) differentiable manifold.
49
+
50
+ Given a differentiable manifold `U`, a differentiable map
51
+ `\Phi: U \rightarrow M` to a differentiable manifold `M` and a positive
52
+ integer `p`, a *multivector field of degree* `p` (or `p`-*vector field*)
53
+ *along* `U` *with values on* `M\supset\Phi(U)` is a differentiable map
54
+
55
+ .. MATH::
56
+
57
+ a:\ U \longrightarrow T^{(p,0)}M
58
+
59
+ (`T^{(p,0)}M` being the tensor bundle of type `(p,0)` over `M`) such that
60
+
61
+ .. MATH::
62
+
63
+ \forall x \in U,\quad a(x) \in \Lambda^p(T_{\Phi(x)} M) ,
64
+
65
+ where `T_{\Phi(x)} M` is the vector space tangent to `M` at `\Phi(x)` and
66
+ `\Lambda^p` stands for the exterior power of degree `p` (cf.
67
+ :class:`~sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule`).
68
+ In other words, `a(x)` is an alternating contravariant tensor of degree `p`
69
+ of the tangent vector space `T_{\Phi(x)} M`.
70
+
71
+ The standard case of a multivector field *on* a manifold `M` corresponds to
72
+ `U = M` and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
73
+ immersion and `\Phi` being a curve in `M` (`U` is then an open interval of
74
+ `\RR`).
75
+
76
+ .. NOTE::
77
+
78
+ If `M` is parallelizable, the class :class:`MultivectorFieldParal`
79
+ must be used instead.
80
+
81
+ INPUT:
82
+
83
+ - ``vector_field_module`` -- module `\mathfrak{X}(U,\Phi)` of vector fields
84
+ along `U` with values on `M` via the map `\Phi`
85
+ - ``degree`` -- the degree of the multivector field (i.e. its tensor rank)
86
+ - ``name`` -- (default: ``None``) name given to the multivector field
87
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
88
+ multivector field; if none is provided, the LaTeX symbol is set to
89
+ ``name``
90
+
91
+ EXAMPLES:
92
+
93
+ Multivector field of degree 2 on a non-parallelizable 2-dimensional
94
+ manifold::
95
+
96
+ sage: M = Manifold(2, 'M')
97
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
98
+ sage: M.declare_union(U,V) # M is the union of U and V
99
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
100
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
101
+ ....: intersection_name='W',
102
+ ....: restrictions1= x>0, restrictions2= u+v>0)
103
+ sage: uv_to_xy = xy_to_uv.inverse()
104
+ sage: W = U.intersection(V)
105
+ sage: eU = c_xy.frame() ; eV = c_uv.frame()
106
+ sage: a = M.multivector_field(2, name='a') ; a
107
+ 2-vector field a on the 2-dimensional differentiable manifold M
108
+ sage: a.parent()
109
+ Module A^2(M) of 2-vector fields on the 2-dimensional differentiable
110
+ manifold M
111
+ sage: a.degree()
112
+ 2
113
+
114
+ Setting the components of ``a``::
115
+
116
+ sage: a[eU,0,1] = x*y^2 + 2*x
117
+ sage: a.add_comp_by_continuation(eV, W, c_uv)
118
+ sage: a.display(eU)
119
+ a = (x*y^2 + 2*x) ∂/∂x∧∂/∂y
120
+ sage: a.display(eV)
121
+ a = (-1/4*u^3 + 1/4*u*v^2 - 1/4*v^3 + 1/4*(u^2 - 8)*v - 2*u) ∂/∂u∧∂/∂v
122
+
123
+
124
+ It is also possible to set the components while defining the 2-vector field
125
+ definition, via a dictionary whose keys are the vector frames::
126
+
127
+ sage: a1 = M.multivector_field(2, {eU: [[0, x*y^2 + 2*x],
128
+ ....: [-x*y^2 - 2*x, 0]]}, name='a')
129
+ sage: a1.add_comp_by_continuation(eV, W, c_uv)
130
+ sage: a1 == a
131
+ True
132
+
133
+ The exterior product of two vector fields is a 2-vector field::
134
+
135
+ sage: a = M.vector_field({eU: [-y, x]}, name='a')
136
+ sage: a.add_comp_by_continuation(eV, W, c_uv)
137
+ sage: b = M.vector_field({eU: [1+x*y, x^2]}, name='b')
138
+ sage: b.add_comp_by_continuation(eV, W, c_uv)
139
+ sage: s = a.wedge(b) ; s
140
+ 2-vector field a∧b on the 2-dimensional differentiable manifold M
141
+ sage: s.display(eU)
142
+ a∧b = (-2*x^2*y - x) ∂/∂x∧∂/∂y
143
+ sage: s.display(eV)
144
+ a∧b = (1/2*u^3 - 1/2*u*v^2 - 1/2*v^3 + 1/2*(u^2 + 2)*v + u) ∂/∂u∧∂/∂v
145
+
146
+ Multiplying a 2-vector field by a scalar field results in another
147
+ 2-vector field::
148
+
149
+ sage: f = M.scalar_field({c_xy: (x+y)^2, c_uv: u^2}, name='f')
150
+ sage: s = f*s ; s
151
+ 2-vector field f*(a∧b) on the 2-dimensional differentiable manifold M
152
+ sage: s.display(eU)
153
+ f*(a∧b) = (-2*x^2*y^3 - x^3 - (4*x^3 + x)*y^2 - 2*(x^4 + x^2)*y) ∂/∂x∧∂/∂y
154
+ sage: s.display(eV)
155
+ f*(a∧b) = (1/2*u^5 - 1/2*u^3*v^2 - 1/2*u^2*v^3 + u^3 + 1/2*(u^4 + 2*u^2)*v)
156
+ ∂/∂u∧∂/∂v
157
+ """
158
+ def __init__(self, vector_field_module, degree, name=None, latex_name=None):
159
+ r"""
160
+ Construct a multivector field.
161
+
162
+ TESTS:
163
+
164
+ Construction via ``parent.element_class``, and not via a direct call
165
+ to ``MultivectorField``, to fit with the category framework::
166
+
167
+ sage: M = Manifold(2, 'M')
168
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
169
+ sage: M.declare_union(U,V) # M is the union of U and V
170
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
171
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
172
+ ....: intersection_name='W', restrictions1= x>0,
173
+ ....: restrictions2= u+v>0)
174
+ sage: uv_to_xy = xy_to_uv.inverse()
175
+ sage: W = U.intersection(V)
176
+ sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
177
+ sage: A = M.multivector_module(2)
178
+ sage: XM = M.vector_field_module()
179
+ sage: a = A.element_class(XM, 2, name='a'); a
180
+ 2-vector field a on the 2-dimensional differentiable manifold M
181
+ sage: a[e_xy,0,1] = x+y
182
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
183
+ sage: TestSuite(a).run(skip='_test_pickling')
184
+
185
+ Construction with ``DifferentiableManifold.multivector_field``::
186
+
187
+ sage: a1 = M.multivector_field(2, name='a'); a1
188
+ 2-vector field a on the 2-dimensional differentiable manifold M
189
+ sage: type(a1) == type(a)
190
+ True
191
+ sage: a1.parent() is a.parent()
192
+ True
193
+
194
+ .. TODO::
195
+
196
+ Fix ``_test_pickling`` (in the superclass :class:`TensorField`).
197
+ """
198
+ TensorField.__init__(self, vector_field_module, (degree, 0), name=name,
199
+ latex_name=latex_name, antisym=range(degree),
200
+ parent=vector_field_module.exterior_power(degree))
201
+ self._init_derived() # initialization of derived quantities
202
+
203
+ def _repr_(self):
204
+ r"""
205
+ String representation of ``self``.
206
+
207
+ TESTS::
208
+
209
+ sage: M = Manifold(3, 'M')
210
+ sage: a = M.multivector_field(2, name='a')
211
+ sage: a._repr_()
212
+ '2-vector field a on the 3-dimensional differentiable manifold M'
213
+ sage: repr(a) # indirect doctest
214
+ '2-vector field a on the 3-dimensional differentiable manifold M'
215
+ sage: a # indirect doctest
216
+ 2-vector field a on the 3-dimensional differentiable manifold M
217
+ sage: b = M.multivector_field(2)
218
+ sage: b._repr_()
219
+ '2-vector field on the 3-dimensional differentiable manifold M'
220
+ """
221
+ description = "{}-vector field ".format(self._tensor_rank)
222
+ if self._name is not None:
223
+ description += self._name + " "
224
+ return self._final_repr(description)
225
+
226
+ def _new_instance(self):
227
+ r"""
228
+ Create an instance of the same class, of the same degree and on the
229
+ same domain.
230
+
231
+ TESTS::
232
+
233
+ sage: M = Manifold(3, 'M')
234
+ sage: a = M.multivector_field(2, name='a')
235
+ sage: a1 = a._new_instance(); a1
236
+ 2-vector field on the 3-dimensional differentiable manifold M
237
+ sage: type(a1) == type(a)
238
+ True
239
+ sage: a1.parent() is a.parent()
240
+ True
241
+ """
242
+ return type(self)(self._vmodule, self._tensor_rank)
243
+
244
+ def degree(self):
245
+ r"""
246
+ Return the degree of ``self``.
247
+
248
+ OUTPUT: integer `p` such that ``self`` is a `p`-vector field
249
+
250
+ EXAMPLES::
251
+
252
+ sage: M = Manifold(3, 'M')
253
+ sage: a = M.multivector_field(2); a
254
+ 2-vector field on the 3-dimensional differentiable manifold M
255
+ sage: a.degree()
256
+ 2
257
+ sage: b = M.vector_field(); b
258
+ Vector field on the 3-dimensional differentiable manifold M
259
+ sage: b.degree()
260
+ 1
261
+ """
262
+ return self._tensor_rank
263
+
264
+ def wedge(self, other):
265
+ r"""
266
+ Exterior product with another multivector field.
267
+
268
+ INPUT:
269
+
270
+ - ``other`` -- another multivector field (on the same manifold)
271
+
272
+ OUTPUT:
273
+
274
+ - instance of :class:`MultivectorField` representing the exterior
275
+ product ``self ∧ other``
276
+
277
+ EXAMPLES:
278
+
279
+ Exterior product of two vector fields on the 2-sphere::
280
+
281
+ sage: M = Manifold(2, 'S^2', start_index=1) # the sphere S^2
282
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
283
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
284
+ sage: c_xy.<x,y> = U.chart() # stereographic coord. North
285
+ sage: c_uv.<u,v> = V.chart() # stereographic coord. South
286
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
287
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
288
+ ....: restrictions2= u^2+v^2!=0)
289
+ sage: uv_to_xy = xy_to_uv.inverse()
290
+ sage: W = U.intersection(V) # The complement of the two poles
291
+ sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
292
+ sage: a = M.vector_field({e_xy: [y, x]}, name='a')
293
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
294
+ sage: b = M.vector_field({e_xy: [x^2 + y^2, y]}, name='b')
295
+ sage: b.add_comp_by_continuation(e_uv, W, c_uv)
296
+ sage: c = a.wedge(b); c
297
+ 2-vector field a∧b on the 2-dimensional differentiable
298
+ manifold S^2
299
+ sage: c.display(e_xy)
300
+ a∧b = (-x^3 - (x - 1)*y^2) ∂/∂x∧∂/∂y
301
+ sage: c.display(e_uv)
302
+ a∧b = (-v^2 + u) ∂/∂u∧∂/∂v
303
+ """
304
+ from sage.tensor.modules.format_utilities import is_atomic
305
+ from sage.typeset.unicode_characters import unicode_wedge
306
+ if self._domain.is_subset(other._domain):
307
+ if not self._ambient_domain.is_subset(other._ambient_domain):
308
+ raise ValueError("incompatible ambient domains for exterior " +
309
+ "product")
310
+ elif other._domain.is_subset(self._domain):
311
+ if not other._ambient_domain.is_subset(self._ambient_domain):
312
+ raise ValueError("incompatible ambient domains for exterior " +
313
+ "product")
314
+ dom_resu = self._domain.intersection(other._domain)
315
+ ambient_dom_resu = self._ambient_domain.intersection(other._ambient_domain)
316
+ self_r = self.restrict(dom_resu)
317
+ other_r = other.restrict(dom_resu)
318
+ if ambient_dom_resu.is_manifestly_parallelizable():
319
+ # call of the AlternatingContrTensor version:
320
+ return AlternatingContrTensor.wedge(self_r, other_r)
321
+ # otherwise, the result is created here:
322
+ resu_name = None
323
+ if self._name is not None and other._name is not None:
324
+ sname = self._name
325
+ oname = other._name
326
+ if not is_atomic(sname):
327
+ sname = '(' + sname + ')'
328
+ if not is_atomic(oname):
329
+ oname = '(' + oname + ')'
330
+ resu_name = sname + unicode_wedge + oname
331
+ resu_latex_name = None
332
+ if self._latex_name is not None and other._latex_name is not None:
333
+ slname = self._latex_name
334
+ olname = other._latex_name
335
+ if not is_atomic(slname):
336
+ slname = '(' + slname + ')'
337
+ if not is_atomic(olname):
338
+ olname = '(' + olname + ')'
339
+ resu_latex_name = slname + r'\wedge ' + olname
340
+ dest_map = self._vmodule._dest_map
341
+ dest_map_resu = dest_map.restrict(dom_resu,
342
+ subcodomain=ambient_dom_resu)
343
+ vmodule = dom_resu.vector_field_module(dest_map=dest_map_resu)
344
+ resu_degree = self._tensor_rank + other._tensor_rank
345
+ resu = vmodule.alternating_contravariant_tensor(resu_degree,
346
+ name=resu_name, latex_name=resu_latex_name)
347
+ for dom in self_r._restrictions:
348
+ if dom in other_r._restrictions:
349
+ resu._restrictions[dom] = self_r._restrictions[dom].wedge(
350
+ other_r._restrictions[dom])
351
+ return resu
352
+
353
+ def interior_product(self, form):
354
+ r"""
355
+ Interior product with a differential form.
356
+
357
+ If ``self`` is a multivector field `A` of degree `p` and `B` is a
358
+ differential form of degree `q\geq p` on the same manifold as `A`, the
359
+ interior product of `A` by `B` is the differential form `\iota_A B` of
360
+ degree `q-p` defined by
361
+
362
+ .. MATH::
363
+
364
+ (\iota_A B)_{i_1\ldots i_{q-p}} = A^{k_1\ldots k_p}
365
+ B_{k_1\ldots k_p i_1\ldots i_{q-p}}
366
+
367
+ .. NOTE::
368
+
369
+ ``A.interior_product(B)`` yields the same result as
370
+ ``A.contract(0,..., p-1, B, 0,..., p-1)`` (cf.
371
+ :meth:`~sage.manifolds.differentiable.tensorfield.TensorField.contract`),
372
+ but ``interior_product`` is more efficient, the alternating
373
+ character of `A` being not used to reduce the computation in
374
+ :meth:`~sage.manifolds.differentiable.tensorfield.TensorField.contract`
375
+
376
+ INPUT:
377
+
378
+ - ``form`` -- differential form `B` (instance of
379
+ :class:`~sage.manifolds.differentiable.diff_form.DiffForm`);
380
+ the degree of `B` must be at least equal to the degree of ``self``
381
+
382
+ OUTPUT:
383
+
384
+ - scalar field (case `p=q`) or
385
+ :class:`~sage.manifolds.differentiable.diff_form.DiffForm`
386
+ (case `p<q`) representing the interior product `\iota_A B`, where `A`
387
+ is ``self``
388
+
389
+ .. SEEALSO::
390
+
391
+ :meth:`~sage.manifolds.differentiable.diff_form.DiffForm.interior_product`
392
+ for the interior product of a differential form with a multivector
393
+ field
394
+
395
+ EXAMPLES:
396
+
397
+ Interior product of a vector field (`p=1`) with a 2-form (`q=2`) on the
398
+ 2-sphere::
399
+
400
+ sage: M = Manifold(2, 'S^2', start_index=1) # the sphere S^2
401
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
402
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
403
+ sage: c_xy.<x,y> = U.chart() # stereographic coord. North
404
+ sage: c_uv.<u,v> = V.chart() # stereographic coord. South
405
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
406
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
407
+ ....: restrictions2= u^2+v^2!=0)
408
+ sage: uv_to_xy = xy_to_uv.inverse()
409
+ sage: W = U.intersection(V) # The complement of the two poles
410
+ sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
411
+ sage: a = M.vector_field({e_xy: [-y, x]}, name='a')
412
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
413
+ sage: b = M.diff_form(2, name='b')
414
+ sage: b[e_xy,1,2] = 4/(x^2+y^2+1)^2 # the standard area 2-form
415
+ sage: b.add_comp_by_continuation(e_uv, W, c_uv)
416
+ sage: b.display(e_xy)
417
+ b = 4/(x^2 + y^2 + 1)^2 dx∧dy
418
+ sage: b.display(e_uv)
419
+ b = -4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) du∧dv
420
+ sage: s = a.interior_product(b); s
421
+ 1-form i_a b on the 2-dimensional differentiable manifold S^2
422
+ sage: s.display(e_xy)
423
+ i_a b = -4*x/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx
424
+ - 4*y/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dy
425
+ sage: s.display(e_uv)
426
+ i_a b = 4*u/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) du
427
+ + 4*v/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) dv
428
+ sage: s == a.contract(b)
429
+ True
430
+
431
+ Example with `p=2` and `q=2`::
432
+
433
+ sage: a = M.multivector_field(2, name='a')
434
+ sage: a[e_xy,1,2] = x*y
435
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
436
+ sage: a.display(e_xy)
437
+ a = x*y ∂/∂x∧∂/∂y
438
+ sage: a.display(e_uv)
439
+ a = -u*v ∂/∂u∧∂/∂v
440
+ sage: s = a.interior_product(b); s
441
+ Scalar field i_a b on the 2-dimensional differentiable manifold S^2
442
+ sage: s.display()
443
+ i_a b: S^2 → ℝ
444
+ on U: (x, y) ↦ 8*x*y/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1)
445
+ on V: (u, v) ↦ 8*u*v/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1)
446
+
447
+ Some checks::
448
+
449
+ sage: s == a.contract(0, 1, b, 0, 1)
450
+ True
451
+ sage: s.restrict(U) == 2 * a[[e_xy,1,2]] * b[[e_xy,1,2]]
452
+ True
453
+ sage: s.restrict(V) == 2 * a[[e_uv,1,2]] * b[[e_uv,1,2]]
454
+ True
455
+ """
456
+ from sage.tensor.modules.format_utilities import is_atomic
457
+ if self._domain.is_subset(form._domain):
458
+ if not self._ambient_domain.is_subset(form._ambient_domain):
459
+ raise ValueError("incompatible ambient domains for interior " +
460
+ "product")
461
+ elif form._domain.is_subset(self._domain):
462
+ if not form._ambient_domain.is_subset(self._ambient_domain):
463
+ raise ValueError("incompatible ambient domains for interior " +
464
+ "product")
465
+ dom_resu = self._domain.intersection(form._domain)
466
+ ambient_dom_resu = self._ambient_domain.intersection(form._ambient_domain)
467
+ self_r = self.restrict(dom_resu)
468
+ form_r = form.restrict(dom_resu)
469
+ if ambient_dom_resu.is_manifestly_parallelizable():
470
+ # call of the AlternatingContrTensor version:
471
+ return AlternatingContrTensor.interior_product(self_r, form_r)
472
+ # Otherwise, the result is created here:
473
+ # Name of the result
474
+ resu_name = None
475
+ if self._name is not None and form._name is not None:
476
+ sname = self._name
477
+ oname = form._name
478
+ if not is_atomic(sname):
479
+ sname = '(' + sname + ')'
480
+ if not is_atomic(oname):
481
+ oname = '(' + oname + ')'
482
+ resu_name = 'i_' + sname + ' ' + oname
483
+ resu_latex_name = None
484
+ if self._latex_name is not None and form._latex_name is not None:
485
+ slname = self._latex_name
486
+ olname = form._latex_name
487
+ if not is_atomic(olname):
488
+ olname = r'\left(' + olname + r'\right)'
489
+ resu_latex_name = r'\iota_{' + slname + '} ' + olname
490
+ # Domain and computation of the result
491
+ dest_map = self._vmodule._dest_map
492
+ dest_map_resu = dest_map.restrict(dom_resu,
493
+ subcodomain=ambient_dom_resu)
494
+ vmodule = dom_resu.vector_field_module(dest_map=dest_map_resu)
495
+ resu_degree = form._tensor_rank - self._tensor_rank
496
+ resu = vmodule.alternating_form(resu_degree,
497
+ name=resu_name,
498
+ latex_name=resu_latex_name)
499
+ for dom in self_r._restrictions:
500
+ if dom in form_r._restrictions:
501
+ resu._restrictions[dom] = \
502
+ self_r._restrictions[dom].interior_product(
503
+ form_r._restrictions[dom])
504
+ if resu_degree == 0:
505
+ if not resu._express:
506
+ # only the restrictions to subdomains have
507
+ # been initialized
508
+ for chart in dom_resu.top_charts():
509
+ resu._express[chart] = \
510
+ resu.restrict(chart.domain()).coord_function(chart)
511
+ return resu
512
+
513
+ def bracket(self, other):
514
+ r"""
515
+ Return the Schouten-Nijenhuis bracket of ``self`` with another
516
+ multivector field.
517
+
518
+ The Schouten-Nijenhuis bracket extends the Lie bracket of
519
+ vector fields (cf.
520
+ :meth:`~sage.manifolds.differentiable.vectorfield.VectorField.bracket`)
521
+ to multivector fields.
522
+
523
+ Denoting by `A^p(M)` the `C^k(M)`-module of `p`-vector fields on the
524
+ `C^k`-differentiable manifold `M` over the field `K` (cf.
525
+ :class:`~sage.manifolds.differentiable.multivector_module.MultivectorModule`),
526
+ the *Schouten-Nijenhuis bracket* is a `K`-bilinear map
527
+
528
+ .. MATH::
529
+
530
+ \begin{array}{ccc}
531
+ A^p(M)\times A^q(M) & \longrightarrow & A^{p+q-1}(M) \\
532
+ (a,b) & \longmapsto & [a,b]
533
+ \end{array}
534
+
535
+ which obeys the following properties:
536
+
537
+ - if `p=0` and `q=0`, (i.e. `a` and `b` are two scalar fields), `[a,b]=0`
538
+ - if `p=0` (i.e. `a` is a scalar field) and `q\geq 1`,
539
+ `[a,b] = - \iota_{\mathrm{d}a} b` (minus the interior product of
540
+ the differential of `a` by `b`)
541
+ - if `p=1` (i.e. `a` is a vector field), `[a,b] = \mathcal{L}_a b`
542
+ (the Lie derivative of `b` along `a`)
543
+ - `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]`
544
+ - for any multivector field `c` and `(a,b) \in A^p(M)\times A^q(M)`,
545
+ `[a,.]` obeys the *graded Leibniz rule*
546
+
547
+ .. MATH::
548
+
549
+ [a,b\wedge c] = [a,b]\wedge c + (-1)^{(p-1)q} b\wedge [a,c]
550
+
551
+ - for `(a,b,c) \in A^p(M)\times A^q(M)\times A^r(M)`, the *graded
552
+ Jacobi identity* holds:
553
+
554
+ .. MATH::
555
+
556
+ (-1)^{(p-1)(r-1)}[a,[b,c]] + (-1)^{(q-1)(p-1)}[b,[c,a]] +
557
+ (-1)^{(r-1)(q-1)}[c,[a,b]] = 0
558
+
559
+ .. NOTE::
560
+
561
+ There are two definitions of the Schouten-Nijenhuis bracket in
562
+ the literature, which differ from each other when `p` is even
563
+ by an overall sign. The definition adopted here is that of
564
+ [Mar1997]_, [Kos1985]_ and :wikipedia:`Schouten-Nijenhuis_bracket`.
565
+ The other definition, adopted e.g. by [Nij1955]_, [Lic1977]_
566
+ and [Vai1994]_, is `[a,b]' = (-1)^{p+1} [a,b]`.
567
+
568
+ INPUT:
569
+
570
+ - ``other`` -- a multivector field
571
+
572
+ OUTPUT:
573
+
574
+ - instance of :class:`MultivectorField` (or of
575
+ :class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
576
+ if `p=1` and `q=0`) representing the
577
+ Schouten-Nijenhuis bracket `[a,b]`, where `a` is ``self`` and `b` is
578
+ ``other``
579
+
580
+ EXAMPLES:
581
+
582
+ Bracket of two vector fields on the 2-sphere::
583
+
584
+ sage: M = Manifold(2, 'S^2', start_index=1) # the sphere S^2
585
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
586
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
587
+ sage: c_xy.<x,y> = U.chart() # stereographic coord. North
588
+ sage: c_uv.<u,v> = V.chart() # stereographic coord. South
589
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
590
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
591
+ ....: restrictions2= u^2+v^2!=0)
592
+ sage: uv_to_xy = xy_to_uv.inverse()
593
+ sage: W = U.intersection(V) # The complement of the two poles
594
+ sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
595
+ sage: a = M.vector_field({e_xy: [y, x]}, name='a')
596
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
597
+ sage: b = M.vector_field({e_xy: [x*y, x-y]}, name='b')
598
+ sage: b.add_comp_by_continuation(e_uv, W, c_uv)
599
+ sage: s = a.bracket(b); s
600
+ Vector field [a,b] on the 2-dimensional differentiable manifold S^2
601
+ sage: s.display(e_xy)
602
+ [a,b] = (x^2 + y^2 - x + y) ∂/∂x + (-(x - 1)*y - x) ∂/∂y
603
+
604
+ For two vector fields, the bracket coincides with the Lie derivative::
605
+
606
+ sage: s == b.lie_derivative(a)
607
+ True
608
+
609
+ Schouten-Nijenhuis bracket of a 2-vector field and a 1-vector field::
610
+
611
+ sage: c = a.wedge(b); c
612
+ 2-vector field a∧b on the 2-dimensional differentiable
613
+ manifold S^2
614
+ sage: s = c.bracket(a); s
615
+ 2-vector field [a∧b,a] on the 2-dimensional differentiable
616
+ manifold S^2
617
+ sage: s.display(e_xy)
618
+ [a∧b,a] = (x^3 + (2*x - 1)*y^2 - x^2 + 2*x*y) ∂/∂x∧∂/∂y
619
+
620
+ Since `a` is a vector field, we have in this case::
621
+
622
+ sage: s == - c.lie_derivative(a)
623
+ True
624
+
625
+ .. SEEALSO::
626
+
627
+ :meth:`MultivectorFieldParal.bracket` for more examples and check
628
+ of standards identities involving the Schouten-Nijenhuis bracket
629
+ """
630
+ from sage.manifolds.differentiable.scalarfield import DiffScalarField
631
+ pp = self._tensor_rank
632
+ mp1 = (-1)**(pp+1)
633
+ if isinstance(other, DiffScalarField):
634
+ resu = other.differential().interior_product(self)
635
+ if mp1 == 1:
636
+ return resu
637
+ return - resu
638
+ # Some checks:
639
+ if not isinstance(other, (MultivectorField, MultivectorFieldParal)):
640
+ raise TypeError("{} is not a multivector field".format(other))
641
+ if (self._vmodule.destination_map() is not self._domain.identity_map()
642
+ or other._vmodule.destination_map() is not
643
+ other._domain.identity_map()):
644
+ raise ValueError("the Schouten-Nijenhuis bracket is defined " +
645
+ "only for fields with a trivial destination map")
646
+ # Search for a common domain
647
+ dom_resu = self._domain.intersection(other._domain)
648
+ self_r = self.restrict(dom_resu)
649
+ other_r = other.restrict(dom_resu)
650
+ if dom_resu.is_manifestly_parallelizable():
651
+ # call of the MultivectorFieldParal version:
652
+ return MultivectorFieldParal.bracket(self_r, other_r)
653
+ # otherwise, the result is created here:
654
+ # Name of the result:
655
+ resu_name = None
656
+ resu_latex_name = None
657
+ if self._name is not None and other._name is not None:
658
+ resu_name = '[' + self._name + ',' + other._name + ']'
659
+ if self._latex_name is not None and other._latex_name is not None:
660
+ resu_latex_name = r'\left[' + self._latex_name + ',' + \
661
+ other._latex_name + r'\right]'
662
+ vmodule = dom_resu.vector_field_module()
663
+ deg_resu = pp + other._tensor_rank - 1 # degree of the result
664
+ resu = vmodule.alternating_contravariant_tensor(deg_resu,
665
+ name=resu_name, latex_name=resu_latex_name)
666
+ for dom in self_r._restrictions:
667
+ if dom in other_r._restrictions:
668
+ resu._restrictions[dom] = self_r._restrictions[dom].bracket(
669
+ other_r._restrictions[dom])
670
+ return resu
671
+
672
+
673
+ #******************************************************************************
674
+
675
+ class MultivectorFieldParal(AlternatingContrTensor, TensorFieldParal):
676
+ r"""
677
+ Multivector field with values on a parallelizable manifold.
678
+
679
+ Given a differentiable manifold `U`, a differentiable map
680
+ `\Phi: U \rightarrow M` to a parallelizable manifold `M` and a positive
681
+ integer `p`, a *multivector field of degree* `p` (or `p`-*vector field*)
682
+ *along* `U` *with values on* `M\supset\Phi(U)` is a differentiable map
683
+
684
+ .. MATH::
685
+
686
+ a:\ U \longrightarrow T^{(p,0)}M
687
+
688
+ (`T^{(p,0)}M` being the tensor bundle of type `(p,0)` over `M`) such that
689
+
690
+ .. MATH::
691
+
692
+ \forall x \in U,\quad a(x) \in \Lambda^p(T_{\Phi(x)} M) ,
693
+
694
+ where `T_{\Phi(x)} M` is the vector space tangent to `M` at `\Phi(x)` and
695
+ `\Lambda^p` stands for the exterior power of degree `p` (cf.
696
+ :class:`~sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule`).
697
+ In other words, `a(x)` is an alternating contravariant tensor of degree `p`
698
+ of the tangent vector space `T_{\Phi(x)} M`.
699
+
700
+ The standard case of a multivector field *on* a manifold `M` corresponds to
701
+ `U = M` and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
702
+ immersion and `\Phi` being a curve in `M` (`U` is then an open interval of
703
+ `\RR`).
704
+
705
+ .. NOTE::
706
+
707
+ If `M` is not parallelizable, the class :class:`MultivectorField` must
708
+ be used instead.
709
+
710
+ INPUT:
711
+
712
+ - ``vector_field_module`` -- free module `\mathfrak{X}(U,\Phi)` of vector
713
+ fields along `U` with values on `M` via the map `\Phi`
714
+ - ``degree`` -- the degree of the multivector field (i.e. its tensor rank)
715
+ - ``name`` -- (default: ``None``) name given to the multivector field
716
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
717
+ multivector field; if none is provided, the LaTeX symbol is set to
718
+ ``name``
719
+
720
+ EXAMPLES:
721
+
722
+ A 2-vector field on a 4-dimensional manifold::
723
+
724
+ sage: M = Manifold(4, 'M')
725
+ sage: c_txyz.<t,x,y,z> = M.chart()
726
+ sage: a = M.multivector_field(2, name='a') ; a
727
+ 2-vector field a on the 4-dimensional differentiable manifold M
728
+ sage: a.parent()
729
+ Free module A^2(M) of 2-vector fields on the 4-dimensional
730
+ differentiable manifold M
731
+
732
+ A multivector field is a tensor field of purely contravariant type::
733
+
734
+ sage: a.tensor_type()
735
+ (2, 0)
736
+
737
+ It is antisymmetric, its components being
738
+ :class:`~sage.tensor.modules.comp.CompFullyAntiSym`::
739
+
740
+ sage: a.symmetries()
741
+ no symmetry; antisymmetry: (0, 1)
742
+ sage: a[0,1] = 2*x
743
+ sage: a[1,0]
744
+ -2*x
745
+ sage: a.comp()
746
+ Fully antisymmetric 2-indices components w.r.t. Coordinate frame
747
+ (M, (∂/∂t,∂/∂x,∂/∂y,∂/∂z))
748
+ sage: type(a.comp())
749
+ <class 'sage.tensor.modules.comp.CompFullyAntiSym'>
750
+
751
+ Setting a component with repeated indices to a nonzero value results in
752
+ an error::
753
+
754
+ sage: a[1,1] = 3
755
+ Traceback (most recent call last):
756
+ ...
757
+ ValueError: by antisymmetry, the component cannot have a nonzero value
758
+ for the indices (1, 1)
759
+ sage: a[1,1] = 0 # OK, albeit useless
760
+ sage: a[1,2] = 3 # OK
761
+
762
+ The expansion of a multivector field with respect to a given frame is
763
+ displayed via the method
764
+ :meth:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor.display`::
765
+
766
+ sage: a.display() # expansion w.r.t. the default frame
767
+ a = 2*x ∂/∂t∧∂/∂x + 3 ∂/∂x∧∂/∂y
768
+ sage: latex(a.display()) # output for the notebook
769
+ a = 2 \, x \frac{\partial}{\partial t }\wedge \frac{\partial}{\partial x }
770
+ + 3 \frac{\partial}{\partial x }\wedge \frac{\partial}{\partial y }
771
+
772
+ Multivector fields can be added or subtracted::
773
+
774
+ sage: b = M.multivector_field(2)
775
+ sage: b[0,1], b[0,2], b[0,3] = y, 2, x+z
776
+ sage: s = a + b ; s
777
+ 2-vector field on the 4-dimensional differentiable manifold M
778
+ sage: s.display()
779
+ (2*x + y) ∂/∂t∧∂/∂x + 2 ∂/∂t∧∂/∂y + (x + z) ∂/∂t∧∂/∂z + 3 ∂/∂x∧∂/∂y
780
+ sage: s = a - b ; s
781
+ 2-vector field on the 4-dimensional differentiable manifold M
782
+ sage: s.display()
783
+ (2*x - y) ∂/∂t∧∂/∂x - 2 ∂/∂t∧∂/∂y + (-x - z) ∂/∂t∧∂/∂z + 3 ∂/∂x∧∂/∂y
784
+
785
+ An example of 3-vector field in `\RR^3` with Cartesian coordinates::
786
+
787
+ sage: M = Manifold(3, 'R3', latex_name=r'\RR^3', start_index=1)
788
+ sage: c_cart.<x,y,z> = M.chart()
789
+ sage: a = M.multivector_field(3, name='a')
790
+ sage: a[1,2,3] = x^2+y^2+z^2 # the only independent component
791
+ sage: a[:] # all the components are set from the previous line:
792
+ [[[0, 0, 0], [0, 0, x^2 + y^2 + z^2], [0, -x^2 - y^2 - z^2, 0]],
793
+ [[0, 0, -x^2 - y^2 - z^2], [0, 0, 0], [x^2 + y^2 + z^2, 0, 0]],
794
+ [[0, x^2 + y^2 + z^2, 0], [-x^2 - y^2 - z^2, 0, 0], [0, 0, 0]]]
795
+ sage: a.display()
796
+ a = (x^2 + y^2 + z^2) ∂/∂x∧∂/∂y∧∂/∂z
797
+
798
+ Spherical components from the tensorial change-of-frame formula::
799
+
800
+ sage: c_spher.<r,th,ph> = M.chart(r'r:[0,+oo) th:[0,pi]:\theta ph:[0,2*pi):\phi')
801
+ sage: spher_to_cart = c_spher.transition_map(c_cart,
802
+ ....: [r*sin(th)*cos(ph), r*sin(th)*sin(ph), r*cos(th)])
803
+ sage: cart_to_spher = spher_to_cart.set_inverse(sqrt(x^2+y^2+z^2),
804
+ ....: atan2(sqrt(x^2+y^2),z), atan2(y, x))
805
+ Check of the inverse coordinate transformation:
806
+ r == r *passed*
807
+ th == arctan2(r*sin(th), r*cos(th)) **failed**
808
+ ph == arctan2(r*sin(ph)*sin(th), r*cos(ph)*sin(th)) **failed**
809
+ x == x *passed*
810
+ y == y *passed*
811
+ z == z *passed*
812
+ NB: a failed report can reflect a mere lack of simplification.
813
+ sage: a.comp(c_spher.frame()) # computation of components w.r.t. spherical frame
814
+ Fully antisymmetric 3-indices components w.r.t. Coordinate frame
815
+ (R3, (∂/∂r,∂/∂th,∂/∂ph))
816
+ sage: a.comp(c_spher.frame())[1,2,3, c_spher]
817
+ 1/sin(th)
818
+ sage: a.display(c_spher.frame())
819
+ a = sqrt(x^2 + y^2 + z^2)/sqrt(x^2 + y^2) ∂/∂r∧∂/∂th∧∂/∂ph
820
+ sage: a.display(c_spher.frame(), c_spher)
821
+ a = 1/sin(th) ∂/∂r∧∂/∂th∧∂/∂ph
822
+
823
+ As a shortcut of the above command, on can pass just the chart ``c_spher``
824
+ to ``display``, the vector frame being then assumed to be the coordinate
825
+ frame associated with the chart::
826
+
827
+ sage: a.display(c_spher)
828
+ a = 1/sin(th) ∂/∂r∧∂/∂th∧∂/∂ph
829
+
830
+ The exterior product of two multivector fields is performed via the method
831
+ :meth:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor.wedge`::
832
+
833
+ sage: a = M.vector_field([x*y, -z*x, y], name='A')
834
+ sage: b = M.vector_field([y, z+y, x^2-z^2], name='B')
835
+ sage: ab = a.wedge(b) ; ab
836
+ 2-vector field A∧B on the 3-dimensional differentiable manifold R3
837
+ sage: ab.display()
838
+ A∧B = (x*y^2 + 2*x*y*z) ∂/∂x∧∂/∂y + (x^3*y - x*y*z^2 - y^2) ∂/∂x∧∂/∂z
839
+ + (x*z^3 - y^2 - (x^3 + y)*z) ∂/∂y∧∂/∂z
840
+
841
+ Let us check the formula relating the exterior product to the tensor
842
+ product for vector fields::
843
+
844
+ sage: a.wedge(b) == a*b - b*a
845
+ True
846
+
847
+ The tensor product of a vector field and a 2-vector field is not a 3-vector
848
+ field but a tensor field of type `(3,0)` with less symmetries::
849
+
850
+ sage: c = a*ab ; c
851
+ Tensor field A⊗(A∧B) of type (3,0) on the 3-dimensional differentiable
852
+ manifold R3
853
+ sage: c.symmetries() # the antisymmetry is only w.r.t. the last 2 arguments:
854
+ no symmetry; antisymmetry: (1, 2)
855
+
856
+ The Lie derivative of a 2-vector field is a 2-vector field::
857
+
858
+ sage: ab.lie_der(a)
859
+ 2-vector field on the 3-dimensional differentiable manifold R3
860
+ """
861
+ def __init__(self, vector_field_module, degree, name=None,
862
+ latex_name=None):
863
+ r"""
864
+ Construct a multivector field.
865
+
866
+ TESTS:
867
+
868
+ Construction via ``parent.element_class``, and not via a direct call
869
+ to ``MultivectorFieldParal``, to fit with the category framework::
870
+
871
+ sage: M = Manifold(2, 'M')
872
+ sage: X.<x,y> = M.chart() # makes M parallelizable
873
+ sage: A = M.multivector_module(2)
874
+ sage: XM = M.vector_field_module()
875
+ sage: a = A.element_class(XM, 2, name='a'); a
876
+ 2-vector field a on the 2-dimensional differentiable manifold M
877
+ sage: a[0,1] = x*y
878
+ sage: TestSuite(a).run()
879
+
880
+ Construction via ``DifferentiableManifold.multivector_field``::
881
+
882
+ sage: a1 = M.multivector_field(2, name='a'); a1
883
+ 2-vector field a on the 2-dimensional differentiable manifold M
884
+ sage: type(a1) == type(a)
885
+ True
886
+ sage: a1.parent() is a.parent()
887
+ True
888
+ """
889
+ AlternatingContrTensor.__init__(self, vector_field_module, degree,
890
+ name=name, latex_name=latex_name)
891
+ # TensorFieldParal attributes:
892
+ self._vmodule = vector_field_module
893
+ self._domain = vector_field_module._domain
894
+ self._ambient_domain = vector_field_module._ambient_domain
895
+ # initialization of derived quantities:
896
+ self._init_derived()
897
+
898
+ def _repr_(self):
899
+ r"""
900
+ String representation of ``self``.
901
+
902
+ TESTS::
903
+
904
+ sage: M = Manifold(3, 'M')
905
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
906
+ sage: a = M.multivector_field(2, name='a')
907
+ sage: a._repr_()
908
+ '2-vector field a on the 3-dimensional differentiable manifold M'
909
+ sage: repr(a) # indirect doctest
910
+ '2-vector field a on the 3-dimensional differentiable manifold M'
911
+ sage: a # indirect doctest
912
+ 2-vector field a on the 3-dimensional differentiable manifold M
913
+ sage: b = M.multivector_field(2)
914
+ sage: b._repr_()
915
+ '2-vector field on the 3-dimensional differentiable manifold M'
916
+ """
917
+ description = "{}-vector field ".format(self._tensor_rank)
918
+ if self._name is not None:
919
+ description += self._name + " "
920
+ return self._final_repr(description)
921
+
922
+ def _new_instance(self):
923
+ r"""
924
+ Create an instance of the same class, of the same degree and on the
925
+ same domain.
926
+
927
+ TESTS::
928
+
929
+ sage: M = Manifold(3, 'M')
930
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
931
+ sage: a = M.multivector_field(2, name='a')
932
+ sage: a1 = a._new_instance(); a1
933
+ 2-vector field on the 3-dimensional differentiable manifold M
934
+ sage: type(a1) == type(a)
935
+ True
936
+ sage: a1.parent() is a.parent()
937
+ True
938
+ """
939
+ return type(self)(self._fmodule, self._tensor_rank)
940
+
941
+ # This method is needed to redirect to the correct class (TensorFieldParal)
942
+ def _init_derived(self):
943
+ r"""
944
+ Initialize the derived quantities of ``self``.
945
+
946
+ TESTS::
947
+
948
+ sage: M = Manifold(3, 'M')
949
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
950
+ sage: a = M.multivector_field(2, name='a')
951
+ sage: a._init_derived()
952
+ """
953
+ TensorFieldParal._init_derived(self)
954
+
955
+ def _del_derived(self, del_restrictions=True):
956
+ r"""
957
+ Delete the derived quantities.
958
+
959
+ INPUT:
960
+
961
+ - ``del_restrictions`` -- boolean (default: ``True``); determines whether the
962
+ restrictions of ``self`` to subdomains are deleted
963
+
964
+ TESTS::
965
+
966
+ sage: M = Manifold(3, 'M')
967
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
968
+ sage: a = M.multivector_field(2, name='a')
969
+ sage: a._del_derived()
970
+ """
971
+ TensorFieldParal._del_derived(self, del_restrictions=del_restrictions)
972
+
973
+ def __call__(self, *args):
974
+ r"""
975
+ Redefinition of
976
+ :meth:`~sage.tensor.modules.free_module_tensor.FreeModuleTensor.__call__`
977
+ to allow for domain treatment.
978
+
979
+ TESTS::
980
+
981
+ sage: M = Manifold(2, 'M')
982
+ sage: X.<x,y> = M.chart()
983
+ sage: a = M.multivector_field(2, name='a')
984
+ sage: a[0,1] = x*y
985
+ sage: a.display()
986
+ a = x*y ∂/∂x∧∂/∂y
987
+ sage: b = M.one_form([1+x, 2-y], name='b')
988
+ sage: c = M.one_form([-y, x], name='c')
989
+ sage: s = a.__call__(b,c); s
990
+ Scalar field a(b,c) on the 2-dimensional differentiable manifold M
991
+ sage: s.display()
992
+ a(b,c): M → ℝ
993
+ (x, y) ↦ -x*y^3 + 2*x*y^2 + (x^3 + x^2)*y
994
+ sage: s == a[[0,1]]*(b[[0]]*c[[1]] - b[[1]]*c[[0]])
995
+ True
996
+ sage: s == a(b,c) # indirect doctest
997
+ True
998
+ """
999
+ return TensorFieldParal.__call__(self, *args)
1000
+
1001
+ def wedge(self, other):
1002
+ r"""
1003
+ Exterior product of ``self`` with another multivector field.
1004
+
1005
+ INPUT:
1006
+
1007
+ - ``other`` -- another multivector field
1008
+
1009
+ OUTPUT:
1010
+
1011
+ - instance of :class:`MultivectorFieldParal` representing the
1012
+ exterior product ``self ∧ other``
1013
+
1014
+ EXAMPLES:
1015
+
1016
+ Exterior product of a vector field and a 2-vector field on a
1017
+ 3-dimensional manifold::
1018
+
1019
+ sage: M = Manifold(3, 'M', start_index=1)
1020
+ sage: X.<x,y,z> = M.chart()
1021
+ sage: a = M.vector_field([2, 1+x, y*z], name='a')
1022
+ sage: b = M.multivector_field(2, name='b')
1023
+ sage: b[1,2], b[1,3], b[2,3] = y^2, z+x, z^2
1024
+ sage: a.display()
1025
+ a = 2 ∂/∂x + (x + 1) ∂/∂y + y*z ∂/∂z
1026
+ sage: b.display()
1027
+ b = y^2 ∂/∂x∧∂/∂y + (x + z) ∂/∂x∧∂/∂z + z^2 ∂/∂y∧∂/∂z
1028
+ sage: s = a.wedge(b); s
1029
+ 3-vector field a∧b on the 3-dimensional differentiable manifold M
1030
+ sage: s.display()
1031
+ a∧b = (-x^2 + (y^3 - x - 1)*z + 2*z^2 - x) ∂/∂x∧∂/∂y∧∂/∂z
1032
+
1033
+ Check::
1034
+
1035
+ sage: s[1,2,3] == a[1]*b[2,3] + a[2]*b[3,1] + a[3]*b[1,2]
1036
+ True
1037
+
1038
+ Exterior product with a scalar field::
1039
+
1040
+ sage: f = M.scalar_field(x, name='f')
1041
+ sage: s = b.wedge(f); s
1042
+ 2-vector field f*b on the 3-dimensional differentiable manifold M
1043
+ sage: s.display()
1044
+ f*b = x*y^2 ∂/∂x∧∂/∂y + (x^2 + x*z) ∂/∂x∧∂/∂z + x*z^2 ∂/∂y∧∂/∂z
1045
+ sage: s == f*b
1046
+ True
1047
+ sage: s == f.wedge(b)
1048
+ True
1049
+ """
1050
+ if other._tensor_rank == 0: # wedge product with a scalar field
1051
+ return self * other
1052
+ if self._domain.is_subset(other._domain):
1053
+ if not self._ambient_domain.is_subset(other._ambient_domain):
1054
+ raise ValueError("incompatible ambient domains for exterior " +
1055
+ "product")
1056
+ elif other._domain.is_subset(self._domain):
1057
+ if not other._ambient_domain.is_subset(self._ambient_domain):
1058
+ raise ValueError("incompatible ambient domains for exterior " +
1059
+ "product")
1060
+ dom_resu = self._domain.intersection(other._domain)
1061
+ self_r = self.restrict(dom_resu)
1062
+ other_r = other.restrict(dom_resu)
1063
+ return AlternatingContrTensor.wedge(self_r, other_r)
1064
+
1065
+ def interior_product(self, form):
1066
+ r"""
1067
+ Interior product with a differential form.
1068
+
1069
+ If ``self`` is a multivector field `A` of degree `p` and `B` is a
1070
+ differential form of degree `q\geq p` on the same manifold as `A`, the
1071
+ interior product of `A` by `B` is the differential form `\iota_A B` of
1072
+ degree `q-p` defined by
1073
+
1074
+ .. MATH::
1075
+
1076
+ (\iota_A B)_{i_1\ldots i_{q-p}} = A^{k_1\ldots k_p}
1077
+ B_{k_1\ldots k_p i_1\ldots i_{q-p}}
1078
+
1079
+ .. NOTE::
1080
+
1081
+ ``A.interior_product(B)`` yields the same result as
1082
+ ``A.contract(0,..., p-1, B, 0,..., p-1)`` (cf.
1083
+ :meth:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal.contract`),
1084
+ but ``interior_product`` is more efficient, the alternating
1085
+ character of `A` being not used to reduce the computation in
1086
+ :meth:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal.contract`
1087
+
1088
+ INPUT:
1089
+
1090
+ - ``form`` -- differential form `B` (instance of
1091
+ :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal`);
1092
+ the degree of `B` must be at least equal to the degree of ``self``
1093
+
1094
+ OUTPUT:
1095
+
1096
+ - scalar field (case `p=q`) or
1097
+ :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal`
1098
+ (case `p<q`) representing the interior product `\iota_A B`, where `A`
1099
+ is ``self``
1100
+
1101
+ .. SEEALSO::
1102
+
1103
+ :meth:`~sage.manifolds.differentiable.diff_form.DiffFormParal.interior_product`
1104
+ for the interior product of a differential form with a
1105
+ multivector field
1106
+
1107
+ EXAMPLES:
1108
+
1109
+ Interior product with `p=1` and `q=1` on 4-dimensional manifold::
1110
+
1111
+ sage: M = Manifold(4, 'M')
1112
+ sage: X.<t,x,y,z> = M.chart()
1113
+ sage: a = M.vector_field([x, 1+t^2, x*z, y-3], name='a')
1114
+ sage: b = M.one_form([-z^2, 2, x, x-y], name='b')
1115
+ sage: s = a.interior_product(b); s
1116
+ Scalar field i_a b on the 4-dimensional differentiable manifold M
1117
+ sage: s.display()
1118
+ i_a b: M → ℝ
1119
+ (t, x, y, z) ↦ x^2*z - x*z^2 + 2*t^2 + (x + 3)*y - y^2
1120
+ - 3*x + 2
1121
+
1122
+ In this case, we have `\iota_a b = a^i b_i = a(b) = b(a)`::
1123
+
1124
+ sage: all([s == a.contract(b), s == a(b), s == b(a)])
1125
+ True
1126
+
1127
+ Case `p=1` and `q=3`::
1128
+
1129
+ sage: c = M.diff_form(3, name='c')
1130
+ sage: c[0,1,2], c[0,1,3] = x*y - z, -3*t
1131
+ sage: c[0,2,3], c[1,2,3] = t+x, y
1132
+ sage: s = a.interior_product(c); s
1133
+ 2-form i_a c on the 4-dimensional differentiable manifold M
1134
+ sage: s.display()
1135
+ i_a c = (x^2*y*z - x*z^2 - 3*t*y + 9*t) dt∧dx
1136
+ + (-(t^2*x - t)*y + (t^2 + 1)*z - 3*t - 3*x) dt∧dy
1137
+ + (3*t^3 - (t*x + x^2)*z + 3*t) dt∧dz
1138
+ + ((x^2 - 3)*y + y^2 - x*z) dx∧dy
1139
+ + (-x*y*z - 3*t*x) dx∧dz + (t*x + x^2 + (t^2 + 1)*y) dy∧dz
1140
+ sage: s == a.contract(c)
1141
+ True
1142
+
1143
+ Case `p=2` and `q=3`::
1144
+
1145
+ sage: d = M.multivector_field(2, name='d')
1146
+ sage: d[0,1], d[0,2], d[0,3] = t-x, 2*z, y-1
1147
+ sage: d[1,2], d[1,3], d[2,3] = z, y+t, 4
1148
+ sage: s = d.interior_product(c); s
1149
+ 1-form i_d c on the 4-dimensional differentiable manifold M
1150
+ sage: s.display()
1151
+ i_d c = (2*x*y*z - 6*t^2 - 6*t*y - 2*z^2 + 8*t + 8*x) dt
1152
+ + (-4*x*y*z + 2*(3*t + 4)*y + 4*z^2 - 6*t) dx
1153
+ + (2*((t - 1)*x - x^2 - 2*t)*y - 2*y^2 - 2*(t - x)*z + 2*t
1154
+ + 2*x) dy + (-6*t^2 + 6*t*x + 2*(2*t + 2*x + y)*z) dz
1155
+ sage: s == d.contract(0, 1, c, 0, 1)
1156
+ True
1157
+
1158
+ TESTS:
1159
+
1160
+ Check that :issue:`33780` is fixed::
1161
+
1162
+ sage: v = X.frame()[0] # vector field d/dt
1163
+ sage: f = X.coframe()[1] # 1-form dx
1164
+ sage: v.interior_product(f)
1165
+ Scalar field zero on the 4-dimensional differentiable manifold M
1166
+ """
1167
+ if self._domain.is_subset(form._domain):
1168
+ if not self._ambient_domain.is_subset(form._ambient_domain):
1169
+ raise ValueError("incompatible ambient domains for interior " +
1170
+ "product")
1171
+ elif form._domain.is_subset(self._domain):
1172
+ if not form._ambient_domain.is_subset(self._ambient_domain):
1173
+ raise ValueError("incompatible ambient domains for interior " +
1174
+ "product")
1175
+ dom_resu = self._domain.intersection(form._domain)
1176
+ self_r = self.restrict(dom_resu)
1177
+ form_r = form.restrict(dom_resu)
1178
+ return AlternatingContrTensor.interior_product(self_r, form_r)
1179
+
1180
+ def bracket(self, other):
1181
+ r"""
1182
+ Return the Schouten-Nijenhuis bracket of ``self`` with another
1183
+ multivector field.
1184
+
1185
+ The Schouten-Nijenhuis bracket extends the Lie bracket of
1186
+ vector fields (cf.
1187
+ :meth:`~sage.manifolds.differentiable.vectorfield.VectorField.bracket`)
1188
+ to multivector fields.
1189
+
1190
+ Denoting by `A^p(M)` the `C^k(M)`-module of `p`-vector fields on the
1191
+ `C^k`-differentiable manifold `M` over the field `K` (cf.
1192
+ :class:`~sage.manifolds.differentiable.multivector_module.MultivectorModule`),
1193
+ the *Schouten-Nijenhuis bracket* is a `K`-bilinear map
1194
+
1195
+ .. MATH::
1196
+
1197
+ \begin{array}{ccc}
1198
+ A^p(M)\times A^q(M) & \longrightarrow & A^{p+q-1}(M) \\
1199
+ (a,b) & \longmapsto & [a,b]
1200
+ \end{array}
1201
+
1202
+ which obeys the following properties:
1203
+
1204
+ - if `p=0` and `q=0`, (i.e. `a` and `b` are two scalar fields), `[a,b]=0`
1205
+ - if `p=0` (i.e. `a` is a scalar field) and `q\geq 1`,
1206
+ `[a,b] = - \iota_{\mathrm{d}a} b` (minus the interior product of
1207
+ the differential of `a` by `b`)
1208
+ - if `p=1` (i.e. `a` is a vector field), `[a,b] = \mathcal{L}_a b`
1209
+ (the Lie derivative of `b` along `a`)
1210
+ - `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]`
1211
+ - for any multivector field `c` and `(a,b) \in A^p(M)\times A^q(M)`,
1212
+ `[a,.]` obeys the *graded Leibniz rule*
1213
+
1214
+ .. MATH::
1215
+
1216
+ [a,b\wedge c] = [a,b]\wedge c + (-1)^{(p-1)q} b\wedge [a,c]
1217
+
1218
+ - for `(a,b,c) \in A^p(M)\times A^q(M)\times A^r(M)`, the *graded
1219
+ Jacobi identity* holds:
1220
+
1221
+ .. MATH::
1222
+
1223
+ (-1)^{(p-1)(r-1)}[a,[b,c]] + (-1)^{(q-1)(p-1)}[b,[c,a]] +
1224
+ (-1)^{(r-1)(q-1)}[c,[a,b]] = 0
1225
+
1226
+ .. NOTE::
1227
+
1228
+ There are two definitions of the Schouten-Nijenhuis bracket in
1229
+ the literature, which differ from each other when `p` is even
1230
+ by an overall sign. The definition adopted here is that of
1231
+ [Mar1997]_, [Kos1985]_ and :wikipedia:`Schouten-Nijenhuis_bracket`.
1232
+ The other definition, adopted e.g. by [Nij1955]_, [Lic1977]_
1233
+ and [Vai1994]_, is `[a,b]' = (-1)^{p+1} [a,b]`.
1234
+
1235
+ INPUT:
1236
+
1237
+ - ``other`` -- a multivector field
1238
+
1239
+ OUTPUT:
1240
+
1241
+ - instance of :class:`MultivectorFieldParal` (or of
1242
+ :class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
1243
+ if `p=1` and `q=0`) representing the
1244
+ Schouten-Nijenhuis bracket `[a,b]`, where `a` is ``self`` and `b` is
1245
+ ``other``
1246
+
1247
+ EXAMPLES:
1248
+
1249
+ Let us consider two vector fields on a 3-dimensional manifold::
1250
+
1251
+ sage: M = Manifold(3, 'M')
1252
+ sage: X.<x,y,z> = M.chart()
1253
+ sage: a = M.vector_field([x*y+z, x+y-z, z-2*x+y], name='a')
1254
+ sage: b = M.vector_field([y+2*z-x, x^2-y+z, z-x], name='b')
1255
+
1256
+ and form their Schouten-Nijenhuis bracket::
1257
+
1258
+ sage: s = a.bracket(b); s
1259
+ Vector field [a,b] on the 3-dimensional differentiable manifold M
1260
+ sage: s.display()
1261
+ [a,b] = (-x^3 + (x + 3)*y - y^2 - (x + 2*y + 1)*z - 2*x) ∂/∂x
1262
+ + (2*x^2*y - x^2 + 2*x*z - 3*x) ∂/∂y
1263
+ + (-x^2 - (x - 4)*y - 3*x + 2*z) ∂/∂z
1264
+
1265
+ Check that `[a,b]` is actually the Lie bracket::
1266
+
1267
+ sage: f = M.scalar_field({X: x+y*z}, name='f')
1268
+ sage: s(f) == a(b(f)) - b(a(f))
1269
+ True
1270
+
1271
+ Check that `[a,b]` coincides with the Lie derivative of `b` along `a`::
1272
+
1273
+ sage: s == b.lie_derivative(a)
1274
+ True
1275
+
1276
+ Schouten-Nijenhuis bracket for `p=0` and `q=1`::
1277
+
1278
+ sage: s = f.bracket(a); s
1279
+ Scalar field -i_df a on the 3-dimensional differentiable manifold M
1280
+ sage: s.display()
1281
+ -i_df a: M → ℝ
1282
+ (x, y, z) ↦ x*y - y^2 - (x + 2*y + 1)*z + z^2
1283
+
1284
+ Check that `[f,a] = - \iota_{\mathrm{d}f} a = - \mathrm{d}f(a)`::
1285
+
1286
+ sage: s == - f.differential()(a)
1287
+ True
1288
+
1289
+ Schouten-Nijenhuis bracket for `p=0` and `q=2`::
1290
+
1291
+ sage: c = M.multivector_field(2, name='c')
1292
+ sage: c[0,1], c[0,2], c[1,2] = x+z+1, x*y+z, x-y
1293
+ sage: s = f.bracket(c); s
1294
+ Vector field -i_df c on the 3-dimensional differentiable manifold M
1295
+ sage: s.display()
1296
+ -i_df c = (x*y^2 + (x + y + 1)*z + z^2) ∂/∂x
1297
+ + (x*y - y^2 - x - z - 1) ∂/∂y + (-x*y - (x - y + 1)*z) ∂/∂z
1298
+
1299
+ Check that `[f,c] = - \iota_{\mathrm{d}f} c`::
1300
+
1301
+ sage: s == - f.differential().interior_product(c)
1302
+ True
1303
+
1304
+ Schouten-Nijenhuis bracket for `p=1` and `q=2`::
1305
+
1306
+ sage: s = a.bracket(c); s
1307
+ 2-vector field [a,c] on the 3-dimensional differentiable manifold M
1308
+ sage: s.display()
1309
+ [a,c] = ((x - 1)*y - (y - 2)*z - 2*x - 1) ∂/∂x∧∂/∂y
1310
+ + ((x + 1)*y - (x + 1)*z - 3*x - 1) ∂/∂x∧∂/∂z
1311
+ + (-5*x + y - z - 2) ∂/∂y∧∂/∂z
1312
+
1313
+ Again, since `a` is a vector field, the Schouten-Nijenhuis bracket
1314
+ coincides with the Lie derivative::
1315
+
1316
+ sage: s == c.lie_derivative(a)
1317
+ True
1318
+
1319
+ Schouten-Nijenhuis bracket for `p=2` and `q=2`::
1320
+
1321
+ sage: d = M.multivector_field(2, name='d')
1322
+ sage: d[0,1], d[0,2], d[1,2] = x-y^2, x+z, z-x-1
1323
+ sage: s = c.bracket(d); s
1324
+ 3-vector field [c,d] on the 3-dimensional differentiable manifold M
1325
+ sage: s.display()
1326
+ [c,d] = (-y^3 + (3*x + 1)*y - y^2 - x - z + 2) ∂/∂x∧∂/∂y∧∂/∂z
1327
+
1328
+ Let us check the component formula (with respect to the manifold's
1329
+ default coordinate chart, i.e. ``X``) for `p=q=2`, taking into
1330
+ account the tensor antisymmetries::
1331
+
1332
+ sage: s[0,1,2] == - sum(c[i,0]*d[1,2].diff(i)
1333
+ ....: + c[i,1]*d[2,0].diff(i) + c[i,2]*d[0,1].diff(i)
1334
+ ....: + d[i,0]*c[1,2].diff(i) + d[i,1]*c[2,0].diff(i)
1335
+ ....: + d[i,2]*c[0,1].diff(i) for i in M.irange())
1336
+ True
1337
+
1338
+ Schouten-Nijenhuis bracket for `p=1` and `q=3`::
1339
+
1340
+ sage: e = M.multivector_field(3, name='e')
1341
+ sage: e[0,1,2] = x+y*z+1
1342
+ sage: s = a.bracket(e); s
1343
+ 3-vector field [a,e] on the 3-dimensional differentiable manifold M
1344
+ sage: s.display()
1345
+ [a,e] = (-(2*x + 1)*y + y^2 - (y^2 - x - 1)*z - z^2
1346
+ - 2*x - 2) ∂/∂x∧∂/∂y∧∂/∂z
1347
+
1348
+ Again, since `p=1`, the bracket coincides with the Lie derivative::
1349
+
1350
+ sage: s == e.lie_derivative(a)
1351
+ True
1352
+
1353
+ Schouten-Nijenhuis bracket for `p=2` and `q=3`::
1354
+
1355
+ sage: s = c.bracket(e); s
1356
+ 4-vector field [c,e] on the 3-dimensional differentiable manifold M
1357
+
1358
+ Since on a 3-dimensional manifold, any 4-vector field is zero, we have::
1359
+
1360
+ sage: s.display()
1361
+ [c,e] = 0
1362
+
1363
+ Let us check the graded commutation law
1364
+ `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]` for various values of `p` and `q`::
1365
+
1366
+ sage: f.bracket(a) == - a.bracket(f) # p=0 and q=1
1367
+ True
1368
+ sage: f.bracket(c) == c.bracket(f) # p=0 and q=2
1369
+ True
1370
+ sage: a.bracket(b) == - b.bracket(a) # p=1 and q=1
1371
+ True
1372
+ sage: a.bracket(c) == - c.bracket(a) # p=1 and q=2
1373
+ True
1374
+ sage: c.bracket(d) == d.bracket(c) # p=2 and q=2
1375
+ True
1376
+
1377
+ Let us check the graded Leibniz rule for `p=1` and `q=1`::
1378
+
1379
+ sage: a.bracket(b.wedge(c)) == a.bracket(b).wedge(c) + b.wedge(a.bracket(c)) # long time
1380
+ True
1381
+
1382
+ as well as for `p=2` and `q=1`::
1383
+
1384
+ sage: c.bracket(a.wedge(b)) == c.bracket(a).wedge(b) - a.wedge(c.bracket(b)) # long time
1385
+ True
1386
+
1387
+ Finally let us check the graded Jacobi identity for `p=1`, `q=1` and
1388
+ `r=2`::
1389
+
1390
+ sage: # long time
1391
+ sage: a_bc = a.bracket(b.bracket(c))
1392
+ sage: b_ca = b.bracket(c.bracket(a))
1393
+ sage: c_ab = c.bracket(a.bracket(b))
1394
+ sage: a_bc + b_ca + c_ab == 0
1395
+ True
1396
+
1397
+ as well as for `p=1`, `q=2` and `r=2`::
1398
+
1399
+ sage: # long time
1400
+ sage: a_cd = a.bracket(c.bracket(d))
1401
+ sage: c_da = c.bracket(d.bracket(a))
1402
+ sage: d_ac = d.bracket(a.bracket(c))
1403
+ sage: a_cd + c_da - d_ac == 0
1404
+ True
1405
+ """
1406
+ from itertools import combinations
1407
+
1408
+ from sage.combinat.permutation import Permutation
1409
+ from sage.manifolds.differentiable.scalarfield import DiffScalarField
1410
+ from sage.tensor.modules.comp import CompFullyAntiSym, Components, CompWithSym
1411
+ pp = self._tensor_rank
1412
+ mp1 = (-1)**(pp+1)
1413
+ if isinstance(other, DiffScalarField):
1414
+ resu = other.differential().interior_product(self)
1415
+ if mp1 == 1:
1416
+ return resu
1417
+ return - resu
1418
+ # Some checks:
1419
+ if not isinstance(other, (MultivectorField, MultivectorFieldParal)):
1420
+ raise TypeError("{} is not a multivector field".format(other))
1421
+ if (self._vmodule.destination_map() is not self._domain.identity_map()
1422
+ or other._vmodule.destination_map() is not
1423
+ other._domain.identity_map()):
1424
+ raise ValueError("the Schouten-Nijenhuis bracket is defined " +
1425
+ "only for fields with a trivial destination map")
1426
+ # Search for a common domain
1427
+ dom_resu = self._domain.intersection(other._domain)
1428
+ self_r = self.restrict(dom_resu)
1429
+ other_r = other.restrict(dom_resu)
1430
+ # Search for a common coordinate frame:
1431
+ coord_frame = self_r._common_coord_frame(other_r)
1432
+ if coord_frame is None:
1433
+ raise ValueError("no common coordinate frame found")
1434
+ chart = coord_frame.chart()
1435
+ dom_resu = chart.domain()
1436
+ fmodule = dom_resu.vector_field_module()
1437
+ ring = fmodule.base_ring() # same as dom_resu.scalar_field_algebra()
1438
+ aa = self_r.comp(coord_frame) # components A^{i_1...i_p}
1439
+ bb = other_r.comp(coord_frame) # components B^{j_1...j_q}
1440
+ qq = other._tensor_rank
1441
+ deg_resu = pp + qq - 1 # degree of the result
1442
+ if deg_resu == 1:
1443
+ resuc = Components(ring, coord_frame, 1,
1444
+ start_index=fmodule._sindex,
1445
+ output_formatter=fmodule._output_formatter)
1446
+ else:
1447
+ resuc = CompFullyAntiSym(ring, coord_frame, deg_resu,
1448
+ start_index=fmodule._sindex,
1449
+ output_formatter=fmodule._output_formatter)
1450
+ # Partial derivatives of the components of self:
1451
+ if pp == 1:
1452
+ daa = Components(ring, coord_frame, 2,
1453
+ start_index=fmodule._sindex,
1454
+ output_formatter=fmodule._output_formatter)
1455
+ else:
1456
+ daa = CompWithSym(ring, coord_frame, pp+1,
1457
+ start_index=fmodule._sindex,
1458
+ output_formatter=fmodule._output_formatter,
1459
+ antisym=range(pp))
1460
+ for ind, val in aa._comp.items():
1461
+ for k in fmodule.irange():
1462
+ daa[[ind+(k,)]] = val.coord_function(chart).diff(k)
1463
+ # Partial derivatives of the components of other:
1464
+ if qq == 1:
1465
+ dbb = Components(ring, coord_frame, 2,
1466
+ start_index=fmodule._sindex,
1467
+ output_formatter=fmodule._output_formatter)
1468
+ else:
1469
+ dbb = CompWithSym(ring, coord_frame, qq+1,
1470
+ start_index=fmodule._sindex,
1471
+ output_formatter=fmodule._output_formatter,
1472
+ antisym=range(qq))
1473
+ for ind, val in bb._comp.items():
1474
+ for k in fmodule.irange():
1475
+ dbb[[ind+(k,)]] = val.coord_function(chart).diff(k)
1476
+ # Computation
1477
+ for ind in resuc.non_redundant_index_generator():
1478
+ sind = set(ind) # {i_1, i_2, ..., i_{p+q-1}}
1479
+ # Term a^{l j_2 ... j_p} \partial_l b^{k_1 ... k_q}
1480
+ # with (j_2,...,j_p,k_1,...,k_q) spanning all permutations of
1481
+ # (i_1, i_2, ..., i_{p+q-1})
1482
+ for sind_a in combinations(sind, pp-1):
1483
+ sind_b = sind.difference(sind_a)
1484
+ ind_a = tuple(sorted(sind_a))
1485
+ ind_b = tuple(sorted(sind_b))
1486
+ sum = 0
1487
+ for l in fmodule.irange():
1488
+ sum += aa[[(l,) + ind_a]] * dbb[[ind_b + (l,)]]
1489
+ ind_ab = ind_a + ind_b
1490
+ sign = Permutation([ind_ab.index(i) + 1 for i in ind]).signature()
1491
+ if mp1*sign == 1:
1492
+ resuc[[ind]] += sum
1493
+ else:
1494
+ resuc[[ind]] -= sum
1495
+ # Term b^{l k_2 ... k_q} \partial_l a^{j_1 ... j_p}
1496
+ # with (j_1,...,j_p,k_2,...,k_q) spanning all permutations of
1497
+ # (i_1, i_2, ..., i_{p+q-1})
1498
+ for sind_b in combinations(sind, qq-1):
1499
+ sind_a = sind.difference(sind_b)
1500
+ ind_a = tuple(sorted(sind_a))
1501
+ ind_b = tuple(sorted(sind_b))
1502
+ sum = 0
1503
+ for l in fmodule.irange():
1504
+ sum += bb[[(l,) + ind_b]] * daa[[ind_a + (l,)]]
1505
+ ind_ab = ind_a + ind_b
1506
+ sign = Permutation([ind_ab.index(i) + 1 for i in ind]).signature()
1507
+ if sign == 1:
1508
+ resuc[[ind]] -= sum
1509
+ else:
1510
+ resuc[[ind]] += sum
1511
+ # Name of the result:
1512
+ resu_name = None
1513
+ resu_latex_name = None
1514
+ if self._name is not None and other._name is not None:
1515
+ resu_name = '[' + self._name + ',' + other._name + ']'
1516
+ if self._latex_name is not None and other._latex_name is not None:
1517
+ resu_latex_name = r'\left[' + self._latex_name + ',' + \
1518
+ other._latex_name + r'\right]'
1519
+ # Creation of the multivector with the components obtained above:
1520
+ resu = fmodule.tensor_from_comp((deg_resu, 0), resuc, name=resu_name,
1521
+ latex_name=resu_latex_name)
1522
+ return resu