passagemath-symbolics 10.8.1a1__cp311-cp311-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_symbolics/__init__.py +3 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/RECORD +182 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +6 -0
  6. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_symbolics.py +17 -0
  8. sage/calculus/all.py +14 -0
  9. sage/calculus/calculus.py +2838 -0
  10. sage/calculus/desolvers.py +1864 -0
  11. sage/calculus/predefined.py +51 -0
  12. sage/calculus/tests.py +225 -0
  13. sage/calculus/var.cpython-311-darwin.so +0 -0
  14. sage/calculus/var.pyx +401 -0
  15. sage/dynamics/all__sagemath_symbolics.py +6 -0
  16. sage/dynamics/complex_dynamics/all.py +5 -0
  17. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-311-darwin.so +0 -0
  19. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  20. sage/ext/all__sagemath_symbolics.py +1 -0
  21. sage/ext_data/kenzo/CP2.txt +45 -0
  22. sage/ext_data/kenzo/CP3.txt +349 -0
  23. sage/ext_data/kenzo/CP4.txt +4774 -0
  24. sage/ext_data/kenzo/README.txt +49 -0
  25. sage/ext_data/kenzo/S4.txt +20 -0
  26. sage/ext_data/magma/latex/latex.m +1021 -0
  27. sage/ext_data/magma/latex/latex.spec +1 -0
  28. sage/ext_data/magma/sage/basic.m +356 -0
  29. sage/ext_data/magma/sage/sage.spec +1 -0
  30. sage/ext_data/magma/spec +9 -0
  31. sage/geometry/all__sagemath_symbolics.py +8 -0
  32. sage/geometry/hyperbolic_space/all.py +5 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  39. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  40. sage/geometry/riemannian_manifolds/all.py +7 -0
  41. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  42. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  43. sage/interfaces/all__sagemath_symbolics.py +1 -0
  44. sage/interfaces/magma.py +2991 -0
  45. sage/interfaces/magma_free.py +90 -0
  46. sage/interfaces/maple.py +1402 -0
  47. sage/interfaces/mathematica.py +1345 -0
  48. sage/interfaces/mathics.py +1312 -0
  49. sage/interfaces/sympy.py +1398 -0
  50. sage/interfaces/sympy_wrapper.py +197 -0
  51. sage/interfaces/tides.py +938 -0
  52. sage/libs/all__sagemath_symbolics.py +6 -0
  53. sage/manifolds/all.py +7 -0
  54. sage/manifolds/calculus_method.py +553 -0
  55. sage/manifolds/catalog.py +437 -0
  56. sage/manifolds/chart.py +4010 -0
  57. sage/manifolds/chart_func.py +3416 -0
  58. sage/manifolds/continuous_map.py +2183 -0
  59. sage/manifolds/continuous_map_image.py +155 -0
  60. sage/manifolds/differentiable/affine_connection.py +2475 -0
  61. sage/manifolds/differentiable/all.py +1 -0
  62. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  63. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  64. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  65. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  66. sage/manifolds/differentiable/chart.py +1241 -0
  67. sage/manifolds/differentiable/curve.py +1028 -0
  68. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  69. sage/manifolds/differentiable/degenerate.py +559 -0
  70. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  71. sage/manifolds/differentiable/diff_form.py +1660 -0
  72. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  73. sage/manifolds/differentiable/diff_map.py +1315 -0
  74. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  75. sage/manifolds/differentiable/examples/all.py +1 -0
  76. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  77. sage/manifolds/differentiable/examples/real_line.py +897 -0
  78. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  79. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  80. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  81. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  82. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  83. sage/manifolds/differentiable/manifold.py +4254 -0
  84. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  85. sage/manifolds/differentiable/metric.py +3032 -0
  86. sage/manifolds/differentiable/mixed_form.py +1507 -0
  87. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  88. sage/manifolds/differentiable/multivector_module.py +800 -0
  89. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  90. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  91. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  92. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  93. sage/manifolds/differentiable/scalarfield.py +1343 -0
  94. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  95. sage/manifolds/differentiable/symplectic_form.py +912 -0
  96. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  97. sage/manifolds/differentiable/tangent_space.py +412 -0
  98. sage/manifolds/differentiable/tangent_vector.py +616 -0
  99. sage/manifolds/differentiable/tensorfield.py +4665 -0
  100. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  101. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  102. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  103. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  104. sage/manifolds/differentiable/vectorfield.py +1717 -0
  105. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  106. sage/manifolds/differentiable/vectorframe.py +1832 -0
  107. sage/manifolds/family.py +270 -0
  108. sage/manifolds/local_frame.py +1490 -0
  109. sage/manifolds/manifold.py +3090 -0
  110. sage/manifolds/manifold_homset.py +452 -0
  111. sage/manifolds/operators.py +359 -0
  112. sage/manifolds/point.py +994 -0
  113. sage/manifolds/scalarfield.py +3718 -0
  114. sage/manifolds/scalarfield_algebra.py +629 -0
  115. sage/manifolds/section.py +3111 -0
  116. sage/manifolds/section_module.py +831 -0
  117. sage/manifolds/structure.py +229 -0
  118. sage/manifolds/subset.py +2721 -0
  119. sage/manifolds/subsets/all.py +1 -0
  120. sage/manifolds/subsets/closure.py +131 -0
  121. sage/manifolds/subsets/pullback.py +883 -0
  122. sage/manifolds/topological_submanifold.py +891 -0
  123. sage/manifolds/trivialization.py +733 -0
  124. sage/manifolds/utilities.py +1348 -0
  125. sage/manifolds/vector_bundle.py +1347 -0
  126. sage/manifolds/vector_bundle_fiber.py +332 -0
  127. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  128. sage/matrix/all__sagemath_symbolics.py +1 -0
  129. sage/matrix/matrix_symbolic_dense.cpython-311-darwin.so +0 -0
  130. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  131. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  132. sage/matrix/matrix_symbolic_sparse.cpython-311-darwin.so +0 -0
  133. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  134. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  135. sage/modules/all__sagemath_symbolics.py +1 -0
  136. sage/modules/vector_callable_symbolic_dense.py +105 -0
  137. sage/modules/vector_symbolic_dense.py +116 -0
  138. sage/modules/vector_symbolic_sparse.py +118 -0
  139. sage/rings/all__sagemath_symbolics.py +4 -0
  140. sage/rings/asymptotic/all.py +6 -0
  141. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  142. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  143. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  144. sage/rings/asymptotic/growth_group.py +5373 -0
  145. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  146. sage/rings/asymptotic/term_monoid.py +5205 -0
  147. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  148. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  149. sage/symbolic/all.py +15 -0
  150. sage/symbolic/assumptions.py +987 -0
  151. sage/symbolic/benchmark.py +93 -0
  152. sage/symbolic/callable.py +456 -0
  153. sage/symbolic/callable.pyi +66 -0
  154. sage/symbolic/comparison_impl.pyi +38 -0
  155. sage/symbolic/complexity_measures.py +35 -0
  156. sage/symbolic/constants.py +1286 -0
  157. sage/symbolic/constants_c_impl.pyi +10 -0
  158. sage/symbolic/expression_conversion_algebraic.py +310 -0
  159. sage/symbolic/expression_conversion_sympy.py +317 -0
  160. sage/symbolic/expression_conversions.py +1727 -0
  161. sage/symbolic/function_factory.py +355 -0
  162. sage/symbolic/function_factory.pyi +41 -0
  163. sage/symbolic/getitem_impl.pyi +24 -0
  164. sage/symbolic/integration/all.py +1 -0
  165. sage/symbolic/integration/external.py +271 -0
  166. sage/symbolic/integration/integral.py +1075 -0
  167. sage/symbolic/maxima_wrapper.py +162 -0
  168. sage/symbolic/operators.py +267 -0
  169. sage/symbolic/operators.pyi +61 -0
  170. sage/symbolic/pynac_constant_impl.pyi +13 -0
  171. sage/symbolic/pynac_function_impl.pyi +8 -0
  172. sage/symbolic/random_tests.py +461 -0
  173. sage/symbolic/relation.py +2062 -0
  174. sage/symbolic/ring.cpython-311-darwin.so +0 -0
  175. sage/symbolic/ring.pxd +5 -0
  176. sage/symbolic/ring.pyi +110 -0
  177. sage/symbolic/ring.pyx +1393 -0
  178. sage/symbolic/series_impl.pyi +10 -0
  179. sage/symbolic/subring.py +1025 -0
  180. sage/symbolic/symengine.py +19 -0
  181. sage/symbolic/tests.py +40 -0
  182. sage/symbolic/units.py +1468 -0
@@ -0,0 +1,3111 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Sections
4
+
5
+ The class :class:`~sage.manifolds.section.Section` implements sections on vector
6
+ bundles. The derived class :class:`~sage.manifolds.section.TrivialSection`
7
+ is devoted to sections on trivial parts of a vector bundle.
8
+
9
+ AUTHORS:
10
+
11
+ - Michael Jung (2019): initial version
12
+ """
13
+
14
+ #******************************************************************************
15
+ # Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
16
+ # Copyright (C) 2019 Michael Jung <micjung@uni-potsdam.de>
17
+ #
18
+ # Distributed under the terms of the GNU General Public License (GPL)
19
+ # as published by the Free Software Foundation; either version 2 of
20
+ # the License, or (at your option) any later version.
21
+ # http://www.gnu.org/licenses/
22
+ #******************************************************************************
23
+ from sage.rings.integer import Integer
24
+ from sage.rings.integer_ring import ZZ
25
+ from sage.structure.element import ModuleElementWithMutability
26
+ from sage.tensor.modules.free_module_element import FiniteRankFreeModuleElement
27
+ from sage.tensor.modules.tensor_with_indices import TensorWithIndices
28
+
29
+
30
+ class Section(ModuleElementWithMutability):
31
+ r"""
32
+ Section in a vector bundle.
33
+
34
+ An instance of this class is a section in a vector bundle `E \to M` of class
35
+ `C^k`, where `E|_U` is not manifestly trivial. More precisely, a
36
+ *(local) section* on a subset `U \in M` is a map of class `C^k`
37
+
38
+ .. MATH::
39
+
40
+ s: U \longrightarrow E
41
+
42
+ such that
43
+
44
+ .. MATH::
45
+
46
+ \forall p \in U,\ s(p) \in E_p
47
+
48
+ where `E_p` denotes the vector bundle fiber of `E` over the point `p \in U`.
49
+
50
+ If `E|_U` is trivial, the class
51
+ :class:`~sage.manifolds.section.TrivialSection` should be used instead.
52
+
53
+ This is a Sage *element* class, the corresponding *parent* class being
54
+ :class:`~sage.manifolds.section_module.SectionModule`.
55
+
56
+ INPUT:
57
+
58
+ - ``section_module`` -- module `C^k(U;E)` of sections on `E` over `U`
59
+ (cf. :class:`~sage.manifolds.section_module.SectionModule`)
60
+ - ``name`` -- (default: ``None``) name given to the section
61
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the section;
62
+ if none is provided, the LaTeX symbol is set to ``name``
63
+
64
+ EXAMPLES:
65
+
66
+ A section on a non-trivial rank 2 vector bundle over a non-trivial
67
+ 2-manifold::
68
+
69
+ sage: M = Manifold(2, 'M', structure='top')
70
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
71
+ sage: M.declare_union(U,V) # M is the union of U and V
72
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
73
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
74
+ ....: intersection_name='W', restrictions1= x>0,
75
+ ....: restrictions2= u+v>0)
76
+ sage: uv_to_xy = xy_to_uv.inverse()
77
+ sage: W = U.intersection(V)
78
+ sage: E = M.vector_bundle(2, 'E') # define the vector bundle
79
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
80
+ sage: phi_V = E.trivialization('phi_V', domain=V)
81
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]]) # transition map between trivializations
82
+ sage: fU = phi_U.frame(); fV = phi_V.frame() # define induced frames
83
+ sage: s = E.section(name='s'); s
84
+ Section s on the 2-dimensional topological manifold M with values in the
85
+ real vector bundle E of rank 2
86
+
87
+ The parent of `s` is not a free module, since `E` is not trivial::
88
+
89
+ sage: isinstance(s.parent(), FiniteRankFreeModule)
90
+ False
91
+
92
+ To fully define `s`, we have to specify its components in some local
93
+ frames defined on the trivial parts of `E`. The components consist of
94
+ scalar fields defined on the corresponding domain. Let us start with
95
+ `E|_U`::
96
+
97
+ sage: s[fU,:] = [x^2, 1-y]
98
+ sage: s.display(fU)
99
+ s = x^2 (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
100
+
101
+ To set the components of `s` on `V` consistently, we copy the expressions
102
+ of the components in the common subset `W`::
103
+
104
+ sage: fUW = fU.restrict(W); fVW = fV.restrict(W)
105
+ sage: c_uvW = c_uv.restrict(W)
106
+ sage: s[fV,0] = s[fVW,0,c_uvW].expr() # long time
107
+ sage: s[fV,1] = s[fVW,1,c_uvW].expr() # long time
108
+
109
+ Actually, the operation above can be performed in a single line by means
110
+ of the method :meth:`add_comp_by_continuation`::
111
+
112
+ sage: s.add_comp_by_continuation(fV, W, chart=c_uv)
113
+
114
+ At this stage, `s` is fully defined, having components in frames ``fU``
115
+ and ``fV`` and the union of the domains of ``fU`` and ``fV`` being the
116
+ whole manifold::
117
+
118
+ sage: s.display(fV)
119
+ s = (-1/4*u^2 + 1/4*v^2 + 1/2*u + 1/2*v) (phi_V^*e_1)
120
+ + (1/8*u^3 + 3/8*u^2*v + 3/8*u*v^2 + 1/8*v^3) (phi_V^*e_2)
121
+
122
+ Sections can be pointwisely added::
123
+
124
+ sage: t = E.section([x,y], frame=fU, name='t'); t
125
+ Section t on the 2-dimensional topological manifold M with values in the
126
+ real vector bundle E of rank 2
127
+ sage: t.add_comp_by_continuation(fV, W, chart=c_uv)
128
+ sage: t.display(fV)
129
+ t = (1/4*u^2 - 1/4*v^2) (phi_V^*e_1) + (1/4*u^2 + 1/2*u*v + 1/4*v^2) (phi_V^*e_2)
130
+ sage: a = s + t; a
131
+ Section s+t on the 2-dimensional topological manifold M with values
132
+ in the real vector bundle E of rank 2
133
+ sage: a.display(fU)
134
+ s+t = (x^2 + x) (phi_U^*e_1) + (phi_U^*e_2)
135
+ sage: a.display(fV)
136
+ s+t = (1/2*u + 1/2*v) (phi_V^*e_1) + (1/8*u^3 + 1/8*(3*u + 2)*v^2
137
+ + 1/8*v^3 + 1/4*u^2 + 1/8*(3*u^2 + 4*u)*v) (phi_V^*e_2)
138
+
139
+ and multiplied by scalar fields::
140
+
141
+ sage: f = M.scalar_field(y^2-x^2, name='f')
142
+ sage: f.add_expr_by_continuation(c_uv, W)
143
+ sage: f.display()
144
+ f: M → ℝ
145
+ on U: (x, y) ↦ -x^2 + y^2
146
+ on V: (u, v) ↦ -u*v
147
+ sage: b = f*s; b
148
+ Section f*s on the 2-dimensional topological manifold M with values
149
+ in the real vector bundle E of rank 2
150
+ sage: b.display(fU)
151
+ f*s = (-x^4 + x^2*y^2) (phi_U^*e_1) + (x^2*y - y^3 - x^2 + y^2) (phi_U^*e_2)
152
+ sage: b.display(fV)
153
+ f*s = (-1/4*u*v^3 - 1/2*u*v^2 + 1/4*(u^3 - 2*u^2)*v) (phi_V^*e_1)
154
+ + (-1/8*u^4*v - 3/8*u^3*v^2 - 3/8*u^2*v^3 - 1/8*u*v^4) (phi_V^*e_2)
155
+
156
+ The domain on which the section should be defined, can be stated via the
157
+ ``domain`` option in :meth:`~sage.manifolds.vector_bundle.TopologicalVectorBundle.section`::
158
+
159
+ sage: cU = E.section([1,x], domain=U, name='c'); cU
160
+ Section c on the Open subset U of the 2-dimensional topological manifold
161
+ M with values in the real vector bundle E of rank 2
162
+ sage: cU.display()
163
+ c = (phi_U^*e_1) + x (phi_U^*e_2)
164
+
165
+ Since `E|_U` is trivial, ``cU`` now belongs to the free module::
166
+
167
+ sage: isinstance(cU.parent(), FiniteRankFreeModule)
168
+ True
169
+
170
+ Omitting the ``domain`` option, the section is defined on the whole base
171
+ space::
172
+
173
+ sage: c = E.section(name='c'); c
174
+ Section c on the 2-dimensional topological manifold M with values in the
175
+ real vector bundle E of rank 2
176
+
177
+ Via :meth:`set_restriction`, ``cU`` can be defined as the restriction of
178
+ ``c`` to `U`::
179
+
180
+ sage: c.set_restriction(cU)
181
+ sage: c.display(fU)
182
+ c = (phi_U^*e_1) + x (phi_U^*e_2)
183
+ sage: c.restrict(U) == cU
184
+ True
185
+
186
+ Notice that the zero section is immutable, and therefore its components
187
+ cannot be changed::
188
+
189
+ sage: zer = E.section_module().zero()
190
+ sage: zer.is_immutable()
191
+ True
192
+ sage: zer.set_comp()
193
+ Traceback (most recent call last):
194
+ ...
195
+ ValueError: the components of an immutable element cannot be
196
+ changed
197
+
198
+ Other sections can be declared immutable, too::
199
+
200
+ sage: c.is_immutable()
201
+ False
202
+ sage: c.set_immutable()
203
+ sage: c.is_immutable()
204
+ True
205
+ sage: c.set_comp()
206
+ Traceback (most recent call last):
207
+ ...
208
+ ValueError: the components of an immutable element cannot be
209
+ changed
210
+ sage: c.set_name('b')
211
+ Traceback (most recent call last):
212
+ ...
213
+ ValueError: the name of an immutable element cannot be changed
214
+ """
215
+ def __init__(self, section_module, name=None, latex_name=None):
216
+ r"""
217
+ Construct a local section.
218
+
219
+ TESTS::
220
+
221
+ sage: M = Manifold(1, 'S^1', structure='top', start_index=1)
222
+ sage: U = M.open_subset('U') # the complement of one point
223
+ sage: c_t.<t> = U.chart('t:(0,2*pi)') # the standard angle coordinate
224
+ sage: V = M.open_subset('V') # the complement of the point t=pi
225
+ sage: M.declare_union(U,V) # S^1 is the union of U and V
226
+ sage: c_u.<u> = V.chart('u:(0,2*pi)') # the angle t-pi
227
+ sage: t_to_u = c_t.transition_map(c_u, (t-pi,), intersection_name='W',
228
+ ....: restrictions1 = t!=pi, restrictions2 = u!=pi)
229
+ sage: u_to_t = t_to_u.inverse()
230
+ sage: W = U.intersection(V)
231
+ sage: E = M.vector_bundle(1, 'E')
232
+ sage: phi_U = E.trivialization('phi_U', domain=U)
233
+ sage: phi_V = E.trivialization('phi_V', domain=V)
234
+ sage: transf = phi_U.transition_map(phi_V, [[-1]])
235
+ sage: C0 = E.section_module()
236
+ sage: s = E.section([t], frame=phi_U.frame(), name='s')
237
+ sage: s.add_comp_by_continuation(phi_V.frame(), W)
238
+ sage: s in C0
239
+ True
240
+ sage: TestSuite(s).run()
241
+ """
242
+ ModuleElementWithMutability.__init__(self, section_module)
243
+ self._smodule = section_module
244
+ self._domain = section_module.domain()
245
+ self._base_space = section_module.base_space()
246
+ self._vbundle = section_module.vector_bundle()
247
+ self._is_zero = False # a priori
248
+ self._name = name
249
+ if latex_name is None:
250
+ self._latex_name = self._name
251
+ else:
252
+ self._latex_name = latex_name
253
+ self._init_derived()
254
+
255
+ ####### Required methods for ModuleElement (beside arithmetic) #######
256
+
257
+ def __bool__(self):
258
+ r"""
259
+ Return ``True`` if ``self`` is nonzero and ``False`` otherwise.
260
+
261
+ This method is called by :meth:`is_zero`.
262
+
263
+ EXAMPLES::
264
+
265
+ sage: M = Manifold(3, 'M', structure='top')
266
+ sage: X.<x,y,z> = M.chart()
267
+ sage: U = M.open_subset('U'); V = M.open_subset('V')
268
+ sage: M.declare_union(U,V)
269
+ sage: XU = X.restrict(U); XV = X.restrict(V)
270
+ sage: XUV = X.restrict(U.intersection(V))
271
+ sage: E = M.vector_bundle(2, 'E')
272
+ sage: e = E.local_frame('e', domain=U)
273
+ sage: f = E.local_frame('f', domain=V)
274
+ sage: s = E.section(name='s')
275
+ sage: su = E.section(name='s', domain=U)
276
+ sage: sv = E.section(name='s', domain=V)
277
+ sage: su[0] = 0
278
+ sage: sv[0] = 0
279
+ sage: s.set_restriction(su); s.set_restriction(sv)
280
+ sage: bool(s)
281
+ False
282
+ sage: s.is_zero() # indirect doctest
283
+ True
284
+ sage: sv[0] = 1
285
+ sage: s.set_restriction(sv)
286
+ sage: bool(s)
287
+ True
288
+ sage: s.is_zero() # indirect doctest
289
+ False
290
+ """
291
+ if self._is_zero:
292
+ return False
293
+ if any(bool(rst) for rst in self._restrictions.values()):
294
+ self._is_zero = False
295
+ return True
296
+ self._is_zero = True
297
+ return False
298
+
299
+ ##### End of required methods for ModuleElement (beside arithmetic) #####
300
+
301
+ def _repr_(self):
302
+ r"""
303
+ Return a string representation of ``self``.
304
+
305
+ TESTS::
306
+
307
+ sage: M = Manifold(3, 'M')
308
+ sage: E = M.vector_bundle(2, 'E')
309
+ sage: s = E.section(name='s')
310
+ sage: s._repr_()
311
+ 'Section s on the 3-dimensional differentiable manifold M with
312
+ values in the real vector bundle E of rank 2'
313
+ sage: repr(s) # indirect doctest
314
+ 'Section s on the 3-dimensional differentiable manifold M with
315
+ values in the real vector bundle E of rank 2'
316
+ sage: s # indirect doctest
317
+ Section s on the 3-dimensional differentiable manifold M with values
318
+ in the real vector bundle E of rank 2
319
+ """
320
+ desc = "Section "
321
+ if self._name is not None:
322
+ desc += self._name + " "
323
+ desc += "on the {} ".format(self._domain)
324
+ desc += "with values in the " + self._vbundle.base_field_type() + " "
325
+ desc += "vector bundle " + self._vbundle._name + " "
326
+ desc += "of rank {}".format(self._vbundle.rank())
327
+ return desc
328
+
329
+ def _latex_(self):
330
+ r"""
331
+ LaTeX representation of ``self``.
332
+
333
+ TESTS::
334
+
335
+ sage: M = Manifold(3, 'M')
336
+ sage: E = M.vector_bundle(2, 'E')
337
+ sage: sigma = E.section(name='sigma', latex_name=r'\sigma')
338
+ sage: sigma._latex_()
339
+ '\\sigma'
340
+ sage: latex(sigma) # indirect doctest
341
+ \sigma
342
+ """
343
+ if self._latex_name is None:
344
+ return r'\text{' + str(self) + r'}'
345
+ else:
346
+ return self._latex_name
347
+
348
+ def _init_derived(self):
349
+ r"""
350
+ Initialize the derived quantities.
351
+
352
+ TESTS::
353
+
354
+ sage: M = Manifold(2, 'M', structure='top')
355
+ sage: E = M.vector_bundle(2, 'E')
356
+ sage: s = E.section(name='s')
357
+ sage: s._init_derived()
358
+ """
359
+ self._restrictions = {} # dict. of restrictions of self on subdomains
360
+ # of self._domain, with the subdomains as keys
361
+ self._extensions_graph = {self._domain: self}
362
+ self._restrictions_graph = {self._domain: self}
363
+
364
+ def _del_derived(self, del_restrictions=False):
365
+ r"""
366
+ Delete the derived quantities.
367
+
368
+ TESTS::
369
+
370
+ sage: M = Manifold(2, 'M', structure='top')
371
+ sage: E = M.vector_bundle(2, 'E')
372
+ sage: s = E.section(name='s')
373
+ sage: s._del_derived()
374
+ """
375
+ if del_restrictions:
376
+ self._restrictions.clear()
377
+ self._extensions_graph = {self._domain: self}
378
+ self._restrictions_graph = {self._domain: self}
379
+
380
+ def set_name(self, name=None, latex_name=None):
381
+ r"""
382
+ Set (or change) the text name and LaTeX name of ``self``.
383
+
384
+ INPUT:
385
+
386
+ - ``name`` -- string (default: ``None``); name given to the section
387
+ - ``latex_name`` -- string (default: ``None``); LaTeX symbol to denote
388
+ the section; if ``None`` while ``name`` is provided, the LaTeX
389
+ symbol is set to ``name``
390
+
391
+ EXAMPLES::
392
+
393
+ sage: M = Manifold(3, 'M', structure='top')
394
+ sage: E = M.vector_bundle(2, 'E')
395
+ sage: s = E.section(); s
396
+ Section on the 3-dimensional topological manifold M with values in
397
+ the real vector bundle E of rank 2
398
+ sage: s.set_name(name='s')
399
+ sage: s
400
+ Section s on the 3-dimensional topological manifold M with values in
401
+ the real vector bundle E of rank 2
402
+ sage: latex(s)
403
+ s
404
+ sage: s.set_name(latex_name=r'\sigma')
405
+ sage: latex(s)
406
+ \sigma
407
+ sage: s.set_name(name='a')
408
+ sage: s
409
+ Section a on the 3-dimensional topological manifold M with values in
410
+ the real vector bundle E of rank 2
411
+ sage: latex(s)
412
+ a
413
+ """
414
+ if self.is_immutable():
415
+ raise ValueError("the name of an immutable element "
416
+ "cannot be changed")
417
+ if name is not None:
418
+ self._name = name
419
+ if latex_name is None:
420
+ self._latex_name = self._name
421
+ if latex_name is not None:
422
+ self._latex_name = latex_name
423
+ for rst in self._restrictions.values():
424
+ rst.set_name(name=name, latex_name=latex_name)
425
+
426
+ def _new_instance(self):
427
+ r"""
428
+ Create an instance of the same class as ``self`` on the same
429
+ section module.
430
+
431
+ TESTS::
432
+
433
+ sage: M = Manifold(3, 'M')
434
+ sage: U = M.open_subset('U')
435
+ sage: E = M.vector_bundle(2, 'E')
436
+ sage: s = E.section(name='s', domain=U); s
437
+ Section s on the Open subset U of the 3-dimensional differentiable
438
+ manifold M with values in the real vector bundle E of rank 2
439
+ sage: s1 = s._new_instance(); s1
440
+ Section on the Open subset U of the 3-dimensional differentiable
441
+ manifold M with values in the real vector bundle E of rank 2
442
+ sage: type(s1) == type(s)
443
+ True
444
+ sage: s1.parent() is s.parent()
445
+ True
446
+ """
447
+ return type(self)(self._smodule)
448
+
449
+ def _del_restrictions(self):
450
+ r"""
451
+ Delete the restrictions defined on ``self``.
452
+
453
+ TESTS::
454
+
455
+ sage: M = Manifold(2, 'M')
456
+ sage: c_xy.<x,y> = M.chart()
457
+ sage: U = M.open_subset('U', coord_def={c_xy: x<0})
458
+ sage: E = M.vector_bundle(2, 'E')
459
+ sage: e = E.local_frame('e')
460
+ sage: s = E.section()
461
+ sage: t = s.restrict(U)
462
+ sage: s._restrictions
463
+ {Open subset U of the 2-dimensional differentiable manifold M:
464
+ Section on the Open subset U of the 2-dimensional differentiable
465
+ manifold M with values in the real vector bundle E of rank 2}
466
+ sage: s._del_restrictions()
467
+ sage: s._restrictions
468
+ {}
469
+ """
470
+ self._restrictions.clear()
471
+ self._extensions_graph = {self._domain: self}
472
+ self._restrictions_graph = {self._domain: self}
473
+
474
+ def _init_components(self, *comp, **kwargs):
475
+ r"""
476
+ Initialize the section components in some given local frames.
477
+
478
+ INPUT:
479
+
480
+ - ``comp`` -- either the components of the section with respect
481
+ to the local frame specified by the argument ``frame`` or a
482
+ dictionary of components, the keys of which are local frames or
483
+ pairs ``(f,c)`` where ``f`` is a local frame and ``c`` a chart
484
+ - ``frame`` -- (default: ``None``; unused if ``comp`` is a dictionary)
485
+ local frame in which the components are given; if ``None``, the
486
+ default local frame on the domain of ``self`` is assumed
487
+ - ``chart`` -- (default: ``None``; unused if ``comp`` is a dictionary)
488
+ coordinate chart in which the components are expressed; if ``None``,
489
+ the default chart on some subdomain of ``frame`` is assumed
490
+
491
+ EXAMPLES::
492
+
493
+ sage: M = Manifold(3, 'M', structure='top')
494
+ sage: X.<x,y,z> = M.chart()
495
+ sage: E = M.vector_bundle(2, 'E')
496
+ sage: e = E.local_frame('e')
497
+ sage: s = E.section(name='s')
498
+ sage: s._init_components([1+x, y^2])
499
+ sage: s.display()
500
+ s = (x + 1) e_0 + y^2 e_1
501
+ sage: f = E.local_frame('f')
502
+ sage: Y.<u,v,t> = M.chart()
503
+ sage: s._init_components([2*v, -u], frame=f)
504
+ sage: s.display(f, Y)
505
+ s = 2*v f_0 - u f_1
506
+ sage: s._init_components({e: [1-y, x]})
507
+ sage: s.display()
508
+ s = (-y + 1) e_0 + x e_1
509
+ sage: s._init_components({(f, Y): [t, v^3]})
510
+ sage: s.display(f, Y)
511
+ s = t f_0 + v^3 f_1
512
+ """
513
+ comp0 = comp[0]
514
+ self._is_zero = False # a priori
515
+ if isinstance(comp0, dict):
516
+ for frame, components in comp0.items():
517
+ chart = None
518
+ if isinstance(frame, tuple):
519
+ # frame is actually a pair (frame, chart):
520
+ frame, chart = frame
521
+ self.add_comp(frame)[:, chart] = components
522
+ elif isinstance(comp0, str):
523
+ # For consistency with tensor fields:
524
+ self.set_name(comp0)
525
+ else:
526
+ if hasattr(comp0, '__getitem__'):
527
+ # comp0 is a list/vector of components
528
+ # otherwise comp is the tuple of components in a specific frame
529
+ comp = comp0
530
+ frame = kwargs.get('frame')
531
+ chart = kwargs.get('chart')
532
+ self.add_comp(frame)[:, chart] = comp
533
+
534
+ def domain(self):
535
+ r"""
536
+ Return the manifold on which ``self`` is defined.
537
+
538
+ OUTPUT:
539
+
540
+ - instance of class
541
+ :class:`~sage.manifolds.manifold.TopologicalManifold`
542
+
543
+ EXAMPLES::
544
+
545
+ sage: M = Manifold(3, 'M', structure='top')
546
+ sage: U = M.open_subset('U')
547
+ sage: E = M.vector_bundle(2, 'E')
548
+ sage: C0_U = E.section_module(domain=U, force_free=True)
549
+ sage: z = C0_U.zero()
550
+ sage: z.domain()
551
+ Open subset U of the 3-dimensional topological manifold M
552
+ """
553
+ return self._domain
554
+
555
+ def base_module(self):
556
+ r"""
557
+ Return the section module on which ``self`` acts as a section.
558
+
559
+ OUTPUT:
560
+
561
+ - instance of
562
+ :class:`~sage.manifolds.section_module.SectionModule`
563
+
564
+ EXAMPLES::
565
+
566
+ sage: M = Manifold(3, 'M', structure='top')
567
+ sage: U = M.open_subset('U')
568
+ sage: E = M.vector_bundle(2, 'E')
569
+ sage: s = E.section(domain=U)
570
+ sage: s.base_module()
571
+ Module C^0(U;E) of sections on the Open subset U of the
572
+ 3-dimensional topological manifold M with values in the real vector
573
+ bundle E of rank 2
574
+ """
575
+ return self._smodule
576
+
577
+ def set_restriction(self, rst):
578
+ r"""
579
+ Define a restriction of ``self`` to some subdomain.
580
+
581
+ INPUT:
582
+
583
+ - ``rst`` -- :class:`Section` defined on a subdomain of the domain of
584
+ ``self``
585
+
586
+ EXAMPLES::
587
+
588
+ sage: S2 = Manifold(2, 'S^2', structure='top')
589
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
590
+ sage: S2.declare_union(U,V)
591
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
592
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
593
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
594
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
595
+ ....: intersection_name='W',
596
+ ....: restrictions1= x^2+y^2!=0,
597
+ ....: restrictions2= u^2+v^2!=0)
598
+ sage: W = U.intersection(V)
599
+ sage: uv_to_xy = xy_to_uv.inverse()
600
+ sage: E = S2.vector_bundle(2, 'E')
601
+ sage: phi_U = E.trivialization('phi_U', domain=U)
602
+ sage: phi_V = E.trivialization('phi_V', domain=V)
603
+ sage: s = E.section(name='s')
604
+ sage: sU = E.section(domain=U, name='s')
605
+ sage: sU[:] = x+y, x
606
+ sage: s.set_restriction(sU)
607
+ sage: s.display(phi_U.frame())
608
+ s = (x + y) (phi_U^*e_1) + x (phi_U^*e_2)
609
+ sage: s.restrict(U) == sU
610
+ True
611
+ """
612
+ if self.is_immutable():
613
+ raise ValueError("the restrictions of an immutable element "
614
+ "cannot be changed")
615
+ self._restrictions[rst._domain] = rst.copy(name=self._name,
616
+ latex_name=self._latex_name)
617
+ self._is_zero = False # a priori
618
+
619
+ def restrict(self, subdomain):
620
+ r"""
621
+ Return the restriction of ``self`` to some subdomain.
622
+
623
+ If the restriction has not been defined yet, it is constructed here.
624
+
625
+ INPUT:
626
+
627
+ - ``subdomain`` --
628
+ :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`;
629
+ open subset `U` of the section domain `S`
630
+
631
+ OUTPUT: :class:`Section` representing the restriction
632
+
633
+ EXAMPLES:
634
+
635
+ Restrictions of a section on a rank 2 vector bundle over the 2-sphere::
636
+
637
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
638
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
639
+ sage: S2.declare_union(U,V)
640
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
641
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
642
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
643
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
644
+ ....: intersection_name='W',
645
+ ....: restrictions1= x^2+y^2!=0,
646
+ ....: restrictions2= u^2+v^2!=0)
647
+ sage: W = U.intersection(V)
648
+ sage: uv_to_xy = xy_to_uv.inverse()
649
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
650
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
651
+ sage: phi_V = E.trivialization('phi_V', domain=V)
652
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[y,0]])
653
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
654
+ sage: fN_W = fN.restrict(W); fS_W = fS.restrict(W) # restrict them
655
+ sage: stereoN_W = stereoN.restrict(W) # restrict charts, too
656
+ sage: stereoS_W = stereoS.restrict(W)
657
+ sage: s = E.section({fN: [1, 0]}, name='s')
658
+ sage: s.display(fN)
659
+ s = (phi_U^*e_1)
660
+ sage: sU = s.restrict(U) ; sU
661
+ Section s on the Open subset U of the 2-dimensional topological
662
+ manifold S^2 with values in the real vector bundle E of rank 2
663
+ sage: sU.display() # fN is the default frame on U
664
+ s = (phi_U^*e_1)
665
+ sage: sU == fN[1]
666
+ True
667
+ sage: sW = s.restrict(W) ; sW
668
+ Section s on the Open subset W of the 2-dimensional topological
669
+ manifold S^2 with values in the real vector bundle E of rank 2
670
+ sage: sW.display(fN_W)
671
+ s = (phi_U^*e_1)
672
+ sage: sW.display(fS_W, stereoN_W)
673
+ s = y (phi_V^*e_2)
674
+ sage: sW.display(fS_W, stereoS_W)
675
+ s = v/(u^2 + v^2) (phi_V^*e_2)
676
+ sage: sW == fN_W[1]
677
+ True
678
+
679
+ At this stage, defining the restriction of ``s`` to the open
680
+ subset ``V`` fully specifies ``s``::
681
+
682
+ sage: s.restrict(V)[1] = sW[fS_W, 1, stereoS_W].expr() # note that fS is the default frame on V
683
+ sage: s.restrict(V)[2] = sW[fS_W, 2, stereoS_W].expr()
684
+ sage: s.display(fS, stereoS)
685
+ s = v/(u^2 + v^2) (phi_V^*e_2)
686
+ sage: s.restrict(U).display()
687
+ s = (phi_U^*e_1)
688
+ sage: s.restrict(V).display()
689
+ s = v/(u^2 + v^2) (phi_V^*e_2)
690
+
691
+ The restriction of the section to its own domain is of course itself::
692
+
693
+ sage: s.restrict(S2) is s
694
+ True
695
+ sage: sU.restrict(U) is sU
696
+ True
697
+ """
698
+ if subdomain == self._domain:
699
+ return self
700
+ if subdomain not in self._restrictions:
701
+ if not subdomain.is_subset(self._domain):
702
+ raise ValueError("the provided domain is not a subset of " +
703
+ "the field's domain")
704
+
705
+ # First one tries to get the restriction from a tighter domain:
706
+ for dom, rst in self._restrictions.items():
707
+ if subdomain.is_subset(dom) and subdomain in rst._restrictions:
708
+ res = rst._restrictions[subdomain]
709
+ self._restrictions[subdomain] = res
710
+ self._restrictions_graph[subdomain] = res
711
+ res._extensions_graph.update(self._extensions_graph)
712
+ for ext in self._extensions_graph.values():
713
+ ext._restrictions[subdomain] = res
714
+ ext._restrictions_graph[subdomain] = res
715
+ return self._restrictions[subdomain]
716
+
717
+ for dom, rst in self._restrictions.items():
718
+ if subdomain.is_subset(dom) and dom is not self._domain:
719
+ self._restrictions[subdomain] = rst.restrict(subdomain)
720
+ self._restrictions_graph[subdomain] = rst.restrict(subdomain)
721
+ return self._restrictions[subdomain]
722
+
723
+ # Secondly one tries to get the restriction from one previously
724
+ # defined on a larger domain:
725
+ for dom, ext in self._extensions_graph.items():
726
+ if subdomain in ext._restrictions:
727
+ res = ext._restrictions_graph[subdomain]
728
+ self._restrictions[subdomain] = res
729
+ self._restrictions_graph[subdomain] = res
730
+ res._extensions_graph.update(self._extensions_graph)
731
+ for ext in self._extensions_graph.values():
732
+ ext._restrictions[subdomain] = res
733
+ ext._restrictions_graph[subdomain] = res
734
+ return self._restrictions[subdomain]
735
+
736
+ # If this fails, the restriction is created from scratch:
737
+ smodule = self._vbundle.section_module(domain=subdomain)
738
+ res = smodule.element_class(smodule, name=self._name,
739
+ latex_name=self._latex_name)
740
+ res._extensions_graph.update(self._extensions_graph)
741
+
742
+ for dom, ext in self._extensions_graph.items():
743
+ ext._restrictions[subdomain] = res
744
+ ext._restrictions_graph[subdomain] = res
745
+ for dom, rst in self._restrictions.items():
746
+ if dom.is_subset(subdomain):
747
+ if rst is not res:
748
+ res._restrictions.update(rst._restrictions)
749
+ res._restrictions_graph.update(rst._restrictions_graph)
750
+ rst._extensions_graph.update(res._extensions_graph)
751
+ if self.is_immutable():
752
+ res.set_immutable() # restrictions must be immutable, too
753
+ self._restrictions[subdomain] = res
754
+ self._restrictions_graph[subdomain] = res
755
+ res._extensions_graph.update(self._extensions_graph)
756
+
757
+ return self._restrictions[subdomain]
758
+
759
+ def _set_comp_unsafe(self, basis=None):
760
+ r"""
761
+ Return the components of ``self`` in a given local frame for
762
+ assignment. This private method invokes no security check. Use
763
+ this method at your own risk.
764
+
765
+ The components with respect to other frames having the same domain
766
+ as the provided local frame are deleted, in order to avoid any
767
+ inconsistency. To keep them, use the method :meth:`_add_comp_unsafe`
768
+ instead.
769
+
770
+ INPUT:
771
+
772
+ - ``basis`` -- (default: ``None``) local frame in which the
773
+ components are defined; if none is provided, the components are
774
+ assumed to refer to the section domain's default frame
775
+
776
+ OUTPUT:
777
+
778
+ - components in the given frame, as a
779
+ :class:`~sage.tensor.modules.comp.Components`; if such
780
+ components did not exist previously, they are created
781
+
782
+ EXAMPLES::
783
+
784
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
785
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
786
+ sage: S2.declare_union(U,V)
787
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
788
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
789
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
790
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
791
+ ....: intersection_name='W',
792
+ ....: restrictions1= x^2+y^2!=0,
793
+ ....: restrictions2= u^2+v^2!=0)
794
+ sage: W = U.intersection(V)
795
+ sage: uv_to_xy = xy_to_uv.inverse()
796
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
797
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
798
+ sage: phi_V = E.trivialization('phi_V', domain=V)
799
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[y,0]])
800
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
801
+ sage: s = E.section(name='s')
802
+ sage: s._set_comp_unsafe(fS)
803
+ 1-index components w.r.t. Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
804
+ sage: s._set_comp_unsafe(fS)[1] = u+v
805
+ sage: s.display(fS)
806
+ s = (u + v) (phi_V^*e_1)
807
+
808
+ Setting the components in a new frame (``e``)::
809
+
810
+ sage: e = E.local_frame('e', domain=V)
811
+ sage: s._set_comp_unsafe(e)
812
+ 1-index components w.r.t. Local frame (E|_V, (e_1,e_2))
813
+ sage: s._set_comp_unsafe(e)[1] = u*v
814
+ sage: s.display(e)
815
+ s = u*v e_1
816
+
817
+ Since the frames ``e`` and ``fS`` are defined on the same domain, the
818
+ components w.r.t. ``fS`` have been erased::
819
+
820
+ sage: s.display(phi_V.frame())
821
+ Traceback (most recent call last):
822
+ ...
823
+ ValueError: no basis could be found for computing the components in
824
+ the Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
825
+ """
826
+ if basis is None:
827
+ basis = self._smodule.default_frame()
828
+ if basis is None: # should be "is still None" ;-)
829
+ raise ValueError("a frame must be provided for the display")
830
+ rst = self.restrict(basis._domain)
831
+ return rst._set_comp_unsafe(basis)
832
+
833
+ def set_comp(self, basis=None):
834
+ r"""
835
+ Return the components of ``self`` in a given local frame for assignment.
836
+
837
+ The components with respect to other frames having the same domain
838
+ as the provided local frame are deleted, in order to avoid any
839
+ inconsistency. To keep them, use the method :meth:`add_comp` instead.
840
+
841
+ INPUT:
842
+
843
+ - ``basis`` -- (default: ``None``) local frame in which the
844
+ components are defined; if none is provided, the components are
845
+ assumed to refer to the section domain's default frame
846
+
847
+ OUTPUT:
848
+
849
+ - components in the given frame, as a
850
+ :class:`~sage.tensor.modules.comp.Components`; if such
851
+ components did not exist previously, they are created
852
+
853
+ EXAMPLES::
854
+
855
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
856
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
857
+ sage: S2.declare_union(U,V)
858
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
859
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
860
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
861
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
862
+ ....: intersection_name='W',
863
+ ....: restrictions1= x^2+y^2!=0,
864
+ ....: restrictions2= u^2+v^2!=0)
865
+ sage: W = U.intersection(V)
866
+ sage: uv_to_xy = xy_to_uv.inverse()
867
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
868
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
869
+ sage: phi_V = E.trivialization('phi_V', domain=V)
870
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[y,0]])
871
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
872
+ sage: s = E.section(name='s')
873
+ sage: s.set_comp(fS)
874
+ 1-index components w.r.t. Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
875
+ sage: s.set_comp(fS)[1] = u+v
876
+ sage: s.display(fS)
877
+ s = (u + v) (phi_V^*e_1)
878
+
879
+ Setting the components in a new frame (``e``)::
880
+
881
+ sage: e = E.local_frame('e', domain=V)
882
+ sage: s.set_comp(e)
883
+ 1-index components w.r.t. Local frame (E|_V, (e_1,e_2))
884
+ sage: s.set_comp(e)[1] = u*v
885
+ sage: s.display(e)
886
+ s = u*v e_1
887
+
888
+ Since the frames ``e`` and ``fS`` are defined on the same domain, the
889
+ components w.r.t. ``fS`` have been erased::
890
+
891
+ sage: s.display(phi_V.frame())
892
+ Traceback (most recent call last):
893
+ ...
894
+ ValueError: no basis could be found for computing the components in
895
+ the Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
896
+ """
897
+ if self.is_immutable():
898
+ raise ValueError("the components of an immutable element "
899
+ "cannot be changed")
900
+ if basis is None:
901
+ basis = self._smodule.default_frame()
902
+ if basis is None: # should be "is still None" ;-)
903
+ raise ValueError("a frame must be provided for the display")
904
+ rst = self.restrict(basis._domain)
905
+ self._is_zero = False # a priori
906
+ return rst.set_comp(basis)
907
+
908
+ def _add_comp_unsafe(self, basis=None):
909
+ r"""
910
+ Return the components of ``self`` in a given local frame for
911
+ assignment. This private method invokes no security check. Use
912
+ this method at your own risk.
913
+
914
+ The components with respect to other frames having the same domain
915
+ as the provided local frame are kept. To delete them, use the
916
+ method :meth:`_set_comp_unsafe` instead.
917
+
918
+ INPUT:
919
+
920
+ - ``basis`` -- (default: ``None``) local frame in which the
921
+ components are defined; if ``None``, the components are assumed
922
+ to refer to the section domain's default frame
923
+
924
+ OUTPUT:
925
+
926
+ - components in the given frame, as a
927
+ :class:`~sage.tensor.modules.comp.Components`; if such
928
+ components did not exist previously, they are created
929
+
930
+ EXAMPLES::
931
+
932
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
933
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
934
+ sage: S2.declare_union(U,V)
935
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
936
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
937
+ sage: xy_to_uv = stereoN.transition_map(stereoS, (x/(x^2+y^2), y/(x^2+y^2)),
938
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
939
+ ....: restrictions2= u^2+v^2!=0)
940
+ sage: W = U.intersection(V)
941
+ sage: uv_to_xy = xy_to_uv.inverse()
942
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
943
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
944
+ sage: phi_V = E.trivialization('phi_V', domain=V)
945
+ sage: transf = phi_U.transition_map(phi_V, [[0,1],[1,0]])
946
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
947
+ sage: s = E.section(name='s')
948
+ sage: s._add_comp_unsafe(fS)
949
+ 1-index components w.r.t. Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
950
+ sage: s._add_comp_unsafe(fS)[1] = u+v
951
+ sage: s.display(fS)
952
+ s = (u + v) (phi_V^*e_1)
953
+
954
+ Setting the components in a new frame::
955
+
956
+ sage: e = E.local_frame('e', domain=V)
957
+ sage: s._add_comp_unsafe(e)
958
+ 1-index components w.r.t. Local frame (E|_V, (e_1,e_2))
959
+ sage: s._add_comp_unsafe(e)[1] = u*v
960
+ sage: s.display(e)
961
+ s = u*v e_1
962
+
963
+ The components with respect to ``fS`` are kept::
964
+
965
+ sage: s.display(fS)
966
+ s = (u + v) (phi_V^*e_1)
967
+ """
968
+ if basis is None:
969
+ basis = self._smodule.default_frame()
970
+ if basis is None: # should be "is still None" ;-)
971
+ raise ValueError("a frame must be provided for the display")
972
+ rst = self.restrict(basis._domain)
973
+ return rst._add_comp_unsafe(basis)
974
+
975
+ def add_comp(self, basis=None):
976
+ r"""
977
+ Return the components of ``self`` in a given local frame for assignment.
978
+
979
+ The components with respect to other frames having the same domain
980
+ as the provided local frame are kept. To delete them, use the
981
+ method :meth:`set_comp` instead.
982
+
983
+ INPUT:
984
+
985
+ - ``basis`` -- (default: ``None``) local frame in which the
986
+ components are defined; if ``None``, the components are assumed
987
+ to refer to the section domain's default frame
988
+
989
+ OUTPUT:
990
+
991
+ - components in the given frame, as a
992
+ :class:`~sage.tensor.modules.comp.Components`; if such
993
+ components did not exist previously, they are created
994
+
995
+ EXAMPLES::
996
+
997
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
998
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
999
+ sage: S2.declare_union(U,V)
1000
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
1001
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
1002
+ sage: xy_to_uv = stereoN.transition_map(stereoS, (x/(x^2+y^2), y/(x^2+y^2)),
1003
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
1004
+ ....: restrictions2= u^2+v^2!=0)
1005
+ sage: W = U.intersection(V)
1006
+ sage: uv_to_xy = xy_to_uv.inverse()
1007
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
1008
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1009
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1010
+ sage: transf = phi_U.transition_map(phi_V, [[0,1],[1,0]])
1011
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
1012
+ sage: s = E.section(name='s')
1013
+ sage: s.add_comp(fS)
1014
+ 1-index components w.r.t. Trivialization frame (E|_V, ((phi_V^*e_1),(phi_V^*e_2)))
1015
+ sage: s.add_comp(fS)[1] = u+v
1016
+ sage: s.display(fS)
1017
+ s = (u + v) (phi_V^*e_1)
1018
+
1019
+ Setting the components in a new frame::
1020
+
1021
+ sage: e = E.local_frame('e', domain=V)
1022
+ sage: s.add_comp(e)
1023
+ 1-index components w.r.t. Local frame (E|_V, (e_1,e_2))
1024
+ sage: s.add_comp(e)[1] = u*v
1025
+ sage: s.display(e)
1026
+ s = u*v e_1
1027
+
1028
+ The components with respect to ``fS`` are kept::
1029
+
1030
+ sage: s.display(fS)
1031
+ s = (u + v) (phi_V^*e_1)
1032
+ """
1033
+ if self.is_immutable():
1034
+ raise ValueError("the components of an immutable element "
1035
+ "cannot be changed")
1036
+ if basis is None:
1037
+ basis = self._smodule.default_frame()
1038
+ if basis is None: # should be "is still None" ;-)
1039
+ raise ValueError("a frame must be provided for the display")
1040
+ rst = self.restrict(basis._domain)
1041
+ self._is_zero = False # a priori
1042
+ return rst.add_comp(basis)
1043
+
1044
+ def add_comp_by_continuation(self, frame, subdomain, chart=None):
1045
+ r"""
1046
+ Set components with respect to a local frame by continuation of the
1047
+ coordinate expression of the components in a subframe.
1048
+
1049
+ The continuation is performed by demanding that the components have
1050
+ the same coordinate expression as those on the restriction of the
1051
+ frame to a given subdomain.
1052
+
1053
+ INPUT:
1054
+
1055
+ - ``frame`` -- local frame `e` in which the components are to be set
1056
+ - ``subdomain`` -- open subset of `e`'s domain in which the
1057
+ components are known or can be evaluated from other components
1058
+ - ``chart`` -- (default: ``None``) coordinate chart on `e`'s domain in
1059
+ which the extension of the expression of the components is to be
1060
+ performed; if ``None``, the default's chart of `e`'s domain is
1061
+ assumed
1062
+
1063
+ EXAMPLES:
1064
+
1065
+ Components of a vector field on the sphere `S^2`::
1066
+
1067
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
1068
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
1069
+ sage: S2.declare_union(U,V)
1070
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
1071
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
1072
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
1073
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
1074
+ ....: intersection_name='W',
1075
+ ....: restrictions1= x^2+y^2!=0,
1076
+ ....: restrictions2= u^2+v^2!=0)
1077
+ sage: W = U.intersection(V)
1078
+ sage: uv_to_xy = xy_to_uv.inverse()
1079
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
1080
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1081
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1082
+ sage: transf = phi_U.transition_map(phi_V, [[0,1],[1,0]])
1083
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
1084
+ sage: a = E.section({fN: [x, 2+y]}, name='a')
1085
+
1086
+ At this stage, the section has been defined only on the open subset
1087
+ ``U`` (through its components in the frame ``fN``)::
1088
+
1089
+ sage: a.display(fN)
1090
+ a = x (phi_U^*e_1) + (y + 2) (phi_U^*e_2)
1091
+
1092
+ The components with respect to the restriction of ``fS`` to the common
1093
+ subdomain ``W``, in terms of the ``(u,v)`` coordinates, are obtained
1094
+ by a change-of-frame formula on ``W``::
1095
+
1096
+ sage: a.display(fS.restrict(W), stereoS.restrict(W))
1097
+ a = (2*u^2 + 2*v^2 + v)/(u^2 + v^2) (phi_V^*e_1) + u/(u^2 + v^2)
1098
+ (phi_V^*e_2)
1099
+
1100
+ The continuation consists in extending the definition of the vector
1101
+ field to the whole open subset ``V`` by demanding that the components
1102
+ in the frame eV have the same coordinate expression as the above one::
1103
+
1104
+ sage: a.add_comp_by_continuation(fS, W, chart=stereoS)
1105
+
1106
+ We have then::
1107
+
1108
+ sage: a.display(fS)
1109
+ a = (2*u^2 + 2*v^2 + v)/(u^2 + v^2) (phi_V^*e_1) + u/(u^2 + v^2)
1110
+ (phi_V^*e_2)
1111
+
1112
+ and `a` is defined on the entire manifold `S^2`.
1113
+ """
1114
+ if self.is_immutable():
1115
+ raise ValueError("the components of an immutable element "
1116
+ "cannot be changed")
1117
+ dom = frame._domain
1118
+ if not dom.is_subset(self._domain):
1119
+ raise ValueError("the local frame is not defined on a subset " +
1120
+ "of the section's domain")
1121
+ if chart is None:
1122
+ chart = dom._def_chart
1123
+ sframe = frame.restrict(subdomain)
1124
+ schart = chart.restrict(subdomain)
1125
+ scomp = self.comp(sframe)
1126
+ resu = self.add_comp(frame) # _del_derived is performed here
1127
+ for ind in resu.non_redundant_index_generator():
1128
+ resu[[ind]] = dom.scalar_field({chart: scomp[[ind]].expr(schart)})
1129
+
1130
+ def add_expr_from_subdomain(self, frame, subdomain):
1131
+ r"""
1132
+ Add an expression to an existing component from a subdomain.
1133
+
1134
+ INPUT:
1135
+
1136
+ - ``frame`` -- local frame `e` in which the components are to be set
1137
+ - ``subdomain`` -- open subset of `e`'s domain in which the
1138
+ components have additional expressions
1139
+
1140
+ EXAMPLES:
1141
+
1142
+ We are going to consider a section on the trivial rank 2 vector bundle
1143
+ over the 2-sphere::
1144
+
1145
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
1146
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
1147
+ sage: S2.declare_union(U,V)
1148
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
1149
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
1150
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
1151
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
1152
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
1153
+ ....: restrictions2= u^2+v^2!=0)
1154
+ sage: W = U.intersection(V)
1155
+ sage: uv_to_xy = xy_to_uv.inverse()
1156
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
1157
+ sage: e = E.local_frame('e') # frame to trivialize E
1158
+ sage: eU = e.restrict(U); eV = e.restrict(V); eW = e.restrict(W) # this step is essential since U, V and W must be trivial
1159
+
1160
+ To define a section ``s`` on `S^2`, we first set the components on
1161
+ ``U``::
1162
+
1163
+ sage: s = E.section(name='s')
1164
+ sage: sU = s.restrict(U)
1165
+ sage: sU[:] = [x, y]
1166
+
1167
+ But because ``E`` is trivial, these components can be extended with
1168
+ respect to the global frame ``e`` onto `S^2`::
1169
+
1170
+ sage: s.add_comp_by_continuation(e, U)
1171
+
1172
+ One can see that ``s`` is not yet fully defined: the components
1173
+ (scalar fields) do not have values on the whole manifold::
1174
+
1175
+ sage: sorted(s._components.values())[0]._comp[(1,)].display()
1176
+ S^2 → ℝ
1177
+ on U: (x, y) ↦ x
1178
+ on W: (u, v) ↦ u/(u^2 + v^2)
1179
+
1180
+ To fix that, we extend the components from ``W`` to ``V`` first, using
1181
+ :meth:`add_comp_by_continuation`::
1182
+
1183
+ sage: s.add_comp_by_continuation(eV, W, stereoS)
1184
+
1185
+ Then, the expression on the subdomain ``V`` is added to the
1186
+ components on `S^2` already known by::
1187
+
1188
+ sage: s.add_expr_from_subdomain(e, V)
1189
+
1190
+ The definition of ``s`` is now complete::
1191
+
1192
+ sage: sorted(s._components.values())[0]._comp[(2,)].display()
1193
+ S^2 → ℝ
1194
+ on U: (x, y) ↦ y
1195
+ on V: (u, v) ↦ v/(u^2 + v^2)
1196
+ """
1197
+ if self.is_immutable():
1198
+ raise ValueError("the expressions of an immutable element "
1199
+ "cannot be changed")
1200
+ dom = frame._domain
1201
+ if not dom.is_subset(self._domain):
1202
+ raise ValueError("the local frame is not defined on a subset " +
1203
+ "of the section's domain")
1204
+ if frame not in self.restrict(frame.domain())._components:
1205
+ raise ValueError("the section doesn't have an expression in "
1206
+ "the frame " + frame._repr_())
1207
+ comp = self.comp(frame)
1208
+ scomp = self.restrict(subdomain).comp(frame.restrict(subdomain))
1209
+ for ind in comp.non_redundant_index_generator():
1210
+ comp[[ind]]._express.update(scomp[[ind]]._express)
1211
+
1212
+ rst = self._restrictions.copy()
1213
+ self._del_derived() # delete restrictions
1214
+ self._restrictions = rst
1215
+
1216
+ def comp(self, basis=None, from_basis=None):
1217
+ r"""
1218
+ Return the components in a given local frame.
1219
+
1220
+ If the components are not known already, they are computed by the
1221
+ change-of-basis formula from components in another local frame.
1222
+
1223
+ INPUT:
1224
+
1225
+ - ``basis`` -- (default: ``None``) local frame in which the components
1226
+ are required; if none is provided, the components are assumed to
1227
+ refer to the section module's default frame on the corresponding
1228
+ domain
1229
+ - ``from_basis`` -- (default: ``None``) local frame from which the
1230
+ required components are computed, via the change-of-basis
1231
+ formula, if they are not known already in the basis ``basis``
1232
+
1233
+ OUTPUT:
1234
+
1235
+ - components in the local frame ``basis``, as a
1236
+ :class:`~sage.tensor.modules.comp.Components`
1237
+
1238
+ EXAMPLES:
1239
+
1240
+ Components of a section defined on a rank 2 vector bundle over two
1241
+ open subsets::
1242
+
1243
+ sage: M = Manifold(2, 'M', structure='top')
1244
+ sage: X.<x, y> = M.chart()
1245
+ sage: U = M.open_subset('U'); V = M.open_subset('V')
1246
+ sage: M.declare_union(U, V)
1247
+ sage: XU = X.restrict(U); XV = X.restrict(V)
1248
+ sage: E = M.vector_bundle(2, 'E')
1249
+ sage: e = E.local_frame('e', domain=U); e
1250
+ Local frame (E|_U, (e_0,e_1))
1251
+ sage: f = E.local_frame('f', domain=V); f
1252
+ Local frame (E|_V, (f_0,f_1))
1253
+ sage: s = E.section(name='s')
1254
+ sage: s[e,:] = - x + y^3, 2+x
1255
+ sage: s[f,0] = x^2
1256
+ sage: s[f,1] = x+y
1257
+ sage: s.comp(e)
1258
+ 1-index components w.r.t. Local frame (E|_U, (e_0,e_1))
1259
+ sage: s.comp(e)[:]
1260
+ [y^3 - x, x + 2]
1261
+ sage: s.comp(f)
1262
+ 1-index components w.r.t. Local frame (E|_V, (f_0,f_1))
1263
+ sage: s.comp(f)[:]
1264
+ [x^2, x + y]
1265
+
1266
+ Since ``e`` is the default frame of ``E|_U``, the argument ``e`` can
1267
+ be omitted after restricting::
1268
+
1269
+ sage: e is E.section_module(domain=U).default_frame()
1270
+ True
1271
+ sage: s.restrict(U).comp() is s.comp(e)
1272
+ True
1273
+ """
1274
+ if basis is None:
1275
+ basis = self._smodule.default_frame()
1276
+ if basis is None: # should be "is still None" ;-)
1277
+ raise ValueError("a frame must be provided for the display")
1278
+
1279
+ rst = self.restrict(basis._domain)
1280
+ return rst.comp(basis=basis, from_basis=from_basis)
1281
+
1282
+ def display(self, frame=None, chart=None):
1283
+ r"""
1284
+ Display the section in terms of its expansion with respect to a given
1285
+ local frame.
1286
+
1287
+ The output is either text-formatted (console mode) or LaTeX-formatted
1288
+ (notebook mode).
1289
+
1290
+ INPUT:
1291
+
1292
+ - ``frame`` -- (default: ``None``) local frame with respect to
1293
+ which the section is expanded; if ``frame`` is ``None`` and ``chart``
1294
+ is not ``None``, the default frame in the corresponding section module
1295
+ is assumed
1296
+ - ``chart`` -- (default: ``None``) chart with respect to which the
1297
+ components of the section in the selected frame are expressed;
1298
+ if ``None``, the default chart of the local frame domain is assumed
1299
+
1300
+ EXAMPLES:
1301
+
1302
+ Display of section on a rank 2 vector bundle over the 2-sphere::
1303
+
1304
+ sage: S2 = Manifold(2, 'S^2', structure='top', start_index=1)
1305
+ sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively
1306
+ sage: S2.declare_union(U,V)
1307
+ sage: stereoN.<x,y> = U.chart() # stereographic coordinates from the North pole
1308
+ sage: stereoS.<u,v> = V.chart() # stereographic coordinates from the South pole
1309
+ sage: xy_to_uv = stereoN.transition_map(stereoS,
1310
+ ....: (x/(x^2+y^2), y/(x^2+y^2)),
1311
+ ....: intersection_name='W',
1312
+ ....: restrictions1= x^2+y^2!=0,
1313
+ ....: restrictions2= u^2+v^2!=0)
1314
+ sage: W = U.intersection(V)
1315
+ sage: uv_to_xy = xy_to_uv.inverse()
1316
+ sage: E = S2.vector_bundle(2, 'E') # define vector bundle
1317
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1318
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1319
+ sage: transf = phi_U.transition_map(phi_V, [[0,1],[1,0]])
1320
+ sage: fN = phi_U.frame(); fS = phi_V.frame() # get induced frames
1321
+ sage: s = E.section(name='s')
1322
+ sage: s[fN,:] = [x, y]
1323
+ sage: s.add_comp_by_continuation(fS, W, stereoS)
1324
+ sage: s.display(fN)
1325
+ s = x (phi_U^*e_1) + y (phi_U^*e_2)
1326
+ sage: s.display(fS)
1327
+ s = v/(u^2 + v^2) (phi_V^*e_1) + u/(u^2 + v^2) (phi_V^*e_2)
1328
+
1329
+ Since ``fN`` is the default frame on ``E|_U``, the argument ``fN`` can
1330
+ be omitted after restricting::
1331
+
1332
+ sage: fN is E.section_module(domain=U).default_frame()
1333
+ True
1334
+ sage: s.restrict(U).display()
1335
+ s = x (phi_U^*e_1) + y (phi_U^*e_2)
1336
+
1337
+ Similarly, since ``fS`` is ``V``'s default frame, the argument ``fS``
1338
+ can be omitted when considering the restriction of ``s`` to ``V``::
1339
+
1340
+ sage: s.restrict(V).display()
1341
+ s = v/(u^2 + v^2) (phi_V^*e_1) + u/(u^2 + v^2) (phi_V^*e_2)
1342
+
1343
+ The second argument comes into play whenever the frame's domain is
1344
+ covered by two distinct charts. Since ``stereoN.restrict(W)`` is the
1345
+ default chart on ``W``, the second argument can be omitted for the
1346
+ expression in this chart::
1347
+
1348
+ sage: s.display(fS.restrict(W))
1349
+ s = y (phi_V^*e_1) + x (phi_V^*e_2)
1350
+
1351
+ To get the expression in the other chart, the second argument must be
1352
+ used::
1353
+
1354
+ sage: s.display(fN.restrict(W), stereoS.restrict(W))
1355
+ s = u/(u^2 + v^2) (phi_U^*e_1) + v/(u^2 + v^2) (phi_U^*e_2)
1356
+
1357
+ One can ask for the display with respect to a frame in which ``s`` has
1358
+ not been initialized yet (this will automatically trigger the use of
1359
+ the change-of-frame formula for tensors)::
1360
+
1361
+ sage: a = E.section_module(domain=U).automorphism()
1362
+ sage: a[:] = [[1+x^2,0],[0,1+y^2]]
1363
+ sage: e = fN.new_frame(a, 'e')
1364
+ sage: [e[i].display() for i in S2.irange()]
1365
+ [e_1 = (x^2 + 1) (phi_U^*e_1), e_2 = (y^2 + 1) (phi_U^*e_2)]
1366
+ sage: s.display(e)
1367
+ s = x/(x^2 + 1) e_1 + y/(y^2 + 1) e_2
1368
+
1369
+ A shortcut of ``display()`` is ``disp()``::
1370
+
1371
+ sage: s.disp(fS)
1372
+ s = v/(u^2 + v^2) (phi_V^*e_1) + u/(u^2 + v^2) (phi_V^*e_2)
1373
+ """
1374
+ if frame is None:
1375
+ frame = self._smodule.default_frame()
1376
+ if frame is None: # should be "is still None" ;-)
1377
+ raise ValueError("a frame must be provided for the display")
1378
+ rst = self.restrict(frame._domain)
1379
+ return rst.display(frame, chart)
1380
+
1381
+ disp = display
1382
+
1383
+ def display_comp(self, frame=None, chart=None, only_nonzero=True):
1384
+ r"""
1385
+ Display the section components with respect to a given frame,
1386
+ one per line.
1387
+
1388
+ The output is either text-formatted (console mode) or LaTeX-formatted
1389
+ (notebook mode).
1390
+
1391
+ INPUT:
1392
+
1393
+ - ``frame`` -- (default: ``None``) local frame with respect to which
1394
+ the section components are defined; if ``None``, then the default
1395
+ frame on the section module is used
1396
+ - ``chart`` -- (default: ``None``) chart specifying the coordinate
1397
+ expression of the components; if ``None``, the default chart of the
1398
+ section domain is used
1399
+ - ``only_nonzero`` -- boolean (default: ``True``); if ``True``, only
1400
+ nonzero components are displayed
1401
+
1402
+ EXAMPLES:
1403
+
1404
+ Display of the components of a section defined on two open subsets::
1405
+
1406
+ sage: M = Manifold(2, 'M', structure='top')
1407
+ sage: U = M.open_subset('U')
1408
+ sage: c_xy.<x, y> = U.chart()
1409
+ sage: V = M.open_subset('V')
1410
+ sage: c_uv.<u, v> = V.chart()
1411
+ sage: M.declare_union(U,V) # M is the union of U and V
1412
+ sage: E = M.vector_bundle(2, 'E')
1413
+ sage: e = E.local_frame('e', domain=U)
1414
+ sage: f = E.local_frame('f', domain=V)
1415
+ sage: s = E.section(name='s')
1416
+ sage: s[e,0] = - x + y^3
1417
+ sage: s[e,1] = 2+x
1418
+ sage: s[f,1] = - u*v
1419
+ sage: s.display_comp(e)
1420
+ s^0 = y^3 - x
1421
+ s^1 = x + 2
1422
+ sage: s.display_comp(f)
1423
+ s^1 = -u*v
1424
+
1425
+ See documentation of
1426
+ :meth:`sage.manifolds.section.TrivialSection.display_comp`
1427
+ for more options.
1428
+ """
1429
+ if frame is None:
1430
+ frame = self._smodule.default_frame()
1431
+ if frame is None: # should be "is still None" ;-)
1432
+ raise ValueError("a frame must be provided for the display")
1433
+ rst = self.restrict(frame.domain())
1434
+ return rst.display_comp(frame=frame, chart=chart,
1435
+ only_nonzero=only_nonzero)
1436
+
1437
+ def at(self, point):
1438
+ r"""
1439
+ Value of ``self`` at a point of its domain.
1440
+
1441
+ If the current section is
1442
+
1443
+ .. MATH::
1444
+
1445
+ s:\ U \longrightarrow E ,
1446
+
1447
+ then for any point `p \in U`, `s(p)` is a vector in the fiber `E_p` of
1448
+ `E` at `p`.
1449
+
1450
+ INPUT:
1451
+
1452
+ - ``point`` -- :class:`~sage.manifolds.point.ManifoldPoint`;
1453
+ point `p` in the domain of the section `U`
1454
+
1455
+ OUTPUT:
1456
+
1457
+ - :class:`~sage.manifolds.vector_bundle_fiber_element.VectorBundleFiberElement`
1458
+ representing the vector `s(p)` in the fiber `E_p` of `E` at `p`.
1459
+
1460
+ EXAMPLES:
1461
+
1462
+ Vector on a rank 2 vector bundle fiber over a non-parallelizable
1463
+ 2-dimensional manifold::
1464
+
1465
+ sage: M = Manifold(2, 'M', structure='top')
1466
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1467
+ sage: M.declare_union(U,V) # M is the union of U and V
1468
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1469
+ sage: transf = c_xy.transition_map(c_uv, (x+y, x-y),
1470
+ ....: intersection_name='W', restrictions1= x>0,
1471
+ ....: restrictions2= u+v>0)
1472
+ sage: inv = transf.inverse()
1473
+ sage: W = U.intersection(V)
1474
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1475
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1476
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1477
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1478
+ sage: fU = phi_U.frame(); fV = phi_V.frame() # get induced frames
1479
+ sage: s = E.section({fU: [1+y, x]}, name='s')
1480
+ sage: s.add_comp_by_continuation(fV, W, chart=c_uv)
1481
+ sage: s.display(fU)
1482
+ s = (y + 1) (phi_U^*e_1) + x (phi_U^*e_2)
1483
+ sage: s.display(fV)
1484
+ s = (1/4*u^2 + 1/2*u*v + 1/4*v^2) (phi_V^*e_1) + (1/4*u^2 - 1/4*v^2
1485
+ + 1/2*u + 1/2*v) (phi_V^*e_2)
1486
+ sage: p = M.point((2,3), chart=c_xy, name='p')
1487
+ sage: sp = s.at(p) ; sp
1488
+ Vector s in the fiber of E at Point p on the 2-dimensional
1489
+ topological manifold M
1490
+ sage: sp.parent()
1491
+ Fiber of E at Point p on the 2-dimensional topological manifold M
1492
+ sage: sp.display(fU.at(p))
1493
+ s = 4 (phi_U^*e_1) + 2 (phi_U^*e_2)
1494
+ sage: sp.display(fV.at(p))
1495
+ s = 4 (phi_V^*e_1) + 8 (phi_V^*e_2)
1496
+ sage: p.coord(c_uv) # to check the above expression
1497
+ (5, -1)
1498
+ """
1499
+ if point not in self._domain:
1500
+ raise ValueError("the {} is not a point in the ".format(point) +
1501
+ "domain of {}".format(self))
1502
+ for dom, rst in self._restrictions.items():
1503
+ if point in dom:
1504
+ return rst.at(point)
1505
+
1506
+ def __getitem__(self, args):
1507
+ r"""
1508
+ Return a component with respect to some frame.
1509
+
1510
+ INPUT:
1511
+
1512
+ - ``args`` -- list of indices defining the component; if ``[:]`` is
1513
+ provided, all the components are returned
1514
+
1515
+ The frame can be passed as the first item of ``args``. If not, the
1516
+ default frame of the corresponding section module is assumed.
1517
+
1518
+ TESTS::
1519
+
1520
+ sage: M = Manifold(3, 'M', structure='top') # the 2-dimensional sphere S^3
1521
+ sage: U = M.open_subset('U') # complement of the North pole
1522
+ sage: c_xyz.<x,y,z> = U.chart() # stereographic coordinates from the North pole
1523
+ sage: V = M.open_subset('V') # complement of the South pole
1524
+ sage: c_uvt.<u,v,t> = V.chart() # stereographic coordinates from the South pole
1525
+ sage: M.declare_union(U,V) # S^3 is the union of U and V
1526
+ sage: E = M.vector_bundle(3, 'E')
1527
+ sage: e = E.local_frame('e')
1528
+ sage: s = E.section(name='s')
1529
+ sage: s[e, :] = [x+y, -2*z, 3*y^2]
1530
+ sage: s.__getitem__(1)
1531
+ -2*z
1532
+ sage: s.__getitem__(2)
1533
+ 3*y^2
1534
+ sage: s.__getitem__((e,1))
1535
+ -2*z
1536
+ sage: s.__getitem__((e, 1, c_xyz))
1537
+ -2*z
1538
+ sage: s.__getitem__(slice(None))
1539
+ [x + y, -2*z, 3*y^2]
1540
+ sage: s.__getitem__((e,slice(None)))
1541
+ [x + y, -2*z, 3*y^2]
1542
+ sage: s.__getitem__((e,[slice(None)]))
1543
+ [Scalar field on the 3-dimensional topological manifold M,
1544
+ Scalar field on the 3-dimensional topological manifold M,
1545
+ Scalar field on the 3-dimensional topological manifold M]
1546
+ """
1547
+ if isinstance(args, str): # section with specified indices
1548
+ return TensorWithIndices(self, args).update()
1549
+ if isinstance(args, list): # case of [[...]] syntax
1550
+ if not isinstance(args[0], (int, Integer, slice)):
1551
+ frame = args[0]
1552
+ args = args[1:]
1553
+ else:
1554
+ frame = self._smodule.default_frame()
1555
+ else:
1556
+ if isinstance(args, (int, Integer, slice)):
1557
+ frame = self._smodule.default_frame()
1558
+ elif not isinstance(args[0], (int, Integer, slice)):
1559
+ frame = args[0]
1560
+ args = args[1:]
1561
+ else:
1562
+ frame = self._smodule.default_frame()
1563
+ return self.comp(frame)[args]
1564
+
1565
+ def __setitem__(self, args, value):
1566
+ r"""
1567
+ Set a component with respect to some local frame.
1568
+
1569
+ INPUT:
1570
+
1571
+ - ``args`` -- list of indices; if ``[:]`` is provided, all the
1572
+ components are set; the frame can be passed as the first item
1573
+ of ``args``; if not, the default frame of the corresponding section
1574
+ module is assumed
1575
+ - ``value`` -- the value to be set or a list of values if
1576
+ ``args = [:]``
1577
+
1578
+ TESTS::
1579
+
1580
+ sage: M = Manifold(3, 'M', structure='top') # the 3-dimensional sphere S^3
1581
+ sage: U = M.open_subset('U') # complement of the North pole
1582
+ sage: c_xyz.<x,y,z> = U.chart() # stereographic coordinates from the North pole
1583
+ sage: V = M.open_subset('V') # complement of the South pole
1584
+ sage: c_uvt.<u,v,t> = V.chart() # stereographic coordinates from the South pole
1585
+ sage: M.declare_union(U,V) # S^3 is the union of U and V
1586
+ sage: E = M.vector_bundle(3, 'E')
1587
+ sage: e = E.local_frame('e')
1588
+ sage: s = E.section(name='s')
1589
+ sage: s.__setitem__((e, 0), x+y^2)
1590
+ sage: s.display(e)
1591
+ s = (y^2 + x) e_0
1592
+ sage: s.__setitem__(0, x+y^2) # same as above since e is the default frame on E
1593
+ sage: s.display()
1594
+ s = (y^2 + x) e_0
1595
+ sage: s.__setitem__(slice(None), [x+y, 3*y^2, x*y])
1596
+ sage: s.display()
1597
+ s = (x + y) e_0 + 3*y^2 e_1 + x*y e_2
1598
+ """
1599
+ if isinstance(args, list): # case of [[...]] syntax
1600
+ if not isinstance(args[0], (int, Integer, slice)):
1601
+ frame = args[0]
1602
+ args = args[1:]
1603
+ else:
1604
+ frame = self._smodule.default_frame()
1605
+ else:
1606
+ if isinstance(args, (int, Integer, slice)):
1607
+ frame = self._smodule.default_frame()
1608
+ elif not isinstance(args[0], (int, Integer, slice)):
1609
+ frame = args[0]
1610
+ args = args[1:]
1611
+ else:
1612
+ frame = self._smodule.default_frame()
1613
+ self.set_comp(frame)[args] = value
1614
+
1615
+ def copy_from(self, other):
1616
+ r"""
1617
+ Make ``self`` a copy of ``other``.
1618
+
1619
+ INPUT:
1620
+
1621
+ - ``other`` -- other section, in the same module as ``self``
1622
+
1623
+ .. NOTE::
1624
+
1625
+ While the derived quantities are not copied, the name is kept.
1626
+
1627
+ .. WARNING::
1628
+
1629
+ All previous defined components and restrictions will be deleted!
1630
+
1631
+ EXAMPLES::
1632
+
1633
+ sage: M = Manifold(2, 'M', structure='top')
1634
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1635
+ sage: M.declare_union(U,V) # M is the union of U and V
1636
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1637
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1638
+ ....: intersection_name='W', restrictions1= x>0,
1639
+ ....: restrictions2= u+v>0)
1640
+ sage: uv_to_xy = xy_to_uv.inverse()
1641
+ sage: W = U.intersection(V)
1642
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1643
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1644
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1645
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1646
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1647
+ sage: s = E.section(name='s')
1648
+ sage: s[fU,:] = [2, 1-y]
1649
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1650
+ sage: t = E.section(name='t')
1651
+ sage: t.copy_from(s)
1652
+ sage: t.display(fU)
1653
+ t = 2 (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1654
+ sage: s == t
1655
+ True
1656
+
1657
+ If the original section is modified, the copy is not::
1658
+
1659
+ sage: s[fU,0] = -1
1660
+ sage: s.display(fU)
1661
+ s = -(phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1662
+ sage: t.display(fU)
1663
+ t = 2 (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1664
+ sage: s == t
1665
+ False
1666
+ """
1667
+ if self.is_immutable():
1668
+ raise ValueError("the components of an immutable element "
1669
+ "cannot be changed")
1670
+ if other not in self.parent():
1671
+ raise TypeError("the original must be an element of "
1672
+ f"{self.parent()}")
1673
+ self._del_derived()
1674
+ self._del_restrictions() # delete restrictions
1675
+ for dom, rst in other._restrictions.items():
1676
+ self._restrictions[dom] = rst.copy(name=self._name,
1677
+ latex_name=self._latex_name)
1678
+ self._is_zero = other._is_zero
1679
+
1680
+ def copy(self, name=None, latex_name=None):
1681
+ r"""
1682
+ Return an exact copy of ``self``.
1683
+
1684
+ INPUT:
1685
+
1686
+ - ``name`` -- (default: ``None``) name given to the copy
1687
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
1688
+ copy; if none is provided, the LaTeX symbol is set to ``name``
1689
+
1690
+ .. NOTE::
1691
+
1692
+ The name and the derived quantities are not copied.
1693
+
1694
+ EXAMPLES:
1695
+
1696
+ Copy of a section on a rank 2 vector bundle over a 2-dimensional
1697
+ manifold::
1698
+
1699
+ sage: M = Manifold(2, 'M', structure='top')
1700
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1701
+ sage: M.declare_union(U,V) # M is the union of U and V
1702
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1703
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1704
+ ....: intersection_name='W', restrictions1= x>0,
1705
+ ....: restrictions2= u+v>0)
1706
+ sage: uv_to_xy = xy_to_uv.inverse()
1707
+ sage: W = U.intersection(V)
1708
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1709
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1710
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1711
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1712
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1713
+ sage: s = E.section(name='s')
1714
+ sage: s[fU,:] = [2, 1-y]
1715
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1716
+ sage: t = s.copy(); t
1717
+ Section on the 2-dimensional topological manifold M with values in
1718
+ the real vector bundle E of rank 2
1719
+ sage: t.display(fU)
1720
+ 2 (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1721
+ sage: t == s
1722
+ True
1723
+
1724
+ If the original section is modified, the copy is not::
1725
+
1726
+ sage: s[fU,0] = -1
1727
+ sage: s.display(fU)
1728
+ s = -(phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1729
+ sage: t.display(fU)
1730
+ 2 (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
1731
+ sage: t == s
1732
+ False
1733
+ """
1734
+ resu = self._new_instance()
1735
+ # set resu name
1736
+ if name is not None:
1737
+ resu._name = name
1738
+ if latex_name is None:
1739
+ resu._latex_name = name
1740
+ if latex_name is not None:
1741
+ resu._latex_name = latex_name
1742
+ # set restrictions
1743
+ for dom, rst in self._restrictions.items():
1744
+ resu._restrictions[dom] = rst.copy(name=name,
1745
+ latex_name=latex_name)
1746
+ resu._is_zero = self._is_zero
1747
+ return resu
1748
+
1749
+ def _common_subdomains(self, other):
1750
+ r"""
1751
+ Return the list of subdomains of ``self._domain`` on which
1752
+ both ``self`` and ``other`` have known restrictions.
1753
+
1754
+ TESTS::
1755
+
1756
+ sage: M = Manifold(2, 'M', structure='top')
1757
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1758
+ sage: M.declare_union(U,V) # M is the union of U and V
1759
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1760
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1761
+ ....: intersection_name='W', restrictions1= x>0,
1762
+ ....: restrictions2= u+v>0)
1763
+ sage: uv_to_xy = xy_to_uv.inverse()
1764
+ sage: W = U.intersection(V)
1765
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1766
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1767
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1768
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1769
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1770
+ sage: s = E.section(name='s')
1771
+ sage: s[fU,:] = [x+y, 0]
1772
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1773
+ sage: sorted(s._common_subdomains(s), key=str)
1774
+ [Open subset U of the 2-dimensional topological manifold M,
1775
+ Open subset V of the 2-dimensional topological manifold M,
1776
+ Open subset W of the 2-dimensional topological manifold M]
1777
+ sage: t = E.section(name='t')
1778
+ sage: t._common_subdomains(s)
1779
+ []
1780
+ sage: t[fU, 0] = 0
1781
+ sage: t._common_subdomains(s)
1782
+ [Open subset U of the 2-dimensional topological manifold M]
1783
+ sage: t[fV, 0] = 0
1784
+ sage: sorted(t._common_subdomains(s), key=str)
1785
+ [Open subset U of the 2-dimensional topological manifold M,
1786
+ Open subset V of the 2-dimensional topological manifold M]
1787
+ """
1788
+ resu = []
1789
+ for dom in self._restrictions:
1790
+ if dom in other._restrictions:
1791
+ resu.append(dom)
1792
+ return resu
1793
+
1794
+ def __eq__(self, other):
1795
+ r"""
1796
+ Comparison (equality) operator.
1797
+
1798
+ INPUT:
1799
+
1800
+ - ``other`` -- a section or 0
1801
+
1802
+ OUTPUT: ``True`` if ``self`` is equal to ``other`` and ``False`` otherwise
1803
+
1804
+ TESTS::
1805
+
1806
+ sage: M = Manifold(2, 'M', structure='top')
1807
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1808
+ sage: M.declare_union(U,V) # M is the union of U and V
1809
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1810
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1811
+ ....: intersection_name='W', restrictions1= x>0,
1812
+ ....: restrictions2= u+v>0)
1813
+ sage: uv_to_xy = xy_to_uv.inverse()
1814
+ sage: W = U.intersection(V)
1815
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1816
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1817
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1818
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1819
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1820
+ sage: s = E.section(name='s')
1821
+ sage: s[fU,:] = [x+y, 0]
1822
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1823
+ sage: s == s
1824
+ True
1825
+ sage: s == s.copy()
1826
+ True
1827
+ sage: t = E.section(name='t')
1828
+ sage: t.set_restriction(s.restrict(U))
1829
+ sage: s == t # False since t has not been defined on V
1830
+ False
1831
+ sage: t.set_restriction(s.restrict(V))
1832
+ sage: s == t # True now
1833
+ True
1834
+ sage: t[fU, 0] = -1
1835
+ sage: s == t # False since a has been reset on U (domain of fU)
1836
+ False
1837
+ sage: s.parent().zero() == 0
1838
+ True
1839
+ """
1840
+ if other is self:
1841
+ return True
1842
+ if other in ZZ: # to compare with 0
1843
+ if other == 0:
1844
+ return self.is_zero()
1845
+ return False
1846
+ elif not isinstance(other, Section):
1847
+ return False
1848
+ else: # other is another section
1849
+ if other._smodule != self._smodule:
1850
+ return False
1851
+ # Non-trivial open covers of the domain:
1852
+ for oc in self._domain.open_covers(trivial=False):
1853
+ resu = True
1854
+ for dom in oc:
1855
+ try:
1856
+ resu = resu and \
1857
+ bool(self.restrict(dom) == other.restrict(dom))
1858
+ except ValueError:
1859
+ break
1860
+ else:
1861
+ # If this point is reached, no exception has occurred; hence
1862
+ # the result is valid and can be returned:
1863
+ return resu
1864
+ # If this point is reached, the comparison has not been possible
1865
+ # on any open cover; we then compare the restrictions to
1866
+ # subdomains:
1867
+ if not self._restrictions:
1868
+ return False # self is not initialized
1869
+ if len(self._restrictions) != len(other._restrictions):
1870
+ return False # the restrictions are not on the same subdomains
1871
+ resu = True
1872
+ for dom, rst in self._restrictions.items():
1873
+ if dom in other._restrictions:
1874
+ resu = resu and bool(rst == other._restrictions[dom])
1875
+ else:
1876
+ return False # the restrictions are not on the same
1877
+ # subdomains
1878
+ return resu
1879
+
1880
+ def __ne__(self, other):
1881
+ r"""
1882
+ Inequality operator.
1883
+
1884
+ INPUT:
1885
+
1886
+ - ``other`` -- section or 0
1887
+
1888
+ OUTPUT:
1889
+
1890
+ - ``True`` if ``self`` is different from ``other`` and ``False``
1891
+ otherwise
1892
+
1893
+ TESTS::
1894
+
1895
+ sage: M = Manifold(2, 'M', structure='top')
1896
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1897
+ sage: M.declare_union(U,V) # M is the union of U and V
1898
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1899
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1900
+ ....: intersection_name='W', restrictions1= x>0,
1901
+ ....: restrictions2= u+v>0)
1902
+ sage: uv_to_xy = xy_to_uv.inverse()
1903
+ sage: W = U.intersection(V)
1904
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1905
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1906
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1907
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1908
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1909
+ sage: s = E.section(name='s')
1910
+ sage: s[fU,:] = [x+y, 0]
1911
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1912
+ sage: s != s
1913
+ False
1914
+ sage: s != s.copy()
1915
+ False
1916
+ sage: s != 0
1917
+ True
1918
+ """
1919
+ return not (self == other)
1920
+
1921
+ def __pos__(self):
1922
+ r"""
1923
+ Unary plus operator.
1924
+
1925
+ OUTPUT: an exact copy of ``self``
1926
+
1927
+ TESTS::
1928
+
1929
+ sage: M = Manifold(2, 'M', structure='top')
1930
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1931
+ sage: M.declare_union(U,V) # M is the union of U and V
1932
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1933
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1934
+ ....: intersection_name='W', restrictions1= x>0,
1935
+ ....: restrictions2= u+v>0)
1936
+ sage: uv_to_xy = xy_to_uv.inverse()
1937
+ sage: W = U.intersection(V)
1938
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1939
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1940
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1941
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1942
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1943
+ sage: s = E.section(name='s')
1944
+ sage: s[fU,:] = [x, 1]
1945
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1946
+ sage: t = s.__pos__(); t
1947
+ Section +s on the 2-dimensional topological manifold M with values
1948
+ in the real vector bundle E of rank 2
1949
+ sage: t.display(fU)
1950
+ +s = x (phi_U^*e_1) + (phi_U^*e_2)
1951
+ """
1952
+ resu = self._new_instance()
1953
+ for dom, rst in self._restrictions.items():
1954
+ resu._restrictions[dom] = + rst
1955
+ if self._name is not None:
1956
+ resu._name = '+' + self._name
1957
+ if self._latex_name is not None:
1958
+ resu._latex_name = '+' + self._latex_name
1959
+ return resu
1960
+
1961
+ def __neg__(self):
1962
+ r"""
1963
+ Unary minus operator.
1964
+
1965
+ OUTPUT: the tensor field `-T`, where `T` is ``self``
1966
+
1967
+ TESTS::
1968
+
1969
+ sage: M = Manifold(2, 'M', structure='top')
1970
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
1971
+ sage: M.declare_union(U,V) # M is the union of U and V
1972
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
1973
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
1974
+ ....: intersection_name='W', restrictions1= x>0,
1975
+ ....: restrictions2= u+v>0)
1976
+ sage: uv_to_xy = xy_to_uv.inverse()
1977
+ sage: W = U.intersection(V)
1978
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
1979
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
1980
+ sage: phi_V = E.trivialization('phi_V', domain=V)
1981
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
1982
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
1983
+ sage: s = E.section(name='s')
1984
+ sage: s[fU,:] = [x, 1]
1985
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
1986
+ sage: s.display(fU)
1987
+ s = x (phi_U^*e_1) + (phi_U^*e_2)
1988
+ sage: s.display(fV)
1989
+ s = (1/2*u + 1/2*v) (phi_V^*e_1) + (1/4*u^2 + 1/2*u*v + 1/4*v^2) (phi_V^*e_2)
1990
+ sage: t = s.__neg__(); t
1991
+ Section -s on the 2-dimensional topological manifold M with values
1992
+ in the real vector bundle E of rank 2
1993
+ sage: t.display(fU)
1994
+ -s = -x (phi_U^*e_1) - (phi_U^*e_2)
1995
+ sage: t.display(fV)
1996
+ -s = (-1/2*u - 1/2*v) (phi_V^*e_1) + (-1/4*u^2 - 1/2*u*v - 1/4*v^2) (phi_V^*e_2)
1997
+ sage: s == -t # indirect doctest
1998
+ True
1999
+ """
2000
+ resu = self._new_instance()
2001
+ for dom, rst in self._restrictions.items():
2002
+ resu._restrictions[dom] = - rst
2003
+ if self._name is not None:
2004
+ resu._name = '-' + self._name
2005
+ if self._latex_name is not None:
2006
+ resu._latex_name = '-' + self._latex_name
2007
+ return resu
2008
+
2009
+ ######### ModuleElement arithmetic operators ########
2010
+
2011
+ def _add_(self, other):
2012
+ r"""
2013
+ Section addition.
2014
+
2015
+ INPUT:
2016
+
2017
+ - ``other`` -- a section, in the same section module as ``self``
2018
+
2019
+ OUTPUT: the section resulting from the addition of ``self`` and ``other``
2020
+
2021
+ TESTS::
2022
+
2023
+ sage: M = Manifold(2, 'M', structure='top')
2024
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
2025
+ sage: M.declare_union(U,V) # M is the union of U and V
2026
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
2027
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
2028
+ ....: intersection_name='W', restrictions1= x>0,
2029
+ ....: restrictions2= u+v>0)
2030
+ sage: uv_to_xy = xy_to_uv.inverse()
2031
+ sage: W = U.intersection(V)
2032
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
2033
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
2034
+ sage: phi_V = E.trivialization('phi_V', domain=V)
2035
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
2036
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
2037
+ sage: s = E.section(name='s')
2038
+ sage: s[fU,:] = [x, 1]
2039
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
2040
+ sage: t = E.section(name='t')
2041
+ sage: t[fU,:] = [2, y]
2042
+ sage: t.add_comp_by_continuation(fV, U.intersection(V), c_uv)
2043
+ sage: u = s._add_(t); u
2044
+ Section s+t on the 2-dimensional topological manifold M with values
2045
+ in the real vector bundle E of rank 2
2046
+ sage: s.display(fU)
2047
+ s = x (phi_U^*e_1) + (phi_U^*e_2)
2048
+ sage: t.display(fU)
2049
+ t = 2 (phi_U^*e_1) + y (phi_U^*e_2)
2050
+ sage: u.display(fU)
2051
+ s+t = (x + 2) (phi_U^*e_1) + (y + 1) (phi_U^*e_2)
2052
+ sage: u == s + t # indirect doctest
2053
+ True
2054
+ sage: z = s.parent().zero(); z
2055
+ Section zero on the 2-dimensional topological manifold M with values
2056
+ in the real vector bundle E of rank 2
2057
+ sage: s._add_(z) == s
2058
+ True
2059
+ sage: z._add_(s) == s
2060
+ True
2061
+ """
2062
+ # Case zero:
2063
+ if self._is_zero:
2064
+ return other
2065
+ if other._is_zero:
2066
+ return self
2067
+ # Generic case:
2068
+ resu_rst = {}
2069
+ for dom in self._common_subdomains(other):
2070
+ resu_rst[dom] = self._restrictions[dom] + other._restrictions[dom]
2071
+ resu = self._vbundle.section(domain=self._domain)
2072
+ resu._restrictions = resu_rst
2073
+ if self._name is not None and other._name is not None:
2074
+ resu._name = self._name + '+' + other._name
2075
+ if self._latex_name is not None and other._latex_name is not None:
2076
+ resu._latex_name = self._latex_name + '+' + other._latex_name
2077
+ return resu
2078
+
2079
+ def _sub_(self, other):
2080
+ r"""
2081
+ Section subtraction.
2082
+
2083
+ INPUT:
2084
+
2085
+ - ``other`` -- a section in the same section module as ``self``
2086
+
2087
+ OUTPUT: the section resulting from the subtraction of ``other`` from ``self``
2088
+
2089
+ TESTS::
2090
+
2091
+ sage: M = Manifold(2, 'M', structure='top')
2092
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
2093
+ sage: M.declare_union(U,V) # M is the union of U and V
2094
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
2095
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
2096
+ ....: intersection_name='W', restrictions1= x>0,
2097
+ ....: restrictions2= u+v>0)
2098
+ sage: uv_to_xy = xy_to_uv.inverse()
2099
+ sage: W = U.intersection(V)
2100
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
2101
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
2102
+ sage: phi_V = E.trivialization('phi_V', domain=V)
2103
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
2104
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
2105
+ sage: s = E.section(name='s')
2106
+ sage: s[fU,:] = [x, 1]
2107
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
2108
+ sage: t = E.section(name='t')
2109
+ sage: t[fU,:] = [2, y]
2110
+ sage: t.add_comp_by_continuation(fV, U.intersection(V), c_uv)
2111
+ sage: u = s._sub_(t); s
2112
+ Section s on the 2-dimensional topological manifold M with values in
2113
+ the real vector bundle E of rank 2
2114
+ sage: s.display(fU)
2115
+ s = x (phi_U^*e_1) + (phi_U^*e_2)
2116
+ sage: t.display(fU)
2117
+ t = 2 (phi_U^*e_1) + y (phi_U^*e_2)
2118
+ sage: u.display(fU)
2119
+ s-t = (x - 2) (phi_U^*e_1) + (-y + 1) (phi_U^*e_2)
2120
+ sage: u == s - t
2121
+ True
2122
+ sage: z = s.parent().zero()
2123
+ sage: s._sub_(z) == s
2124
+ True
2125
+ sage: z._sub_(s) == -s
2126
+ True
2127
+ """
2128
+ # Case zero:
2129
+ if self._is_zero:
2130
+ return -other
2131
+ if other._is_zero:
2132
+ return self
2133
+ # Generic case:
2134
+ resu_rst = {}
2135
+ for dom in self._common_subdomains(other):
2136
+ resu_rst[dom] = self._restrictions[dom] - other._restrictions[dom]
2137
+ resu = self._vbundle.section(domain=self._domain)
2138
+ resu._restrictions = resu_rst
2139
+ if self._name is not None and other._name is not None:
2140
+ resu._name = self._name + '-' + other._name
2141
+ if self._latex_name is not None and other._latex_name is not None:
2142
+ resu._latex_name = self._latex_name + '-' + other._latex_name
2143
+ return resu
2144
+
2145
+ def _rmul_(self, scalar):
2146
+ r"""
2147
+ Reflected multiplication operator: performs ``scalar * self``.
2148
+
2149
+ This is actually the multiplication by an element of the ring over
2150
+ which the tensor field module is constructed.
2151
+
2152
+ INPUT:
2153
+
2154
+ - ``scalar`` -- scalar field in the scalar field algebra over which
2155
+ the module containing ``self`` is defined
2156
+
2157
+ OUTPUT: the tensor field ``scalar * self``
2158
+
2159
+ TESTS::
2160
+
2161
+ sage: M = Manifold(2, 'M', structure='top')
2162
+ sage: U = M.open_subset('U') ; V = M.open_subset('V')
2163
+ sage: M.declare_union(U,V) # M is the union of U and V
2164
+ sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
2165
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
2166
+ ....: intersection_name='W', restrictions1= x>0,
2167
+ ....: restrictions2= u+v>0)
2168
+ sage: uv_to_xy = xy_to_uv.inverse()
2169
+ sage: W = U.intersection(V)
2170
+ sage: E = M.vector_bundle(2, 'E') # define vector bundle
2171
+ sage: phi_U = E.trivialization('phi_U', domain=U) # define trivializations
2172
+ sage: phi_V = E.trivialization('phi_V', domain=V)
2173
+ sage: transf = phi_U.transition_map(phi_V, [[0,x],[x,0]])
2174
+ sage: fU = phi_U.frame(); fV = phi_V.frame()
2175
+ sage: s = E.section(name='s')
2176
+ sage: s[fU,:] = [x, 1]
2177
+ sage: s.add_comp_by_continuation(fV, U.intersection(V), c_uv)
2178
+ sage: g = M.scalar_field({c_xy: 1/(1+x^2+y^2)}, name='g')
2179
+ sage: g.add_expr_by_continuation(c_uv, U.intersection(V))
2180
+ sage: g.display()
2181
+ g: M → ℝ
2182
+ on U: (x, y) ↦ 1/(x^2 + y^2 + 1)
2183
+ on V: (u, v) ↦ 2/(u^2 + v^2 + 2)
2184
+ sage: t = s._rmul_(g); t
2185
+ Section g*s on the 2-dimensional topological manifold M with values
2186
+ in the real vector bundle E of rank 2
2187
+ sage: s.display(fU)
2188
+ s = x (phi_U^*e_1) + (phi_U^*e_2)
2189
+ sage: t.display(fU)
2190
+ g*s = x/(x^2 + y^2 + 1) (phi_U^*e_1) + 1/(x^2 + y^2 + 1) (phi_U^*e_2)
2191
+ sage: s.display(fV)
2192
+ s = (1/2*u + 1/2*v) (phi_V^*e_1) + (1/4*u^2 + 1/2*u*v + 1/4*v^2) (phi_V^*e_2)
2193
+ sage: t.display(fV)
2194
+ g*s = (u + v)/(u^2 + v^2 + 2) (phi_V^*e_1) + 1/2*(u^2 + 2*u*v + v^2)/(u^2 + v^2 + 2) (phi_V^*e_2)
2195
+ sage: t == g*s # indirect doctest
2196
+ True
2197
+ sage: z = s.parent().zero(); z
2198
+ Section zero on the 2-dimensional topological manifold M with values
2199
+ in the real vector bundle E of rank 2
2200
+ sage: s._rmul_(M.zero_scalar_field()) == z
2201
+ True
2202
+ sage: z._rmul_(g) == z
2203
+ True
2204
+ """
2205
+ ###
2206
+ # Case zero:
2207
+ zero = scalar.parent().zero()
2208
+ if scalar is zero:
2209
+ return self.parent().zero()
2210
+ ###
2211
+ # Case one:
2212
+ one = scalar.parent().one()
2213
+ if scalar is one:
2214
+ return self.copy()
2215
+ ###
2216
+ # General case:
2217
+ from sage.tensor.modules.format_utilities import (
2218
+ format_mul_latex,
2219
+ format_mul_txt,
2220
+ )
2221
+ resu = self._new_instance()
2222
+ for dom, rst in self._restrictions.items():
2223
+ resu._restrictions[dom] = scalar.restrict(dom) * rst
2224
+ resu_name = format_mul_txt(scalar._name, '*', self._name)
2225
+ resu_latex = format_mul_latex(scalar._latex_name, r' \cdot ',
2226
+ self._latex_name)
2227
+ resu.set_name(name=resu_name, latex_name=resu_latex)
2228
+ return resu
2229
+
2230
+ ######### End of ModuleElement arithmetic operators ########
2231
+
2232
+ def set_immutable(self):
2233
+ r"""
2234
+ Set ``self`` and all restrictions of ``self`` immutable.
2235
+
2236
+ EXAMPLES::
2237
+
2238
+ sage: M = Manifold(2, 'M')
2239
+ sage: X.<x,y> = M.chart()
2240
+ sage: U = M.open_subset('U', coord_def={X: x^2+y^2<1})
2241
+ sage: E = M.vector_bundle(2, 'E')
2242
+ sage: e = E.local_frame('e')
2243
+ sage: s = E.section([1+y,x], name='s')
2244
+ sage: sU = s.restrict(U)
2245
+ sage: s.set_immutable()
2246
+ sage: s.is_immutable()
2247
+ True
2248
+ sage: sU.is_immutable()
2249
+ True
2250
+ """
2251
+ for rst in self._restrictions.values():
2252
+ rst.set_immutable()
2253
+ super().set_immutable()
2254
+
2255
+ #******************************************************************************
2256
+
2257
+
2258
+ class TrivialSection(FiniteRankFreeModuleElement, Section):
2259
+ r"""
2260
+ Section in a trivial vector bundle.
2261
+
2262
+ An instance of this class is a section in a vector bundle `E \to M` of class
2263
+ `C^k`, where `E|_U` is manifestly trivial. More precisely, a *(local)
2264
+ section* on a subset `U \in M` is a map of class `C^k`
2265
+
2266
+ .. MATH::
2267
+
2268
+ s: U \longrightarrow E
2269
+
2270
+ such that
2271
+
2272
+ .. MATH::
2273
+
2274
+ \forall p \in U,\ s(p) \in E_p
2275
+
2276
+ where `E_p` denotes the vector bundle fiber of `E` over the point `p \in U`.
2277
+ `E` being trivial means `E` being homeomorphic to `E \times F`, for `F` is
2278
+ the typical fiber of `E`, namely the underlying topological vector space. By
2279
+ this means, `s` can be seen as a map of class `C^k(U;E)`
2280
+
2281
+ .. MATH::
2282
+
2283
+ s: U \longrightarrow F ,
2284
+
2285
+ so that the set of all sections `C^k(U;E)` becomes a *free* module over the
2286
+ algebra of scalar fields on `U`.
2287
+
2288
+ .. NOTE::
2289
+
2290
+ If `E|_U` is not manifestly trivial, the class
2291
+ :class:`~sage.manifolds.section.Section` should be used instead.
2292
+
2293
+ This is a Sage *element* class, the corresponding *parent* class being
2294
+ :class:`~sage.manifolds.section_module.SectionFreeModule`.
2295
+
2296
+ INPUT:
2297
+
2298
+ - ``section_module`` -- free module `C^k(U;E)` of sections on `E` over `U`
2299
+ (cf. :class:`~sage.manifolds.section_module.SectionFreeModule`)
2300
+ - ``name`` -- (default: ``None``) name given to the section
2301
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the section;
2302
+ if none is provided, the LaTeX symbol is set to ``name``
2303
+
2304
+ EXAMPLES:
2305
+
2306
+ A section on a trivial rank 3 vector bundle over the 3-sphere::
2307
+
2308
+ sage: M = Manifold(3, 'S^3', structure='top')
2309
+ sage: U = M.open_subset('U') ; V = M.open_subset('V') # complement of the North and South pole, respectively
2310
+ sage: M.declare_union(U,V)
2311
+ sage: stereoN.<x,y,z> = U.chart() # stereographic coordinates from the North pole
2312
+ sage: stereoS.<u,v,t> = V.chart() # stereographic coordinates from the South pole
2313
+ sage: xyz_to_uvt = stereoN.transition_map(stereoS,
2314
+ ....: (x/(x^2+y^2+z^2), y/(x^2+y^2+z^2), z/(x^2+y^2+z^2)),
2315
+ ....: intersection_name='W',
2316
+ ....: restrictions1= x^2+y^2+z^2!=0,
2317
+ ....: restrictions2= u^2+v^2+t^2!=0)
2318
+ sage: W = U.intersection(V)
2319
+ sage: uvt_to_xyz = xyz_to_uvt.inverse()
2320
+ sage: E = M.vector_bundle(3, 'E')
2321
+ sage: e = E.local_frame('e') # Trivializes E
2322
+ sage: s = E.section(name='s'); s
2323
+ Section s on the 3-dimensional topological manifold S^3 with values in
2324
+ the real vector bundle E of rank 3
2325
+ sage: s[e,:] = z^2, x-y, 1-x
2326
+ sage: s.display()
2327
+ s = z^2 e_0 + (x - y) e_1 + (-x + 1) e_2
2328
+
2329
+ Since `E` is trivial, `s` is now element of a free section module::
2330
+
2331
+ sage: s.parent()
2332
+ Free module C^0(S^3;E) of sections on the 3-dimensional topological
2333
+ manifold S^3 with values in the real vector bundle E of rank 3
2334
+ sage: isinstance(s.parent(), FiniteRankFreeModule)
2335
+ True
2336
+ """
2337
+ def __init__(self, section_module, name=None, latex_name=None):
2338
+ r"""
2339
+ Construct a section on a trivial vector bundle.
2340
+
2341
+ TESTS:
2342
+
2343
+ Construction via ``parent.element_class``, and not via a direct call
2344
+ to ``TrivialSection``, to fit with the category framework::
2345
+
2346
+ sage: M = Manifold(2, 'M', structure='top')
2347
+ sage: X.<x,y> = M.chart()
2348
+ sage: E = M.vector_bundle(2, 'E')
2349
+ sage: e = E.local_frame('e')
2350
+ sage: C0 = E.section_module()
2351
+ sage: s = C0.element_class(C0, name='s'); s
2352
+ Section s on the 2-dimensional topological manifold M with values in
2353
+ the real vector bundle E of rank 2
2354
+ sage: s[:] = [1+x^2, x*y]
2355
+ sage: s.display()
2356
+ s = (x^2 + 1) e_0 + x*y e_1
2357
+ sage: s.parent()
2358
+ Free module C^0(M;E) of sections on the 2-dimensional topological
2359
+ manifold M with values in the real vector bundle E of rank 2
2360
+ sage: TestSuite(s).run()
2361
+ """
2362
+ FiniteRankFreeModuleElement.__init__(self, section_module,
2363
+ name=name, latex_name=latex_name)
2364
+ self._domain = section_module.domain()
2365
+ self._vbundle = section_module.vector_bundle()
2366
+ self._base_space = section_module.base_space()
2367
+ self._smodule = section_module
2368
+ self._is_zero = False # a priori
2369
+ # Initialization of derived quantities:
2370
+ self._init_derived()
2371
+
2372
+ def _init_derived(self):
2373
+ r"""
2374
+ Initialize the derived quantities.
2375
+
2376
+ TESTS::
2377
+
2378
+ sage: M = Manifold(2, 'M', structure='top')
2379
+ sage: E = M.vector_bundle(2, 'E')
2380
+ sage: e = E.local_frame('e') # makes E trivial
2381
+ sage: s = E.section(name='s')
2382
+ sage: s._init_derived()
2383
+ """
2384
+ FiniteRankFreeModuleElement._init_derived(self)
2385
+ Section._init_derived(self)
2386
+
2387
+ def _del_derived(self, del_restrictions=True):
2388
+ r"""
2389
+ Delete the derived quantities.
2390
+
2391
+ INPUT:
2392
+
2393
+ - ``del_restrictions`` -- boolean (default: ``True``); determines whether the
2394
+ restrictions of ``self`` to subdomains are deleted
2395
+
2396
+ TESTS::
2397
+
2398
+ sage: M = Manifold(2, 'M', structure='top')
2399
+ sage: E = M.vector_bundle(2, 'E')
2400
+ sage: e = E.local_frame('e') # makes E trivial
2401
+ sage: s = E.section(name='s')
2402
+ sage: s._del_derived()
2403
+ """
2404
+ FiniteRankFreeModuleElement._del_derived(self)
2405
+ Section._del_derived(self, del_restrictions=del_restrictions)
2406
+
2407
+ def _repr_(self) :
2408
+ r"""
2409
+ String representation of ``self``.
2410
+
2411
+ TESTS::
2412
+
2413
+ sage: M = Manifold(2, 'M', structure='top')
2414
+ sage: E = M.vector_bundle(2, 'E')
2415
+ sage: e = E.local_frame('e') # makes E trivial
2416
+ sage: s = E.section(name='s')
2417
+ sage: s._repr_()
2418
+ 'Section s on the 2-dimensional topological manifold M with values
2419
+ in the real vector bundle E of rank 2'
2420
+ sage: repr(s) # indirect doctest
2421
+ 'Section s on the 2-dimensional topological manifold M with values
2422
+ in the real vector bundle E of rank 2'
2423
+ sage: s # indirect doctest
2424
+ Section s on the 2-dimensional topological manifold M with values in
2425
+ the real vector bundle E of rank 2
2426
+ """
2427
+ return Section._repr_(self)
2428
+
2429
+ def _new_instance(self):
2430
+ r"""
2431
+ Create an instance of the same class as ``self`` on the same section
2432
+ module.
2433
+
2434
+ TESTS::
2435
+
2436
+ sage: M = Manifold(2, 'M', structure='top')
2437
+ sage: E = M.vector_bundle(2, 'E')
2438
+ sage: e = E.local_frame('e') # makes E trivial
2439
+ sage: s = E.section(name='s')
2440
+ sage: s._new_instance()
2441
+ Section on the 2-dimensional topological manifold M with values in
2442
+ the real vector bundle E of rank 2
2443
+ sage: type(s._new_instance()) is type(s)
2444
+ True
2445
+ """
2446
+ return type(self)(self._smodule)
2447
+
2448
+ def _set_comp_unsafe(self, basis=None):
2449
+ r"""
2450
+ Return the components of the section in a given local frame for
2451
+ assignment. This private method invokes no security check. Use
2452
+ this method at your own risk.
2453
+
2454
+ The components with respect to other frames on the same domain are
2455
+ deleted, in order to avoid any inconsistency. To keep them, use the
2456
+ method :meth:`_add_comp_unsafe` instead.
2457
+
2458
+ INPUT:
2459
+
2460
+ - ``basis`` -- (default: ``None``) local frame in which the
2461
+ components are defined; if none is provided, the components are
2462
+ assumed to refer to the section module's default frame
2463
+
2464
+ OUTPUT:
2465
+
2466
+ - components in the given frame, as an instance of the
2467
+ class :class:`~sage.tensor.modules.comp.Components`; if such
2468
+ components did not exist previously, they are created
2469
+
2470
+ EXAMPLES::
2471
+
2472
+ sage: M = Manifold(2, 'M', structure='top')
2473
+ sage: X.<x,y> = M.chart()
2474
+ sage: E = M.vector_bundle(2, 'E')
2475
+ sage: e = E.local_frame('e') # makes E trivial
2476
+ sage: s = E.section(name='s')
2477
+ sage: s._set_comp_unsafe(e)
2478
+ 1-index components w.r.t. Local frame (E|_M, (e_0,e_1))
2479
+ sage: s._set_comp_unsafe(e)[0] = 2
2480
+ sage: s.display(e)
2481
+ s = 2 e_0
2482
+
2483
+ Setting components in a new frame (``f``)::
2484
+
2485
+ sage: f = E.local_frame('f')
2486
+ sage: s._set_comp_unsafe(f)
2487
+ 1-index components w.r.t. Local frame (E|_M, (f_0,f_1))
2488
+ sage: s._set_comp_unsafe(f)[0] = x
2489
+ sage: s.display(f)
2490
+ s = x f_0
2491
+
2492
+ The components with respect to the frame ``e`` have be erased::
2493
+
2494
+ sage: s.display(e)
2495
+ Traceback (most recent call last):
2496
+ ...
2497
+ ValueError: no basis could be found for computing the components
2498
+ in the Local frame (E|_M, (e_0,e_1))
2499
+
2500
+ Setting components in a frame defined on a subdomain deletes
2501
+ previously defined components as well::
2502
+
2503
+ sage: U = M.open_subset('U', coord_def={X: x>0})
2504
+ sage: g = E.local_frame('g', domain=U)
2505
+ sage: s._set_comp_unsafe(g)
2506
+ 1-index components w.r.t. Local frame (E|_U, (g_0,g_1))
2507
+ sage: s._set_comp_unsafe(g)[0] = 1+y
2508
+ sage: s.display(g)
2509
+ s = (y + 1) g_0
2510
+ sage: s.display(f)
2511
+ Traceback (most recent call last):
2512
+ ...
2513
+ ValueError: no basis could be found for computing the components
2514
+ in the Local frame (E|_M, (f_0,f_1))
2515
+ """
2516
+ if basis is None:
2517
+ basis = self._smodule.default_frame()
2518
+
2519
+ if basis._domain == self._domain:
2520
+ # Setting components on the section domain:
2521
+ return FiniteRankFreeModuleElement._set_comp_unsafe(self,
2522
+ basis=basis)
2523
+ # Setting components on a subdomain:
2524
+ #
2525
+ # Creating or saving the restriction to the subdomain:
2526
+ rst = self.restrict(basis._domain)
2527
+ # Deleting all the components on self._domain and the derived
2528
+ # quantities:
2529
+ self._components.clear()
2530
+ # Restoring the restriction to the subdomain (which has been
2531
+ # deleted by _del_derived):
2532
+ self._restrictions[basis._domain] = rst
2533
+ # The set_comp operation is performed on the subdomain:
2534
+ return rst._set_comp_unsafe(basis=basis)
2535
+
2536
+ def set_comp(self, basis=None):
2537
+ r"""
2538
+ Return the components of the section in a given local frame for
2539
+ assignment.
2540
+
2541
+ The components with respect to other frames on the same domain are
2542
+ deleted, in order to avoid any inconsistency. To keep them, use the
2543
+ method :meth:`add_comp` instead.
2544
+
2545
+ INPUT:
2546
+
2547
+ - ``basis`` -- (default: ``None``) local frame in which the
2548
+ components are defined; if none is provided, the components are
2549
+ assumed to refer to the section module's default frame
2550
+
2551
+ OUTPUT:
2552
+
2553
+ - components in the given frame, as an instance of the
2554
+ class :class:`~sage.tensor.modules.comp.Components`; if such
2555
+ components did not exist previously, they are created
2556
+
2557
+ EXAMPLES::
2558
+
2559
+ sage: M = Manifold(2, 'M', structure='top')
2560
+ sage: X.<x,y> = M.chart()
2561
+ sage: E = M.vector_bundle(2, 'E')
2562
+ sage: e = E.local_frame('e') # makes E trivial
2563
+ sage: s = E.section(name='s')
2564
+ sage: s.set_comp(e)
2565
+ 1-index components w.r.t. Local frame (E|_M, (e_0,e_1))
2566
+ sage: s.set_comp(e)[0] = 2
2567
+ sage: s.display(e)
2568
+ s = 2 e_0
2569
+
2570
+ Setting components in a new frame (``f``)::
2571
+
2572
+ sage: f = E.local_frame('f')
2573
+ sage: s.set_comp(f)
2574
+ 1-index components w.r.t. Local frame (E|_M, (f_0,f_1))
2575
+ sage: s.set_comp(f)[0] = x
2576
+ sage: s.display(f)
2577
+ s = x f_0
2578
+
2579
+ The components with respect to the frame ``e`` have be erased::
2580
+
2581
+ sage: s.display(e)
2582
+ Traceback (most recent call last):
2583
+ ...
2584
+ ValueError: no basis could be found for computing the components
2585
+ in the Local frame (E|_M, (e_0,e_1))
2586
+
2587
+ Setting components in a frame defined on a subdomain deletes
2588
+ previously defined components as well::
2589
+
2590
+ sage: U = M.open_subset('U', coord_def={X: x>0})
2591
+ sage: g = E.local_frame('g', domain=U)
2592
+ sage: s.set_comp(g)
2593
+ 1-index components w.r.t. Local frame (E|_U, (g_0,g_1))
2594
+ sage: s.set_comp(g)[0] = 1+y
2595
+ sage: s.display(g)
2596
+ s = (y + 1) g_0
2597
+ sage: s.display(f)
2598
+ Traceback (most recent call last):
2599
+ ...
2600
+ ValueError: no basis could be found for computing the components
2601
+ in the Local frame (E|_M, (f_0,f_1))
2602
+ """
2603
+ if self.is_immutable():
2604
+ raise ValueError("the components of an immutable element "
2605
+ "cannot be changed")
2606
+ if basis is None:
2607
+ basis = self._smodule.default_frame()
2608
+
2609
+ if basis._domain == self._domain:
2610
+ # Setting components on the section domain:
2611
+ return FiniteRankFreeModuleElement.set_comp(self, basis=basis)
2612
+
2613
+ # Setting components on a subdomain:
2614
+ #
2615
+ # Creating or saving the restriction to the subdomain:
2616
+ rst = self.restrict(basis._domain)
2617
+ # Deleting all the components on self._domain and the derived
2618
+ # quantities:
2619
+ self._components.clear()
2620
+ # Restoring the restriction to the subdomain (which has been
2621
+ # deleted by _del_derived):
2622
+ self._restrictions[basis._domain] = rst
2623
+ # The set_comp operation is performed on the subdomain:
2624
+ return rst.set_comp(basis=basis)
2625
+
2626
+ def _add_comp_unsafe(self, basis=None):
2627
+ r"""
2628
+ Return the components of the section in a given local frame for
2629
+ assignment.
2630
+
2631
+ The components with respect to other frames on the same domain are
2632
+ kept. To delete them, use the method :meth:`_set_comp_unsafe` instead.
2633
+
2634
+ INPUT:
2635
+
2636
+ - ``basis`` -- (default: ``None``) local frame in which the
2637
+ components are defined; if none is provided, the components are
2638
+ assumed to refer to the section module's default frame
2639
+
2640
+ OUTPUT:
2641
+
2642
+ - components in the given frame, as an instance of the
2643
+ class :class:`~sage.tensor.modules.comp.Components`; if such
2644
+ components did not exist previously, they are created
2645
+
2646
+ EXAMPLES::
2647
+
2648
+ sage: M = Manifold(2, 'M', structure='top')
2649
+ sage: X.<x,y> = M.chart()
2650
+ sage: E = M.vector_bundle(2, 'E')
2651
+ sage: e = E.local_frame('e') # makes E trivial
2652
+ sage: s = E.section(name='s')
2653
+ sage: s._add_comp_unsafe(e)
2654
+ 1-index components w.r.t. Local frame (E|_M, (e_0,e_1))
2655
+ sage: s._add_comp_unsafe(e)[0] = 2
2656
+ sage: s.display(e)
2657
+ s = 2 e_0
2658
+
2659
+ Adding components with respect to a new frame (``f``)::
2660
+
2661
+ sage: f = E.local_frame('f')
2662
+ sage: s._add_comp_unsafe(f)
2663
+ 1-index components w.r.t. Local frame (E|_M, (f_0,f_1))
2664
+ sage: s._add_comp_unsafe(f)[0] = x
2665
+ sage: s.display(f)
2666
+ s = x f_0
2667
+
2668
+ The components with respect to the frame ``e`` are kept::
2669
+
2670
+ sage: s.display(e)
2671
+ s = 2 e_0
2672
+
2673
+ Adding components in a frame defined on a subdomain::
2674
+
2675
+ sage: U = M.open_subset('U', coord_def={X: x>0})
2676
+ sage: g = E.local_frame('g', domain=U)
2677
+ sage: s._add_comp_unsafe(g)
2678
+ 1-index components w.r.t. Local frame (E|_U, (g_0,g_1))
2679
+ sage: s._add_comp_unsafe(g)[0] = 1+y
2680
+ sage: s.display(g)
2681
+ s = (y + 1) g_0
2682
+
2683
+ The components previously defined are kept::
2684
+
2685
+ sage: s.display(e)
2686
+ s = 2 e_0
2687
+ sage: s.display(f)
2688
+ s = x f_0
2689
+ """
2690
+ if basis is None:
2691
+ basis = self._smodule.default_frame()
2692
+
2693
+ if basis._domain == self._domain:
2694
+ # Adding components on the tensor field domain:
2695
+ # We perform a backup of the restrictions, since
2696
+ # they are deleted by FreeModuleTensor.add_comp (which
2697
+ # invokes del_derived()), and restore them afterwards
2698
+ restrictions_save = self._restrictions.copy()
2699
+ comp = FiniteRankFreeModuleElement._add_comp_unsafe(self,
2700
+ basis=basis)
2701
+ self._restrictions = restrictions_save
2702
+ return comp
2703
+
2704
+ # Adding components on a subdomain:
2705
+ #
2706
+ # Creating or saving the restriction to the subdomain:
2707
+ rst = self.restrict(basis._domain)
2708
+ # The add_comp operation is performed on the subdomain:
2709
+ return rst._add_comp_unsafe(basis=basis)
2710
+
2711
+ def add_comp(self, basis=None):
2712
+ r"""
2713
+ Return the components of the section in a given local frame for
2714
+ assignment.
2715
+
2716
+ The components with respect to other frames on the same domain are
2717
+ kept. To delete them, use the method :meth:`set_comp` instead.
2718
+
2719
+ INPUT:
2720
+
2721
+ - ``basis`` -- (default: ``None``) local frame in which the
2722
+ components are defined; if none is provided, the components are
2723
+ assumed to refer to the section module's default frame
2724
+
2725
+ OUTPUT:
2726
+
2727
+ - components in the given frame, as an instance of the
2728
+ class :class:`~sage.tensor.modules.comp.Components`; if such
2729
+ components did not exist previously, they are created
2730
+
2731
+ EXAMPLES::
2732
+
2733
+ sage: M = Manifold(2, 'M', structure='top')
2734
+ sage: X.<x,y> = M.chart()
2735
+ sage: E = M.vector_bundle(2, 'E')
2736
+ sage: e = E.local_frame('e') # makes E trivial
2737
+ sage: s = E.section(name='s')
2738
+ sage: s.add_comp(e)
2739
+ 1-index components w.r.t. Local frame (E|_M, (e_0,e_1))
2740
+ sage: s.add_comp(e)[0] = 2
2741
+ sage: s.display(e)
2742
+ s = 2 e_0
2743
+
2744
+ Adding components with respect to a new frame (``f``)::
2745
+
2746
+ sage: f = E.local_frame('f')
2747
+ sage: s.add_comp(f)
2748
+ 1-index components w.r.t. Local frame (E|_M, (f_0,f_1))
2749
+ sage: s.add_comp(f)[0] = x
2750
+ sage: s.display(f)
2751
+ s = x f_0
2752
+
2753
+ The components with respect to the frame ``e`` are kept::
2754
+
2755
+ sage: s.display(e)
2756
+ s = 2 e_0
2757
+
2758
+ Adding components in a frame defined on a subdomain::
2759
+
2760
+ sage: U = M.open_subset('U', coord_def={X: x>0})
2761
+ sage: g = E.local_frame('g', domain=U)
2762
+ sage: s.add_comp(g)
2763
+ 1-index components w.r.t. Local frame (E|_U, (g_0,g_1))
2764
+ sage: s.add_comp(g)[0] = 1+y
2765
+ sage: s.display(g)
2766
+ s = (y + 1) g_0
2767
+
2768
+ The components previously defined are kept::
2769
+
2770
+ sage: s.display(e)
2771
+ s = 2 e_0
2772
+ sage: s.display(f)
2773
+ s = x f_0
2774
+ """
2775
+ if self.is_immutable():
2776
+ raise ValueError("the components of an immutable element "
2777
+ "cannot be changed")
2778
+ if basis is None:
2779
+ basis = self._smodule.default_frame()
2780
+
2781
+ if basis._domain == self._domain:
2782
+ # Adding components on the tensor field domain:
2783
+ # We perform a backup of the restrictions, since
2784
+ # they are deleted by FreeModuleTensor.add_comp (which
2785
+ # invokes del_derived()), and restore them afterwards
2786
+ restrictions_save = self._restrictions.copy()
2787
+ comp = FiniteRankFreeModuleElement.add_comp(self, basis=basis)
2788
+ self._restrictions = restrictions_save
2789
+ return comp
2790
+
2791
+ # Adding components on a subdomain:
2792
+ #
2793
+ # Creating or saving the restriction to the subdomain:
2794
+ rst = self.restrict(basis._domain)
2795
+ # The add_comp operation is performed on the subdomain:
2796
+ return rst.add_comp(basis=basis)
2797
+
2798
+ def comp(self, basis=None, from_basis=None):
2799
+ r"""
2800
+ Return the components in a given local frame.
2801
+
2802
+ If the components are not known already, they are computed by the
2803
+ tensor change-of-basis formula from components in another local frame.
2804
+
2805
+ INPUT:
2806
+
2807
+ - ``basis`` -- (default: ``None``) local frame in which the components
2808
+ are required; if none is provided, the components are assumed to
2809
+ refer to the section module's default frame
2810
+ - ``from_basis`` -- (default: ``None``) local frame from which the
2811
+ required components are computed, via the tensor change-of-basis
2812
+ formula, if they are not known already in the basis ``basis``
2813
+
2814
+ OUTPUT:
2815
+
2816
+ - components in the local frame ``basis``, as an instance of the
2817
+ class :class:`~sage.tensor.modules.comp.Components`
2818
+
2819
+ EXAMPLES::
2820
+
2821
+ sage: M = Manifold(2, 'M', structure='top', start_index=1)
2822
+ sage: X.<x,y> = M.chart()
2823
+ sage: E = M.vector_bundle(2, 'E')
2824
+ sage: e = E.local_frame('e') # makes E trivial
2825
+ sage: s = E.section(name='s')
2826
+ sage: s[1] = x*y
2827
+ sage: s.comp(e)
2828
+ 1-index components w.r.t. Local frame (E|_M, (e_1,e_2))
2829
+ sage: s.comp() # the default frame is e
2830
+ 1-index components w.r.t. Local frame (E|_M, (e_1,e_2))
2831
+ sage: s.comp()[:]
2832
+ [x*y, 0]
2833
+ sage: f = E.local_frame('f')
2834
+ sage: s[f, 1] = x-3
2835
+ sage: s.comp(f)
2836
+ 1-index components w.r.t. Local frame (E|_M, (f_1,f_2))
2837
+ sage: s.comp(f)[:]
2838
+ [x - 3, 0]
2839
+ """
2840
+ if basis is None:
2841
+ basis = self._smodule.default_frame()
2842
+
2843
+ if basis._domain == self._domain:
2844
+ # components on the local section domain:
2845
+ return FiniteRankFreeModuleElement.comp(self, basis=basis,
2846
+ from_basis=from_basis)
2847
+
2848
+ # components on a subdomain:
2849
+ rst = self.restrict(basis._domain)
2850
+ return rst.comp(basis=basis, from_basis=from_basis)
2851
+
2852
+ def restrict(self, subdomain):
2853
+ r"""
2854
+ Return the restriction of ``self`` to some subdomain.
2855
+
2856
+ If the restriction has not been defined yet, it is constructed here.
2857
+
2858
+ INPUT:
2859
+
2860
+ - ``subdomain`` --
2861
+ :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`;
2862
+ open subset `U` of the section module domain `S`
2863
+
2864
+ OUTPUT: instance of :class:`TrivialSection` representing the restriction
2865
+
2866
+ EXAMPLES:
2867
+
2868
+ Restriction of a section defined over `\RR^2` to a disk::
2869
+
2870
+ sage: M = Manifold(2, 'R^2')
2871
+ sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
2872
+ sage: E = M.vector_bundle(2, 'E')
2873
+ sage: e = E.local_frame('e') # makes E trivial
2874
+ sage: s = E.section(x+y, -1+x^2, name='s')
2875
+ sage: D = M.open_subset('D') # the unit open disc
2876
+ sage: e_D = e.restrict(D)
2877
+ sage: c_cart_D = c_cart.restrict(D, x^2+y^2<1)
2878
+ sage: s_D = s.restrict(D) ; s_D
2879
+ Section s on the Open subset D of the 2-dimensional differentiable
2880
+ manifold R^2 with values in the real vector bundle E of rank 2
2881
+ sage: s_D.display(e_D)
2882
+ s = (x + y) e_0 + (x^2 - 1) e_1
2883
+
2884
+ The symbolic expressions of the components with respect to
2885
+ Cartesian coordinates are equal::
2886
+
2887
+ sage: bool( s_D[1].expr() == s[1].expr() )
2888
+ True
2889
+
2890
+ but neither the chart functions representing the components (they are
2891
+ defined on different charts)::
2892
+
2893
+ sage: s_D[1] == s[1]
2894
+ False
2895
+
2896
+ nor the scalar fields representing the components (they are
2897
+ defined on different open subsets)::
2898
+
2899
+ sage: s_D[[1]] == s[[1]]
2900
+ False
2901
+
2902
+ The restriction of the section to its own domain is of course itself::
2903
+
2904
+ sage: s.restrict(M) is s
2905
+ True
2906
+ """
2907
+ if subdomain == self._domain:
2908
+ return self
2909
+ if subdomain not in self._restrictions:
2910
+ if not subdomain.is_subset(self._domain):
2911
+ raise ValueError("the provided domain is not a subset of " +
2912
+ "the field's domain")
2913
+ # First one tries to derive the restriction from a tighter domain:
2914
+ for dom, rst in self._restrictions.items():
2915
+ if subdomain.is_subset(dom) and subdomain in rst._restrictions:
2916
+ res = rst._restrictions[subdomain]
2917
+ self._restrictions[subdomain] = res
2918
+ self._restrictions_graph[subdomain] = res
2919
+ res._extensions_graph.update(self._extensions_graph)
2920
+ for ext in self._extensions_graph.values():
2921
+ ext._restrictions[subdomain] = res
2922
+ ext._restrictions_graph[subdomain] = res
2923
+ return self._restrictions[subdomain]
2924
+
2925
+ for dom, rst in self._restrictions.items():
2926
+ if subdomain.is_subset(dom) and dom is not self._domain:
2927
+ self._restrictions[subdomain] = rst.restrict(subdomain)
2928
+ self._restrictions_graph[subdomain] = rst.restrict(subdomain)
2929
+ return self._restrictions[subdomain]
2930
+
2931
+ # Secondly one tries to get the restriction from one previously
2932
+ # defined on a larger domain:
2933
+ for dom, ext in self._extensions_graph.items():
2934
+ if subdomain in ext._restrictions_graph:
2935
+ res = ext._restrictions_graph[subdomain]
2936
+ self._restrictions[subdomain] = res
2937
+ self._restrictions_graph[subdomain] = res
2938
+ res._extensions_graph.update(self._extensions_graph)
2939
+ for ext in self._extensions_graph.values():
2940
+ ext._restrictions[subdomain] = res
2941
+ ext._restrictions_graph[subdomain] = res
2942
+ return self._restrictions[subdomain]
2943
+
2944
+ # If this fails, the restriction is created from scratch:
2945
+ smodule = self._vbundle.section_module(domain=subdomain)
2946
+ res = smodule.element_class(smodule, name=self._name,
2947
+ latex_name=self._latex_name)
2948
+
2949
+ for frame in self._components:
2950
+ for sframe in self._vbundle._frames:
2951
+ if (sframe.domain() is subdomain and
2952
+ sframe in frame._subframes):
2953
+ comp_store = self._components[frame]._comp
2954
+ scomp = res._new_comp(sframe)
2955
+ scomp_store = scomp._comp
2956
+ # the components of the restriction are evaluated
2957
+ # index by index:
2958
+ for ind, value in comp_store.items():
2959
+ scomp_store[ind] = value.restrict(subdomain)
2960
+ res._components[sframe] = scomp
2961
+
2962
+ res._extensions_graph.update(self._extensions_graph)
2963
+ for dom, ext in self._extensions_graph.items():
2964
+ ext._restrictions[subdomain] = res
2965
+ ext._restrictions_graph[subdomain] = res
2966
+
2967
+ for dom, rst in self._restrictions.items():
2968
+ if dom.is_subset(subdomain):
2969
+ if rst is not res:
2970
+ res._restrictions.update(rst._restrictions)
2971
+ res._restrictions_graph.update(rst._restrictions_graph)
2972
+ rst._extensions_graph.update(res._extensions_graph)
2973
+
2974
+ self._restrictions[subdomain] = res
2975
+ self._restrictions_graph[subdomain] = res
2976
+
2977
+ return self._restrictions[subdomain]
2978
+
2979
+ def display_comp(self, frame=None, chart=None, only_nonzero=False):
2980
+ r"""
2981
+ Display the section components with respect to a given frame, one per
2982
+ line.
2983
+
2984
+ The output is either text-formatted (console mode) or LaTeX-formatted
2985
+ (notebook mode).
2986
+
2987
+ INPUT:
2988
+
2989
+ - ``frame`` -- (default: ``None``) local frame with respect to which
2990
+ the section components are defined; if ``None``, then the default
2991
+ basis of the section module on which the section is defined is used
2992
+ - ``chart`` -- (default: ``None``) chart specifying the coordinate
2993
+ expression of the components; if ``None``, the default chart of the
2994
+ section module domain is used
2995
+ - ``only_nonzero`` -- boolean (default: ``False``); if ``True``, only
2996
+ nonzero components are displayed
2997
+
2998
+ EXAMPLES:
2999
+
3000
+ Display of the components of a section on a rank 4 vector bundle over
3001
+ a 2-dimensional manifold::
3002
+
3003
+ sage: M = Manifold(2, 'M', structure='top')
3004
+ sage: X.<x,y> = M.chart()
3005
+ sage: E = M.vector_bundle(3, 'E')
3006
+ sage: e = E.local_frame('e') # makes E trivial
3007
+ sage: s = E.section(name='s')
3008
+ sage: s[0], s[2] = x+y, x*y
3009
+ sage: s.display_comp()
3010
+ s^0 = x + y
3011
+ s^1 = 0
3012
+ s^2 = x*y
3013
+
3014
+ By default, the vanishing components are displayed, too;
3015
+ to see only non-vanishing components, the argument ``only_nonzero`` must
3016
+ be set to ``True``::
3017
+
3018
+ sage: s.display_comp(only_nonzero=True)
3019
+ s^0 = x + y
3020
+ s^2 = x*y
3021
+
3022
+ Display in a frame different from the default one::
3023
+
3024
+ sage: a = E.section_module().automorphism()
3025
+ sage: a[:] = [[1+y^2, 0, 0], [0, 2+x^2, 0], [0, 0, 1]]
3026
+ sage: f = e.new_frame(a, 'f')
3027
+ sage: s.display_comp(frame=f)
3028
+ s^0 = (x + y)/(y^2 + 1)
3029
+ s^1 = 0
3030
+ s^2 = x*y
3031
+
3032
+ Display with respect to a chart different from the default one::
3033
+
3034
+ sage: Y.<u,v> = M.chart()
3035
+ sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
3036
+ sage: Y_to_X = X_to_Y.inverse()
3037
+ sage: s.display_comp(chart=Y)
3038
+ s^0 = u
3039
+ s^1 = 0
3040
+ s^2 = 1/4*u^2 - 1/4*v^2
3041
+
3042
+ Display of the components with respect to a specific frame, expressed
3043
+ in terms of a specific chart::
3044
+
3045
+ sage: s.display_comp(frame=f, chart=Y)
3046
+ s^0 = 4*u/(u^2 - 2*u*v + v^2 + 4)
3047
+ s^1 = 0
3048
+ s^2 = 1/4*u^2 - 1/4*v^2
3049
+ """
3050
+ if frame is None:
3051
+ frame = self._smodule.default_basis()
3052
+ if chart is None:
3053
+ chart = self._domain.default_chart()
3054
+ return FiniteRankFreeModuleElement.display_comp(self, basis=frame,
3055
+ format_spec=chart,
3056
+ only_nonzero=only_nonzero)
3057
+
3058
+ def at(self, point):
3059
+ r"""
3060
+ Value of ``self`` at a point of its domain.
3061
+
3062
+ If the current section is
3063
+
3064
+ .. MATH::
3065
+
3066
+ s:\ U \longrightarrow E ,
3067
+
3068
+ then for any point `p\in U`, `s(p)` is
3069
+ a vector in the fiber `E_p` of `E` at the point `p \in U`.
3070
+
3071
+ INPUT:
3072
+
3073
+ - ``point`` -- :class:`~sage.manifolds.point.ManifoldPoint`
3074
+ point `p` in the domain of the section `U`
3075
+
3076
+ OUTPUT:
3077
+
3078
+ - :class:`~sage.tensor.modules.free_module_tensor.FreeModuleTensor`
3079
+ representing the vector `s(p)` in the vector space `E_p`
3080
+
3081
+ EXAMPLES:
3082
+
3083
+ Vector in a tangent space of a 2-dimensional manifold::
3084
+
3085
+ sage: M = Manifold(2, 'M', structure='top')
3086
+ sage: X.<x,y> = M.chart()
3087
+ sage: p = M.point((-2,3), name='p')
3088
+ sage: E = M.vector_bundle(2, 'E')
3089
+ sage: e = E.local_frame('e') # makes E trivial
3090
+ sage: s = E.section(y, x^2, name='s')
3091
+ sage: s.display()
3092
+ s = y e_0 + x^2 e_1
3093
+ sage: sp = s.at(p) ; sp
3094
+ Vector s in the fiber of E at Point p on the 2-dimensional
3095
+ topological manifold M
3096
+ sage: sp.parent()
3097
+ Fiber of E at Point p on the 2-dimensional topological manifold M
3098
+ sage: sp.display()
3099
+ s = 3 e_0 + 4 e_1
3100
+ """
3101
+ if point not in self._domain:
3102
+ raise ValueError("the {} is not in the domain of ".format(point) +
3103
+ "the {}".format(self))
3104
+ vbf = self._vbundle.fiber(point)
3105
+ resu = vbf.tensor((1,0), name=self._name,
3106
+ latex_name=self._latex_name)
3107
+ for frame, comp in self._components.items():
3108
+ comp_resu = resu.add_comp(frame.at(point))
3109
+ for ind, val in comp._comp.items():
3110
+ comp_resu._comp[ind] = val(point)
3111
+ return resu