passagemath-symbolics 10.6.37__cp310-cp310-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.37.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.37.dist-info/RECORD +171 -0
- passagemath_symbolics-10.6.37.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.6.37.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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,1507 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Mixed Differential Forms
|
|
4
|
+
|
|
5
|
+
Let `M` and `N` be differentiable manifolds and `\varphi : M \longrightarrow N`
|
|
6
|
+
a differentiable map. A *mixed differential form along* `\varphi` is an element
|
|
7
|
+
of the graded algebra represented by
|
|
8
|
+
:class:`~sage.manifolds.differentiable.mixed_form_algebra.MixedFormAlgebra`.
|
|
9
|
+
Its homogeneous components consist of differential forms along `\varphi`. Mixed
|
|
10
|
+
forms are useful to represent characteristic classes and perform computations
|
|
11
|
+
of such.
|
|
12
|
+
|
|
13
|
+
AUTHORS:
|
|
14
|
+
|
|
15
|
+
- Michael Jung (2019) : initial version
|
|
16
|
+
"""
|
|
17
|
+
# *****************************************************************************
|
|
18
|
+
# Copyright (C) 2019 Michael Jung <micjung@uni-potsdam.de>
|
|
19
|
+
#
|
|
20
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
21
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
22
|
+
# the License, or (at your option) any later version.
|
|
23
|
+
# https://www.gnu.org/licenses/
|
|
24
|
+
# *****************************************************************************
|
|
25
|
+
|
|
26
|
+
from sage.misc.cachefunc import cached_method
|
|
27
|
+
from sage.rings.integer import Integer
|
|
28
|
+
from sage.structure.element import AlgebraElement, ModuleElementWithMutability
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MixedForm(AlgebraElement, ModuleElementWithMutability):
|
|
32
|
+
r"""
|
|
33
|
+
An instance of this class is a mixed form along some differentiable map
|
|
34
|
+
`\varphi: M \to N` between two differentiable manifolds `M` and `N`. More
|
|
35
|
+
precisely, a mixed form `a` along `\varphi: M \to N` can be considered as a
|
|
36
|
+
differentiable map
|
|
37
|
+
|
|
38
|
+
.. MATH::
|
|
39
|
+
|
|
40
|
+
a: M \longrightarrow \bigoplus^n_{k=0} T^{(0,k)}N,
|
|
41
|
+
|
|
42
|
+
where `T^{(0,k)}` denotes the tensor bundle of type `(0,k)`, `\bigoplus`
|
|
43
|
+
the Whitney sum and `n` the dimension of `N`, such that
|
|
44
|
+
|
|
45
|
+
.. MATH::
|
|
46
|
+
|
|
47
|
+
\forall x\in M, \quad a(x) \in \bigoplus^n_{k=0} \Lambda^k\left( T_{\varphi(x)}^* N \right),
|
|
48
|
+
|
|
49
|
+
where `\Lambda^k(T^*_{\varphi(x)} N)` is the `k`-th exterior power of the
|
|
50
|
+
dual of the tangent space `T_{\varphi(x)} N`. Thus, a mixed differential
|
|
51
|
+
form `a` consists of homogeneous components `a_i`, `i=0,1, \dots, n`, where
|
|
52
|
+
the `i`-th homogeneous component represents a differential form of
|
|
53
|
+
degree `i`.
|
|
54
|
+
|
|
55
|
+
The standard case of a mixed form *on* `M` corresponds to `M=N` with
|
|
56
|
+
`\varphi = \mathrm{Id}_M`.
|
|
57
|
+
|
|
58
|
+
INPUT:
|
|
59
|
+
|
|
60
|
+
- ``parent`` -- graded algebra of mixed forms represented by
|
|
61
|
+
:class:`~sage.manifolds.differentiable.mixed_form_algebra.MixedFormAlgebra`
|
|
62
|
+
where the mixed form ``self`` shall belong to
|
|
63
|
+
- ``comp`` -- (default: ``None``) homogeneous components of the mixed form
|
|
64
|
+
as a list; if none is provided, the components are set to innocent unnamed
|
|
65
|
+
differential forms
|
|
66
|
+
- ``name`` -- (default: ``None``) name given to the mixed form
|
|
67
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
68
|
+
mixed form; if none is provided, the LaTeX symbol is set to ``name``
|
|
69
|
+
|
|
70
|
+
EXAMPLES:
|
|
71
|
+
|
|
72
|
+
Initialize a mixed form on a 2-dimensional parallelizable differentiable
|
|
73
|
+
manifold::
|
|
74
|
+
|
|
75
|
+
sage: M = Manifold(2, 'M')
|
|
76
|
+
sage: c_xy.<x,y> = M.chart()
|
|
77
|
+
sage: e_xy = c_xy.frame()
|
|
78
|
+
sage: A = M.mixed_form(name='A'); A
|
|
79
|
+
Mixed differential form A on the 2-dimensional differentiable manifold M
|
|
80
|
+
sage: A.parent()
|
|
81
|
+
Graded algebra Omega^*(M) of mixed differential forms on the
|
|
82
|
+
2-dimensional differentiable manifold M
|
|
83
|
+
|
|
84
|
+
The default way to specify the `i`-th homogeneous component
|
|
85
|
+
of a mixed form is by accessing it via ``A[i]`` or using :meth:`set_comp`::
|
|
86
|
+
|
|
87
|
+
sage: A = M.mixed_form(name='A')
|
|
88
|
+
sage: A[0].set_expr(x) # scalar field
|
|
89
|
+
sage: A.set_comp(1)[0] = y*x
|
|
90
|
+
sage: A.set_comp(2)[0,1] = y^2*x
|
|
91
|
+
sage: A.display() # display names
|
|
92
|
+
A = A_0 + A_1 + A_2
|
|
93
|
+
sage: A.display_expansion() # display expansion in basis
|
|
94
|
+
A = x + x*y dx + x*y^2 dx∧dy
|
|
95
|
+
|
|
96
|
+
Another way to define the homogeneous components is using predefined
|
|
97
|
+
differential forms::
|
|
98
|
+
|
|
99
|
+
sage: f = M.scalar_field(x, name='f'); f
|
|
100
|
+
Scalar field f on the 2-dimensional differentiable manifold M
|
|
101
|
+
sage: omega = M.diff_form(1, name='omega'); omega
|
|
102
|
+
1-form omega on the 2-dimensional differentiable manifold M
|
|
103
|
+
sage: omega[e_xy,0] = y*x; omega.display()
|
|
104
|
+
omega = x*y dx
|
|
105
|
+
sage: eta = M.diff_form(2, name='eta'); eta
|
|
106
|
+
2-form eta on the 2-dimensional differentiable manifold M
|
|
107
|
+
sage: eta[e_xy,0,1] = y^2*x; eta.display()
|
|
108
|
+
eta = x*y^2 dx∧dy
|
|
109
|
+
|
|
110
|
+
The components of a mixed form ``B`` can then be set as follows::
|
|
111
|
+
|
|
112
|
+
sage: B = M.mixed_form(name='B')
|
|
113
|
+
sage: B[:] = [f, omega, eta]; B.display() # display names
|
|
114
|
+
B = f + omega + eta
|
|
115
|
+
sage: B.display_expansion() # display in coordinates
|
|
116
|
+
B = x + x*y dx + x*y^2 dx∧dy
|
|
117
|
+
sage: B[0]
|
|
118
|
+
Scalar field f on the 2-dimensional differentiable manifold M
|
|
119
|
+
sage: B[1]
|
|
120
|
+
1-form omega on the 2-dimensional differentiable manifold M
|
|
121
|
+
sage: B[2]
|
|
122
|
+
2-form eta on the 2-dimensional differentiable manifold M
|
|
123
|
+
|
|
124
|
+
As we can see, the names are applied. However note that the differential
|
|
125
|
+
forms are different instances::
|
|
126
|
+
|
|
127
|
+
sage: f is B[0]
|
|
128
|
+
False
|
|
129
|
+
|
|
130
|
+
Alternatively, the components can be determined from scratch::
|
|
131
|
+
|
|
132
|
+
sage: B = M.mixed_form([f, omega, eta], name='B')
|
|
133
|
+
sage: B.display()
|
|
134
|
+
B = f + omega + eta
|
|
135
|
+
|
|
136
|
+
Mixed forms are elements of an algebra so they can be added, and multiplied
|
|
137
|
+
via the wedge product::
|
|
138
|
+
|
|
139
|
+
sage: C = x*A; C
|
|
140
|
+
Mixed differential form x∧A on the 2-dimensional differentiable
|
|
141
|
+
manifold M
|
|
142
|
+
sage: C.display_expansion()
|
|
143
|
+
x∧A = x^2 + x^2*y dx + x^2*y^2 dx∧dy
|
|
144
|
+
sage: D = A+C; D
|
|
145
|
+
Mixed differential form A+x∧A on the 2-dimensional differentiable
|
|
146
|
+
manifold M
|
|
147
|
+
sage: D.display_expansion()
|
|
148
|
+
A+x∧A = x^2 + x + (x^2 + x)*y dx + (x^2 + x)*y^2 dx∧dy
|
|
149
|
+
sage: E = A*C; E
|
|
150
|
+
Mixed differential form A∧(x∧A) on the 2-dimensional differentiable
|
|
151
|
+
manifold M
|
|
152
|
+
sage: E.display_expansion()
|
|
153
|
+
A∧(x∧A) = x^3 + 2*x^3*y dx + 2*x^3*y^2 dx∧dy
|
|
154
|
+
|
|
155
|
+
Coercions are fully implemented::
|
|
156
|
+
|
|
157
|
+
sage: F = omega*A
|
|
158
|
+
sage: F.display_expansion()
|
|
159
|
+
omega∧A = x^2*y dx
|
|
160
|
+
sage: G = omega+A
|
|
161
|
+
sage: G.display_expansion()
|
|
162
|
+
omega+A = x + 2*x*y dx + x*y^2 dx∧dy
|
|
163
|
+
|
|
164
|
+
Moreover, it is possible to compute the exterior derivative of a
|
|
165
|
+
mixed form::
|
|
166
|
+
|
|
167
|
+
sage: dA = A.exterior_derivative(); dA.display()
|
|
168
|
+
dA = zero + dA_0 + dA_1
|
|
169
|
+
sage: dA.display_expansion()
|
|
170
|
+
dA = dx - x dx∧dy
|
|
171
|
+
|
|
172
|
+
Initialize a mixed form on a 2-dimensional non-parallelizable differentiable
|
|
173
|
+
manifold::
|
|
174
|
+
|
|
175
|
+
sage: M = Manifold(2, 'M')
|
|
176
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
177
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
178
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
179
|
+
sage: transf = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
180
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
181
|
+
....: restrictions2= u+v>0)
|
|
182
|
+
sage: inv = transf.inverse()
|
|
183
|
+
sage: W = U.intersection(V)
|
|
184
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
|
|
185
|
+
sage: A = M.mixed_form(name='A')
|
|
186
|
+
sage: A[0].set_expr(x, c_xy)
|
|
187
|
+
sage: A[0].display()
|
|
188
|
+
A_0: M → ℝ
|
|
189
|
+
on U: (x, y) ↦ x
|
|
190
|
+
on W: (u, v) ↦ 1/2*u + 1/2*v
|
|
191
|
+
sage: A[1][0] = y*x; A[1].display(e_xy)
|
|
192
|
+
A_1 = x*y dx
|
|
193
|
+
sage: A[2][e_uv,0,1] = u*v^2; A[2].display(e_uv)
|
|
194
|
+
A_2 = u*v^2 du∧dv
|
|
195
|
+
sage: A.add_comp_by_continuation(e_uv, W, c_uv)
|
|
196
|
+
sage: A.display_expansion(e_uv)
|
|
197
|
+
A = 1/2*u + 1/2*v + (1/8*u^2 - 1/8*v^2) du + (1/8*u^2 - 1/8*v^2) dv + u*v^2 du∧dv
|
|
198
|
+
sage: A.add_comp_by_continuation(e_xy, W, c_xy)
|
|
199
|
+
sage: A.display_expansion(e_xy)
|
|
200
|
+
A = x + x*y dx + (-2*x^3 + 2*x^2*y + 2*x*y^2 - 2*y^3) dx∧dy
|
|
201
|
+
|
|
202
|
+
Since zero and one are special elements, their components cannot be
|
|
203
|
+
changed::
|
|
204
|
+
|
|
205
|
+
sage: z = M.mixed_form_algebra().zero()
|
|
206
|
+
sage: z[0] = 1
|
|
207
|
+
Traceback (most recent call last):
|
|
208
|
+
...
|
|
209
|
+
ValueError: the components of an immutable element cannot be changed
|
|
210
|
+
sage: one = M.mixed_form_algebra().one()
|
|
211
|
+
sage: one[0] = 0
|
|
212
|
+
Traceback (most recent call last):
|
|
213
|
+
...
|
|
214
|
+
ValueError: the components of an immutable element cannot be changed
|
|
215
|
+
"""
|
|
216
|
+
def __init__(self, parent, name=None, latex_name=None):
|
|
217
|
+
r"""
|
|
218
|
+
Construct a mixed form.
|
|
219
|
+
|
|
220
|
+
TESTS::
|
|
221
|
+
|
|
222
|
+
sage: M = Manifold(2, 'M')
|
|
223
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
224
|
+
sage: M.declare_union(U,V)
|
|
225
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
226
|
+
sage: transf = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
227
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
228
|
+
....: restrictions2= u+v>0)
|
|
229
|
+
sage: inv = transf.inverse()
|
|
230
|
+
sage: W = U.intersection(V)
|
|
231
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
232
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
233
|
+
sage: omega[e_xy,0] = y*x
|
|
234
|
+
sage: omega.add_comp_by_continuation(e_uv, W, c_uv)
|
|
235
|
+
sage: eta = M.diff_form(2, name='eta')
|
|
236
|
+
sage: eta[e_uv,0,1] = u*v^2
|
|
237
|
+
sage: eta.add_comp_by_continuation(e_xy, W, c_xy)
|
|
238
|
+
sage: A = M.mixed_form_algebra()
|
|
239
|
+
sage: F = A([x, omega, eta], name='F')
|
|
240
|
+
sage: TestSuite(F).run(skip='_test_pickling')
|
|
241
|
+
"""
|
|
242
|
+
if parent is None:
|
|
243
|
+
raise ValueError("a parent must be provided")
|
|
244
|
+
# Add this element (instance) to the set of parent algebra:
|
|
245
|
+
AlgebraElement.__init__(self, parent)
|
|
246
|
+
# Get the underlying vector field module:
|
|
247
|
+
vmodule = parent._vmodule
|
|
248
|
+
# Define attributes:
|
|
249
|
+
self._vmodule = vmodule
|
|
250
|
+
self._dest_map = vmodule._dest_map
|
|
251
|
+
self._domain = vmodule._domain
|
|
252
|
+
self._ambient_domain = vmodule._ambient_domain
|
|
253
|
+
self._max_deg = vmodule._ambient_domain.dim()
|
|
254
|
+
self._is_zero = False # a priori, may be changed below or via
|
|
255
|
+
# method __bool__()
|
|
256
|
+
self._comp = None # initialized on demand; see _init_comp
|
|
257
|
+
# Set names:
|
|
258
|
+
self._name = name
|
|
259
|
+
if latex_name is None:
|
|
260
|
+
self._latex_name = self._name
|
|
261
|
+
else:
|
|
262
|
+
self._latex_name = latex_name
|
|
263
|
+
|
|
264
|
+
def _init_comp(self):
|
|
265
|
+
r"""
|
|
266
|
+
Initialize homogeneous components of ``self``.
|
|
267
|
+
|
|
268
|
+
TESTS::
|
|
269
|
+
|
|
270
|
+
sage: M = Manifold(2, 'M')
|
|
271
|
+
sage: A = M.mixed_form(name='A')
|
|
272
|
+
sage: A._comp is None
|
|
273
|
+
True
|
|
274
|
+
sage: A._init_comp()
|
|
275
|
+
sage: A._comp
|
|
276
|
+
[Scalar field A_0 on the 2-dimensional differentiable manifold M,
|
|
277
|
+
1-form A_1 on the 2-dimensional differentiable manifold M,
|
|
278
|
+
2-form A_2 on the 2-dimensional differentiable manifold M]
|
|
279
|
+
"""
|
|
280
|
+
self._comp = []
|
|
281
|
+
for i in self.irange():
|
|
282
|
+
comp_name, comp_latex_name = None, None
|
|
283
|
+
if self._name is not None:
|
|
284
|
+
comp_name = f"{self._name}_{i}"
|
|
285
|
+
if self._latex_name is not None:
|
|
286
|
+
comp_latex_name = '{' + self._latex_name + '}_{' + str(i) + '}'
|
|
287
|
+
diff_form = self._domain.diff_form
|
|
288
|
+
self._comp.append(diff_form(i, name=comp_name,
|
|
289
|
+
latex_name=comp_latex_name))
|
|
290
|
+
|
|
291
|
+
def _repr_(self):
|
|
292
|
+
r"""
|
|
293
|
+
String representation of ``self``.
|
|
294
|
+
|
|
295
|
+
TESTS::
|
|
296
|
+
|
|
297
|
+
sage: M = Manifold(3, 'M')
|
|
298
|
+
sage: F = M.mixed_form(name='F')
|
|
299
|
+
sage: F._repr_()
|
|
300
|
+
'Mixed differential form F on the 3-dimensional differentiable
|
|
301
|
+
manifold M'
|
|
302
|
+
sage: repr(F) # indirect doctest
|
|
303
|
+
'Mixed differential form F on the 3-dimensional differentiable
|
|
304
|
+
manifold M'
|
|
305
|
+
|
|
306
|
+
Check whether :issue:`31784` is fixed::
|
|
307
|
+
|
|
308
|
+
sage: E3 = EuclideanSpace(3)
|
|
309
|
+
sage: S2 = E3.sphere()
|
|
310
|
+
sage: iota = S2.embedding()
|
|
311
|
+
sage: Omega = S2.mixed_form_algebra(dest_map=iota)
|
|
312
|
+
sage: Omega(1)
|
|
313
|
+
Mixed differential form one along the 2-sphere S^2 of radius 1
|
|
314
|
+
smoothly embedded in the Euclidean space E^3 with values on the
|
|
315
|
+
Euclidean space E^3 via the map iota
|
|
316
|
+
"""
|
|
317
|
+
desc = "Mixed differential form "
|
|
318
|
+
if self._name is not None:
|
|
319
|
+
desc += self._name + " "
|
|
320
|
+
if self._dest_map is self._domain.identity_map():
|
|
321
|
+
desc += f"on the {self._domain}"
|
|
322
|
+
else:
|
|
323
|
+
desc += f"along the {self._domain} with values on the {self._ambient_domain} "
|
|
324
|
+
if self._dest_map._name is None:
|
|
325
|
+
dm_name = "unnamed map"
|
|
326
|
+
else:
|
|
327
|
+
dm_name = self._dest_map._name
|
|
328
|
+
desc += "via the map " + dm_name
|
|
329
|
+
return desc
|
|
330
|
+
|
|
331
|
+
def _latex_(self):
|
|
332
|
+
r"""
|
|
333
|
+
Return a LaTeX representation of the object.
|
|
334
|
+
|
|
335
|
+
TESTS::
|
|
336
|
+
|
|
337
|
+
sage: M = Manifold(3, 'M', latex_name=r'\mathcal{M}')
|
|
338
|
+
sage: omega = M.mixed_form(name='omega', latex_name=r'\omega')
|
|
339
|
+
sage: omega._latex_()
|
|
340
|
+
'\\omega'
|
|
341
|
+
sage: latex(omega) # indirect doctest
|
|
342
|
+
\omega
|
|
343
|
+
"""
|
|
344
|
+
if self._name is None:
|
|
345
|
+
return r'\text{' + repr(self) + r'}'
|
|
346
|
+
else:
|
|
347
|
+
return self._latex_name
|
|
348
|
+
|
|
349
|
+
def _new_instance(self, name=None, latex_name=None):
|
|
350
|
+
r"""
|
|
351
|
+
Return a new instance of ``self``.
|
|
352
|
+
|
|
353
|
+
TESTS::
|
|
354
|
+
|
|
355
|
+
sage: M = Manifold(2, 'M')
|
|
356
|
+
sage: F = M.mixed_form(name='F')
|
|
357
|
+
sage: F1 = F._new_instance(); F1
|
|
358
|
+
Mixed differential form on the 2-dimensional differentiable
|
|
359
|
+
manifold M
|
|
360
|
+
sage: type(F1) == type(F)
|
|
361
|
+
True
|
|
362
|
+
sage: F1.parent() is F.parent()
|
|
363
|
+
True
|
|
364
|
+
"""
|
|
365
|
+
return type(self)(self.parent(), name=name, latex_name=latex_name)
|
|
366
|
+
|
|
367
|
+
def display_expansion(self, frame=None, chart=None, from_chart=None):
|
|
368
|
+
r"""
|
|
369
|
+
Display the expansion in a particular basis and chart of mixed forms.
|
|
370
|
+
|
|
371
|
+
The output is either text-formatted (console mode) or LaTeX-formatted
|
|
372
|
+
(notebook mode).
|
|
373
|
+
|
|
374
|
+
INPUT:
|
|
375
|
+
|
|
376
|
+
- ``frame`` -- (default: ``None``) vector frame with respect to
|
|
377
|
+
which the mixed form is expanded; if ``None``, only the names
|
|
378
|
+
of the components are displayed
|
|
379
|
+
- ``chart`` -- (default: ``None``) chart with respect to which the
|
|
380
|
+
components of the mixed form in the selected frame are expressed;
|
|
381
|
+
if ``None``, the default chart of the vector frame domain is assumed
|
|
382
|
+
|
|
383
|
+
EXAMPLES:
|
|
384
|
+
|
|
385
|
+
Display the expansion of a mixed form on a 2-dimensional
|
|
386
|
+
non-parallelizable differentiable manifold::
|
|
387
|
+
|
|
388
|
+
sage: M = Manifold(2, 'M')
|
|
389
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
390
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
391
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
392
|
+
sage: transf = c_xy.transition_map(c_uv, (x-y, x+y),
|
|
393
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
394
|
+
....: restrictions2= u+v>0)
|
|
395
|
+
sage: inv = transf.inverse()
|
|
396
|
+
sage: W = U.intersection(V)
|
|
397
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
|
|
398
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
399
|
+
sage: omega[e_xy,0] = x; omega.display(e_xy)
|
|
400
|
+
omega = x dx
|
|
401
|
+
sage: omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
|
|
402
|
+
sage: eta = M.diff_form(2, name='eta')
|
|
403
|
+
sage: eta[e_uv,0,1] = u*v; eta.display(e_uv)
|
|
404
|
+
eta = u*v du∧dv
|
|
405
|
+
sage: eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
|
|
406
|
+
sage: F = M.mixed_form([0, omega, eta], name='F'); F
|
|
407
|
+
Mixed differential form F on the 2-dimensional differentiable
|
|
408
|
+
manifold M
|
|
409
|
+
sage: F.display() # display names of homogeneous components
|
|
410
|
+
F = zero + omega + eta
|
|
411
|
+
sage: F.display_expansion(e_uv)
|
|
412
|
+
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
|
|
413
|
+
sage: F.display_expansion(e_xy)
|
|
414
|
+
F = x dx + (2*x^2 - 2*y^2) dx∧dy
|
|
415
|
+
"""
|
|
416
|
+
from sage.misc.latex import latex
|
|
417
|
+
from sage.tensor.modules.format_utilities import FormattedExpansion, is_atomic
|
|
418
|
+
from sage.typeset.unicode_characters import unicode_wedge
|
|
419
|
+
# In case, no frame is given:
|
|
420
|
+
if frame is None:
|
|
421
|
+
frame = self._domain._def_frame
|
|
422
|
+
# In case, no chart is given:
|
|
423
|
+
if chart is None:
|
|
424
|
+
chart = frame._chart
|
|
425
|
+
# Check names:
|
|
426
|
+
if self._name is not None:
|
|
427
|
+
resu_txt = self._name + " = "
|
|
428
|
+
else:
|
|
429
|
+
resu_txt = ""
|
|
430
|
+
if self._latex_name is not None:
|
|
431
|
+
resu_latex = self._latex_name + r" = "
|
|
432
|
+
else:
|
|
433
|
+
resu_latex = ""
|
|
434
|
+
# Get terms
|
|
435
|
+
terms_txt = []
|
|
436
|
+
terms_latex = []
|
|
437
|
+
# Scalar field term:
|
|
438
|
+
if not self[0].is_trivial_zero():
|
|
439
|
+
terms_txt.append(repr(self[0].expr(chart, from_chart)))
|
|
440
|
+
terms_latex.append(latex(self[0].expr(chart, from_chart)))
|
|
441
|
+
# Differential form terms:
|
|
442
|
+
for j in self.irange(1):
|
|
443
|
+
rst = self[j].restrict(frame._domain, dest_map=frame._dest_map)
|
|
444
|
+
basis, format_spec = rst._preparse_display(basis=frame,
|
|
445
|
+
format_spec=chart)
|
|
446
|
+
cobasis = basis.dual_basis()
|
|
447
|
+
comp = rst.comp(basis)
|
|
448
|
+
for ind in comp.non_redundant_index_generator():
|
|
449
|
+
ind_arg = ind + (format_spec,)
|
|
450
|
+
coef = comp[ind_arg]
|
|
451
|
+
# Check whether the coefficient is zero, preferably via
|
|
452
|
+
# the fast method is_trivial_zero():
|
|
453
|
+
if hasattr(coef, 'is_trivial_zero'):
|
|
454
|
+
zero_coef = coef.is_trivial_zero()
|
|
455
|
+
else:
|
|
456
|
+
zero_coef = coef == 0
|
|
457
|
+
if not zero_coef:
|
|
458
|
+
bases_txt = []
|
|
459
|
+
bases_latex = []
|
|
460
|
+
for k in range(rst._tensor_rank):
|
|
461
|
+
bases_txt.append(cobasis[ind[k]]._name)
|
|
462
|
+
bases_latex.append(latex(cobasis[ind[k]]))
|
|
463
|
+
basis_term_txt = unicode_wedge.join(bases_txt)
|
|
464
|
+
basis_term_latex = r"\wedge ".join(bases_latex)
|
|
465
|
+
coef_txt = repr(coef)
|
|
466
|
+
if coef_txt == "1":
|
|
467
|
+
terms_txt.append(basis_term_txt)
|
|
468
|
+
terms_latex.append(basis_term_latex)
|
|
469
|
+
elif coef_txt == "-1":
|
|
470
|
+
terms_txt.append("-" + basis_term_txt)
|
|
471
|
+
terms_latex.append("-" + basis_term_latex)
|
|
472
|
+
else:
|
|
473
|
+
coef_latex = latex(coef)
|
|
474
|
+
if is_atomic(coef_txt):
|
|
475
|
+
terms_txt.append(coef_txt + " " + basis_term_txt)
|
|
476
|
+
else:
|
|
477
|
+
terms_txt.append("(" + coef_txt + ") " +
|
|
478
|
+
basis_term_txt)
|
|
479
|
+
if is_atomic(coef_latex):
|
|
480
|
+
terms_latex.append(coef_latex + basis_term_latex)
|
|
481
|
+
else:
|
|
482
|
+
terms_latex.append(r"\left(" + coef_latex +
|
|
483
|
+
r"\right)" + basis_term_latex)
|
|
484
|
+
if not terms_txt:
|
|
485
|
+
resu_txt += "0"
|
|
486
|
+
else:
|
|
487
|
+
resu_txt += terms_txt[0]
|
|
488
|
+
for term in terms_txt[1:]:
|
|
489
|
+
if term[0] == "-":
|
|
490
|
+
resu_txt += " - " + term[1:]
|
|
491
|
+
else:
|
|
492
|
+
resu_txt += " + " + term
|
|
493
|
+
if not terms_latex:
|
|
494
|
+
resu_latex += "0"
|
|
495
|
+
else:
|
|
496
|
+
resu_latex += terms_latex[0]
|
|
497
|
+
for term in terms_latex[1:]:
|
|
498
|
+
if term[0] == "-":
|
|
499
|
+
resu_latex += term
|
|
500
|
+
else:
|
|
501
|
+
resu_latex += "+" + term
|
|
502
|
+
return FormattedExpansion(resu_txt, resu_latex)
|
|
503
|
+
|
|
504
|
+
disp_exp = display_expansion
|
|
505
|
+
display_exp = display_expansion
|
|
506
|
+
|
|
507
|
+
def display(self):
|
|
508
|
+
r"""
|
|
509
|
+
Display the homogeneous components of the mixed form.
|
|
510
|
+
|
|
511
|
+
The output is either text-formatted (console mode) or LaTeX-formatted
|
|
512
|
+
(notebook mode).
|
|
513
|
+
|
|
514
|
+
EXAMPLES::
|
|
515
|
+
|
|
516
|
+
sage: M = Manifold(2, 'M')
|
|
517
|
+
sage: f = M.scalar_field(name='f')
|
|
518
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
519
|
+
sage: eta = M.diff_form(2, name='eta')
|
|
520
|
+
sage: F = M.mixed_form([f, omega, eta], name='F'); F
|
|
521
|
+
Mixed differential form F on the 2-dimensional differentiable
|
|
522
|
+
manifold M
|
|
523
|
+
sage: F.display() # display names of homogeneous components
|
|
524
|
+
F = f + omega + eta
|
|
525
|
+
"""
|
|
526
|
+
from sage.misc.latex import latex
|
|
527
|
+
from sage.tensor.modules.format_utilities import FormattedExpansion
|
|
528
|
+
# Mixed form name:
|
|
529
|
+
if self._name is not None:
|
|
530
|
+
resu_txt = self._name + " = "
|
|
531
|
+
else:
|
|
532
|
+
resu_txt = ""
|
|
533
|
+
if self._latex_name is not None:
|
|
534
|
+
resu_latex = self._latex_name + r" = "
|
|
535
|
+
else:
|
|
536
|
+
resu_latex = ""
|
|
537
|
+
# Scalar field:
|
|
538
|
+
if self[0]._name is None:
|
|
539
|
+
resu_txt += "(unnamed scalar field) "
|
|
540
|
+
else:
|
|
541
|
+
resu_txt += self[0]._name
|
|
542
|
+
if self[0]._latex_name is None:
|
|
543
|
+
resu_latex += r"\text{(unnamed scalar field)}"
|
|
544
|
+
else:
|
|
545
|
+
resu_latex += latex(self[0])
|
|
546
|
+
# Differential forms:
|
|
547
|
+
for j in self.irange(1):
|
|
548
|
+
if self[j]._name is None:
|
|
549
|
+
resu_txt += " + (unnamed " + str(j) + "-form)"
|
|
550
|
+
else:
|
|
551
|
+
resu_txt += " + " + self[j]._name
|
|
552
|
+
if self[j]._latex_name is None:
|
|
553
|
+
resu_latex += r"+\text{(unnamed " + str(j) + r"-form)}"
|
|
554
|
+
else:
|
|
555
|
+
resu_latex += r"+" + latex(self[j])
|
|
556
|
+
return FormattedExpansion(resu_txt, resu_latex)
|
|
557
|
+
|
|
558
|
+
disp = display
|
|
559
|
+
|
|
560
|
+
def set_name(self, name=None, latex_name=None, apply_to_comp=True):
|
|
561
|
+
r"""
|
|
562
|
+
Redefine the string and LaTeX representation of the object.
|
|
563
|
+
|
|
564
|
+
INPUT:
|
|
565
|
+
|
|
566
|
+
- ``name`` -- (default: ``None``) name given to the mixed form
|
|
567
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
568
|
+
mixed form; if none is provided, the LaTeX symbol is set to ``name``
|
|
569
|
+
- ``apply_to_comp`` -- boolean (default: ``True``); if ``True`` all homogeneous
|
|
570
|
+
components will be renamed accordingly. If ``False`` only the mixed
|
|
571
|
+
form will be renamed
|
|
572
|
+
|
|
573
|
+
EXAMPLES:
|
|
574
|
+
|
|
575
|
+
Rename a mixed form::
|
|
576
|
+
|
|
577
|
+
sage: M = Manifold(4, 'M')
|
|
578
|
+
sage: F = M.mixed_form(name='dummy', latex_name=r'\ugly'); F
|
|
579
|
+
Mixed differential form dummy on the 4-dimensional differentiable
|
|
580
|
+
manifold M
|
|
581
|
+
sage: latex(F)
|
|
582
|
+
\ugly
|
|
583
|
+
sage: F.set_name(name='F', latex_name=r'\mathcal{F}'); F
|
|
584
|
+
Mixed differential form F on the 4-dimensional differentiable
|
|
585
|
+
manifold M
|
|
586
|
+
sage: latex(F)
|
|
587
|
+
\mathcal{F}
|
|
588
|
+
|
|
589
|
+
If not stated otherwise, all homogeneous components are renamed
|
|
590
|
+
accordingly::
|
|
591
|
+
|
|
592
|
+
sage: F.display()
|
|
593
|
+
F = F_0 + F_1 + F_2 + F_3 + F_4
|
|
594
|
+
|
|
595
|
+
Setting the argument ``set_all`` to ``False`` prevents the renaming
|
|
596
|
+
in the homogeneous components::
|
|
597
|
+
|
|
598
|
+
sage: F.set_name(name='eta', latex_name=r'\eta', apply_to_comp=False)
|
|
599
|
+
sage: F.display()
|
|
600
|
+
eta = F_0 + F_1 + F_2 + F_3 + F_4
|
|
601
|
+
|
|
602
|
+
To rename a homogeneous component individually, we simply access the
|
|
603
|
+
homogeneous component and use its
|
|
604
|
+
:meth:`~sage.manifolds.differentiable.tensorfield.set_name` method::
|
|
605
|
+
|
|
606
|
+
sage: F[0].set_name(name='g'); F.display()
|
|
607
|
+
eta = g + F_1 + F_2 + F_3 + F_4
|
|
608
|
+
"""
|
|
609
|
+
if self.is_immutable():
|
|
610
|
+
raise ValueError("the name of an immutable element "
|
|
611
|
+
"cannot be changed")
|
|
612
|
+
if name is not None:
|
|
613
|
+
self._name = name
|
|
614
|
+
if latex_name is None:
|
|
615
|
+
self._latex_name = self._name
|
|
616
|
+
if latex_name is not None:
|
|
617
|
+
self._latex_name = latex_name
|
|
618
|
+
if apply_to_comp:
|
|
619
|
+
for i in self.irange():
|
|
620
|
+
comp_name, comp_latex_name = None, None
|
|
621
|
+
if self._name is not None:
|
|
622
|
+
comp_name = f"{self._name}_{i}"
|
|
623
|
+
if self._latex_name is not None:
|
|
624
|
+
comp_latex_name = '{' + self._latex_name + '}_{' + str(i) + '}'
|
|
625
|
+
self[i].set_name(name=comp_name, latex_name=comp_latex_name)
|
|
626
|
+
|
|
627
|
+
def __bool__(self):
|
|
628
|
+
r"""
|
|
629
|
+
Return ``True`` if ``self`` is nonzero and ``False`` otherwise.
|
|
630
|
+
|
|
631
|
+
This method is called by :meth:`is_zero`.
|
|
632
|
+
|
|
633
|
+
EXAMPLES:
|
|
634
|
+
|
|
635
|
+
Mixed form defined by parts on a 2-dimensional manifold::
|
|
636
|
+
|
|
637
|
+
sage: M = Manifold(2, 'M')
|
|
638
|
+
sage: U = M.open_subset('U')
|
|
639
|
+
sage: c_xy.<x,y> = U.chart()
|
|
640
|
+
sage: V = M.open_subset('V')
|
|
641
|
+
sage: c_uv.<u,v> = V.chart()
|
|
642
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
643
|
+
sage: F = M.mixed_form(name='F')
|
|
644
|
+
sage: FU = U.mixed_form(name='F')
|
|
645
|
+
sage: FV = V.mixed_form(name='F')
|
|
646
|
+
sage: FU[:] = [0,0,0]
|
|
647
|
+
sage: FV[:] = [0,0,0]
|
|
648
|
+
sage: F.set_restriction(FU)
|
|
649
|
+
sage: F.set_restriction(FV)
|
|
650
|
+
sage: bool(F)
|
|
651
|
+
False
|
|
652
|
+
sage: F.is_zero() # indirect doctest
|
|
653
|
+
True
|
|
654
|
+
sage: FU[0] = 1
|
|
655
|
+
sage: F.set_restriction(FU)
|
|
656
|
+
sage: bool(F)
|
|
657
|
+
True
|
|
658
|
+
sage: F.is_zero() # indirect doctest
|
|
659
|
+
False
|
|
660
|
+
"""
|
|
661
|
+
if self._is_zero:
|
|
662
|
+
return False
|
|
663
|
+
if any(bool(form) for form in self):
|
|
664
|
+
self._is_zero = False
|
|
665
|
+
return True
|
|
666
|
+
self._is_zero = True
|
|
667
|
+
return False
|
|
668
|
+
|
|
669
|
+
def _richcmp_(self, other, op):
|
|
670
|
+
r"""
|
|
671
|
+
Comparison method for sage objects.
|
|
672
|
+
|
|
673
|
+
INPUT:
|
|
674
|
+
|
|
675
|
+
- ``other`` -- a mixed form
|
|
676
|
+
- ``op`` -- comparison operator for which ``self`` and ``other`` shall
|
|
677
|
+
be compared with
|
|
678
|
+
|
|
679
|
+
TESTS::
|
|
680
|
+
|
|
681
|
+
sage: M = Manifold(2, 'M')
|
|
682
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
683
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
684
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
685
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
686
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
687
|
+
....: restrictions2= u+v>0)
|
|
688
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
689
|
+
sage: W = U.intersection(V)
|
|
690
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
691
|
+
sage: f = M.scalar_field(x, name='f')
|
|
692
|
+
sage: f.add_expr_by_continuation(c_uv, W)
|
|
693
|
+
sage: eta = M.diff_form(1, name='eta')
|
|
694
|
+
sage: eta[e_xy,0] = x+y
|
|
695
|
+
sage: eta.add_comp_by_continuation(e_uv, W, c_uv)
|
|
696
|
+
sage: F = M.mixed_form([f, eta, 0])
|
|
697
|
+
sage: F == F
|
|
698
|
+
True
|
|
699
|
+
sage: F == F.copy()
|
|
700
|
+
True
|
|
701
|
+
sage: G = M.mixed_form()
|
|
702
|
+
sage: G.set_restriction(F.restrict(U))
|
|
703
|
+
sage: F == G # False since G has not been defined on V
|
|
704
|
+
False
|
|
705
|
+
sage: G.set_restriction(F.restrict(V))
|
|
706
|
+
sage: F == G # ``True`` now
|
|
707
|
+
True
|
|
708
|
+
sage: H = M.mixed_form([f, 0, 0])
|
|
709
|
+
sage: F != H # this is fixed by issue #30108
|
|
710
|
+
True
|
|
711
|
+
sage: F.parent().zero() == 0
|
|
712
|
+
True
|
|
713
|
+
"""
|
|
714
|
+
from sage.structure.richcmp import op_EQ, op_NE
|
|
715
|
+
if op == op_NE:
|
|
716
|
+
return not self == other
|
|
717
|
+
elif op == op_EQ:
|
|
718
|
+
# Compare all elements separately:
|
|
719
|
+
return all(self[j] == other[j] for j in self.irange())
|
|
720
|
+
# Fall back on default implementation:
|
|
721
|
+
return super()._richcmp_(self, other, op)
|
|
722
|
+
|
|
723
|
+
def _add_(self, other):
|
|
724
|
+
r"""
|
|
725
|
+
Addition of two mixed forms.
|
|
726
|
+
|
|
727
|
+
INPUT:
|
|
728
|
+
|
|
729
|
+
- ``other`` -- a mixed form, in the same algebra as ``self``
|
|
730
|
+
|
|
731
|
+
OUTPUT:
|
|
732
|
+
|
|
733
|
+
- the mixed form resulting from the addition of ``self``
|
|
734
|
+
and ``other``
|
|
735
|
+
|
|
736
|
+
TESTS::
|
|
737
|
+
|
|
738
|
+
sage: M = Manifold(2, 'M')
|
|
739
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
740
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
741
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
742
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
743
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
744
|
+
....: restrictions2= u+v>0)
|
|
745
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
746
|
+
sage: W = U.intersection(V)
|
|
747
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
748
|
+
sage: f = M.scalar_field(x, name='f')
|
|
749
|
+
sage: f.add_expr_by_continuation(c_uv, W) # continuation onto M
|
|
750
|
+
sage: a = M.diff_form(1, name='a')
|
|
751
|
+
sage: a[e_xy,0] = x
|
|
752
|
+
sage: a.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
|
|
753
|
+
sage: A = M.mixed_form([f, a, 0], name='A')
|
|
754
|
+
sage: g = M.scalar_field(u, name='g', chart=c_uv)
|
|
755
|
+
sage: g.add_expr_by_continuation(c_xy, W) # continuation onto M
|
|
756
|
+
sage: b = M.diff_form(1, name='b')
|
|
757
|
+
sage: b[e_uv,1] = v
|
|
758
|
+
sage: b.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
|
|
759
|
+
sage: B = M.mixed_form([g, b, 0], name='B')
|
|
760
|
+
sage: C = A._add_(B); C
|
|
761
|
+
Mixed differential form A+B on the 2-dimensional differentiable
|
|
762
|
+
manifold M
|
|
763
|
+
sage: A.display_expansion(e_uv)
|
|
764
|
+
A = 1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
|
|
765
|
+
sage: B.display_expansion(e_xy)
|
|
766
|
+
B = x + y + (x - y) dx + (-x + y) dy
|
|
767
|
+
sage: C.display_expansion(e_xy)
|
|
768
|
+
A+B = 2*x + y + (2*x - y) dx + (-x + y) dy
|
|
769
|
+
sage: C.display_expansion(e_uv)
|
|
770
|
+
A+B = 3/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 5/4*v) dv
|
|
771
|
+
sage: C == A + B # indirect doctest
|
|
772
|
+
True
|
|
773
|
+
sage: Z = A.parent().zero(); Z
|
|
774
|
+
Mixed differential form zero on the 2-dimensional differentiable
|
|
775
|
+
manifold M
|
|
776
|
+
sage: A._add_(Z) == A
|
|
777
|
+
True
|
|
778
|
+
sage: Z._add_(A) == A
|
|
779
|
+
True
|
|
780
|
+
"""
|
|
781
|
+
# Case zero:
|
|
782
|
+
if self._is_zero:
|
|
783
|
+
return other
|
|
784
|
+
if other._is_zero:
|
|
785
|
+
return self
|
|
786
|
+
# Generic case:
|
|
787
|
+
resu = self._new_instance()
|
|
788
|
+
resu._comp = [self[j] + other[j] for j in self.irange()]
|
|
789
|
+
# Compose name:
|
|
790
|
+
if self._name is not None and other._name is not None:
|
|
791
|
+
resu._name = self._name + '+' + other._name
|
|
792
|
+
if self._latex_name is not None and other._latex_name is not None:
|
|
793
|
+
resu._latex_name = self._latex_name + '+' + other._latex_name
|
|
794
|
+
return resu
|
|
795
|
+
|
|
796
|
+
def _sub_(self, other):
|
|
797
|
+
r"""
|
|
798
|
+
Subtraction of two mixed forms.
|
|
799
|
+
|
|
800
|
+
INPUT:
|
|
801
|
+
|
|
802
|
+
- ``other`` -- a mixed form, in the same algebra as ``self``
|
|
803
|
+
|
|
804
|
+
OUTPUT:
|
|
805
|
+
|
|
806
|
+
- the mixed form resulting from the subtraction of ``self``
|
|
807
|
+
and ``other``
|
|
808
|
+
|
|
809
|
+
TESTS::
|
|
810
|
+
|
|
811
|
+
sage: M = Manifold(2, 'M')
|
|
812
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
813
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
814
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
815
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
816
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
817
|
+
....: restrictions2= u+v>0)
|
|
818
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
819
|
+
sage: W = U.intersection(V)
|
|
820
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
821
|
+
sage: f = M.scalar_field(x, name='f')
|
|
822
|
+
sage: f.add_expr_by_continuation(c_uv, W) # continuation onto M
|
|
823
|
+
sage: a = M.diff_form(1, name='a')
|
|
824
|
+
sage: a[e_xy,0] = x
|
|
825
|
+
sage: a.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
|
|
826
|
+
sage: A = M.mixed_form([f, a, 0], name='A')
|
|
827
|
+
sage: g = M.scalar_field(u, name='g', chart=c_uv)
|
|
828
|
+
sage: g.add_expr_by_continuation(c_xy, W) # continuation onto M
|
|
829
|
+
sage: b = M.diff_form(1, name='b')
|
|
830
|
+
sage: b[e_uv,1] = v
|
|
831
|
+
sage: b.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
|
|
832
|
+
sage: B = M.mixed_form([g, b, 0], name='B')
|
|
833
|
+
sage: C = A._sub_(B); C
|
|
834
|
+
Mixed differential form A-B on the 2-dimensional differentiable
|
|
835
|
+
manifold M
|
|
836
|
+
sage: A.display_expansion(e_uv)
|
|
837
|
+
A = 1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
|
|
838
|
+
sage: B.display_expansion(e_xy)
|
|
839
|
+
B = x + y + (x - y) dx + (-x + y) dy
|
|
840
|
+
sage: C.display_expansion(e_xy)
|
|
841
|
+
A-B = -y + y dx + (x - y) dy
|
|
842
|
+
sage: C.display_expansion(e_uv)
|
|
843
|
+
A-B = -1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u - 3/4*v) dv
|
|
844
|
+
sage: C == A - B # indirect doctest
|
|
845
|
+
True
|
|
846
|
+
sage: Z = A.parent().zero(); Z
|
|
847
|
+
Mixed differential form zero on the 2-dimensional differentiable
|
|
848
|
+
manifold M
|
|
849
|
+
sage: A._sub_(Z) == A
|
|
850
|
+
True
|
|
851
|
+
sage: Z._sub_(A) == -A
|
|
852
|
+
True
|
|
853
|
+
"""
|
|
854
|
+
# Case zero:
|
|
855
|
+
if self._is_zero:
|
|
856
|
+
return -other
|
|
857
|
+
if other._is_zero:
|
|
858
|
+
return self
|
|
859
|
+
# Generic case:
|
|
860
|
+
resu = self._new_instance()
|
|
861
|
+
resu._comp = [self[j] - other[j] for j in self.irange()]
|
|
862
|
+
# Compose name:
|
|
863
|
+
from sage.tensor.modules.format_utilities import is_atomic
|
|
864
|
+
|
|
865
|
+
if self._name is not None and other._name is not None:
|
|
866
|
+
sname = self._name
|
|
867
|
+
oname = other._name
|
|
868
|
+
if not is_atomic(oname):
|
|
869
|
+
oname = '(' + oname + ')'
|
|
870
|
+
resu._name = sname + '-' + oname
|
|
871
|
+
if self._latex_name is not None and other._latex_name is not None:
|
|
872
|
+
slname = self._latex_name
|
|
873
|
+
olname = other._latex_name
|
|
874
|
+
if not is_atomic(olname):
|
|
875
|
+
olname = '(' + olname + ')'
|
|
876
|
+
resu._latex_name = slname + '-' + olname
|
|
877
|
+
return resu
|
|
878
|
+
|
|
879
|
+
def wedge(self, other):
|
|
880
|
+
r"""
|
|
881
|
+
Wedge product on the graded algebra of mixed forms.
|
|
882
|
+
|
|
883
|
+
More precisely, the wedge product is a bilinear map
|
|
884
|
+
|
|
885
|
+
.. MATH::
|
|
886
|
+
|
|
887
|
+
\wedge: \Omega^k(M,\varphi) \times \Omega^l(M,\varphi) \to \Omega^{k+l}(M,\varphi),
|
|
888
|
+
|
|
889
|
+
where `\Omega^k(M,\varphi)` denotes the space of differential forms of
|
|
890
|
+
degree `k` along `\varphi`. By bilinear extension, this induces a map
|
|
891
|
+
|
|
892
|
+
.. MATH::
|
|
893
|
+
|
|
894
|
+
\wedge: \Omega^*(M,\varphi) \times \Omega^*(M,\varphi) \to \Omega^*(M,\varphi) ``
|
|
895
|
+
|
|
896
|
+
and equips `\Omega^*(M,\varphi)` with a multiplication such that it
|
|
897
|
+
becomes a graded algebra.
|
|
898
|
+
|
|
899
|
+
INPUT:
|
|
900
|
+
|
|
901
|
+
- ``other`` -- mixed form in the same algebra as ``self``
|
|
902
|
+
|
|
903
|
+
OUTPUT:
|
|
904
|
+
|
|
905
|
+
- the mixed form resulting from the wedge product of ``self``
|
|
906
|
+
with ``other``
|
|
907
|
+
|
|
908
|
+
EXAMPLES:
|
|
909
|
+
|
|
910
|
+
Initialize a mixed form on a 3-dimensional manifold::
|
|
911
|
+
|
|
912
|
+
sage: M = Manifold(3, 'M')
|
|
913
|
+
sage: c_xyz.<x,y,z> = M.chart()
|
|
914
|
+
sage: f = M.scalar_field(x, name='f')
|
|
915
|
+
sage: f.display()
|
|
916
|
+
f: M → ℝ
|
|
917
|
+
(x, y, z) ↦ x
|
|
918
|
+
sage: g = M.scalar_field(y, name='g')
|
|
919
|
+
sage: g.display()
|
|
920
|
+
g: M → ℝ
|
|
921
|
+
(x, y, z) ↦ y
|
|
922
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
923
|
+
sage: omega[0] = x
|
|
924
|
+
sage: omega.display()
|
|
925
|
+
omega = x dx
|
|
926
|
+
sage: eta = M.diff_form(1, name='eta')
|
|
927
|
+
sage: eta[1] = y
|
|
928
|
+
sage: eta.display()
|
|
929
|
+
eta = y dy
|
|
930
|
+
sage: mu = M.diff_form(2, name='mu')
|
|
931
|
+
sage: mu[0,2] = z
|
|
932
|
+
sage: mu.display()
|
|
933
|
+
mu = z dx∧dz
|
|
934
|
+
sage: A = M.mixed_form([f, omega, mu, 0], name='A')
|
|
935
|
+
sage: A.display_expansion()
|
|
936
|
+
A = x + x dx + z dx∧dz
|
|
937
|
+
sage: B = M.mixed_form([g, eta, mu, 0], name='B')
|
|
938
|
+
sage: B.display_expansion()
|
|
939
|
+
B = y + y dy + z dx∧dz
|
|
940
|
+
|
|
941
|
+
The wedge product of ``A`` and ``B`` yields::
|
|
942
|
+
|
|
943
|
+
sage: C = A.wedge(B); C
|
|
944
|
+
Mixed differential form A∧B on the 3-dimensional differentiable
|
|
945
|
+
manifold M
|
|
946
|
+
sage: C.display_expansion()
|
|
947
|
+
A∧B = x*y + x*y dx + x*y dy + x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
|
|
948
|
+
sage: D = B.wedge(A); D # Don't even try, it's not commutative!
|
|
949
|
+
Mixed differential form B∧A on the 3-dimensional differentiable
|
|
950
|
+
manifold M
|
|
951
|
+
sage: D.display_expansion() # I told you so!
|
|
952
|
+
B∧A = x*y + x*y dx + x*y dy - x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
|
|
953
|
+
|
|
954
|
+
Alternatively, the multiplication symbol can be used::
|
|
955
|
+
|
|
956
|
+
sage: A*B
|
|
957
|
+
Mixed differential form A∧B on the 3-dimensional differentiable
|
|
958
|
+
manifold M
|
|
959
|
+
sage: A*B == C
|
|
960
|
+
True
|
|
961
|
+
|
|
962
|
+
Yet, the multiplication includes coercions::
|
|
963
|
+
|
|
964
|
+
sage: E = x*A; E.display_expansion()
|
|
965
|
+
x∧A = x^2 + x^2 dx + x*z dx∧dz
|
|
966
|
+
sage: F = A*eta; F.display_expansion()
|
|
967
|
+
A∧eta = x*y dy + x*y dx∧dy - y*z dx∧dy∧dz
|
|
968
|
+
"""
|
|
969
|
+
# Case zero:
|
|
970
|
+
if self._is_zero or other._is_zero:
|
|
971
|
+
return self.parent().zero()
|
|
972
|
+
# Case one:
|
|
973
|
+
if self is self.parent().one():
|
|
974
|
+
return other
|
|
975
|
+
if other is self.parent().one():
|
|
976
|
+
return self
|
|
977
|
+
# Generic case:
|
|
978
|
+
resu = self._new_instance()
|
|
979
|
+
resu._comp = [sum(self[k].wedge(other[j - k]) for k in range(j + 1))
|
|
980
|
+
for j in self.irange()]
|
|
981
|
+
# Compose name:
|
|
982
|
+
from sage.tensor.modules.format_utilities import (
|
|
983
|
+
format_mul_latex,
|
|
984
|
+
format_mul_txt,
|
|
985
|
+
)
|
|
986
|
+
from sage.typeset.unicode_characters import unicode_wedge
|
|
987
|
+
resu._name = format_mul_txt(self._name, unicode_wedge, other._name)
|
|
988
|
+
resu._latex_name = format_mul_latex(self._latex_name, r'\wedge ',
|
|
989
|
+
other._latex_name)
|
|
990
|
+
return resu
|
|
991
|
+
|
|
992
|
+
_mul_ = wedge
|
|
993
|
+
|
|
994
|
+
def _lmul_(self, other):
|
|
995
|
+
r"""
|
|
996
|
+
Scalar multiplication operator: return ``number * self`` or
|
|
997
|
+
``self * number``.
|
|
998
|
+
|
|
999
|
+
INPUT:
|
|
1000
|
+
|
|
1001
|
+
- ``other`` -- an element of the symbolic ring
|
|
1002
|
+
|
|
1003
|
+
OUTPUT:
|
|
1004
|
+
|
|
1005
|
+
- the mixed form resulting from the wedge product of ``self``
|
|
1006
|
+
with ``other``
|
|
1007
|
+
|
|
1008
|
+
TESTS::
|
|
1009
|
+
|
|
1010
|
+
sage: M = Manifold(2, 'M')
|
|
1011
|
+
sage: c_xy.<x,y> = M.chart()
|
|
1012
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
1013
|
+
sage: omega[0] = y*x; omega.display()
|
|
1014
|
+
omega = x*y dx
|
|
1015
|
+
sage: F = M.mixed_form([0, omega, 0], name='F')
|
|
1016
|
+
sage: A = x*F*y; A
|
|
1017
|
+
Mixed differential form y∧(x∧F) on the 2-dimensional
|
|
1018
|
+
differentiable manifold M
|
|
1019
|
+
sage: A.display_expansion()
|
|
1020
|
+
y∧(x∧F) = x^2*y^2 dx
|
|
1021
|
+
"""
|
|
1022
|
+
try:
|
|
1023
|
+
if other.is_trivial_zero():
|
|
1024
|
+
return self.parent().zero()
|
|
1025
|
+
if (other - 1).is_trivial_zero():
|
|
1026
|
+
return self
|
|
1027
|
+
except AttributeError:
|
|
1028
|
+
# in case base ring is not SR:
|
|
1029
|
+
if other == 0:
|
|
1030
|
+
return self.parent().zero()
|
|
1031
|
+
if other == 1:
|
|
1032
|
+
return self
|
|
1033
|
+
resu = self._new_instance()
|
|
1034
|
+
resu._comp = [other * form for form in self]
|
|
1035
|
+
# Compose name:
|
|
1036
|
+
from sage.misc.latex import latex
|
|
1037
|
+
from sage.tensor.modules.format_utilities import (
|
|
1038
|
+
format_mul_latex,
|
|
1039
|
+
format_mul_txt,
|
|
1040
|
+
)
|
|
1041
|
+
from sage.typeset.unicode_characters import unicode_wedge
|
|
1042
|
+
resu._name = format_mul_txt(repr(other), unicode_wedge, self._name)
|
|
1043
|
+
resu._latex_name = format_mul_latex(latex(other), r'\wedge ',
|
|
1044
|
+
self._latex_name)
|
|
1045
|
+
return resu
|
|
1046
|
+
|
|
1047
|
+
@cached_method
|
|
1048
|
+
def exterior_derivative(self):
|
|
1049
|
+
r"""
|
|
1050
|
+
Compute the exterior derivative of ``self``.
|
|
1051
|
+
|
|
1052
|
+
More precisely, the *exterior derivative* on `\Omega^k(M,\varphi)` is a
|
|
1053
|
+
linear map
|
|
1054
|
+
|
|
1055
|
+
.. MATH::
|
|
1056
|
+
|
|
1057
|
+
\mathrm{d}_{k} : \Omega^k(M,\varphi) \to \Omega^{k+1}(M,\varphi),
|
|
1058
|
+
|
|
1059
|
+
where `\Omega^k(M,\varphi)` denotes the space of differential forms of
|
|
1060
|
+
degree `k` along `\varphi`
|
|
1061
|
+
(see :meth:`~sage.manifolds.differentiable.diff_form.DiffForm.exterior_derivative`
|
|
1062
|
+
for further information). By linear extension, this induces a map on
|
|
1063
|
+
`\Omega^*(M,\varphi)`:
|
|
1064
|
+
|
|
1065
|
+
.. MATH::
|
|
1066
|
+
|
|
1067
|
+
\mathrm{d}: \Omega^*(M,\varphi) \to \Omega^*(M,\varphi).
|
|
1068
|
+
|
|
1069
|
+
OUTPUT:
|
|
1070
|
+
|
|
1071
|
+
- a :class:`MixedForm` representing the exterior
|
|
1072
|
+
derivative of the mixed form
|
|
1073
|
+
|
|
1074
|
+
EXAMPLES:
|
|
1075
|
+
|
|
1076
|
+
Exterior derivative of a mixed form on a 3-dimensional manifold::
|
|
1077
|
+
|
|
1078
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
1079
|
+
sage: c_xyz.<x,y,z> = M.chart()
|
|
1080
|
+
sage: f = M.scalar_field(z^2, name='f')
|
|
1081
|
+
sage: f.disp()
|
|
1082
|
+
f: M → ℝ
|
|
1083
|
+
(x, y, z) ↦ z^2
|
|
1084
|
+
sage: a = M.diff_form(2, 'a')
|
|
1085
|
+
sage: a[1,2], a[1,3], a[2,3] = z+y^2, z+x, x^2
|
|
1086
|
+
sage: a.disp()
|
|
1087
|
+
a = (y^2 + z) dx∧dy + (x + z) dx∧dz + x^2 dy∧dz
|
|
1088
|
+
sage: F = M.mixed_form([f, 0, a, 0], name='F'); F.display()
|
|
1089
|
+
F = f + zero + a + zero
|
|
1090
|
+
sage: dF = F.exterior_derivative()
|
|
1091
|
+
sage: dF.display()
|
|
1092
|
+
dF = zero + df + dzero + da
|
|
1093
|
+
sage: dF = F.exterior_derivative()
|
|
1094
|
+
sage: dF.display_expansion()
|
|
1095
|
+
dF = 2*z dz + (2*x + 1) dx∧dy∧dz
|
|
1096
|
+
|
|
1097
|
+
Due to long calculation times, the result is cached::
|
|
1098
|
+
|
|
1099
|
+
sage: F.exterior_derivative() is dF
|
|
1100
|
+
True
|
|
1101
|
+
"""
|
|
1102
|
+
resu = self._new_instance()
|
|
1103
|
+
resu[0] = self._domain.zero_scalar_field()
|
|
1104
|
+
resu[1:] = [self[j].exterior_derivative()
|
|
1105
|
+
for j in range(self._max_deg)]
|
|
1106
|
+
# Compose name:
|
|
1107
|
+
from sage.tensor.modules.format_utilities import (
|
|
1108
|
+
format_unop_latex,
|
|
1109
|
+
format_unop_txt,
|
|
1110
|
+
)
|
|
1111
|
+
resu._name = format_unop_txt('d', self._name)
|
|
1112
|
+
resu._latex_name = format_unop_latex(r'\mathrm{d}', self._latex_name)
|
|
1113
|
+
return resu
|
|
1114
|
+
|
|
1115
|
+
derivative = exterior_derivative
|
|
1116
|
+
|
|
1117
|
+
def copy(self, name=None, latex_name=None):
|
|
1118
|
+
r"""
|
|
1119
|
+
Return an exact copy of ``self``.
|
|
1120
|
+
|
|
1121
|
+
.. NOTE::
|
|
1122
|
+
|
|
1123
|
+
The name and names of the components are not copied.
|
|
1124
|
+
|
|
1125
|
+
INPUT:
|
|
1126
|
+
|
|
1127
|
+
- ``name`` -- (default: ``None``) name given to the copy
|
|
1128
|
+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
|
|
1129
|
+
copy; if none is provided, the LaTeX symbol is set to ``name``
|
|
1130
|
+
|
|
1131
|
+
EXAMPLES:
|
|
1132
|
+
|
|
1133
|
+
Initialize a 2-dimensional manifold and differential forms::
|
|
1134
|
+
|
|
1135
|
+
sage: M = Manifold(2, 'M')
|
|
1136
|
+
sage: U = M.open_subset('U') ; V = M.open_subset('V')
|
|
1137
|
+
sage: M.declare_union(U,V) # M is the union of U and V
|
|
1138
|
+
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
|
|
1139
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
|
|
1140
|
+
....: intersection_name='W', restrictions1= x>0,
|
|
1141
|
+
....: restrictions2= u+v>0)
|
|
1142
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
1143
|
+
sage: W = U.intersection(V)
|
|
1144
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
1145
|
+
sage: f = M.scalar_field(x, name='f', chart=c_xy)
|
|
1146
|
+
sage: f.add_expr_by_continuation(c_uv, W)
|
|
1147
|
+
sage: f.display()
|
|
1148
|
+
f: M → ℝ
|
|
1149
|
+
on U: (x, y) ↦ x
|
|
1150
|
+
on V: (u, v) ↦ 1/2*u + 1/2*v
|
|
1151
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
1152
|
+
sage: omega[e_xy,0] = x
|
|
1153
|
+
sage: omega.add_comp_by_continuation(e_uv, W, c_uv)
|
|
1154
|
+
sage: omega.display()
|
|
1155
|
+
omega = x dx
|
|
1156
|
+
sage: A = M.mixed_form([f, omega, 0], name='A'); A.display()
|
|
1157
|
+
A = f + omega + zero
|
|
1158
|
+
sage: A.display_expansion(e_uv)
|
|
1159
|
+
A = 1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
|
|
1160
|
+
|
|
1161
|
+
An exact copy is made. The copy is an entirely new instance and has a
|
|
1162
|
+
different name, but has the very same values::
|
|
1163
|
+
|
|
1164
|
+
sage: B = A.copy(); B.display()
|
|
1165
|
+
(unnamed scalar field) + (unnamed 1-form) + (unnamed 2-form)
|
|
1166
|
+
sage: B.display_expansion(e_uv)
|
|
1167
|
+
1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
|
|
1168
|
+
sage: A == B
|
|
1169
|
+
True
|
|
1170
|
+
sage: A is B
|
|
1171
|
+
False
|
|
1172
|
+
"""
|
|
1173
|
+
resu = self._new_instance()
|
|
1174
|
+
resu._comp = [form.copy() for form in self]
|
|
1175
|
+
resu.set_name(name=name, latex_name=latex_name)
|
|
1176
|
+
resu._is_zero = self._is_zero # a priori
|
|
1177
|
+
|
|
1178
|
+
return resu
|
|
1179
|
+
|
|
1180
|
+
def __setitem__(self, index, values):
|
|
1181
|
+
r"""
|
|
1182
|
+
Set a component with respect to some vector frame.
|
|
1183
|
+
|
|
1184
|
+
- ``index`` -- list of indices; if ``[:]`` is provided, all the
|
|
1185
|
+
components are set
|
|
1186
|
+
- ``values`` -- the values to be set
|
|
1187
|
+
|
|
1188
|
+
TESTS::
|
|
1189
|
+
|
|
1190
|
+
sage: M = Manifold(2, 'M')
|
|
1191
|
+
sage: c_xy.<x,y> = M.chart()
|
|
1192
|
+
sage: f = M.scalar_field(x, name='f')
|
|
1193
|
+
sage: a = M.diff_form(1, name='a')
|
|
1194
|
+
sage: a[0] = y
|
|
1195
|
+
sage: b = M.diff_form(2, name='b')
|
|
1196
|
+
sage: b[0,1] = x*y
|
|
1197
|
+
sage: A = M.mixed_form([f, 0, 0], name='A'); A.display()
|
|
1198
|
+
A = f + zero + zero
|
|
1199
|
+
sage: A[1:3] = [a, b]; A.display()
|
|
1200
|
+
A = f + a + b
|
|
1201
|
+
sage: A.display_expansion()
|
|
1202
|
+
A = x + y dx + x*y dx∧dy
|
|
1203
|
+
"""
|
|
1204
|
+
if self.is_immutable():
|
|
1205
|
+
raise ValueError("the components of an immutable element "
|
|
1206
|
+
"cannot be changed")
|
|
1207
|
+
if isinstance(index, (int, Integer)):
|
|
1208
|
+
start, stop, step = index, index + 1, 1
|
|
1209
|
+
elif isinstance(index, slice):
|
|
1210
|
+
start, stop, step = index.indices(self._max_deg + 1)
|
|
1211
|
+
else:
|
|
1212
|
+
raise TypeError("index must be int, Integer or slice")
|
|
1213
|
+
if isinstance(values, list):
|
|
1214
|
+
form_list = values
|
|
1215
|
+
else:
|
|
1216
|
+
form_list = [values]
|
|
1217
|
+
if len(form_list) != len(range(start, stop, step)):
|
|
1218
|
+
raise IndexError("either input or index out of range")
|
|
1219
|
+
for deg, j in zip(range(start, stop, step), range(len(form_list))):
|
|
1220
|
+
dmodule = self._domain.diff_form_module(deg, self._dest_map)
|
|
1221
|
+
form = dmodule(form_list[j])
|
|
1222
|
+
self[deg].copy_from(form) # keep the names
|
|
1223
|
+
self[deg].set_name(name=form._name, latex_name=form._latex_name)
|
|
1224
|
+
self._is_zero = False # a priori
|
|
1225
|
+
|
|
1226
|
+
def __getitem__(self, deg):
|
|
1227
|
+
r"""
|
|
1228
|
+
Return a component with respect to some frame.
|
|
1229
|
+
|
|
1230
|
+
INPUT:
|
|
1231
|
+
|
|
1232
|
+
- ``deg`` -- slice of which degrees shall be returned
|
|
1233
|
+
|
|
1234
|
+
TESTS::
|
|
1235
|
+
|
|
1236
|
+
sage: M = Manifold(2, 'M')
|
|
1237
|
+
sage: c_xy.<x,y> = M.chart()
|
|
1238
|
+
sage: f = M.scalar_field(name='f')
|
|
1239
|
+
sage: a = M.diff_form(1, name='a')
|
|
1240
|
+
sage: b = M.diff_form(2, name='b')
|
|
1241
|
+
sage: A = M.mixed_form([f, a, b], name='A'); A.display()
|
|
1242
|
+
A = f + a + b
|
|
1243
|
+
sage: A.__getitem__(0)
|
|
1244
|
+
Scalar field f on the 2-dimensional differentiable manifold M
|
|
1245
|
+
sage: A.__getitem__(1)
|
|
1246
|
+
1-form a on the 2-dimensional differentiable manifold M
|
|
1247
|
+
sage: A.__getitem__(2)
|
|
1248
|
+
2-form b on the 2-dimensional differentiable manifold M
|
|
1249
|
+
sage: A.__getitem__(slice(0,3,1))
|
|
1250
|
+
[Scalar field f on the 2-dimensional differentiable manifold M,
|
|
1251
|
+
1-form a on the 2-dimensional differentiable manifold M,
|
|
1252
|
+
2-form b on the 2-dimensional differentiable manifold M]
|
|
1253
|
+
"""
|
|
1254
|
+
if self._comp is None:
|
|
1255
|
+
self._init_comp()
|
|
1256
|
+
return self._comp[deg]
|
|
1257
|
+
|
|
1258
|
+
def set_restriction(self, rst):
|
|
1259
|
+
r"""
|
|
1260
|
+
Set a (component-wise) restriction of ``self`` to some subdomain.
|
|
1261
|
+
|
|
1262
|
+
INPUT:
|
|
1263
|
+
|
|
1264
|
+
- ``rst`` -- :class:`MixedForm` of the same type as ``self``, defined on
|
|
1265
|
+
a subdomain of the domain of ``self``
|
|
1266
|
+
|
|
1267
|
+
EXAMPLES:
|
|
1268
|
+
|
|
1269
|
+
Initialize the 2-sphere::
|
|
1270
|
+
|
|
1271
|
+
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
|
|
1272
|
+
sage: U = M.open_subset('U') # complement of the North pole
|
|
1273
|
+
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
|
|
1274
|
+
sage: V = M.open_subset('V') # complement of the South pole
|
|
1275
|
+
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
|
|
1276
|
+
sage: M.declare_union(U,V) # S^2 is the union of U and V
|
|
1277
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
1278
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
1279
|
+
....: restrictions2= u^2+v^2!=0)
|
|
1280
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
1281
|
+
sage: W = U.intersection(V)
|
|
1282
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
1283
|
+
|
|
1284
|
+
And define some forms on the subset ``U``::
|
|
1285
|
+
|
|
1286
|
+
sage: f = U.scalar_field(x, name='f', chart=c_xy)
|
|
1287
|
+
sage: omega = U.diff_form(1, name='omega')
|
|
1288
|
+
sage: omega[e_xy,0] = y
|
|
1289
|
+
sage: AU = U.mixed_form([f, omega, 0], name='A'); AU
|
|
1290
|
+
Mixed differential form A on the Open subset U of the 2-dimensional
|
|
1291
|
+
differentiable manifold M
|
|
1292
|
+
sage: AU.display_expansion(e_xy)
|
|
1293
|
+
A = x + y dx
|
|
1294
|
+
|
|
1295
|
+
A mixed form on ``M`` can be specified by some mixed form on a subset::
|
|
1296
|
+
|
|
1297
|
+
sage: A = M.mixed_form(name='A'); A
|
|
1298
|
+
Mixed differential form A on the 2-dimensional differentiable
|
|
1299
|
+
manifold M
|
|
1300
|
+
sage: A.set_restriction(AU)
|
|
1301
|
+
sage: A.display_expansion(e_xy)
|
|
1302
|
+
A = x + y dx
|
|
1303
|
+
sage: A.add_comp_by_continuation(e_uv, W, c_uv)
|
|
1304
|
+
sage: A.display_expansion(e_uv)
|
|
1305
|
+
A = u/(u^2 + v^2) - (u^2*v - v^3)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u*v^2/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv
|
|
1306
|
+
sage: A.restrict(U) == AU
|
|
1307
|
+
True
|
|
1308
|
+
"""
|
|
1309
|
+
if not isinstance(rst, MixedForm):
|
|
1310
|
+
raise TypeError("the argument must be a mixed form")
|
|
1311
|
+
if not rst._domain.is_subset(self._domain):
|
|
1312
|
+
raise ValueError("the specified domain is not a subset of "
|
|
1313
|
+
"the domain of definition of the mixed form")
|
|
1314
|
+
for j in self.irange():
|
|
1315
|
+
self[j].set_restriction(rst[j])
|
|
1316
|
+
self._is_zero = False # a priori
|
|
1317
|
+
|
|
1318
|
+
def restrict(self, subdomain, dest_map=None):
|
|
1319
|
+
r"""
|
|
1320
|
+
Return the restriction of ``self`` to some subdomain.
|
|
1321
|
+
|
|
1322
|
+
INPUT:
|
|
1323
|
+
|
|
1324
|
+
- ``subdomain`` --
|
|
1325
|
+
:class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`;
|
|
1326
|
+
open subset `U` of the domain of ``self``
|
|
1327
|
+
- ``dest_map`` --
|
|
1328
|
+
:class:`~sage.manifolds.differentiable.diff_map.DiffMap`
|
|
1329
|
+
(default: ``None``); destination map `\Psi:\ U \rightarrow V`,
|
|
1330
|
+
where `V` is an open subset of the manifold `N` where the mixed form
|
|
1331
|
+
takes it values; if ``None``, the restriction of `\Phi` to `U` is
|
|
1332
|
+
used, `\Phi` being the differentiable map `S \rightarrow M` associated
|
|
1333
|
+
with the mixed form
|
|
1334
|
+
|
|
1335
|
+
OUTPUT: :class:`MixedForm` representing the restriction
|
|
1336
|
+
|
|
1337
|
+
EXAMPLES:
|
|
1338
|
+
|
|
1339
|
+
Initialize the 2-sphere::
|
|
1340
|
+
|
|
1341
|
+
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
|
|
1342
|
+
sage: U = M.open_subset('U') # complement of the North pole
|
|
1343
|
+
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
|
|
1344
|
+
sage: V = M.open_subset('V') # complement of the South pole
|
|
1345
|
+
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
|
|
1346
|
+
sage: M.declare_union(U,V) # S^2 is the union of U and V
|
|
1347
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
1348
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
1349
|
+
....: restrictions2= u^2+v^2!=0)
|
|
1350
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
1351
|
+
sage: W = U.intersection(V)
|
|
1352
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
1353
|
+
|
|
1354
|
+
And predefine some forms::
|
|
1355
|
+
|
|
1356
|
+
sage: f = M.scalar_field(x^2, name='f', chart=c_xy)
|
|
1357
|
+
sage: f.add_expr_by_continuation(c_uv, W)
|
|
1358
|
+
sage: omega = M.diff_form(1, name='omega')
|
|
1359
|
+
sage: omega[e_xy,0] = y^2
|
|
1360
|
+
sage: omega.add_comp_by_continuation(e_uv, W, c_uv)
|
|
1361
|
+
sage: eta = M.diff_form(2, name='eta')
|
|
1362
|
+
sage: eta[e_xy,0,1] = x^2*y^2
|
|
1363
|
+
sage: eta.add_comp_by_continuation(e_uv, W, c_uv)
|
|
1364
|
+
|
|
1365
|
+
Now, a mixed form can be restricted to some subdomain::
|
|
1366
|
+
|
|
1367
|
+
sage: F = M.mixed_form([f, omega, eta], name='F')
|
|
1368
|
+
sage: FV = F.restrict(V); FV
|
|
1369
|
+
Mixed differential form F on the Open subset V of the 2-dimensional
|
|
1370
|
+
differentiable manifold M
|
|
1371
|
+
sage: FV[:]
|
|
1372
|
+
[Scalar field f on the Open subset V of the 2-dimensional
|
|
1373
|
+
differentiable manifold M,
|
|
1374
|
+
1-form omega on the Open subset V of the 2-dimensional
|
|
1375
|
+
differentiable manifold M,
|
|
1376
|
+
2-form eta on the Open subset V of the 2-dimensional
|
|
1377
|
+
differentiable manifold M]
|
|
1378
|
+
sage: FV.display_expansion(e_uv)
|
|
1379
|
+
F = u^2/(u^4 + 2*u^2*v^2 + v^4) - (u^2*v^2 - v^4)/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) du - 2*u*v^3/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) dv - u^2*v^2/(u^12 + 6*u^10*v^2 + 15*u^8*v^4 + 20*u^6*v^6 + 15*u^4*v^8 + 6*u^2*v^10 + v^12) du∧dv
|
|
1380
|
+
"""
|
|
1381
|
+
resu = type(self)(subdomain.mixed_form_algebra(dest_map=dest_map),
|
|
1382
|
+
name=self._name, latex_name=self._latex_name)
|
|
1383
|
+
resu[0] = self[0].restrict(subdomain)
|
|
1384
|
+
resu[1:] = [self[j].restrict(subdomain, dest_map)
|
|
1385
|
+
for j in self.irange(1)]
|
|
1386
|
+
return resu
|
|
1387
|
+
|
|
1388
|
+
def add_comp_by_continuation(self, frame, subdomain, chart=None):
|
|
1389
|
+
r"""
|
|
1390
|
+
Set components with respect to a vector frame by continuation of the
|
|
1391
|
+
coordinate expression of the components in a subframe.
|
|
1392
|
+
|
|
1393
|
+
The continuation is performed by demanding that the components have
|
|
1394
|
+
the same coordinate expression as those on the restriction of the
|
|
1395
|
+
frame to a given subdomain.
|
|
1396
|
+
|
|
1397
|
+
INPUT:
|
|
1398
|
+
|
|
1399
|
+
- ``frame`` -- vector frame `e` in which the components are to be set
|
|
1400
|
+
- ``subdomain`` -- open subset of `e`'s domain in which the
|
|
1401
|
+
components are known or can be evaluated from other components
|
|
1402
|
+
- ``chart`` -- (default: ``None``) coordinate chart on `e`'s domain in
|
|
1403
|
+
which the extension of the expression of the components is to be
|
|
1404
|
+
performed; if ``None``, the default's chart of `e`'s domain is
|
|
1405
|
+
assumed
|
|
1406
|
+
|
|
1407
|
+
EXAMPLES:
|
|
1408
|
+
|
|
1409
|
+
Mixed form defined by differential forms with components on different
|
|
1410
|
+
parts of the 2-sphere::
|
|
1411
|
+
|
|
1412
|
+
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
|
|
1413
|
+
sage: U = M.open_subset('U') # complement of the North pole
|
|
1414
|
+
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
|
|
1415
|
+
sage: V = M.open_subset('V') # complement of the South pole
|
|
1416
|
+
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
|
|
1417
|
+
sage: M.declare_union(U,V) # S^2 is the union of U and V
|
|
1418
|
+
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
|
|
1419
|
+
....: intersection_name='W', restrictions1= x^2+y^2!=0,
|
|
1420
|
+
....: restrictions2= u^2+v^2!=0)
|
|
1421
|
+
sage: uv_to_xy = xy_to_uv.inverse()
|
|
1422
|
+
sage: W = U.intersection(V)
|
|
1423
|
+
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
|
|
1424
|
+
sage: F = M.mixed_form(name='F') # No predefined components, here
|
|
1425
|
+
sage: F[0] = M.scalar_field(x, name='f')
|
|
1426
|
+
sage: F[1] = M.diff_form(1, {e_xy: [x,0]}, name='omega')
|
|
1427
|
+
sage: F[2].set_name(name='eta')
|
|
1428
|
+
sage: F[2][e_uv,0,1] = u*v
|
|
1429
|
+
sage: F.add_comp_by_continuation(e_uv, W, c_uv)
|
|
1430
|
+
sage: F.add_comp_by_continuation(e_xy, W, c_xy) # Now, F is fully defined
|
|
1431
|
+
sage: F.display_expansion(e_xy)
|
|
1432
|
+
F = x + x dx - x*y/(x^8 + 4*x^6*y^2 + 6*x^4*y^4 + 4*x^2*y^6 + y^8) dx∧dy
|
|
1433
|
+
sage: F.display_expansion(e_uv)
|
|
1434
|
+
F = u/(u^2 + v^2) - (u^3 - u*v^2)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u^2*v/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv + u*v du∧dv
|
|
1435
|
+
"""
|
|
1436
|
+
if chart is None:
|
|
1437
|
+
chart = frame._chart
|
|
1438
|
+
self[0].add_expr_by_continuation(chart, subdomain)
|
|
1439
|
+
for j in self.irange(1):
|
|
1440
|
+
self[j].add_comp_by_continuation(frame, subdomain, chart)
|
|
1441
|
+
|
|
1442
|
+
def irange(self, start=None):
|
|
1443
|
+
r"""
|
|
1444
|
+
Single index generator.
|
|
1445
|
+
|
|
1446
|
+
INPUT:
|
|
1447
|
+
|
|
1448
|
+
- ``start`` -- (default: ``None``) initial value `i_0` of the index
|
|
1449
|
+
between 0 and `n`, where `n` is the manifold's dimension; if none is
|
|
1450
|
+
provided, the value 0 is assumed
|
|
1451
|
+
|
|
1452
|
+
OUTPUT:
|
|
1453
|
+
|
|
1454
|
+
- an iterable index, starting from `i_0` and ending at
|
|
1455
|
+
`n`, where `n` is the manifold's dimension
|
|
1456
|
+
|
|
1457
|
+
EXAMPLES::
|
|
1458
|
+
|
|
1459
|
+
sage: M = Manifold(3, 'M')
|
|
1460
|
+
sage: a = M.mixed_form(name='a')
|
|
1461
|
+
sage: list(a.irange())
|
|
1462
|
+
[0, 1, 2, 3]
|
|
1463
|
+
sage: list(a.irange(2))
|
|
1464
|
+
[2, 3]
|
|
1465
|
+
"""
|
|
1466
|
+
return self.parent().irange(start=start)
|
|
1467
|
+
|
|
1468
|
+
def set_comp(self, i):
|
|
1469
|
+
r"""
|
|
1470
|
+
Return the `i`-th homogeneous component for assignment.
|
|
1471
|
+
|
|
1472
|
+
EXAMPLES::
|
|
1473
|
+
|
|
1474
|
+
sage: M = Manifold(2, 'M')
|
|
1475
|
+
sage: X.<x,y> = M.chart()
|
|
1476
|
+
sage: A = M.mixed_form(name='A')
|
|
1477
|
+
sage: A.set_comp(0).set_expr(x^2) # scalar field
|
|
1478
|
+
sage: A.set_comp(1)[:] = [-y, x]
|
|
1479
|
+
sage: A.set_comp(2)[0,1] = x-y
|
|
1480
|
+
sage: A.display()
|
|
1481
|
+
A = A_0 + A_1 + A_2
|
|
1482
|
+
sage: A.display_expansion()
|
|
1483
|
+
A = x^2 - y dx + x dy + (x - y) dx∧dy
|
|
1484
|
+
"""
|
|
1485
|
+
return self[i]
|
|
1486
|
+
|
|
1487
|
+
def set_immutable(self):
|
|
1488
|
+
r"""
|
|
1489
|
+
Set ``self`` and homogeneous components of ``self`` immutable.
|
|
1490
|
+
|
|
1491
|
+
EXAMPLES::
|
|
1492
|
+
|
|
1493
|
+
sage: M = Manifold(2, 'M')
|
|
1494
|
+
sage: X.<x,y> = M.chart()
|
|
1495
|
+
sage: f = M.scalar_field(x^2, name='f')
|
|
1496
|
+
sage: A = M.mixed_form([f, 0, 0], name='A')
|
|
1497
|
+
sage: A.set_immutable()
|
|
1498
|
+
sage: A.is_immutable()
|
|
1499
|
+
True
|
|
1500
|
+
sage: A[0].is_immutable()
|
|
1501
|
+
True
|
|
1502
|
+
sage: f.is_immutable()
|
|
1503
|
+
False
|
|
1504
|
+
"""
|
|
1505
|
+
for form in self:
|
|
1506
|
+
form.set_immutable()
|
|
1507
|
+
super().set_immutable()
|