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.
- passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.40.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.40.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.40.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.40.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-darwin.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1520 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +910 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1728 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1342 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,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
|