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