passagemath-symbolics 10.6.40__cp314-cp314t-macosx_13_0_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.

Files changed (172) hide show
  1. passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_symbolics/__init__.py +3 -0
  3. passagemath_symbolics-10.6.40.dist-info/METADATA +187 -0
  4. passagemath_symbolics-10.6.40.dist-info/RECORD +172 -0
  5. passagemath_symbolics-10.6.40.dist-info/WHEEL +6 -0
  6. passagemath_symbolics-10.6.40.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 +2826 -0
  10. sage/calculus/desolvers.py +1866 -0
  11. sage/calculus/predefined.py +51 -0
  12. sage/calculus/tests.py +225 -0
  13. sage/calculus/var.cpython-314t-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-314t-darwin.so +0 -0
  19. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -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 +743 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -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 +3017 -0
  45. sage/interfaces/magma_free.py +92 -0
  46. sage/interfaces/maple.py +1397 -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 +555 -0
  55. sage/manifolds/catalog.py +437 -0
  56. sage/manifolds/chart.py +4019 -0
  57. sage/manifolds/chart_func.py +3419 -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 +1671 -0
  71. sage/manifolds/differentiable/diff_form.py +1658 -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 +1520 -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 +910 -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 +1728 -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 +2764 -0
  119. sage/manifolds/subsets/all.py +1 -0
  120. sage/manifolds/subsets/closure.py +131 -0
  121. sage/manifolds/subsets/pullback.py +885 -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 +1342 -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-314t-darwin.so +0 -0
  130. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  131. sage/matrix/matrix_symbolic_dense.pyx +1022 -0
  132. sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
  133. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  134. sage/matrix/matrix_symbolic_sparse.pyx +1029 -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 +4153 -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 +5237 -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 +985 -0
  151. sage/symbolic/benchmark.py +93 -0
  152. sage/symbolic/callable.py +459 -0
  153. sage/symbolic/complexity_measures.py +35 -0
  154. sage/symbolic/constants.py +1287 -0
  155. sage/symbolic/expression_conversion_algebraic.py +310 -0
  156. sage/symbolic/expression_conversion_sympy.py +317 -0
  157. sage/symbolic/expression_conversions.py +1713 -0
  158. sage/symbolic/function_factory.py +355 -0
  159. sage/symbolic/integration/all.py +1 -0
  160. sage/symbolic/integration/external.py +270 -0
  161. sage/symbolic/integration/integral.py +1115 -0
  162. sage/symbolic/maxima_wrapper.py +162 -0
  163. sage/symbolic/operators.py +267 -0
  164. sage/symbolic/random_tests.py +462 -0
  165. sage/symbolic/relation.py +1907 -0
  166. sage/symbolic/ring.cpython-314t-darwin.so +0 -0
  167. sage/symbolic/ring.pxd +5 -0
  168. sage/symbolic/ring.pyx +1396 -0
  169. sage/symbolic/subring.py +1025 -0
  170. sage/symbolic/symengine.py +19 -0
  171. sage/symbolic/tests.py +40 -0
  172. sage/symbolic/units.py +1470 -0
@@ -0,0 +1,1520 @@
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, latex_name=resu_latex_name)
498
+ for dom in self_r._restrictions:
499
+ if dom in form_r._restrictions:
500
+ resu._restrictions[dom] = \
501
+ self_r._restrictions[dom].interior_product(
502
+ form_r._restrictions[dom])
503
+ if resu_degree == 0:
504
+ if not resu._express: # only the restrictions to subdomains have
505
+ # been initialized
506
+ for chart in dom_resu.top_charts():
507
+ resu._express[chart] = \
508
+ resu.restrict(chart.domain()).coord_function(chart)
509
+ return resu
510
+
511
+ def bracket(self, other):
512
+ r"""
513
+ Return the Schouten-Nijenhuis bracket of ``self`` with another
514
+ multivector field.
515
+
516
+ The Schouten-Nijenhuis bracket extends the Lie bracket of
517
+ vector fields (cf.
518
+ :meth:`~sage.manifolds.differentiable.vectorfield.VectorField.bracket`)
519
+ to multivector fields.
520
+
521
+ Denoting by `A^p(M)` the `C^k(M)`-module of `p`-vector fields on the
522
+ `C^k`-differentiable manifold `M` over the field `K` (cf.
523
+ :class:`~sage.manifolds.differentiable.multivector_module.MultivectorModule`),
524
+ the *Schouten-Nijenhuis bracket* is a `K`-bilinear map
525
+
526
+ .. MATH::
527
+
528
+ \begin{array}{ccc}
529
+ A^p(M)\times A^q(M) & \longrightarrow & A^{p+q-1}(M) \\
530
+ (a,b) & \longmapsto & [a,b]
531
+ \end{array}
532
+
533
+ which obeys the following properties:
534
+
535
+ - if `p=0` and `q=0`, (i.e. `a` and `b` are two scalar fields), `[a,b]=0`
536
+ - if `p=0` (i.e. `a` is a scalar field) and `q\geq 1`,
537
+ `[a,b] = - \iota_{\mathrm{d}a} b` (minus the interior product of
538
+ the differential of `a` by `b`)
539
+ - if `p=1` (i.e. `a` is a vector field), `[a,b] = \mathcal{L}_a b`
540
+ (the Lie derivative of `b` along `a`)
541
+ - `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]`
542
+ - for any multivector field `c` and `(a,b) \in A^p(M)\times A^q(M)`,
543
+ `[a,.]` obeys the *graded Leibniz rule*
544
+
545
+ .. MATH::
546
+
547
+ [a,b\wedge c] = [a,b]\wedge c + (-1)^{(p-1)q} b\wedge [a,c]
548
+
549
+ - for `(a,b,c) \in A^p(M)\times A^q(M)\times A^r(M)`, the *graded
550
+ Jacobi identity* holds:
551
+
552
+ .. MATH::
553
+
554
+ (-1)^{(p-1)(r-1)}[a,[b,c]] + (-1)^{(q-1)(p-1)}[b,[c,a]] +
555
+ (-1)^{(r-1)(q-1)}[c,[a,b]] = 0
556
+
557
+ .. NOTE::
558
+
559
+ There are two definitions of the Schouten-Nijenhuis bracket in
560
+ the literature, which differ from each other when `p` is even
561
+ by an overall sign. The definition adopted here is that of
562
+ [Mar1997]_, [Kos1985]_ and :wikipedia:`Schouten-Nijenhuis_bracket`.
563
+ The other definition, adopted e.g. by [Nij1955]_, [Lic1977]_
564
+ and [Vai1994]_, is `[a,b]' = (-1)^{p+1} [a,b]`.
565
+
566
+ INPUT:
567
+
568
+ - ``other`` -- a multivector field
569
+
570
+ OUTPUT:
571
+
572
+ - instance of :class:`MultivectorField` (or of
573
+ :class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
574
+ if `p=1` and `q=0`) representing the
575
+ Schouten-Nijenhuis bracket `[a,b]`, where `a` is ``self`` and `b` is
576
+ ``other``
577
+
578
+ EXAMPLES:
579
+
580
+ Bracket of two vector fields on the 2-sphere::
581
+
582
+ sage: M = Manifold(2, 'S^2', start_index=1) # the sphere S^2
583
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
584
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
585
+ sage: c_xy.<x,y> = U.chart() # stereographic coord. North
586
+ sage: c_uv.<u,v> = V.chart() # stereographic coord. South
587
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
588
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
589
+ ....: restrictions2= u^2+v^2!=0)
590
+ sage: uv_to_xy = xy_to_uv.inverse()
591
+ sage: W = U.intersection(V) # The complement of the two poles
592
+ sage: e_xy = c_xy.frame() ; e_uv = c_uv.frame()
593
+ sage: a = M.vector_field({e_xy: [y, x]}, name='a')
594
+ sage: a.add_comp_by_continuation(e_uv, W, c_uv)
595
+ sage: b = M.vector_field({e_xy: [x*y, x-y]}, name='b')
596
+ sage: b.add_comp_by_continuation(e_uv, W, c_uv)
597
+ sage: s = a.bracket(b); s
598
+ Vector field [a,b] on the 2-dimensional differentiable manifold S^2
599
+ sage: s.display(e_xy)
600
+ [a,b] = (x^2 + y^2 - x + y) ∂/∂x + (-(x - 1)*y - x) ∂/∂y
601
+
602
+ For two vector fields, the bracket coincides with the Lie derivative::
603
+
604
+ sage: s == b.lie_derivative(a)
605
+ True
606
+
607
+ Schouten-Nijenhuis bracket of a 2-vector field and a 1-vector field::
608
+
609
+ sage: c = a.wedge(b); c
610
+ 2-vector field a∧b on the 2-dimensional differentiable
611
+ manifold S^2
612
+ sage: s = c.bracket(a); s
613
+ 2-vector field [a∧b,a] on the 2-dimensional differentiable
614
+ manifold S^2
615
+ sage: s.display(e_xy)
616
+ [a∧b,a] = (x^3 + (2*x - 1)*y^2 - x^2 + 2*x*y) ∂/∂x∧∂/∂y
617
+
618
+ Since `a` is a vector field, we have in this case::
619
+
620
+ sage: s == - c.lie_derivative(a)
621
+ True
622
+
623
+ .. SEEALSO::
624
+
625
+ :meth:`MultivectorFieldParal.bracket` for more examples and check
626
+ of standards identities involving the Schouten-Nijenhuis bracket
627
+ """
628
+ from sage.manifolds.differentiable.scalarfield import DiffScalarField
629
+ pp = self._tensor_rank
630
+ mp1 = (-1)**(pp+1)
631
+ if isinstance(other, DiffScalarField):
632
+ resu = other.differential().interior_product(self)
633
+ if mp1 == 1:
634
+ return resu
635
+ return - resu
636
+ # Some checks:
637
+ if not isinstance(other, (MultivectorField, MultivectorFieldParal)):
638
+ raise TypeError("{} is not a multivector field".format(other))
639
+ if (self._vmodule.destination_map() is not self._domain.identity_map()
640
+ or other._vmodule.destination_map() is not
641
+ other._domain.identity_map()):
642
+ raise ValueError("the Schouten-Nijenhuis bracket is defined " +
643
+ "only for fields with a trivial destination map")
644
+ # Search for a common domain
645
+ dom_resu = self._domain.intersection(other._domain)
646
+ self_r = self.restrict(dom_resu)
647
+ other_r = other.restrict(dom_resu)
648
+ if dom_resu.is_manifestly_parallelizable():
649
+ # call of the MultivectorFieldParal version:
650
+ return MultivectorFieldParal.bracket(self_r, other_r)
651
+ # otherwise, the result is created here:
652
+ # Name of the result:
653
+ resu_name = None
654
+ resu_latex_name = None
655
+ if self._name is not None and other._name is not None:
656
+ resu_name = '[' + self._name + ',' + other._name + ']'
657
+ if self._latex_name is not None and other._latex_name is not None:
658
+ resu_latex_name = r'\left[' + self._latex_name + ',' + \
659
+ other._latex_name + r'\right]'
660
+ vmodule = dom_resu.vector_field_module()
661
+ deg_resu = pp + other._tensor_rank - 1 # degree of the result
662
+ resu = vmodule.alternating_contravariant_tensor(deg_resu,
663
+ name=resu_name, latex_name=resu_latex_name)
664
+ for dom in self_r._restrictions:
665
+ if dom in other_r._restrictions:
666
+ resu._restrictions[dom] = self_r._restrictions[dom].bracket(
667
+ other_r._restrictions[dom])
668
+ return resu
669
+
670
+
671
+ #******************************************************************************
672
+
673
+ class MultivectorFieldParal(AlternatingContrTensor, TensorFieldParal):
674
+ r"""
675
+ Multivector field with values on a parallelizable manifold.
676
+
677
+ Given a differentiable manifold `U`, a differentiable map
678
+ `\Phi: U \rightarrow M` to a parallelizable manifold `M` and a positive
679
+ integer `p`, a *multivector field of degree* `p` (or `p`-*vector field*)
680
+ *along* `U` *with values on* `M\supset\Phi(U)` is a differentiable map
681
+
682
+ .. MATH::
683
+
684
+ a:\ U \longrightarrow T^{(p,0)}M
685
+
686
+ (`T^{(p,0)}M` being the tensor bundle of type `(p,0)` over `M`) such that
687
+
688
+ .. MATH::
689
+
690
+ \forall x \in U,\quad a(x) \in \Lambda^p(T_{\Phi(x)} M) ,
691
+
692
+ where `T_{\Phi(x)} M` is the vector space tangent to `M` at `\Phi(x)` and
693
+ `\Lambda^p` stands for the exterior power of degree `p` (cf.
694
+ :class:`~sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule`).
695
+ In other words, `a(x)` is an alternating contravariant tensor of degree `p`
696
+ of the tangent vector space `T_{\Phi(x)} M`.
697
+
698
+ The standard case of a multivector field *on* a manifold `M` corresponds to
699
+ `U = M` and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
700
+ immersion and `\Phi` being a curve in `M` (`U` is then an open interval of
701
+ `\RR`).
702
+
703
+ .. NOTE::
704
+
705
+ If `M` is not parallelizable, the class :class:`MultivectorField` must
706
+ be used instead.
707
+
708
+ INPUT:
709
+
710
+ - ``vector_field_module`` -- free module `\mathfrak{X}(U,\Phi)` of vector
711
+ fields along `U` with values on `M` via the map `\Phi`
712
+ - ``degree`` -- the degree of the multivector field (i.e. its tensor rank)
713
+ - ``name`` -- (default: ``None``) name given to the multivector field
714
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
715
+ multivector field; if none is provided, the LaTeX symbol is set to
716
+ ``name``
717
+
718
+ EXAMPLES:
719
+
720
+ A 2-vector field on a 4-dimensional manifold::
721
+
722
+ sage: M = Manifold(4, 'M')
723
+ sage: c_txyz.<t,x,y,z> = M.chart()
724
+ sage: a = M.multivector_field(2, name='a') ; a
725
+ 2-vector field a on the 4-dimensional differentiable manifold M
726
+ sage: a.parent()
727
+ Free module A^2(M) of 2-vector fields on the 4-dimensional
728
+ differentiable manifold M
729
+
730
+ A multivector field is a tensor field of purely contravariant type::
731
+
732
+ sage: a.tensor_type()
733
+ (2, 0)
734
+
735
+ It is antisymmetric, its components being
736
+ :class:`~sage.tensor.modules.comp.CompFullyAntiSym`::
737
+
738
+ sage: a.symmetries()
739
+ no symmetry; antisymmetry: (0, 1)
740
+ sage: a[0,1] = 2*x
741
+ sage: a[1,0]
742
+ -2*x
743
+ sage: a.comp()
744
+ Fully antisymmetric 2-indices components w.r.t. Coordinate frame
745
+ (M, (∂/∂t,∂/∂x,∂/∂y,∂/∂z))
746
+ sage: type(a.comp())
747
+ <class 'sage.tensor.modules.comp.CompFullyAntiSym'>
748
+
749
+ Setting a component with repeated indices to a nonzero value results in
750
+ an error::
751
+
752
+ sage: a[1,1] = 3
753
+ Traceback (most recent call last):
754
+ ...
755
+ ValueError: by antisymmetry, the component cannot have a nonzero value
756
+ for the indices (1, 1)
757
+ sage: a[1,1] = 0 # OK, albeit useless
758
+ sage: a[1,2] = 3 # OK
759
+
760
+ The expansion of a multivector field with respect to a given frame is
761
+ displayed via the method
762
+ :meth:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor.display`::
763
+
764
+ sage: a.display() # expansion w.r.t. the default frame
765
+ a = 2*x ∂/∂t∧∂/∂x + 3 ∂/∂x∧∂/∂y
766
+ sage: latex(a.display()) # output for the notebook
767
+ a = 2 \, x \frac{\partial}{\partial t }\wedge \frac{\partial}{\partial x }
768
+ + 3 \frac{\partial}{\partial x }\wedge \frac{\partial}{\partial y }
769
+
770
+ Multivector fields can be added or subtracted::
771
+
772
+ sage: b = M.multivector_field(2)
773
+ sage: b[0,1], b[0,2], b[0,3] = y, 2, x+z
774
+ sage: s = a + b ; s
775
+ 2-vector field on the 4-dimensional differentiable manifold M
776
+ sage: s.display()
777
+ (2*x + y) ∂/∂t∧∂/∂x + 2 ∂/∂t∧∂/∂y + (x + z) ∂/∂t∧∂/∂z + 3 ∂/∂x∧∂/∂y
778
+ sage: s = a - b ; s
779
+ 2-vector field on the 4-dimensional differentiable manifold M
780
+ sage: s.display()
781
+ (2*x - y) ∂/∂t∧∂/∂x - 2 ∂/∂t∧∂/∂y + (-x - z) ∂/∂t∧∂/∂z + 3 ∂/∂x∧∂/∂y
782
+
783
+ An example of 3-vector field in `\RR^3` with Cartesian coordinates::
784
+
785
+ sage: M = Manifold(3, 'R3', latex_name=r'\RR^3', start_index=1)
786
+ sage: c_cart.<x,y,z> = M.chart()
787
+ sage: a = M.multivector_field(3, name='a')
788
+ sage: a[1,2,3] = x^2+y^2+z^2 # the only independent component
789
+ sage: a[:] # all the components are set from the previous line:
790
+ [[[0, 0, 0], [0, 0, x^2 + y^2 + z^2], [0, -x^2 - y^2 - z^2, 0]],
791
+ [[0, 0, -x^2 - y^2 - z^2], [0, 0, 0], [x^2 + y^2 + z^2, 0, 0]],
792
+ [[0, x^2 + y^2 + z^2, 0], [-x^2 - y^2 - z^2, 0, 0], [0, 0, 0]]]
793
+ sage: a.display()
794
+ a = (x^2 + y^2 + z^2) ∂/∂x∧∂/∂y∧∂/∂z
795
+
796
+ Spherical components from the tensorial change-of-frame formula::
797
+
798
+ sage: c_spher.<r,th,ph> = M.chart(r'r:[0,+oo) th:[0,pi]:\theta ph:[0,2*pi):\phi')
799
+ sage: spher_to_cart = c_spher.transition_map(c_cart,
800
+ ....: [r*sin(th)*cos(ph), r*sin(th)*sin(ph), r*cos(th)])
801
+ sage: cart_to_spher = spher_to_cart.set_inverse(sqrt(x^2+y^2+z^2),
802
+ ....: atan2(sqrt(x^2+y^2),z), atan2(y, x))
803
+ Check of the inverse coordinate transformation:
804
+ r == r *passed*
805
+ th == arctan2(r*sin(th), r*cos(th)) **failed**
806
+ ph == arctan2(r*sin(ph)*sin(th), r*cos(ph)*sin(th)) **failed**
807
+ x == x *passed*
808
+ y == y *passed*
809
+ z == z *passed*
810
+ NB: a failed report can reflect a mere lack of simplification.
811
+ sage: a.comp(c_spher.frame()) # computation of components w.r.t. spherical frame
812
+ Fully antisymmetric 3-indices components w.r.t. Coordinate frame
813
+ (R3, (∂/∂r,∂/∂th,∂/∂ph))
814
+ sage: a.comp(c_spher.frame())[1,2,3, c_spher]
815
+ 1/sin(th)
816
+ sage: a.display(c_spher.frame())
817
+ a = sqrt(x^2 + y^2 + z^2)/sqrt(x^2 + y^2) ∂/∂r∧∂/∂th∧∂/∂ph
818
+ sage: a.display(c_spher.frame(), c_spher)
819
+ a = 1/sin(th) ∂/∂r∧∂/∂th∧∂/∂ph
820
+
821
+ As a shortcut of the above command, on can pass just the chart ``c_spher``
822
+ to ``display``, the vector frame being then assumed to be the coordinate
823
+ frame associated with the chart::
824
+
825
+ sage: a.display(c_spher)
826
+ a = 1/sin(th) ∂/∂r∧∂/∂th∧∂/∂ph
827
+
828
+ The exterior product of two multivector fields is performed via the method
829
+ :meth:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor.wedge`::
830
+
831
+ sage: a = M.vector_field([x*y, -z*x, y], name='A')
832
+ sage: b = M.vector_field([y, z+y, x^2-z^2], name='B')
833
+ sage: ab = a.wedge(b) ; ab
834
+ 2-vector field A∧B on the 3-dimensional differentiable manifold R3
835
+ sage: ab.display()
836
+ A∧B = (x*y^2 + 2*x*y*z) ∂/∂x∧∂/∂y + (x^3*y - x*y*z^2 - y^2) ∂/∂x∧∂/∂z
837
+ + (x*z^3 - y^2 - (x^3 + y)*z) ∂/∂y∧∂/∂z
838
+
839
+ Let us check the formula relating the exterior product to the tensor
840
+ product for vector fields::
841
+
842
+ sage: a.wedge(b) == a*b - b*a
843
+ True
844
+
845
+ The tensor product of a vector field and a 2-vector field is not a 3-vector
846
+ field but a tensor field of type `(3,0)` with less symmetries::
847
+
848
+ sage: c = a*ab ; c
849
+ Tensor field A⊗(A∧B) of type (3,0) on the 3-dimensional differentiable
850
+ manifold R3
851
+ sage: c.symmetries() # the antisymmetry is only w.r.t. the last 2 arguments:
852
+ no symmetry; antisymmetry: (1, 2)
853
+
854
+ The Lie derivative of a 2-vector field is a 2-vector field::
855
+
856
+ sage: ab.lie_der(a)
857
+ 2-vector field on the 3-dimensional differentiable manifold R3
858
+ """
859
+ def __init__(self, vector_field_module, degree, name=None,
860
+ latex_name=None):
861
+ r"""
862
+ Construct a multivector field.
863
+
864
+ TESTS:
865
+
866
+ Construction via ``parent.element_class``, and not via a direct call
867
+ to ``MultivectorFieldParal``, to fit with the category framework::
868
+
869
+ sage: M = Manifold(2, 'M')
870
+ sage: X.<x,y> = M.chart() # makes M parallelizable
871
+ sage: A = M.multivector_module(2)
872
+ sage: XM = M.vector_field_module()
873
+ sage: a = A.element_class(XM, 2, name='a'); a
874
+ 2-vector field a on the 2-dimensional differentiable manifold M
875
+ sage: a[0,1] = x*y
876
+ sage: TestSuite(a).run()
877
+
878
+ Construction via ``DifferentiableManifold.multivector_field``::
879
+
880
+ sage: a1 = M.multivector_field(2, name='a'); a1
881
+ 2-vector field a on the 2-dimensional differentiable manifold M
882
+ sage: type(a1) == type(a)
883
+ True
884
+ sage: a1.parent() is a.parent()
885
+ True
886
+ """
887
+ AlternatingContrTensor.__init__(self, vector_field_module, degree,
888
+ name=name, latex_name=latex_name)
889
+ # TensorFieldParal attributes:
890
+ self._vmodule = vector_field_module
891
+ self._domain = vector_field_module._domain
892
+ self._ambient_domain = vector_field_module._ambient_domain
893
+ # initialization of derived quantities:
894
+ self._init_derived()
895
+
896
+ def _repr_(self):
897
+ r"""
898
+ String representation of ``self``.
899
+
900
+ TESTS::
901
+
902
+ sage: M = Manifold(3, 'M')
903
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
904
+ sage: a = M.multivector_field(2, name='a')
905
+ sage: a._repr_()
906
+ '2-vector field a on the 3-dimensional differentiable manifold M'
907
+ sage: repr(a) # indirect doctest
908
+ '2-vector field a on the 3-dimensional differentiable manifold M'
909
+ sage: a # indirect doctest
910
+ 2-vector field a on the 3-dimensional differentiable manifold M
911
+ sage: b = M.multivector_field(2)
912
+ sage: b._repr_()
913
+ '2-vector field on the 3-dimensional differentiable manifold M'
914
+ """
915
+ description = "{}-vector field ".format(self._tensor_rank)
916
+ if self._name is not None:
917
+ description += self._name + " "
918
+ return self._final_repr(description)
919
+
920
+ def _new_instance(self):
921
+ r"""
922
+ Create an instance of the same class, of the same degree and on the
923
+ same domain.
924
+
925
+ TESTS::
926
+
927
+ sage: M = Manifold(3, 'M')
928
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
929
+ sage: a = M.multivector_field(2, name='a')
930
+ sage: a1 = a._new_instance(); a1
931
+ 2-vector field on the 3-dimensional differentiable manifold M
932
+ sage: type(a1) == type(a)
933
+ True
934
+ sage: a1.parent() is a.parent()
935
+ True
936
+ """
937
+ return type(self)(self._fmodule, self._tensor_rank)
938
+
939
+ # This method is needed to redirect to the correct class (TensorFieldParal)
940
+ def _init_derived(self):
941
+ r"""
942
+ Initialize the derived quantities of ``self``.
943
+
944
+ TESTS::
945
+
946
+ sage: M = Manifold(3, 'M')
947
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
948
+ sage: a = M.multivector_field(2, name='a')
949
+ sage: a._init_derived()
950
+ """
951
+ TensorFieldParal._init_derived(self)
952
+
953
+ def _del_derived(self, del_restrictions=True):
954
+ r"""
955
+ Delete the derived quantities.
956
+
957
+ INPUT:
958
+
959
+ - ``del_restrictions`` -- boolean (default: ``True``); determines whether the
960
+ restrictions of ``self`` to subdomains are deleted
961
+
962
+ TESTS::
963
+
964
+ sage: M = Manifold(3, 'M')
965
+ sage: X.<x,y,z> = M.chart() # makes M parallelizable
966
+ sage: a = M.multivector_field(2, name='a')
967
+ sage: a._del_derived()
968
+ """
969
+ TensorFieldParal._del_derived(self, del_restrictions=del_restrictions)
970
+
971
+ def __call__(self, *args):
972
+ r"""
973
+ Redefinition of
974
+ :meth:`~sage.tensor.modules.free_module_tensor.FreeModuleTensor.__call__`
975
+ to allow for domain treatment.
976
+
977
+ TESTS::
978
+
979
+ sage: M = Manifold(2, 'M')
980
+ sage: X.<x,y> = M.chart()
981
+ sage: a = M.multivector_field(2, name='a')
982
+ sage: a[0,1] = x*y
983
+ sage: a.display()
984
+ a = x*y ∂/∂x∧∂/∂y
985
+ sage: b = M.one_form([1+x, 2-y], name='b')
986
+ sage: c = M.one_form([-y, x], name='c')
987
+ sage: s = a.__call__(b,c); s
988
+ Scalar field a(b,c) on the 2-dimensional differentiable manifold M
989
+ sage: s.display()
990
+ a(b,c): M → ℝ
991
+ (x, y) ↦ -x*y^3 + 2*x*y^2 + (x^3 + x^2)*y
992
+ sage: s == a[[0,1]]*(b[[0]]*c[[1]] - b[[1]]*c[[0]])
993
+ True
994
+ sage: s == a(b,c) # indirect doctest
995
+ True
996
+ """
997
+ return TensorFieldParal.__call__(self, *args)
998
+
999
+ def wedge(self, other):
1000
+ r"""
1001
+ Exterior product of ``self`` with another multivector field.
1002
+
1003
+ INPUT:
1004
+
1005
+ - ``other`` -- another multivector field
1006
+
1007
+ OUTPUT:
1008
+
1009
+ - instance of :class:`MultivectorFieldParal` representing the
1010
+ exterior product ``self ∧ other``
1011
+
1012
+ EXAMPLES:
1013
+
1014
+ Exterior product of a vector field and a 2-vector field on a
1015
+ 3-dimensional manifold::
1016
+
1017
+ sage: M = Manifold(3, 'M', start_index=1)
1018
+ sage: X.<x,y,z> = M.chart()
1019
+ sage: a = M.vector_field([2, 1+x, y*z], name='a')
1020
+ sage: b = M.multivector_field(2, name='b')
1021
+ sage: b[1,2], b[1,3], b[2,3] = y^2, z+x, z^2
1022
+ sage: a.display()
1023
+ a = 2 ∂/∂x + (x + 1) ∂/∂y + y*z ∂/∂z
1024
+ sage: b.display()
1025
+ b = y^2 ∂/∂x∧∂/∂y + (x + z) ∂/∂x∧∂/∂z + z^2 ∂/∂y∧∂/∂z
1026
+ sage: s = a.wedge(b); s
1027
+ 3-vector field a∧b on the 3-dimensional differentiable manifold M
1028
+ sage: s.display()
1029
+ a∧b = (-x^2 + (y^3 - x - 1)*z + 2*z^2 - x) ∂/∂x∧∂/∂y∧∂/∂z
1030
+
1031
+ Check::
1032
+
1033
+ sage: s[1,2,3] == a[1]*b[2,3] + a[2]*b[3,1] + a[3]*b[1,2]
1034
+ True
1035
+
1036
+ Exterior product with a scalar field::
1037
+
1038
+ sage: f = M.scalar_field(x, name='f')
1039
+ sage: s = b.wedge(f); s
1040
+ 2-vector field f*b on the 3-dimensional differentiable manifold M
1041
+ sage: s.display()
1042
+ f*b = x*y^2 ∂/∂x∧∂/∂y + (x^2 + x*z) ∂/∂x∧∂/∂z + x*z^2 ∂/∂y∧∂/∂z
1043
+ sage: s == f*b
1044
+ True
1045
+ sage: s == f.wedge(b)
1046
+ True
1047
+ """
1048
+ if other._tensor_rank == 0: # wedge product with a scalar field
1049
+ return self * other
1050
+ if self._domain.is_subset(other._domain):
1051
+ if not self._ambient_domain.is_subset(other._ambient_domain):
1052
+ raise ValueError("incompatible ambient domains for exterior " +
1053
+ "product")
1054
+ elif other._domain.is_subset(self._domain):
1055
+ if not other._ambient_domain.is_subset(self._ambient_domain):
1056
+ raise ValueError("incompatible ambient domains for exterior " +
1057
+ "product")
1058
+ dom_resu = self._domain.intersection(other._domain)
1059
+ self_r = self.restrict(dom_resu)
1060
+ other_r = other.restrict(dom_resu)
1061
+ return AlternatingContrTensor.wedge(self_r, other_r)
1062
+
1063
+ def interior_product(self, form):
1064
+ r"""
1065
+ Interior product with a differential form.
1066
+
1067
+ If ``self`` is a multivector field `A` of degree `p` and `B` is a
1068
+ differential form of degree `q\geq p` on the same manifold as `A`, the
1069
+ interior product of `A` by `B` is the differential form `\iota_A B` of
1070
+ degree `q-p` defined by
1071
+
1072
+ .. MATH::
1073
+
1074
+ (\iota_A B)_{i_1\ldots i_{q-p}} = A^{k_1\ldots k_p}
1075
+ B_{k_1\ldots k_p i_1\ldots i_{q-p}}
1076
+
1077
+ .. NOTE::
1078
+
1079
+ ``A.interior_product(B)`` yields the same result as
1080
+ ``A.contract(0,..., p-1, B, 0,..., p-1)`` (cf.
1081
+ :meth:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal.contract`),
1082
+ but ``interior_product`` is more efficient, the alternating
1083
+ character of `A` being not used to reduce the computation in
1084
+ :meth:`~sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal.contract`
1085
+
1086
+ INPUT:
1087
+
1088
+ - ``form`` -- differential form `B` (instance of
1089
+ :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal`);
1090
+ the degree of `B` must be at least equal to the degree of ``self``
1091
+
1092
+ OUTPUT:
1093
+
1094
+ - scalar field (case `p=q`) or
1095
+ :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal`
1096
+ (case `p<q`) representing the interior product `\iota_A B`, where `A`
1097
+ is ``self``
1098
+
1099
+ .. SEEALSO::
1100
+
1101
+ :meth:`~sage.manifolds.differentiable.diff_form.DiffFormParal.interior_product`
1102
+ for the interior product of a differential form with a
1103
+ multivector field
1104
+
1105
+ EXAMPLES:
1106
+
1107
+ Interior product with `p=1` and `q=1` on 4-dimensional manifold::
1108
+
1109
+ sage: M = Manifold(4, 'M')
1110
+ sage: X.<t,x,y,z> = M.chart()
1111
+ sage: a = M.vector_field([x, 1+t^2, x*z, y-3], name='a')
1112
+ sage: b = M.one_form([-z^2, 2, x, x-y], name='b')
1113
+ sage: s = a.interior_product(b); s
1114
+ Scalar field i_a b on the 4-dimensional differentiable manifold M
1115
+ sage: s.display()
1116
+ i_a b: M → ℝ
1117
+ (t, x, y, z) ↦ x^2*z - x*z^2 + 2*t^2 + (x + 3)*y - y^2
1118
+ - 3*x + 2
1119
+
1120
+ In this case, we have `\iota_a b = a^i b_i = a(b) = b(a)`::
1121
+
1122
+ sage: all([s == a.contract(b), s == a(b), s == b(a)])
1123
+ True
1124
+
1125
+ Case `p=1` and `q=3`::
1126
+
1127
+ sage: c = M.diff_form(3, name='c')
1128
+ sage: c[0,1,2], c[0,1,3] = x*y - z, -3*t
1129
+ sage: c[0,2,3], c[1,2,3] = t+x, y
1130
+ sage: s = a.interior_product(c); s
1131
+ 2-form i_a c on the 4-dimensional differentiable manifold M
1132
+ sage: s.display()
1133
+ i_a c = (x^2*y*z - x*z^2 - 3*t*y + 9*t) dt∧dx
1134
+ + (-(t^2*x - t)*y + (t^2 + 1)*z - 3*t - 3*x) dt∧dy
1135
+ + (3*t^3 - (t*x + x^2)*z + 3*t) dt∧dz
1136
+ + ((x^2 - 3)*y + y^2 - x*z) dx∧dy
1137
+ + (-x*y*z - 3*t*x) dx∧dz + (t*x + x^2 + (t^2 + 1)*y) dy∧dz
1138
+ sage: s == a.contract(c)
1139
+ True
1140
+
1141
+ Case `p=2` and `q=3`::
1142
+
1143
+ sage: d = M.multivector_field(2, name='d')
1144
+ sage: d[0,1], d[0,2], d[0,3] = t-x, 2*z, y-1
1145
+ sage: d[1,2], d[1,3], d[2,3] = z, y+t, 4
1146
+ sage: s = d.interior_product(c); s
1147
+ 1-form i_d c on the 4-dimensional differentiable manifold M
1148
+ sage: s.display()
1149
+ i_d c = (2*x*y*z - 6*t^2 - 6*t*y - 2*z^2 + 8*t + 8*x) dt
1150
+ + (-4*x*y*z + 2*(3*t + 4)*y + 4*z^2 - 6*t) dx
1151
+ + (2*((t - 1)*x - x^2 - 2*t)*y - 2*y^2 - 2*(t - x)*z + 2*t
1152
+ + 2*x) dy + (-6*t^2 + 6*t*x + 2*(2*t + 2*x + y)*z) dz
1153
+ sage: s == d.contract(0, 1, c, 0, 1)
1154
+ True
1155
+
1156
+ TESTS:
1157
+
1158
+ Check that :issue:`33780` is fixed::
1159
+
1160
+ sage: v = X.frame()[0] # vector field d/dt
1161
+ sage: f = X.coframe()[1] # 1-form dx
1162
+ sage: v.interior_product(f)
1163
+ Scalar field zero on the 4-dimensional differentiable manifold M
1164
+ """
1165
+ if self._domain.is_subset(form._domain):
1166
+ if not self._ambient_domain.is_subset(form._ambient_domain):
1167
+ raise ValueError("incompatible ambient domains for interior " +
1168
+ "product")
1169
+ elif form._domain.is_subset(self._domain):
1170
+ if not form._ambient_domain.is_subset(self._ambient_domain):
1171
+ raise ValueError("incompatible ambient domains for interior " +
1172
+ "product")
1173
+ dom_resu = self._domain.intersection(form._domain)
1174
+ self_r = self.restrict(dom_resu)
1175
+ form_r = form.restrict(dom_resu)
1176
+ return AlternatingContrTensor.interior_product(self_r, form_r)
1177
+
1178
+ def bracket(self, other):
1179
+ r"""
1180
+ Return the Schouten-Nijenhuis bracket of ``self`` with another
1181
+ multivector field.
1182
+
1183
+ The Schouten-Nijenhuis bracket extends the Lie bracket of
1184
+ vector fields (cf.
1185
+ :meth:`~sage.manifolds.differentiable.vectorfield.VectorField.bracket`)
1186
+ to multivector fields.
1187
+
1188
+ Denoting by `A^p(M)` the `C^k(M)`-module of `p`-vector fields on the
1189
+ `C^k`-differentiable manifold `M` over the field `K` (cf.
1190
+ :class:`~sage.manifolds.differentiable.multivector_module.MultivectorModule`),
1191
+ the *Schouten-Nijenhuis bracket* is a `K`-bilinear map
1192
+
1193
+ .. MATH::
1194
+
1195
+ \begin{array}{ccc}
1196
+ A^p(M)\times A^q(M) & \longrightarrow & A^{p+q-1}(M) \\
1197
+ (a,b) & \longmapsto & [a,b]
1198
+ \end{array}
1199
+
1200
+ which obeys the following properties:
1201
+
1202
+ - if `p=0` and `q=0`, (i.e. `a` and `b` are two scalar fields), `[a,b]=0`
1203
+ - if `p=0` (i.e. `a` is a scalar field) and `q\geq 1`,
1204
+ `[a,b] = - \iota_{\mathrm{d}a} b` (minus the interior product of
1205
+ the differential of `a` by `b`)
1206
+ - if `p=1` (i.e. `a` is a vector field), `[a,b] = \mathcal{L}_a b`
1207
+ (the Lie derivative of `b` along `a`)
1208
+ - `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]`
1209
+ - for any multivector field `c` and `(a,b) \in A^p(M)\times A^q(M)`,
1210
+ `[a,.]` obeys the *graded Leibniz rule*
1211
+
1212
+ .. MATH::
1213
+
1214
+ [a,b\wedge c] = [a,b]\wedge c + (-1)^{(p-1)q} b\wedge [a,c]
1215
+
1216
+ - for `(a,b,c) \in A^p(M)\times A^q(M)\times A^r(M)`, the *graded
1217
+ Jacobi identity* holds:
1218
+
1219
+ .. MATH::
1220
+
1221
+ (-1)^{(p-1)(r-1)}[a,[b,c]] + (-1)^{(q-1)(p-1)}[b,[c,a]] +
1222
+ (-1)^{(r-1)(q-1)}[c,[a,b]] = 0
1223
+
1224
+ .. NOTE::
1225
+
1226
+ There are two definitions of the Schouten-Nijenhuis bracket in
1227
+ the literature, which differ from each other when `p` is even
1228
+ by an overall sign. The definition adopted here is that of
1229
+ [Mar1997]_, [Kos1985]_ and :wikipedia:`Schouten-Nijenhuis_bracket`.
1230
+ The other definition, adopted e.g. by [Nij1955]_, [Lic1977]_
1231
+ and [Vai1994]_, is `[a,b]' = (-1)^{p+1} [a,b]`.
1232
+
1233
+ INPUT:
1234
+
1235
+ - ``other`` -- a multivector field
1236
+
1237
+ OUTPUT:
1238
+
1239
+ - instance of :class:`MultivectorFieldParal` (or of
1240
+ :class:`~sage.manifolds.differentiable.scalarfield.DiffScalarField`
1241
+ if `p=1` and `q=0`) representing the
1242
+ Schouten-Nijenhuis bracket `[a,b]`, where `a` is ``self`` and `b` is
1243
+ ``other``
1244
+
1245
+ EXAMPLES:
1246
+
1247
+ Let us consider two vector fields on a 3-dimensional manifold::
1248
+
1249
+ sage: M = Manifold(3, 'M')
1250
+ sage: X.<x,y,z> = M.chart()
1251
+ sage: a = M.vector_field([x*y+z, x+y-z, z-2*x+y], name='a')
1252
+ sage: b = M.vector_field([y+2*z-x, x^2-y+z, z-x], name='b')
1253
+
1254
+ and form their Schouten-Nijenhuis bracket::
1255
+
1256
+ sage: s = a.bracket(b); s
1257
+ Vector field [a,b] on the 3-dimensional differentiable manifold M
1258
+ sage: s.display()
1259
+ [a,b] = (-x^3 + (x + 3)*y - y^2 - (x + 2*y + 1)*z - 2*x) ∂/∂x
1260
+ + (2*x^2*y - x^2 + 2*x*z - 3*x) ∂/∂y
1261
+ + (-x^2 - (x - 4)*y - 3*x + 2*z) ∂/∂z
1262
+
1263
+ Check that `[a,b]` is actually the Lie bracket::
1264
+
1265
+ sage: f = M.scalar_field({X: x+y*z}, name='f')
1266
+ sage: s(f) == a(b(f)) - b(a(f))
1267
+ True
1268
+
1269
+ Check that `[a,b]` coincides with the Lie derivative of `b` along `a`::
1270
+
1271
+ sage: s == b.lie_derivative(a)
1272
+ True
1273
+
1274
+ Schouten-Nijenhuis bracket for `p=0` and `q=1`::
1275
+
1276
+ sage: s = f.bracket(a); s
1277
+ Scalar field -i_df a on the 3-dimensional differentiable manifold M
1278
+ sage: s.display()
1279
+ -i_df a: M → ℝ
1280
+ (x, y, z) ↦ x*y - y^2 - (x + 2*y + 1)*z + z^2
1281
+
1282
+ Check that `[f,a] = - \iota_{\mathrm{d}f} a = - \mathrm{d}f(a)`::
1283
+
1284
+ sage: s == - f.differential()(a)
1285
+ True
1286
+
1287
+ Schouten-Nijenhuis bracket for `p=0` and `q=2`::
1288
+
1289
+ sage: c = M.multivector_field(2, name='c')
1290
+ sage: c[0,1], c[0,2], c[1,2] = x+z+1, x*y+z, x-y
1291
+ sage: s = f.bracket(c); s
1292
+ Vector field -i_df c on the 3-dimensional differentiable manifold M
1293
+ sage: s.display()
1294
+ -i_df c = (x*y^2 + (x + y + 1)*z + z^2) ∂/∂x
1295
+ + (x*y - y^2 - x - z - 1) ∂/∂y + (-x*y - (x - y + 1)*z) ∂/∂z
1296
+
1297
+ Check that `[f,c] = - \iota_{\mathrm{d}f} c`::
1298
+
1299
+ sage: s == - f.differential().interior_product(c)
1300
+ True
1301
+
1302
+ Schouten-Nijenhuis bracket for `p=1` and `q=2`::
1303
+
1304
+ sage: s = a.bracket(c); s
1305
+ 2-vector field [a,c] on the 3-dimensional differentiable manifold M
1306
+ sage: s.display()
1307
+ [a,c] = ((x - 1)*y - (y - 2)*z - 2*x - 1) ∂/∂x∧∂/∂y
1308
+ + ((x + 1)*y - (x + 1)*z - 3*x - 1) ∂/∂x∧∂/∂z
1309
+ + (-5*x + y - z - 2) ∂/∂y∧∂/∂z
1310
+
1311
+ Again, since `a` is a vector field, the Schouten-Nijenhuis bracket
1312
+ coincides with the Lie derivative::
1313
+
1314
+ sage: s == c.lie_derivative(a)
1315
+ True
1316
+
1317
+ Schouten-Nijenhuis bracket for `p=2` and `q=2`::
1318
+
1319
+ sage: d = M.multivector_field(2, name='d')
1320
+ sage: d[0,1], d[0,2], d[1,2] = x-y^2, x+z, z-x-1
1321
+ sage: s = c.bracket(d); s
1322
+ 3-vector field [c,d] on the 3-dimensional differentiable manifold M
1323
+ sage: s.display()
1324
+ [c,d] = (-y^3 + (3*x + 1)*y - y^2 - x - z + 2) ∂/∂x∧∂/∂y∧∂/∂z
1325
+
1326
+ Let us check the component formula (with respect to the manifold's
1327
+ default coordinate chart, i.e. ``X``) for `p=q=2`, taking into
1328
+ account the tensor antisymmetries::
1329
+
1330
+ sage: s[0,1,2] == - sum(c[i,0]*d[1,2].diff(i)
1331
+ ....: + c[i,1]*d[2,0].diff(i) + c[i,2]*d[0,1].diff(i)
1332
+ ....: + d[i,0]*c[1,2].diff(i) + d[i,1]*c[2,0].diff(i)
1333
+ ....: + d[i,2]*c[0,1].diff(i) for i in M.irange())
1334
+ True
1335
+
1336
+ Schouten-Nijenhuis bracket for `p=1` and `q=3`::
1337
+
1338
+ sage: e = M.multivector_field(3, name='e')
1339
+ sage: e[0,1,2] = x+y*z+1
1340
+ sage: s = a.bracket(e); s
1341
+ 3-vector field [a,e] on the 3-dimensional differentiable manifold M
1342
+ sage: s.display()
1343
+ [a,e] = (-(2*x + 1)*y + y^2 - (y^2 - x - 1)*z - z^2
1344
+ - 2*x - 2) ∂/∂x∧∂/∂y∧∂/∂z
1345
+
1346
+ Again, since `p=1`, the bracket coincides with the Lie derivative::
1347
+
1348
+ sage: s == e.lie_derivative(a)
1349
+ True
1350
+
1351
+ Schouten-Nijenhuis bracket for `p=2` and `q=3`::
1352
+
1353
+ sage: s = c.bracket(e); s
1354
+ 4-vector field [c,e] on the 3-dimensional differentiable manifold M
1355
+
1356
+ Since on a 3-dimensional manifold, any 4-vector field is zero, we have::
1357
+
1358
+ sage: s.display()
1359
+ [c,e] = 0
1360
+
1361
+ Let us check the graded commutation law
1362
+ `[a,b] = -(-1)^{(p-1)(q-1)} [b,a]` for various values of `p` and `q`::
1363
+
1364
+ sage: f.bracket(a) == - a.bracket(f) # p=0 and q=1
1365
+ True
1366
+ sage: f.bracket(c) == c.bracket(f) # p=0 and q=2
1367
+ True
1368
+ sage: a.bracket(b) == - b.bracket(a) # p=1 and q=1
1369
+ True
1370
+ sage: a.bracket(c) == - c.bracket(a) # p=1 and q=2
1371
+ True
1372
+ sage: c.bracket(d) == d.bracket(c) # p=2 and q=2
1373
+ True
1374
+
1375
+ Let us check the graded Leibniz rule for `p=1` and `q=1`::
1376
+
1377
+ sage: a.bracket(b.wedge(c)) == a.bracket(b).wedge(c) + b.wedge(a.bracket(c)) # long time
1378
+ True
1379
+
1380
+ as well as for `p=2` and `q=1`::
1381
+
1382
+ sage: c.bracket(a.wedge(b)) == c.bracket(a).wedge(b) - a.wedge(c.bracket(b)) # long time
1383
+ True
1384
+
1385
+ Finally let us check the graded Jacobi identity for `p=1`, `q=1` and
1386
+ `r=2`::
1387
+
1388
+ sage: # long time
1389
+ sage: a_bc = a.bracket(b.bracket(c))
1390
+ sage: b_ca = b.bracket(c.bracket(a))
1391
+ sage: c_ab = c.bracket(a.bracket(b))
1392
+ sage: a_bc + b_ca + c_ab == 0
1393
+ True
1394
+
1395
+ as well as for `p=1`, `q=2` and `r=2`::
1396
+
1397
+ sage: # long time
1398
+ sage: a_cd = a.bracket(c.bracket(d))
1399
+ sage: c_da = c.bracket(d.bracket(a))
1400
+ sage: d_ac = d.bracket(a.bracket(c))
1401
+ sage: a_cd + c_da - d_ac == 0
1402
+ True
1403
+ """
1404
+ from itertools import combinations
1405
+
1406
+ from sage.combinat.permutation import Permutation
1407
+ from sage.manifolds.differentiable.scalarfield import DiffScalarField
1408
+ from sage.tensor.modules.comp import CompFullyAntiSym, Components, CompWithSym
1409
+ pp = self._tensor_rank
1410
+ mp1 = (-1)**(pp+1)
1411
+ if isinstance(other, DiffScalarField):
1412
+ resu = other.differential().interior_product(self)
1413
+ if mp1 == 1:
1414
+ return resu
1415
+ return - resu
1416
+ # Some checks:
1417
+ if not isinstance(other, (MultivectorField, MultivectorFieldParal)):
1418
+ raise TypeError("{} is not a multivector field".format(other))
1419
+ if (self._vmodule.destination_map() is not self._domain.identity_map()
1420
+ or other._vmodule.destination_map() is not
1421
+ other._domain.identity_map()):
1422
+ raise ValueError("the Schouten-Nijenhuis bracket is defined " +
1423
+ "only for fields with a trivial destination map")
1424
+ # Search for a common domain
1425
+ dom_resu = self._domain.intersection(other._domain)
1426
+ self_r = self.restrict(dom_resu)
1427
+ other_r = other.restrict(dom_resu)
1428
+ # Search for a common coordinate frame:
1429
+ coord_frame = self_r._common_coord_frame(other_r)
1430
+ if coord_frame is None:
1431
+ raise ValueError("no common coordinate frame found")
1432
+ chart = coord_frame.chart()
1433
+ dom_resu = chart.domain()
1434
+ fmodule = dom_resu.vector_field_module()
1435
+ ring = fmodule.base_ring() # same as dom_resu.scalar_field_algebra()
1436
+ aa = self_r.comp(coord_frame) # components A^{i_1...i_p}
1437
+ bb = other_r.comp(coord_frame) # components B^{j_1...j_q}
1438
+ qq = other._tensor_rank
1439
+ deg_resu = pp + qq - 1 # degree of the result
1440
+ if deg_resu == 1:
1441
+ resuc = Components(ring, coord_frame, 1,
1442
+ start_index=fmodule._sindex,
1443
+ output_formatter=fmodule._output_formatter)
1444
+ else:
1445
+ resuc = CompFullyAntiSym(ring, coord_frame, deg_resu,
1446
+ start_index=fmodule._sindex,
1447
+ output_formatter=fmodule._output_formatter)
1448
+ # Partial derivatives of the components of self:
1449
+ if pp == 1:
1450
+ daa = Components(ring, coord_frame, 2,
1451
+ start_index=fmodule._sindex,
1452
+ output_formatter=fmodule._output_formatter)
1453
+ else:
1454
+ daa = CompWithSym(ring, coord_frame, pp+1,
1455
+ start_index=fmodule._sindex,
1456
+ output_formatter=fmodule._output_formatter,
1457
+ antisym=range(pp))
1458
+ for ind, val in aa._comp.items():
1459
+ for k in fmodule.irange():
1460
+ daa[[ind+(k,)]] = val.coord_function(chart).diff(k)
1461
+ # Partial derivatives of the components of other:
1462
+ if qq == 1:
1463
+ dbb = Components(ring, coord_frame, 2,
1464
+ start_index=fmodule._sindex,
1465
+ output_formatter=fmodule._output_formatter)
1466
+ else:
1467
+ dbb = CompWithSym(ring, coord_frame, qq+1,
1468
+ start_index=fmodule._sindex,
1469
+ output_formatter=fmodule._output_formatter,
1470
+ antisym=range(qq))
1471
+ for ind, val in bb._comp.items():
1472
+ for k in fmodule.irange():
1473
+ dbb[[ind+(k,)]] = val.coord_function(chart).diff(k)
1474
+ # Computation
1475
+ for ind in resuc.non_redundant_index_generator():
1476
+ sind = set(ind) # {i_1, i_2, ..., i_{p+q-1}}
1477
+ # Term a^{l j_2 ... j_p} \partial_l b^{k_1 ... k_q}
1478
+ # with (j_2,...,j_p,k_1,...,k_q) spanning all permutations of
1479
+ # (i_1, i_2, ..., i_{p+q-1})
1480
+ for sind_a in combinations(sind, pp-1):
1481
+ sind_b = sind.difference(sind_a)
1482
+ ind_a = tuple(sorted(sind_a))
1483
+ ind_b = tuple(sorted(sind_b))
1484
+ sum = 0
1485
+ for l in fmodule.irange():
1486
+ sum += aa[[(l,) + ind_a]] * dbb[[ind_b + (l,)]]
1487
+ ind_ab = ind_a + ind_b
1488
+ sign = Permutation([ind_ab.index(i) + 1 for i in ind]).signature()
1489
+ if mp1*sign == 1:
1490
+ resuc[[ind]] += sum
1491
+ else:
1492
+ resuc[[ind]] -= sum
1493
+ # Term b^{l k_2 ... k_q} \partial_l a^{j_1 ... j_p}
1494
+ # with (j_1,...,j_p,k_2,...,k_q) spanning all permutations of
1495
+ # (i_1, i_2, ..., i_{p+q-1})
1496
+ for sind_b in combinations(sind, qq-1):
1497
+ sind_a = sind.difference(sind_b)
1498
+ ind_a = tuple(sorted(sind_a))
1499
+ ind_b = tuple(sorted(sind_b))
1500
+ sum = 0
1501
+ for l in fmodule.irange():
1502
+ sum += bb[[(l,) + ind_b]] * daa[[ind_a + (l,)]]
1503
+ ind_ab = ind_a + ind_b
1504
+ sign = Permutation([ind_ab.index(i) + 1 for i in ind]).signature()
1505
+ if sign == 1:
1506
+ resuc[[ind]] -= sum
1507
+ else:
1508
+ resuc[[ind]] += sum
1509
+ # Name of the result:
1510
+ resu_name = None
1511
+ resu_latex_name = None
1512
+ if self._name is not None and other._name is not None:
1513
+ resu_name = '[' + self._name + ',' + other._name + ']'
1514
+ if self._latex_name is not None and other._latex_name is not None:
1515
+ resu_latex_name = r'\left[' + self._latex_name + ',' + \
1516
+ other._latex_name + r'\right]'
1517
+ # Creation of the multivector with the components obtained above:
1518
+ resu = fmodule.tensor_from_comp((deg_resu, 0), resuc, name=resu_name,
1519
+ latex_name=resu_latex_name)
1520
+ return resu