passagemath-symbolics 10.6.40__cp314-cp314t-macosx_13_0_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-symbolics might be problematic. Click here for more details.
- passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.40.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.40.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.40.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.40.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-darwin.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1520 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +910 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1728 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1342 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,1832 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Vector Frames
|
|
4
|
+
|
|
5
|
+
The class :class:`VectorFrame` implements vector frames on differentiable
|
|
6
|
+
manifolds.
|
|
7
|
+
By *vector frame*, it is meant a field `e` on some
|
|
8
|
+
differentiable manifold `U` endowed with a differentiable map
|
|
9
|
+
`\Phi: U \rightarrow M` to a differentiable manifold `M` such that for each
|
|
10
|
+
`p\in U`, `e(p)` is a vector basis of the tangent space `T_{\Phi(p)}M`.
|
|
11
|
+
|
|
12
|
+
The standard case of a vector frame *on* `U` corresponds to `U = M`
|
|
13
|
+
and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
14
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open
|
|
15
|
+
interval of `\RR`).
|
|
16
|
+
|
|
17
|
+
A derived class of :class:`VectorFrame` is :class:`CoordFrame`;
|
|
18
|
+
it regards the vector frames associated with a chart, i.e. the
|
|
19
|
+
so-called *coordinate bases*.
|
|
20
|
+
|
|
21
|
+
The vector frame duals, i.e. the coframes, are implemented via the class
|
|
22
|
+
:class:`CoFrame`. The derived class :class:`CoordCoFrame` is devoted to
|
|
23
|
+
coframes deriving from a chart.
|
|
24
|
+
|
|
25
|
+
AUTHORS:
|
|
26
|
+
|
|
27
|
+
- Eric Gourgoulhon, Michal Bejger (2013-2015): initial version
|
|
28
|
+
- Travis Scrimshaw (2016): review tweaks
|
|
29
|
+
- Eric Gourgoulhon (2018): some refactoring and more functionalities in the
|
|
30
|
+
choice of symbols for vector frame elements (:issue:`24792`)
|
|
31
|
+
|
|
32
|
+
REFERENCES:
|
|
33
|
+
|
|
34
|
+
- [Lee2013]_
|
|
35
|
+
|
|
36
|
+
EXAMPLES:
|
|
37
|
+
|
|
38
|
+
Introducing a chart on a manifold automatically endows it with a vector frame:
|
|
39
|
+
the coordinate frame associated to the chart::
|
|
40
|
+
|
|
41
|
+
sage: M = Manifold(3, 'M')
|
|
42
|
+
sage: X.<x,y,z> = M.chart()
|
|
43
|
+
sage: M.frames()
|
|
44
|
+
[Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))]
|
|
45
|
+
sage: M.frames()[0] is X.frame()
|
|
46
|
+
True
|
|
47
|
+
|
|
48
|
+
A new vector frame can be defined from a family of 3 linearly independent
|
|
49
|
+
vector fields::
|
|
50
|
+
|
|
51
|
+
sage: e1 = M.vector_field(1, x, y)
|
|
52
|
+
sage: e2 = M.vector_field(z, -2, x*y)
|
|
53
|
+
sage: e3 = M.vector_field(1, 1, 0)
|
|
54
|
+
sage: e = M.vector_frame('e', (e1, e2, e3)); e
|
|
55
|
+
Vector frame (M, (e_0,e_1,e_2))
|
|
56
|
+
sage: latex(e)
|
|
57
|
+
\left(M, \left(e_{0},e_{1},e_{2}\right)\right)
|
|
58
|
+
|
|
59
|
+
The first frame defined on a manifold is its *default frame*; in the present
|
|
60
|
+
case it is the coordinate frame associated to the chart ``X``::
|
|
61
|
+
|
|
62
|
+
sage: M.default_frame()
|
|
63
|
+
Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))
|
|
64
|
+
|
|
65
|
+
The default frame can be changed via the method
|
|
66
|
+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.set_default_frame`::
|
|
67
|
+
|
|
68
|
+
sage: M.set_default_frame(e)
|
|
69
|
+
sage: M.default_frame()
|
|
70
|
+
Vector frame (M, (e_0,e_1,e_2))
|
|
71
|
+
|
|
72
|
+
The elements of a vector frame are vector fields on the manifold::
|
|
73
|
+
|
|
74
|
+
sage: for vec in e:
|
|
75
|
+
....: print(vec)
|
|
76
|
+
....:
|
|
77
|
+
Vector field e_0 on the 3-dimensional differentiable manifold M
|
|
78
|
+
Vector field e_1 on the 3-dimensional differentiable manifold M
|
|
79
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M
|
|
80
|
+
|
|
81
|
+
Each element of a vector frame can be accessed by its index::
|
|
82
|
+
|
|
83
|
+
sage: e[0]
|
|
84
|
+
Vector field e_0 on the 3-dimensional differentiable manifold M
|
|
85
|
+
sage: e[0].display(X.frame())
|
|
86
|
+
e_0 = ∂/∂x + x ∂/∂y + y ∂/∂z
|
|
87
|
+
sage: X.frame()[1]
|
|
88
|
+
Vector field ∂/∂y on the 3-dimensional differentiable manifold M
|
|
89
|
+
sage: X.frame()[1].display(e)
|
|
90
|
+
∂/∂y = x/(x^2 - x + z + 2) e_0 - 1/(x^2 - x + z + 2) e_1
|
|
91
|
+
- (x - z)/(x^2 - x + z + 2) e_2
|
|
92
|
+
|
|
93
|
+
The slice operator ``:`` can be used to access to more than one element::
|
|
94
|
+
|
|
95
|
+
sage: e[0:2]
|
|
96
|
+
(Vector field e_0 on the 3-dimensional differentiable manifold M,
|
|
97
|
+
Vector field e_1 on the 3-dimensional differentiable manifold M)
|
|
98
|
+
sage: e[:]
|
|
99
|
+
(Vector field e_0 on the 3-dimensional differentiable manifold M,
|
|
100
|
+
Vector field e_1 on the 3-dimensional differentiable manifold M,
|
|
101
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M)
|
|
102
|
+
|
|
103
|
+
Vector frames can be constructed from scratch, without any connection to
|
|
104
|
+
previously defined frames or vector fields (the connection can be performed
|
|
105
|
+
later via the method
|
|
106
|
+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.set_change_of_frame`)::
|
|
107
|
+
|
|
108
|
+
sage: f = M.vector_frame('f'); f
|
|
109
|
+
Vector frame (M, (f_0,f_1,f_2))
|
|
110
|
+
sage: M.frames()
|
|
111
|
+
[Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)),
|
|
112
|
+
Vector frame (M, (e_0,e_1,e_2)),
|
|
113
|
+
Vector frame (M, (f_0,f_1,f_2))]
|
|
114
|
+
|
|
115
|
+
The index range depends on the starting index defined on the manifold::
|
|
116
|
+
|
|
117
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
118
|
+
sage: X.<x,y,z> = M.chart()
|
|
119
|
+
sage: e = M.vector_frame('e')
|
|
120
|
+
sage: [e[i] for i in M.irange()]
|
|
121
|
+
[Vector field e_1 on the 3-dimensional differentiable manifold M,
|
|
122
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M,
|
|
123
|
+
Vector field e_3 on the 3-dimensional differentiable manifold M]
|
|
124
|
+
sage: e[1], e[2], e[3]
|
|
125
|
+
(Vector field e_1 on the 3-dimensional differentiable manifold M,
|
|
126
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M,
|
|
127
|
+
Vector field e_3 on the 3-dimensional differentiable manifold M)
|
|
128
|
+
|
|
129
|
+
Let us check that the vector fields ``e[i]`` are the frame vectors from
|
|
130
|
+
their components with respect to the frame `e`::
|
|
131
|
+
|
|
132
|
+
sage: e[1].comp(e)[:]
|
|
133
|
+
[1, 0, 0]
|
|
134
|
+
sage: e[2].comp(e)[:]
|
|
135
|
+
[0, 1, 0]
|
|
136
|
+
sage: e[3].comp(e)[:]
|
|
137
|
+
[0, 0, 1]
|
|
138
|
+
|
|
139
|
+
Defining a vector frame on a manifold automatically creates the dual
|
|
140
|
+
coframe, which, by default, bares the same name (here `e`)::
|
|
141
|
+
|
|
142
|
+
sage: M.coframes()
|
|
143
|
+
[Coordinate coframe (M, (dx,dy,dz)), Coframe (M, (e^1,e^2,e^3))]
|
|
144
|
+
sage: f = M.coframes()[1] ; f
|
|
145
|
+
Coframe (M, (e^1,e^2,e^3))
|
|
146
|
+
sage: f is e.coframe()
|
|
147
|
+
True
|
|
148
|
+
|
|
149
|
+
Each element of the coframe is a 1-form::
|
|
150
|
+
|
|
151
|
+
sage: f[1], f[2], f[3]
|
|
152
|
+
(1-form e^1 on the 3-dimensional differentiable manifold M,
|
|
153
|
+
1-form e^2 on the 3-dimensional differentiable manifold M,
|
|
154
|
+
1-form e^3 on the 3-dimensional differentiable manifold M)
|
|
155
|
+
sage: latex(f[1]), latex(f[2]), latex(f[3])
|
|
156
|
+
(e^{1}, e^{2}, e^{3})
|
|
157
|
+
|
|
158
|
+
Let us check that the coframe `(e^i)` is indeed the dual of the vector
|
|
159
|
+
frame `(e_i)`::
|
|
160
|
+
|
|
161
|
+
sage: f[1](e[1]) # the 1-form e^1 applied to the vector field e_1
|
|
162
|
+
Scalar field e^1(e_1) on the 3-dimensional differentiable manifold M
|
|
163
|
+
sage: f[1](e[1]).expr() # the explicit expression of e^1(e_1)
|
|
164
|
+
1
|
|
165
|
+
sage: f[1](e[1]).expr(), f[1](e[2]).expr(), f[1](e[3]).expr()
|
|
166
|
+
(1, 0, 0)
|
|
167
|
+
sage: f[2](e[1]).expr(), f[2](e[2]).expr(), f[2](e[3]).expr()
|
|
168
|
+
(0, 1, 0)
|
|
169
|
+
sage: f[3](e[1]).expr(), f[3](e[2]).expr(), f[3](e[3]).expr()
|
|
170
|
+
(0, 0, 1)
|
|
171
|
+
|
|
172
|
+
The coordinate frame associated to spherical coordinates of the
|
|
173
|
+
sphere `S^2`::
|
|
174
|
+
|
|
175
|
+
sage: M = Manifold(2, 'S^2', start_index=1) # Part of S^2 covered by spherical coord.
|
|
176
|
+
sage: c_spher.<th,ph> = M.chart(r'th:[0,pi]:\theta ph:[0,2*pi):\phi')
|
|
177
|
+
sage: b = M.default_frame() ; b
|
|
178
|
+
Coordinate frame (S^2, (∂/∂th,∂/∂ph))
|
|
179
|
+
sage: b[1]
|
|
180
|
+
Vector field ∂/∂th on the 2-dimensional differentiable manifold S^2
|
|
181
|
+
sage: b[2]
|
|
182
|
+
Vector field ∂/∂ph on the 2-dimensional differentiable manifold S^2
|
|
183
|
+
|
|
184
|
+
The orthonormal frame constructed from the coordinate frame::
|
|
185
|
+
|
|
186
|
+
sage: e = M.vector_frame('e', (b[1], b[2]/sin(th))); e
|
|
187
|
+
Vector frame (S^2, (e_1,e_2))
|
|
188
|
+
sage: e[1].display()
|
|
189
|
+
e_1 = ∂/∂th
|
|
190
|
+
sage: e[2].display()
|
|
191
|
+
e_2 = 1/sin(th) ∂/∂ph
|
|
192
|
+
|
|
193
|
+
The change-of-frame automorphisms and their matrices::
|
|
194
|
+
|
|
195
|
+
sage: M.change_of_frame(c_spher.frame(), e)
|
|
196
|
+
Field of tangent-space automorphisms on the 2-dimensional
|
|
197
|
+
differentiable manifold S^2
|
|
198
|
+
sage: M.change_of_frame(c_spher.frame(), e)[:]
|
|
199
|
+
[ 1 0]
|
|
200
|
+
[ 0 1/sin(th)]
|
|
201
|
+
sage: M.change_of_frame(e, c_spher.frame())
|
|
202
|
+
Field of tangent-space automorphisms on the 2-dimensional
|
|
203
|
+
differentiable manifold S^2
|
|
204
|
+
sage: M.change_of_frame(e, c_spher.frame())[:]
|
|
205
|
+
[ 1 0]
|
|
206
|
+
[ 0 sin(th)]
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
# *****************************************************************************
|
|
210
|
+
# Copyright (C) 2013-2018 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
|
|
211
|
+
# Copyright (C) 2013, 2014 Michal Bejger <bejger@camk.edu.pl>
|
|
212
|
+
# Copyright (C) 2016 Travis Scrimshaw <tscrimsh@umn.edu>
|
|
213
|
+
#
|
|
214
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
215
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
216
|
+
# the License, or (at your option) any later version.
|
|
217
|
+
# https://www.gnu.org/licenses/
|
|
218
|
+
# *****************************************************************************
|
|
219
|
+
|
|
220
|
+
from sage.misc.cachefunc import cached_method
|
|
221
|
+
from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule
|
|
222
|
+
from sage.tensor.modules.free_module_basis import FreeModuleBasis, FreeModuleCoBasis
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class CoFrame(FreeModuleCoBasis):
|
|
226
|
+
r"""
|
|
227
|
+
Coframe on a differentiable manifold.
|
|
228
|
+
|
|
229
|
+
By *coframe*, it is meant a field `f` on some differentiable manifold `U`
|
|
230
|
+
endowed with a differentiable map `\Phi: U \rightarrow M` to a
|
|
231
|
+
differentiable manifold `M` such that for each `p\in U`, `f(p)` is a basis
|
|
232
|
+
of the vector space `T^*_{\Phi(p)}M` (the dual to the tangent space
|
|
233
|
+
`T_{\Phi(p)}M`).
|
|
234
|
+
|
|
235
|
+
The standard case of a coframe *on* `U` corresponds to `U = M` and
|
|
236
|
+
`\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
237
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open interval
|
|
238
|
+
of `\RR`).
|
|
239
|
+
|
|
240
|
+
INPUT:
|
|
241
|
+
|
|
242
|
+
- ``frame`` -- the vector frame dual to the coframe
|
|
243
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
244
|
+
symbols of the 1-forms constituting the coframe, or a tuple of strings,
|
|
245
|
+
representing the individual symbols of the 1-forms
|
|
246
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
247
|
+
as a common base for the LaTeX symbols of the 1-forms constituting the
|
|
248
|
+
coframe, or a tuple of strings, representing the individual LaTeX symbols
|
|
249
|
+
of the 1-forms; if ``None``, ``symbol`` is used in place of
|
|
250
|
+
``latex_symbol``
|
|
251
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a single
|
|
252
|
+
string) tuple of strings representing the indices labelling the 1-forms
|
|
253
|
+
of the coframe; if ``None``, the indices will be generated as integers
|
|
254
|
+
within the range declared on the coframe's domain
|
|
255
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings representing
|
|
256
|
+
the indices for the LaTeX symbols of the 1-forms of the coframe; if
|
|
257
|
+
``None``, ``indices`` is used instead
|
|
258
|
+
|
|
259
|
+
EXAMPLES:
|
|
260
|
+
|
|
261
|
+
Coframe on a 3-dimensional manifold::
|
|
262
|
+
|
|
263
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
264
|
+
sage: X.<x,y,z> = M.chart()
|
|
265
|
+
sage: v = M.vector_frame('v')
|
|
266
|
+
sage: from sage.manifolds.differentiable.vectorframe import CoFrame
|
|
267
|
+
sage: e = CoFrame(v, 'e') ; e
|
|
268
|
+
Coframe (M, (e^1,e^2,e^3))
|
|
269
|
+
|
|
270
|
+
Instead of importing CoFrame in the global namespace, the coframe can be
|
|
271
|
+
obtained by means of the method
|
|
272
|
+
:meth:`~sage.tensor.modules.free_module_basis.FreeModuleBasis.dual_basis`;
|
|
273
|
+
the symbol is then the same as that of the frame::
|
|
274
|
+
|
|
275
|
+
sage: a = v.dual_basis() ; a
|
|
276
|
+
Coframe (M, (v^1,v^2,v^3))
|
|
277
|
+
sage: a[1] == e[1]
|
|
278
|
+
True
|
|
279
|
+
sage: a[1] is e[1]
|
|
280
|
+
False
|
|
281
|
+
sage: e[1].display(v)
|
|
282
|
+
e^1 = v^1
|
|
283
|
+
|
|
284
|
+
The 1-forms composing the coframe are obtained via the operator ``[]``::
|
|
285
|
+
|
|
286
|
+
sage: e[1], e[2], e[3]
|
|
287
|
+
(1-form e^1 on the 3-dimensional differentiable manifold M,
|
|
288
|
+
1-form e^2 on the 3-dimensional differentiable manifold M,
|
|
289
|
+
1-form e^3 on the 3-dimensional differentiable manifold M)
|
|
290
|
+
|
|
291
|
+
Checking that `e` is the dual of `v`::
|
|
292
|
+
|
|
293
|
+
sage: e[1](v[1]).expr(), e[1](v[2]).expr(), e[1](v[3]).expr()
|
|
294
|
+
(1, 0, 0)
|
|
295
|
+
sage: e[2](v[1]).expr(), e[2](v[2]).expr(), e[2](v[3]).expr()
|
|
296
|
+
(0, 1, 0)
|
|
297
|
+
sage: e[3](v[1]).expr(), e[3](v[2]).expr(), e[3](v[3]).expr()
|
|
298
|
+
(0, 0, 1)
|
|
299
|
+
"""
|
|
300
|
+
def __init__(self, frame, symbol, latex_symbol=None, indices=None,
|
|
301
|
+
latex_indices=None):
|
|
302
|
+
r"""
|
|
303
|
+
Construct a coframe, dual to a given vector frame.
|
|
304
|
+
|
|
305
|
+
TESTS::
|
|
306
|
+
|
|
307
|
+
sage: M = Manifold(2, 'M')
|
|
308
|
+
sage: e = M.vector_frame('e')
|
|
309
|
+
sage: from sage.manifolds.differentiable.vectorframe import CoFrame
|
|
310
|
+
sage: f = CoFrame(e, 'f'); f
|
|
311
|
+
Coframe (M, (f^0,f^1))
|
|
312
|
+
sage: TestSuite(f).run()
|
|
313
|
+
"""
|
|
314
|
+
self._domain = frame._domain
|
|
315
|
+
self._manifold = self._domain.manifold()
|
|
316
|
+
FreeModuleCoBasis.__init__(self, frame, symbol,
|
|
317
|
+
latex_symbol=latex_symbol, indices=indices,
|
|
318
|
+
latex_indices=latex_indices)
|
|
319
|
+
# The coframe is added to the domain's set of coframes, as well as to
|
|
320
|
+
# all the superdomains' sets of coframes
|
|
321
|
+
for sd in self._domain.open_supersets():
|
|
322
|
+
sd._coframes.append(self)
|
|
323
|
+
|
|
324
|
+
def _repr_(self):
|
|
325
|
+
r"""
|
|
326
|
+
String representation of ``self``.
|
|
327
|
+
|
|
328
|
+
TESTS::
|
|
329
|
+
|
|
330
|
+
sage: M = Manifold(2, 'M')
|
|
331
|
+
sage: e = M.vector_frame('e')
|
|
332
|
+
sage: f = e.coframe()
|
|
333
|
+
sage: f._repr_()
|
|
334
|
+
'Coframe (M, (e^0,e^1))'
|
|
335
|
+
sage: repr(f) # indirect doctest
|
|
336
|
+
'Coframe (M, (e^0,e^1))'
|
|
337
|
+
sage: f # indirect doctest
|
|
338
|
+
Coframe (M, (e^0,e^1))
|
|
339
|
+
|
|
340
|
+
Test with a nontrivial destination map::
|
|
341
|
+
|
|
342
|
+
sage: N = Manifold(3, 'N', start_index=1)
|
|
343
|
+
sage: phi = M.diff_map(N)
|
|
344
|
+
sage: h = M.vector_frame('h', dest_map=phi)
|
|
345
|
+
sage: h.coframe()._repr_()
|
|
346
|
+
'Coframe (M, (h^1,h^2,h^3)) with values on the 3-dimensional differentiable manifold N'
|
|
347
|
+
"""
|
|
348
|
+
description = "Coframe " + self._name
|
|
349
|
+
dest_map = self._basis.destination_map()
|
|
350
|
+
if dest_map is not self._domain.identity_map():
|
|
351
|
+
description += " with values on the {}".format(dest_map.codomain())
|
|
352
|
+
return description
|
|
353
|
+
|
|
354
|
+
def at(self, point):
|
|
355
|
+
r"""
|
|
356
|
+
Return the value of ``self`` at a given point on the manifold, this
|
|
357
|
+
value being a basis of the dual of the tangent space at the point.
|
|
358
|
+
|
|
359
|
+
INPUT:
|
|
360
|
+
|
|
361
|
+
- ``point`` -- :class:`~sage.manifolds.point.ManifoldPoint`;
|
|
362
|
+
point `p` in the domain `U` of the coframe (denoted `f` hereafter)
|
|
363
|
+
|
|
364
|
+
OUTPUT:
|
|
365
|
+
|
|
366
|
+
- :class:`~sage.tensor.modules.free_module_basis.FreeModuleCoBasis`
|
|
367
|
+
representing the basis `f(p)` of the vector space `T^*_{\Phi(p)} M`,
|
|
368
|
+
dual to the tangent space `T_{\Phi(p)} M`, where
|
|
369
|
+
`\Phi: U \to M` is the differentiable map associated with
|
|
370
|
+
`f` (possibly `\Phi = \mathrm{Id}_U`)
|
|
371
|
+
|
|
372
|
+
EXAMPLES:
|
|
373
|
+
|
|
374
|
+
Cobasis of a tangent space on a 2-dimensional manifold::
|
|
375
|
+
|
|
376
|
+
sage: M = Manifold(2, 'M')
|
|
377
|
+
sage: X.<x,y> = M.chart()
|
|
378
|
+
sage: p = M.point((-1,2), name='p')
|
|
379
|
+
sage: f = X.coframe() ; f
|
|
380
|
+
Coordinate coframe (M, (dx,dy))
|
|
381
|
+
sage: fp = f.at(p) ; fp
|
|
382
|
+
Dual basis (dx,dy) on the Tangent space at Point p on the
|
|
383
|
+
2-dimensional differentiable manifold M
|
|
384
|
+
sage: type(fp)
|
|
385
|
+
<class 'sage.tensor.modules.free_module_basis.FreeModuleCoBasis_with_category'>
|
|
386
|
+
sage: fp[0]
|
|
387
|
+
Linear form dx on the Tangent space at Point p on the 2-dimensional
|
|
388
|
+
differentiable manifold M
|
|
389
|
+
sage: fp[1]
|
|
390
|
+
Linear form dy on the Tangent space at Point p on the 2-dimensional
|
|
391
|
+
differentiable manifold M
|
|
392
|
+
sage: fp is X.frame().at(p).dual_basis()
|
|
393
|
+
True
|
|
394
|
+
"""
|
|
395
|
+
return self._basis.at(point).dual_basis()
|
|
396
|
+
|
|
397
|
+
def set_name(self, symbol, latex_symbol=None, indices=None,
|
|
398
|
+
latex_indices=None, index_position='up',
|
|
399
|
+
include_domain=True):
|
|
400
|
+
r"""
|
|
401
|
+
Set (or change) the text name and LaTeX name of ``self``.
|
|
402
|
+
|
|
403
|
+
INPUT:
|
|
404
|
+
|
|
405
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
406
|
+
symbols of the 1-forms constituting the coframe, or a list/tuple of
|
|
407
|
+
strings, representing the individual symbols of the 1-forms
|
|
408
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
409
|
+
as a common base for the LaTeX symbols of the 1-forms constituting
|
|
410
|
+
the coframe, or a list/tuple of strings, representing the individual
|
|
411
|
+
LaTeX symbols of the 1-forms; if ``None``, ``symbol`` is used in
|
|
412
|
+
place of ``latex_symbol``
|
|
413
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a
|
|
414
|
+
single string) tuple of strings representing the indices labelling
|
|
415
|
+
the 1-forms of the coframe; if ``None``, the indices will be
|
|
416
|
+
generated as integers within the range declared on ``self``
|
|
417
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings
|
|
418
|
+
representing the indices for the LaTeX symbols of the 1-forms;
|
|
419
|
+
if ``None``, ``indices`` is used instead
|
|
420
|
+
- ``index_position`` -- (default: ``'up'``) determines the position
|
|
421
|
+
of the indices labelling the 1-forms of the coframe; can be
|
|
422
|
+
either ``'down'`` or ``'up'``
|
|
423
|
+
- ``include_domain`` -- boolean (default: ``True``); determining whether
|
|
424
|
+
the name of the domain is included in the beginning of the coframe
|
|
425
|
+
name
|
|
426
|
+
|
|
427
|
+
EXAMPLES::
|
|
428
|
+
|
|
429
|
+
sage: M = Manifold(2, 'M')
|
|
430
|
+
sage: e = M.vector_frame('e').coframe(); e
|
|
431
|
+
Coframe (M, (e^0,e^1))
|
|
432
|
+
sage: e.set_name('f'); e
|
|
433
|
+
Coframe (M, (f^0,f^1))
|
|
434
|
+
sage: e.set_name('e', latex_symbol=r'\epsilon')
|
|
435
|
+
sage: latex(e)
|
|
436
|
+
\left(M, \left(\epsilon^{0},\epsilon^{1}\right)\right)
|
|
437
|
+
sage: e.set_name('e', include_domain=False); e
|
|
438
|
+
Coframe (e^0,e^1)
|
|
439
|
+
sage: e.set_name(['a', 'b'], latex_symbol=[r'\alpha', r'\beta']); e
|
|
440
|
+
Coframe (M, (a,b))
|
|
441
|
+
sage: latex(e)
|
|
442
|
+
\left(M, \left(\alpha,\beta\right)\right)
|
|
443
|
+
sage: e.set_name('e', indices=['x','y'],
|
|
444
|
+
....: latex_indices=[r'\xi', r'\zeta']); e
|
|
445
|
+
Coframe (M, (e^x,e^y))
|
|
446
|
+
sage: latex(e)
|
|
447
|
+
\left(M, \left(e^{\xi},e^{\zeta}\right)\right)
|
|
448
|
+
"""
|
|
449
|
+
super().set_name(symbol, latex_symbol=latex_symbol,
|
|
450
|
+
indices=indices,
|
|
451
|
+
latex_indices=latex_indices,
|
|
452
|
+
index_position=index_position)
|
|
453
|
+
if include_domain:
|
|
454
|
+
# Redefinition of the name and the LaTeX name to include the domain
|
|
455
|
+
self._name = "({}, {})".format(self._domain._name, self._name)
|
|
456
|
+
self._latex_name = r"\left({}, {}\right)".format(
|
|
457
|
+
self._domain._latex_name, self._latex_name)
|
|
458
|
+
|
|
459
|
+
# ******************************************************************************
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
class VectorFrame(FreeModuleBasis):
|
|
463
|
+
r"""
|
|
464
|
+
Vector frame on a differentiable manifold.
|
|
465
|
+
|
|
466
|
+
By *vector frame*, it is meant a field `e` on some
|
|
467
|
+
differentiable manifold `U` endowed with a differentiable map
|
|
468
|
+
`\Phi: U\rightarrow M` to a differentiable manifold `M` such that for
|
|
469
|
+
each `p\in U`, `e(p)` is a vector basis of the tangent space
|
|
470
|
+
`T_{\Phi(p)}M`.
|
|
471
|
+
|
|
472
|
+
The standard case of a vector frame *on* `U` corresponds to `U=M`
|
|
473
|
+
and `\Phi = \mathrm{Id}_M`. Other common cases are `\Phi` being an
|
|
474
|
+
immersion and `\Phi` being a curve in `M` (`U` is then an open interval
|
|
475
|
+
of `\RR`).
|
|
476
|
+
|
|
477
|
+
For each instantiation of a vector frame, a coframe is automatically
|
|
478
|
+
created, as an instance of the class :class:`CoFrame`. It is returned by
|
|
479
|
+
the method :meth:`coframe`.
|
|
480
|
+
|
|
481
|
+
INPUT:
|
|
482
|
+
|
|
483
|
+
- ``vector_field_module`` -- free module `\mathfrak{X}(U, \Phi)`
|
|
484
|
+
of vector fields along `U` with values on `M \supset \Phi(U)`
|
|
485
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
486
|
+
symbols of the vector fields constituting the vector frame, or a tuple
|
|
487
|
+
of strings, representing the individual symbols of the vector fields
|
|
488
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
489
|
+
as a common base for the LaTeX symbols of the vector fields constituting
|
|
490
|
+
the vector frame, or a tuple of strings, representing the individual
|
|
491
|
+
LaTeX symbols of the vector fields; if ``None``, ``symbol`` is used in
|
|
492
|
+
place of ``latex_symbol``
|
|
493
|
+
- ``from_frame`` -- (default: ``None``) vector frame `\tilde e` on the
|
|
494
|
+
codomain `M` of the destination map `\Phi`; the constructed frame `e`
|
|
495
|
+
is then such that `\forall p \in U, e(p) = \tilde{e}(\Phi(p))`
|
|
496
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a single
|
|
497
|
+
string) tuple of strings representing the indices labelling the vector
|
|
498
|
+
fields of the frame; if ``None``, the indices will be generated as
|
|
499
|
+
integers within the range declared on the vector frame's domain
|
|
500
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings representing
|
|
501
|
+
the indices for the LaTeX symbols of the vector fields; if
|
|
502
|
+
``None``, ``indices`` is used instead
|
|
503
|
+
- ``symbol_dual`` -- (default: ``None``) same as ``symbol`` but for the
|
|
504
|
+
dual coframe; if ``None``, ``symbol`` must be a string and is used
|
|
505
|
+
for the common base of the symbols of the elements of the dual coframe
|
|
506
|
+
- ``latex_symbol_dual`` -- (default: ``None``) same as ``latex_symbol``
|
|
507
|
+
but for the dual coframe
|
|
508
|
+
|
|
509
|
+
EXAMPLES:
|
|
510
|
+
|
|
511
|
+
Defining a vector frame on a 3-dimensional manifold::
|
|
512
|
+
|
|
513
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
514
|
+
sage: X.<x,y,z> = M.chart()
|
|
515
|
+
sage: e = M.vector_frame('e') ; e
|
|
516
|
+
Vector frame (M, (e_1,e_2,e_3))
|
|
517
|
+
sage: latex(e)
|
|
518
|
+
\left(M, \left(e_{1},e_{2},e_{3}\right)\right)
|
|
519
|
+
|
|
520
|
+
The individual elements of the vector frame are accessed via square
|
|
521
|
+
brackets, with the possibility to invoke the slice operator '``:``' to
|
|
522
|
+
get more than a single element::
|
|
523
|
+
|
|
524
|
+
sage: e[2]
|
|
525
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M
|
|
526
|
+
sage: e[1:3]
|
|
527
|
+
(Vector field e_1 on the 3-dimensional differentiable manifold M,
|
|
528
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M)
|
|
529
|
+
sage: e[:]
|
|
530
|
+
(Vector field e_1 on the 3-dimensional differentiable manifold M,
|
|
531
|
+
Vector field e_2 on the 3-dimensional differentiable manifold M,
|
|
532
|
+
Vector field e_3 on the 3-dimensional differentiable manifold M)
|
|
533
|
+
|
|
534
|
+
The LaTeX symbol can be specified::
|
|
535
|
+
|
|
536
|
+
sage: E = M.vector_frame('E', latex_symbol=r"\epsilon")
|
|
537
|
+
sage: latex(E)
|
|
538
|
+
\left(M, \left(\epsilon_{1},\epsilon_{2},\epsilon_{3}\right)\right)
|
|
539
|
+
|
|
540
|
+
By default, the elements of the vector frame are labelled by integers
|
|
541
|
+
within the range specified at the manifold declaration. It is however
|
|
542
|
+
possible to fully customize the labels, via the argument ``indices``::
|
|
543
|
+
|
|
544
|
+
sage: u = M.vector_frame('u', indices=('x', 'y', 'z')) ; u
|
|
545
|
+
Vector frame (M, (u_x,u_y,u_z))
|
|
546
|
+
sage: u[1]
|
|
547
|
+
Vector field u_x on the 3-dimensional differentiable manifold M
|
|
548
|
+
sage: u.coframe()
|
|
549
|
+
Coframe (M, (u^x,u^y,u^z))
|
|
550
|
+
|
|
551
|
+
The LaTeX format of the indices can be adjusted::
|
|
552
|
+
|
|
553
|
+
sage: v = M.vector_frame('v', indices=('a', 'b', 'c'),
|
|
554
|
+
....: latex_indices=(r'\alpha', r'\beta', r'\gamma'))
|
|
555
|
+
sage: v
|
|
556
|
+
Vector frame (M, (v_a,v_b,v_c))
|
|
557
|
+
sage: latex(v)
|
|
558
|
+
\left(M, \left(v_{\alpha},v_{\beta},v_{\gamma}\right)\right)
|
|
559
|
+
sage: latex(v.coframe())
|
|
560
|
+
\left(M, \left(v^{\alpha},v^{\beta},v^{\gamma}\right)\right)
|
|
561
|
+
|
|
562
|
+
The symbol of each element of the vector frame can also be freely chosen,
|
|
563
|
+
by providing a tuple of symbols as the first argument of ``vector_frame``;
|
|
564
|
+
it is then mandatory to specify as well some symbols for the dual coframe::
|
|
565
|
+
|
|
566
|
+
sage: h = M.vector_frame(('a', 'b', 'c'), symbol_dual=('A', 'B', 'C'))
|
|
567
|
+
sage: h
|
|
568
|
+
Vector frame (M, (a,b,c))
|
|
569
|
+
sage: h[1]
|
|
570
|
+
Vector field a on the 3-dimensional differentiable manifold M
|
|
571
|
+
sage: h.coframe()
|
|
572
|
+
Coframe (M, (A,B,C))
|
|
573
|
+
sage: h.coframe()[1]
|
|
574
|
+
1-form A on the 3-dimensional differentiable manifold M
|
|
575
|
+
|
|
576
|
+
Example with a non-trivial map `\Phi` (see above); a vector frame along a
|
|
577
|
+
curve::
|
|
578
|
+
|
|
579
|
+
sage: U = Manifold(1, 'U') # open interval (-1,1) as a 1-dimensional manifold
|
|
580
|
+
sage: T.<t> = U.chart('t:(-1,1)') # canonical chart on U
|
|
581
|
+
sage: Phi = U.diff_map(M, [cos(t), sin(t), t], name='Phi',
|
|
582
|
+
....: latex_name=r'\Phi')
|
|
583
|
+
sage: Phi
|
|
584
|
+
Differentiable map Phi from the 1-dimensional differentiable manifold U
|
|
585
|
+
to the 3-dimensional differentiable manifold M
|
|
586
|
+
sage: f = U.vector_frame('f', dest_map=Phi) ; f
|
|
587
|
+
Vector frame (U, (f_1,f_2,f_3)) with values on the 3-dimensional
|
|
588
|
+
differentiable manifold M
|
|
589
|
+
sage: f.domain()
|
|
590
|
+
1-dimensional differentiable manifold U
|
|
591
|
+
sage: f.ambient_domain()
|
|
592
|
+
3-dimensional differentiable manifold M
|
|
593
|
+
|
|
594
|
+
The value of the vector frame at a given point is a basis of the
|
|
595
|
+
corresponding tangent space::
|
|
596
|
+
|
|
597
|
+
sage: p = U((0,), name='p') ; p
|
|
598
|
+
Point p on the 1-dimensional differentiable manifold U
|
|
599
|
+
sage: f.at(p)
|
|
600
|
+
Basis (f_1,f_2,f_3) on the Tangent space at Point Phi(p) on the
|
|
601
|
+
3-dimensional differentiable manifold M
|
|
602
|
+
|
|
603
|
+
Vector frames are bases of free modules formed by vector fields::
|
|
604
|
+
|
|
605
|
+
sage: e.module()
|
|
606
|
+
Free module X(M) of vector fields on the 3-dimensional differentiable
|
|
607
|
+
manifold M
|
|
608
|
+
sage: e.module().base_ring()
|
|
609
|
+
Algebra of differentiable scalar fields on the 3-dimensional
|
|
610
|
+
differentiable manifold M
|
|
611
|
+
sage: e.module() is M.vector_field_module()
|
|
612
|
+
True
|
|
613
|
+
sage: e in M.vector_field_module().bases()
|
|
614
|
+
True
|
|
615
|
+
|
|
616
|
+
::
|
|
617
|
+
|
|
618
|
+
sage: f.module()
|
|
619
|
+
Free module X(U,Phi) of vector fields along the 1-dimensional
|
|
620
|
+
differentiable manifold U mapped into the 3-dimensional differentiable
|
|
621
|
+
manifold M
|
|
622
|
+
sage: f.module().base_ring()
|
|
623
|
+
Algebra of differentiable scalar fields on the 1-dimensional
|
|
624
|
+
differentiable manifold U
|
|
625
|
+
sage: f.module() is U.vector_field_module(dest_map=Phi)
|
|
626
|
+
True
|
|
627
|
+
sage: f in U.vector_field_module(dest_map=Phi).bases()
|
|
628
|
+
True
|
|
629
|
+
"""
|
|
630
|
+
|
|
631
|
+
# The following class attribute must be redefined by any derived class:
|
|
632
|
+
_cobasis_class = CoFrame
|
|
633
|
+
|
|
634
|
+
@staticmethod
|
|
635
|
+
def __classcall_private__(cls, vector_field_module, symbol,
|
|
636
|
+
latex_symbol=None, from_frame=None, indices=None,
|
|
637
|
+
latex_indices=None, symbol_dual=None,
|
|
638
|
+
latex_symbol_dual=None):
|
|
639
|
+
"""
|
|
640
|
+
Transform input lists into tuples for the unique representation of
|
|
641
|
+
VectorFrame.
|
|
642
|
+
|
|
643
|
+
TESTS::
|
|
644
|
+
|
|
645
|
+
sage: M = Manifold(2, 'M')
|
|
646
|
+
sage: XM = M.vector_field_module(force_free=True)
|
|
647
|
+
sage: from sage.manifolds.differentiable.vectorframe import VectorFrame
|
|
648
|
+
sage: e = VectorFrame(XM, ['a', 'b'], symbol_dual=['A', 'B']); e
|
|
649
|
+
Vector frame (M, (a,b))
|
|
650
|
+
sage: e.dual_basis()
|
|
651
|
+
Coframe (M, (A,B))
|
|
652
|
+
sage: e is VectorFrame(XM, ('a', 'b'), symbol_dual=('A', 'B'))
|
|
653
|
+
True
|
|
654
|
+
"""
|
|
655
|
+
if isinstance(symbol, list):
|
|
656
|
+
symbol = tuple(symbol)
|
|
657
|
+
if isinstance(latex_symbol, list):
|
|
658
|
+
latex_symbol = tuple(latex_symbol)
|
|
659
|
+
if isinstance(indices, list):
|
|
660
|
+
indices = tuple(indices)
|
|
661
|
+
if isinstance(latex_indices, list):
|
|
662
|
+
latex_indices = tuple(latex_indices)
|
|
663
|
+
if isinstance(symbol_dual, list):
|
|
664
|
+
symbol_dual = tuple(symbol_dual)
|
|
665
|
+
if isinstance(latex_symbol_dual, list):
|
|
666
|
+
latex_symbol_dual = tuple(latex_symbol_dual)
|
|
667
|
+
return super().__classcall__(cls, vector_field_module,
|
|
668
|
+
symbol, latex_symbol=latex_symbol,
|
|
669
|
+
from_frame=from_frame, indices=indices,
|
|
670
|
+
latex_indices=latex_indices,
|
|
671
|
+
symbol_dual=symbol_dual,
|
|
672
|
+
latex_symbol_dual=latex_symbol_dual)
|
|
673
|
+
|
|
674
|
+
def __init__(self, vector_field_module, symbol, latex_symbol=None,
|
|
675
|
+
from_frame=None, indices=None, latex_indices=None,
|
|
676
|
+
symbol_dual=None, latex_symbol_dual=None):
|
|
677
|
+
r"""
|
|
678
|
+
Construct a vector frame on a parallelizable manifold.
|
|
679
|
+
|
|
680
|
+
TESTS::
|
|
681
|
+
|
|
682
|
+
sage: M = Manifold(2, 'M')
|
|
683
|
+
sage: XM = M.vector_field_module(force_free=True) # makes M parallelizable
|
|
684
|
+
sage: from sage.manifolds.differentiable.vectorframe import VectorFrame
|
|
685
|
+
sage: e = VectorFrame(XM, 'e', latex_symbol=r'\epsilon'); e
|
|
686
|
+
Vector frame (M, (e_0,e_1))
|
|
687
|
+
sage: TestSuite(e).run()
|
|
688
|
+
"""
|
|
689
|
+
from sage.manifolds.differentiable.manifold import DifferentiableManifold
|
|
690
|
+
# Some sanity check:
|
|
691
|
+
if not isinstance(vector_field_module, FiniteRankFreeModule):
|
|
692
|
+
raise ValueError("the {} has already been constructed as a "
|
|
693
|
+
"non-free module and therefore cannot have "
|
|
694
|
+
"a basis".format(vector_field_module))
|
|
695
|
+
self._domain = vector_field_module._domain
|
|
696
|
+
self._ambient_domain = vector_field_module._ambient_domain
|
|
697
|
+
self._dest_map = vector_field_module._dest_map
|
|
698
|
+
self._from_frame = from_frame
|
|
699
|
+
self._manifold = self._domain.manifold()
|
|
700
|
+
if from_frame is not None:
|
|
701
|
+
if not from_frame._domain.is_subset(self._dest_map._codomain):
|
|
702
|
+
raise ValueError("the domain of the frame 'from_frame' is " +
|
|
703
|
+
"not included in the codomain of the " +
|
|
704
|
+
"destination map")
|
|
705
|
+
if symbol is None:
|
|
706
|
+
if from_frame is None:
|
|
707
|
+
raise TypeError("some frame symbol must be provided")
|
|
708
|
+
symbol = from_frame._symbol
|
|
709
|
+
latex_symbol = from_frame._latex_symbol
|
|
710
|
+
indices = from_frame._indices
|
|
711
|
+
latex_indices = from_frame._latex_indices
|
|
712
|
+
symbol_dual = from_frame._symbol_dual
|
|
713
|
+
latex_symbol_dual = from_frame._latex_symbol_dual
|
|
714
|
+
FreeModuleBasis.__init__(self, vector_field_module,
|
|
715
|
+
symbol, latex_symbol=latex_symbol,
|
|
716
|
+
indices=indices, latex_indices=latex_indices,
|
|
717
|
+
symbol_dual=symbol_dual,
|
|
718
|
+
latex_symbol_dual=latex_symbol_dual)
|
|
719
|
+
# The frame is added to the domain's set of frames, as well as to all
|
|
720
|
+
# the superdomains' sets of frames; moreover the first defined frame
|
|
721
|
+
# is considered as the default one
|
|
722
|
+
dest_map = self._dest_map
|
|
723
|
+
for sd in self._domain.open_supersets():
|
|
724
|
+
sd._frames.append(self)
|
|
725
|
+
sd._top_frames.append(self)
|
|
726
|
+
if sd._def_frame is None:
|
|
727
|
+
sd._def_frame = self
|
|
728
|
+
if isinstance(sd, DifferentiableManifold):
|
|
729
|
+
# Initialization of the zero elements of tensor field modules:
|
|
730
|
+
if dest_map in sd._vector_field_modules:
|
|
731
|
+
xsd = sd._vector_field_modules[dest_map]
|
|
732
|
+
if not isinstance(xsd, FiniteRankFreeModule):
|
|
733
|
+
for t in xsd._tensor_modules.values():
|
|
734
|
+
t.zero()._add_comp_unsafe(self)
|
|
735
|
+
# (since new components are initialized to zero)
|
|
736
|
+
if dest_map is self._domain.identity_map():
|
|
737
|
+
# The frame is added to the list of the domain's covering frames:
|
|
738
|
+
self._domain._set_covering_frame(self)
|
|
739
|
+
|
|
740
|
+
# Dual coframe
|
|
741
|
+
self._coframe = self.dual_basis() # self._coframe = a shortcut for
|
|
742
|
+
# self._dual_basis
|
|
743
|
+
|
|
744
|
+
# Derived quantities:
|
|
745
|
+
# Initialization of the set of frames that are restrictions of the
|
|
746
|
+
# current frame to subdomains of the frame domain:
|
|
747
|
+
self._subframes = set([self])
|
|
748
|
+
# Initialization of the set of frames which the current frame is a
|
|
749
|
+
# restriction of:
|
|
750
|
+
self._superframes = set([self])
|
|
751
|
+
|
|
752
|
+
self._restrictions = {} # dict. of the restrictions of self to
|
|
753
|
+
# subdomains of self._domain, with the
|
|
754
|
+
# subdomains as keys
|
|
755
|
+
# NB: set(self._restrictions.values()) is identical to
|
|
756
|
+
# self._subframes
|
|
757
|
+
|
|
758
|
+
###### Methods that must be redefined by derived classes of ######
|
|
759
|
+
###### FreeModuleBasis ######
|
|
760
|
+
|
|
761
|
+
def _repr_(self):
|
|
762
|
+
r"""
|
|
763
|
+
String representation of ``self``.
|
|
764
|
+
|
|
765
|
+
TESTS::
|
|
766
|
+
|
|
767
|
+
sage: M = Manifold(2, 'M')
|
|
768
|
+
sage: e = M.vector_frame('e')
|
|
769
|
+
sage: e._repr_()
|
|
770
|
+
'Vector frame (M, (e_0,e_1))'
|
|
771
|
+
sage: repr(e) # indirect doctest
|
|
772
|
+
'Vector frame (M, (e_0,e_1))'
|
|
773
|
+
sage: e # indirect doctest
|
|
774
|
+
Vector frame (M, (e_0,e_1))
|
|
775
|
+
|
|
776
|
+
Test with a nontrivial destination map::
|
|
777
|
+
|
|
778
|
+
sage: N = Manifold(3, 'N', start_index=1)
|
|
779
|
+
sage: phi = M.diff_map(N)
|
|
780
|
+
sage: h = M.vector_frame('h', dest_map=phi)
|
|
781
|
+
sage: h._repr_()
|
|
782
|
+
'Vector frame (M, (h_1,h_2,h_3)) with values on the 3-dimensional differentiable manifold N'
|
|
783
|
+
"""
|
|
784
|
+
description = "Vector frame " + self._name
|
|
785
|
+
if self._dest_map is not self._domain.identity_map():
|
|
786
|
+
description += " with values on the {}".format(self._dest_map.codomain())
|
|
787
|
+
return description
|
|
788
|
+
|
|
789
|
+
def _new_instance(self, symbol, latex_symbol=None, indices=None,
|
|
790
|
+
latex_indices=None, symbol_dual=None,
|
|
791
|
+
latex_symbol_dual=None):
|
|
792
|
+
r"""
|
|
793
|
+
Construct a new vector frame on the same vector field module
|
|
794
|
+
as ``self``.
|
|
795
|
+
|
|
796
|
+
INPUT:
|
|
797
|
+
|
|
798
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
799
|
+
symbols of the vector fields constituting the vector frame, or a
|
|
800
|
+
tuple of strings, representing the individual symbols of the vector
|
|
801
|
+
fields
|
|
802
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
803
|
+
as a common base for the LaTeX symbols of the vector fields
|
|
804
|
+
constituting the vector frame, or a tuple of strings, representing
|
|
805
|
+
the individual LaTeX symbols of the vector fields; if ``None``,
|
|
806
|
+
``symbol`` is used in place of ``latex_symbol``
|
|
807
|
+
- ``from_frame`` -- (default: ``None``) vector frame `\tilde e` on the
|
|
808
|
+
codomain `M` of the destination map `\Phi`; the constructed frame `e`
|
|
809
|
+
is then such that `\forall p \in U, e(p) = \tilde{e}(\Phi(p))`
|
|
810
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a
|
|
811
|
+
single string) tuple of strings representing the indices labelling
|
|
812
|
+
the vector fields of the frame; if ``None``, the indices will be
|
|
813
|
+
generated as integers within the range declared on the vector frame's
|
|
814
|
+
domain
|
|
815
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings
|
|
816
|
+
representing the indices for the LaTeX symbols of the vector fields;
|
|
817
|
+
if ``None``, ``indices`` is used instead
|
|
818
|
+
- ``symbol_dual`` -- (default: ``None``) same as ``symbol`` but for the
|
|
819
|
+
dual coframe; if ``None``, ``symbol`` must be a string and is used
|
|
820
|
+
for the common base of the symbols of the elements of the dual
|
|
821
|
+
coframe
|
|
822
|
+
- ``latex_symbol_dual`` -- (default: ``None``) same as ``latex_symbol``
|
|
823
|
+
but for the dual coframe
|
|
824
|
+
|
|
825
|
+
OUTPUT: instance of :class:`VectorFrame`
|
|
826
|
+
|
|
827
|
+
TESTS::
|
|
828
|
+
|
|
829
|
+
sage: M = Manifold(2, 'M')
|
|
830
|
+
sage: e = M.vector_frame('e')
|
|
831
|
+
sage: e._new_instance('f')
|
|
832
|
+
Vector frame (M, (f_0,f_1))
|
|
833
|
+
"""
|
|
834
|
+
return VectorFrame(self._fmodule, symbol, latex_symbol=latex_symbol,
|
|
835
|
+
indices=indices, latex_indices=latex_indices,
|
|
836
|
+
symbol_dual=symbol_dual,
|
|
837
|
+
latex_symbol_dual=latex_symbol_dual)
|
|
838
|
+
|
|
839
|
+
###### End of methods to be redefined by derived classes ######
|
|
840
|
+
|
|
841
|
+
def domain(self):
|
|
842
|
+
r"""
|
|
843
|
+
Return the domain on which ``self`` is defined.
|
|
844
|
+
|
|
845
|
+
OUTPUT:
|
|
846
|
+
|
|
847
|
+
- a :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`;
|
|
848
|
+
representing the domain of the vector frame
|
|
849
|
+
|
|
850
|
+
EXAMPLES::
|
|
851
|
+
|
|
852
|
+
sage: M = Manifold(2, 'M')
|
|
853
|
+
sage: e = M.vector_frame('e')
|
|
854
|
+
sage: e.domain()
|
|
855
|
+
2-dimensional differentiable manifold M
|
|
856
|
+
sage: U = M.open_subset('U')
|
|
857
|
+
sage: f = e.restrict(U)
|
|
858
|
+
sage: f.domain()
|
|
859
|
+
Open subset U of the 2-dimensional differentiable manifold M
|
|
860
|
+
"""
|
|
861
|
+
return self._domain
|
|
862
|
+
|
|
863
|
+
def ambient_domain(self):
|
|
864
|
+
r"""
|
|
865
|
+
Return the differentiable manifold in which ``self`` takes its values.
|
|
866
|
+
|
|
867
|
+
The ambient domain is the codomain `M` of the differentiable map
|
|
868
|
+
`\Phi: U \rightarrow M` associated with the frame.
|
|
869
|
+
|
|
870
|
+
OUTPUT:
|
|
871
|
+
|
|
872
|
+
- a :class:`~sage.manifolds.differentiable.manifold.DifferentiableManifold`
|
|
873
|
+
representing `M`
|
|
874
|
+
|
|
875
|
+
EXAMPLES::
|
|
876
|
+
|
|
877
|
+
sage: M = Manifold(2, 'M')
|
|
878
|
+
sage: e = M.vector_frame('e')
|
|
879
|
+
sage: e.ambient_domain()
|
|
880
|
+
2-dimensional differentiable manifold M
|
|
881
|
+
|
|
882
|
+
In the present case, since `\Phi` is the identity map::
|
|
883
|
+
|
|
884
|
+
sage: e.ambient_domain() == e.domain()
|
|
885
|
+
True
|
|
886
|
+
|
|
887
|
+
An example with a non trivial map `\Phi`::
|
|
888
|
+
|
|
889
|
+
sage: U = Manifold(1, 'U')
|
|
890
|
+
sage: T.<t> = U.chart()
|
|
891
|
+
sage: X.<x,y> = M.chart()
|
|
892
|
+
sage: Phi = U.diff_map(M, {(T,X): [cos(t), t]}, name='Phi',
|
|
893
|
+
....: latex_name=r'\Phi') ; Phi
|
|
894
|
+
Differentiable map Phi from the 1-dimensional differentiable
|
|
895
|
+
manifold U to the 2-dimensional differentiable manifold M
|
|
896
|
+
sage: f = U.vector_frame('f', dest_map=Phi); f
|
|
897
|
+
Vector frame (U, (f_0,f_1)) with values on the 2-dimensional
|
|
898
|
+
differentiable manifold M
|
|
899
|
+
sage: f.ambient_domain()
|
|
900
|
+
2-dimensional differentiable manifold M
|
|
901
|
+
sage: f.domain()
|
|
902
|
+
1-dimensional differentiable manifold U
|
|
903
|
+
"""
|
|
904
|
+
return self._ambient_domain
|
|
905
|
+
|
|
906
|
+
def destination_map(self):
|
|
907
|
+
r"""
|
|
908
|
+
Return the differential map associated to this vector frame.
|
|
909
|
+
|
|
910
|
+
Let `e` denote the vector frame; the differential map associated to
|
|
911
|
+
it is the map `\Phi: U\rightarrow M` such that for each `p \in U`,
|
|
912
|
+
`e(p)` is a vector basis of the tangent space `T_{\Phi(p)}M`.
|
|
913
|
+
|
|
914
|
+
OUTPUT:
|
|
915
|
+
|
|
916
|
+
- a :class:`~sage.manifolds.differentiable.diff_map.DiffMap`
|
|
917
|
+
representing the differential map `\Phi`
|
|
918
|
+
|
|
919
|
+
EXAMPLES::
|
|
920
|
+
|
|
921
|
+
sage: M = Manifold(2, 'M')
|
|
922
|
+
sage: e = M.vector_frame('e')
|
|
923
|
+
sage: e.destination_map()
|
|
924
|
+
Identity map Id_M of the 2-dimensional differentiable manifold M
|
|
925
|
+
|
|
926
|
+
An example with a non trivial map `\Phi`::
|
|
927
|
+
|
|
928
|
+
sage: U = Manifold(1, 'U')
|
|
929
|
+
sage: T.<t> = U.chart()
|
|
930
|
+
sage: X.<x,y> = M.chart()
|
|
931
|
+
sage: Phi = U.diff_map(M, {(T,X): [cos(t), t]}, name='Phi',
|
|
932
|
+
....: latex_name=r'\Phi') ; Phi
|
|
933
|
+
Differentiable map Phi from the 1-dimensional differentiable
|
|
934
|
+
manifold U to the 2-dimensional differentiable manifold M
|
|
935
|
+
sage: f = U.vector_frame('f', dest_map=Phi); f
|
|
936
|
+
Vector frame (U, (f_0,f_1)) with values on the 2-dimensional
|
|
937
|
+
differentiable manifold M
|
|
938
|
+
sage: f.destination_map()
|
|
939
|
+
Differentiable map Phi from the 1-dimensional differentiable
|
|
940
|
+
manifold U to the 2-dimensional differentiable manifold M
|
|
941
|
+
"""
|
|
942
|
+
return self._dest_map
|
|
943
|
+
|
|
944
|
+
def coframe(self):
|
|
945
|
+
r"""
|
|
946
|
+
Return the coframe of ``self``.
|
|
947
|
+
|
|
948
|
+
EXAMPLES::
|
|
949
|
+
|
|
950
|
+
sage: M = Manifold(2, 'M')
|
|
951
|
+
sage: e = M.vector_frame('e')
|
|
952
|
+
sage: e.coframe()
|
|
953
|
+
Coframe (M, (e^0,e^1))
|
|
954
|
+
sage: X.<x,y> = M.chart()
|
|
955
|
+
sage: X.frame().coframe()
|
|
956
|
+
Coordinate coframe (M, (dx,dy))
|
|
957
|
+
"""
|
|
958
|
+
return self._coframe
|
|
959
|
+
|
|
960
|
+
def new_frame(self, change_of_frame, symbol, latex_symbol=None,
|
|
961
|
+
indices=None, latex_indices=None, symbol_dual=None,
|
|
962
|
+
latex_symbol_dual=None):
|
|
963
|
+
r"""
|
|
964
|
+
Define a new vector frame from ``self``.
|
|
965
|
+
|
|
966
|
+
The new vector frame is defined from a field of tangent-space
|
|
967
|
+
automorphisms; its domain is the same as that of the current frame.
|
|
968
|
+
|
|
969
|
+
INPUT:
|
|
970
|
+
|
|
971
|
+
- ``change_of_frame`` --
|
|
972
|
+
:class:`~sage.manifolds.differentiable.automorphismfield.AutomorphismFieldParal`;
|
|
973
|
+
the field of tangent space automorphisms `P` that relates
|
|
974
|
+
the current frame `(e_i)` to the new frame `(n_i)` according
|
|
975
|
+
to `n_i = P(e_i)`
|
|
976
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
977
|
+
symbols of the vector fields constituting the vector frame, or a
|
|
978
|
+
list/tuple of strings, representing the individual symbols of the
|
|
979
|
+
vector fields
|
|
980
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
981
|
+
as a common base for the LaTeX symbols of the vector fields
|
|
982
|
+
constituting the vector frame, or a list/tuple of strings,
|
|
983
|
+
representing the individual LaTeX symbols of the vector fields;
|
|
984
|
+
if ``None``, ``symbol`` is used in place of ``latex_symbol``
|
|
985
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a
|
|
986
|
+
single string) tuple of strings representing the indices labelling
|
|
987
|
+
the vector fields of the frame; if ``None``, the indices will be
|
|
988
|
+
generated as integers within the range declared on ``self``
|
|
989
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings
|
|
990
|
+
representing the indices for the LaTeX symbols of the vector fields;
|
|
991
|
+
if ``None``, ``indices`` is used instead
|
|
992
|
+
- ``symbol_dual`` -- (default: ``None``) same as ``symbol`` but for the
|
|
993
|
+
dual coframe; if ``None``, ``symbol`` must be a string and is used
|
|
994
|
+
for the common base of the symbols of the elements of the dual
|
|
995
|
+
coframe
|
|
996
|
+
- ``latex_symbol_dual`` -- (default: ``None``) same as ``latex_symbol``
|
|
997
|
+
but for the dual coframe
|
|
998
|
+
|
|
999
|
+
OUTPUT:
|
|
1000
|
+
|
|
1001
|
+
- the new frame `(n_i)`, as an instance of :class:`VectorFrame`
|
|
1002
|
+
|
|
1003
|
+
EXAMPLES:
|
|
1004
|
+
|
|
1005
|
+
Frame resulting from a `\pi/3`-rotation in the Euclidean plane::
|
|
1006
|
+
|
|
1007
|
+
sage: M = Manifold(2, 'R^2')
|
|
1008
|
+
sage: X.<x,y> = M.chart()
|
|
1009
|
+
sage: e = M.vector_frame('e') ; M.set_default_frame(e)
|
|
1010
|
+
sage: M._frame_changes
|
|
1011
|
+
{}
|
|
1012
|
+
sage: rot = M.automorphism_field()
|
|
1013
|
+
sage: rot[:] = [[sqrt(3)/2, -1/2], [1/2, sqrt(3)/2]]
|
|
1014
|
+
sage: n = e.new_frame(rot, 'n')
|
|
1015
|
+
sage: n[0][:]
|
|
1016
|
+
[1/2*sqrt(3), 1/2]
|
|
1017
|
+
sage: n[1][:]
|
|
1018
|
+
[-1/2, 1/2*sqrt(3)]
|
|
1019
|
+
sage: a = M.change_of_frame(e,n)
|
|
1020
|
+
sage: a[:]
|
|
1021
|
+
[1/2*sqrt(3) -1/2]
|
|
1022
|
+
[ 1/2 1/2*sqrt(3)]
|
|
1023
|
+
sage: a == rot
|
|
1024
|
+
True
|
|
1025
|
+
sage: a is rot
|
|
1026
|
+
False
|
|
1027
|
+
sage: a._components # random (dictionary output)
|
|
1028
|
+
{Vector frame (R^2, (e_0,e_1)): 2-indices components w.r.t.
|
|
1029
|
+
Vector frame (R^2, (e_0,e_1)),
|
|
1030
|
+
Vector frame (R^2, (n_0,n_1)): 2-indices components w.r.t.
|
|
1031
|
+
Vector frame (R^2, (n_0,n_1))}
|
|
1032
|
+
sage: a.comp(n)[:]
|
|
1033
|
+
[1/2*sqrt(3) -1/2]
|
|
1034
|
+
[ 1/2 1/2*sqrt(3)]
|
|
1035
|
+
sage: a1 = M.change_of_frame(n,e)
|
|
1036
|
+
sage: a1[:]
|
|
1037
|
+
[1/2*sqrt(3) 1/2]
|
|
1038
|
+
[ -1/2 1/2*sqrt(3)]
|
|
1039
|
+
sage: a1 == rot.inverse()
|
|
1040
|
+
True
|
|
1041
|
+
sage: a1 is rot.inverse()
|
|
1042
|
+
False
|
|
1043
|
+
sage: e[0].comp(n)[:]
|
|
1044
|
+
[1/2*sqrt(3), -1/2]
|
|
1045
|
+
sage: e[1].comp(n)[:]
|
|
1046
|
+
[1/2, 1/2*sqrt(3)]
|
|
1047
|
+
"""
|
|
1048
|
+
the_new_frame = self.new_basis(change_of_frame, symbol,
|
|
1049
|
+
latex_symbol=latex_symbol,
|
|
1050
|
+
indices=indices,
|
|
1051
|
+
latex_indices=latex_indices,
|
|
1052
|
+
symbol_dual=symbol_dual,
|
|
1053
|
+
latex_symbol_dual=latex_symbol_dual)
|
|
1054
|
+
for sdom in self._domain.open_supersets():
|
|
1055
|
+
sdom._frame_changes[(self, the_new_frame)] = \
|
|
1056
|
+
self._fmodule._basis_changes[(self, the_new_frame)]
|
|
1057
|
+
sdom._frame_changes[(the_new_frame, self)] = \
|
|
1058
|
+
self._fmodule._basis_changes[(the_new_frame, self)]
|
|
1059
|
+
return the_new_frame
|
|
1060
|
+
|
|
1061
|
+
def restrict(self, subdomain):
|
|
1062
|
+
r"""
|
|
1063
|
+
Return the restriction of ``self`` to some open subset of its domain.
|
|
1064
|
+
|
|
1065
|
+
If the restriction has not been defined yet, it is constructed here.
|
|
1066
|
+
|
|
1067
|
+
INPUT:
|
|
1068
|
+
|
|
1069
|
+
- ``subdomain`` -- open subset `V` of the current frame domain `U`
|
|
1070
|
+
|
|
1071
|
+
OUTPUT: the restriction of the current frame to `V` as a :class:`VectorFrame`
|
|
1072
|
+
|
|
1073
|
+
EXAMPLES:
|
|
1074
|
+
|
|
1075
|
+
Restriction of a frame defined on `\RR^2` to the unit disk::
|
|
1076
|
+
|
|
1077
|
+
sage: M = Manifold(2, 'R^2', start_index=1)
|
|
1078
|
+
sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
|
|
1079
|
+
sage: a = M.automorphism_field()
|
|
1080
|
+
sage: a[:] = [[1-y^2,0], [1+x^2, 2]]
|
|
1081
|
+
sage: e = c_cart.frame().new_frame(a, 'e') ; e
|
|
1082
|
+
Vector frame (R^2, (e_1,e_2))
|
|
1083
|
+
sage: U = M.open_subset('U', coord_def={c_cart: x^2+y^2<1})
|
|
1084
|
+
sage: e_U = e.restrict(U) ; e_U
|
|
1085
|
+
Vector frame (U, (e_1,e_2))
|
|
1086
|
+
|
|
1087
|
+
The vectors of the restriction have the same symbols as those of the
|
|
1088
|
+
original frame::
|
|
1089
|
+
|
|
1090
|
+
sage: e_U[1].display()
|
|
1091
|
+
e_1 = (-y^2 + 1) ∂/∂x + (x^2 + 1) ∂/∂y
|
|
1092
|
+
sage: e_U[2].display()
|
|
1093
|
+
e_2 = 2 ∂/∂y
|
|
1094
|
+
|
|
1095
|
+
They are actually the restrictions of the original frame vectors::
|
|
1096
|
+
|
|
1097
|
+
sage: e_U[1] is e[1].restrict(U)
|
|
1098
|
+
True
|
|
1099
|
+
sage: e_U[2] is e[2].restrict(U)
|
|
1100
|
+
True
|
|
1101
|
+
"""
|
|
1102
|
+
if subdomain == self._domain:
|
|
1103
|
+
return self
|
|
1104
|
+
if subdomain not in self._restrictions:
|
|
1105
|
+
if not subdomain.is_subset(self._domain):
|
|
1106
|
+
raise ValueError("the provided domain is not a subdomain of " +
|
|
1107
|
+
"the current frame's domain")
|
|
1108
|
+
# First one tries to get the restriction from a tighter domain:
|
|
1109
|
+
for dom, rst in self._restrictions.items():
|
|
1110
|
+
if subdomain.is_subset(dom) and subdomain in rst._restrictions:
|
|
1111
|
+
res = rst._restrictions[subdomain]
|
|
1112
|
+
self._restrictions[subdomain] = res
|
|
1113
|
+
res._superframes.update(self._superframes)
|
|
1114
|
+
for sframe2 in self._superframes:
|
|
1115
|
+
sframe2._subframes.add(res)
|
|
1116
|
+
return self._restrictions[subdomain]
|
|
1117
|
+
# Secondly one tries to get the restriction from one previously
|
|
1118
|
+
# defined on a larger domain:
|
|
1119
|
+
for sframe in self._superframes:
|
|
1120
|
+
if subdomain in sframe._restrictions:
|
|
1121
|
+
res = sframe._restrictions[subdomain]
|
|
1122
|
+
self._restrictions[subdomain] = res
|
|
1123
|
+
res._superframes.update(self._superframes)
|
|
1124
|
+
for sframe2 in self._superframes:
|
|
1125
|
+
sframe2._subframes.add(res)
|
|
1126
|
+
return self._restrictions[subdomain]
|
|
1127
|
+
# If this point is reached, the restriction has to be created
|
|
1128
|
+
# from scratch
|
|
1129
|
+
sdest_map = self._dest_map.restrict(subdomain)
|
|
1130
|
+
resmodule = subdomain.vector_field_module(sdest_map,
|
|
1131
|
+
force_free=True)
|
|
1132
|
+
if subdomain in self._restrictions:
|
|
1133
|
+
# the restriction has been generated during the creation of
|
|
1134
|
+
# resmodule (which may happen if sdest_map is not trivial)
|
|
1135
|
+
return self._restrictions[subdomain]
|
|
1136
|
+
res = VectorFrame(resmodule,
|
|
1137
|
+
self._symbol, latex_symbol=self._latex_symbol,
|
|
1138
|
+
indices=self._indices,
|
|
1139
|
+
latex_indices=self._latex_indices,
|
|
1140
|
+
symbol_dual=self._symbol_dual,
|
|
1141
|
+
latex_symbol_dual=self._latex_symbol_dual)
|
|
1142
|
+
|
|
1143
|
+
res._from_frame = self._from_frame
|
|
1144
|
+
|
|
1145
|
+
for dom in subdomain.open_supersets():
|
|
1146
|
+
if dom is not subdomain:
|
|
1147
|
+
dom._top_frames.remove(res) # since it was added by
|
|
1148
|
+
# VectorFrame constructor
|
|
1149
|
+
new_vectors = list()
|
|
1150
|
+
for i in self._fmodule.irange():
|
|
1151
|
+
vrest = self[i].restrict(subdomain)
|
|
1152
|
+
for j in self._fmodule.irange():
|
|
1153
|
+
vrest.add_comp(res)[j] = 0
|
|
1154
|
+
vrest.add_comp(res)[i] = 1
|
|
1155
|
+
new_vectors.append(vrest)
|
|
1156
|
+
res._vec = tuple(new_vectors)
|
|
1157
|
+
# Update of superframes and subframes:
|
|
1158
|
+
for sframe in self._subframes:
|
|
1159
|
+
if subdomain.is_subset(sframe.domain()):
|
|
1160
|
+
res._superframes.update(sframe._superframes)
|
|
1161
|
+
for sframe in res._superframes:
|
|
1162
|
+
sframe._subframes.add(res)
|
|
1163
|
+
sframe._restrictions[subdomain] = res # includes sframe = self
|
|
1164
|
+
for dom, rst in self._restrictions.items():
|
|
1165
|
+
if dom.is_subset(subdomain):
|
|
1166
|
+
res._restrictions.update(rst._restrictions)
|
|
1167
|
+
res._subframes.update(rst._subframes)
|
|
1168
|
+
rst._superframes.update(res._superframes)
|
|
1169
|
+
|
|
1170
|
+
return self._restrictions[subdomain]
|
|
1171
|
+
|
|
1172
|
+
@cached_method
|
|
1173
|
+
def structure_coeff(self):
|
|
1174
|
+
r"""
|
|
1175
|
+
Evaluate the structure coefficients associated to ``self``.
|
|
1176
|
+
|
|
1177
|
+
`n` being the manifold's dimension, the structure coefficients of the
|
|
1178
|
+
vector frame `(e_i)` are the `n^3` scalar fields `C^k_{\ \, ij}`
|
|
1179
|
+
defined by
|
|
1180
|
+
|
|
1181
|
+
.. MATH::
|
|
1182
|
+
|
|
1183
|
+
[e_i, e_j] = C^k_{\ \, ij} e_k
|
|
1184
|
+
|
|
1185
|
+
OUTPUT:
|
|
1186
|
+
|
|
1187
|
+
- the structure coefficients `C^k_{\ \, ij}`, as an instance of
|
|
1188
|
+
:class:`~sage.tensor.modules.comp.CompWithSym`
|
|
1189
|
+
with 3 indices ordered as `(k,i,j)`.
|
|
1190
|
+
|
|
1191
|
+
EXAMPLES:
|
|
1192
|
+
|
|
1193
|
+
Structure coefficients of the orthonormal frame associated to
|
|
1194
|
+
spherical coordinates in the Euclidean space `\RR^3`::
|
|
1195
|
+
|
|
1196
|
+
sage: M = Manifold(3, 'R^3', r'\RR^3', start_index=1) # Part of R^3 covered by spherical coordinates
|
|
1197
|
+
sage: c_spher.<r,th,ph> = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1198
|
+
sage: ch_frame = M.automorphism_field()
|
|
1199
|
+
sage: ch_frame[1,1], ch_frame[2,2], ch_frame[3,3] = 1, 1/r, 1/(r*sin(th))
|
|
1200
|
+
sage: M.frames()
|
|
1201
|
+
[Coordinate frame (R^3, (∂/∂r,∂/∂th,∂/∂ph))]
|
|
1202
|
+
sage: e = c_spher.frame().new_frame(ch_frame, 'e')
|
|
1203
|
+
sage: e[1][:] # components of e_1 in the manifold's default frame (∂/∂r, ∂/∂th, ∂/∂th)
|
|
1204
|
+
[1, 0, 0]
|
|
1205
|
+
sage: e[2][:]
|
|
1206
|
+
[0, 1/r, 0]
|
|
1207
|
+
sage: e[3][:]
|
|
1208
|
+
[0, 0, 1/(r*sin(th))]
|
|
1209
|
+
sage: c = e.structure_coeff() ; c
|
|
1210
|
+
3-indices components w.r.t. Vector frame (R^3, (e_1,e_2,e_3)), with
|
|
1211
|
+
antisymmetry on the index positions (1, 2)
|
|
1212
|
+
sage: c[:]
|
|
1213
|
+
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
|
|
1214
|
+
[[0, -1/r, 0], [1/r, 0, 0], [0, 0, 0]],
|
|
1215
|
+
[[0, 0, -1/r], [0, 0, -cos(th)/(r*sin(th))], [1/r, cos(th)/(r*sin(th)), 0]]]
|
|
1216
|
+
sage: c[2,1,2] # C^2_{12}
|
|
1217
|
+
-1/r
|
|
1218
|
+
sage: c[3,1,3] # C^3_{13}
|
|
1219
|
+
-1/r
|
|
1220
|
+
sage: c[3,2,3] # C^3_{23}
|
|
1221
|
+
-cos(th)/(r*sin(th))
|
|
1222
|
+
"""
|
|
1223
|
+
from sage.tensor.modules.comp import CompWithSym
|
|
1224
|
+
|
|
1225
|
+
fmodule = self._fmodule
|
|
1226
|
+
structure_coeff = CompWithSym(self._fmodule._ring, self, 3,
|
|
1227
|
+
start_index=fmodule._sindex,
|
|
1228
|
+
output_formatter=fmodule._output_formatter,
|
|
1229
|
+
antisym=(1,2))
|
|
1230
|
+
si = fmodule._sindex
|
|
1231
|
+
nsi = si + fmodule.rank()
|
|
1232
|
+
for k in range(si, nsi):
|
|
1233
|
+
ce_k = self._coframe._vec[k-si]
|
|
1234
|
+
for i in range(si, nsi):
|
|
1235
|
+
e_i = self._vec[i-si]
|
|
1236
|
+
for j in range(i+1, nsi):
|
|
1237
|
+
e_j = self._vec[j-si]
|
|
1238
|
+
structure_coeff[[k,i,j]] = ce_k(e_j.lie_der(e_i))
|
|
1239
|
+
return structure_coeff
|
|
1240
|
+
|
|
1241
|
+
def along(self, mapping):
|
|
1242
|
+
r"""
|
|
1243
|
+
Return the vector frame deduced from the current frame via a
|
|
1244
|
+
differentiable map, the codomain of which is included in the domain of
|
|
1245
|
+
of the current frame.
|
|
1246
|
+
|
|
1247
|
+
If `e` is the current vector frame, `V` its domain and if
|
|
1248
|
+
`\Phi: U \rightarrow V` is a differentiable map from some
|
|
1249
|
+
differentiable manifold `U` to `V`, the returned object is
|
|
1250
|
+
a vector frame `\tilde e` along `U` with values on `V` such that
|
|
1251
|
+
|
|
1252
|
+
.. MATH::
|
|
1253
|
+
|
|
1254
|
+
\forall p \in U,\ \tilde e(p) = e(\Phi(p)).
|
|
1255
|
+
|
|
1256
|
+
INPUT:
|
|
1257
|
+
|
|
1258
|
+
- ``mapping`` -- differentiable map `\Phi: U \rightarrow V`
|
|
1259
|
+
|
|
1260
|
+
OUTPUT: vector frame `\tilde e` along `U` defined above
|
|
1261
|
+
|
|
1262
|
+
EXAMPLES:
|
|
1263
|
+
|
|
1264
|
+
Vector frame along a curve::
|
|
1265
|
+
|
|
1266
|
+
sage: M = Manifold(2, 'M')
|
|
1267
|
+
sage: X.<x,y> = M.chart()
|
|
1268
|
+
sage: R = Manifold(1, 'R') # R as a 1-dimensional manifold
|
|
1269
|
+
sage: T.<t> = R.chart() # canonical chart on R
|
|
1270
|
+
sage: Phi = R.diff_map(M, {(T,X): [cos(t), t]}, name='Phi',
|
|
1271
|
+
....: latex_name=r'\Phi') ; Phi
|
|
1272
|
+
Differentiable map Phi from the 1-dimensional differentiable
|
|
1273
|
+
manifold R to the 2-dimensional differentiable manifold M
|
|
1274
|
+
sage: e = X.frame() ; e
|
|
1275
|
+
Coordinate frame (M, (∂/∂x,∂/∂y))
|
|
1276
|
+
sage: te = e.along(Phi) ; te
|
|
1277
|
+
Vector frame (R, (∂/∂x,∂/∂y)) with values on the 2-dimensional
|
|
1278
|
+
differentiable manifold M
|
|
1279
|
+
|
|
1280
|
+
Check of the formula `\tilde e(p) = e(\Phi(p))`::
|
|
1281
|
+
|
|
1282
|
+
sage: p = R((pi,)) ; p
|
|
1283
|
+
Point on the 1-dimensional differentiable manifold R
|
|
1284
|
+
sage: te[0].at(p) == e[0].at(Phi(p))
|
|
1285
|
+
True
|
|
1286
|
+
sage: te[1].at(p) == e[1].at(Phi(p))
|
|
1287
|
+
True
|
|
1288
|
+
|
|
1289
|
+
The result is cached::
|
|
1290
|
+
|
|
1291
|
+
sage: te is e.along(Phi)
|
|
1292
|
+
True
|
|
1293
|
+
"""
|
|
1294
|
+
dom = self._domain
|
|
1295
|
+
if mapping.codomain().is_subset(dom):
|
|
1296
|
+
rmapping = mapping
|
|
1297
|
+
else:
|
|
1298
|
+
rmapping = None
|
|
1299
|
+
for doms, rest in mapping._restrictions.items():
|
|
1300
|
+
if doms[1].is_subset(dom):
|
|
1301
|
+
rmapping = rest
|
|
1302
|
+
break
|
|
1303
|
+
else:
|
|
1304
|
+
raise ValueError("the codomain of {} is not ".format(mapping) +
|
|
1305
|
+
" included in the domain of {}".format(self))
|
|
1306
|
+
vmodule = rmapping.domain().vector_field_module(dest_map=rmapping)
|
|
1307
|
+
return vmodule.basis(from_frame=self)
|
|
1308
|
+
|
|
1309
|
+
def at(self, point):
|
|
1310
|
+
r"""
|
|
1311
|
+
Return the value of ``self`` at a given point, this value being
|
|
1312
|
+
a basis of the tangent vector space at the point.
|
|
1313
|
+
|
|
1314
|
+
INPUT:
|
|
1315
|
+
|
|
1316
|
+
- ``point`` -- :class:`~sage.manifolds.point.ManifoldPoint`; point
|
|
1317
|
+
`p` in the domain `U` of the vector frame (denoted `e` hereafter)
|
|
1318
|
+
|
|
1319
|
+
OUTPUT:
|
|
1320
|
+
|
|
1321
|
+
- :class:`~sage.tensor.modules.free_module_basis.FreeModuleBasis`
|
|
1322
|
+
representing the basis `e(p)` of the tangent vector space
|
|
1323
|
+
`T_{\Phi(p)} M`, where `\Phi: U \to M` is the differentiable map
|
|
1324
|
+
associated with `e` (possibly `\Phi = \mathrm{Id}_U`)
|
|
1325
|
+
|
|
1326
|
+
EXAMPLES:
|
|
1327
|
+
|
|
1328
|
+
Basis of a tangent space to a 2-dimensional manifold::
|
|
1329
|
+
|
|
1330
|
+
sage: M = Manifold(2, 'M')
|
|
1331
|
+
sage: X.<x,y> = M.chart()
|
|
1332
|
+
sage: p = M.point((-1,2), name='p')
|
|
1333
|
+
sage: e = X.frame() ; e
|
|
1334
|
+
Coordinate frame (M, (∂/∂x,∂/∂y))
|
|
1335
|
+
sage: ep = e.at(p) ; ep
|
|
1336
|
+
Basis (∂/∂x,∂/∂y) on the Tangent space at Point p on the
|
|
1337
|
+
2-dimensional differentiable manifold M
|
|
1338
|
+
sage: type(ep)
|
|
1339
|
+
<class 'sage.tensor.modules.free_module_basis.FreeModuleBasis_with_category'>
|
|
1340
|
+
sage: ep[0]
|
|
1341
|
+
Tangent vector ∂/∂x at Point p on the 2-dimensional differentiable
|
|
1342
|
+
manifold M
|
|
1343
|
+
sage: ep[1]
|
|
1344
|
+
Tangent vector ∂/∂y at Point p on the 2-dimensional differentiable
|
|
1345
|
+
manifold M
|
|
1346
|
+
|
|
1347
|
+
Note that the symbols used to denote the vectors are same as those
|
|
1348
|
+
for the vector fields of the frame. At this stage, ``ep`` is the unique
|
|
1349
|
+
basis on the tangent space at ``p``::
|
|
1350
|
+
|
|
1351
|
+
sage: Tp = M.tangent_space(p)
|
|
1352
|
+
sage: Tp.bases()
|
|
1353
|
+
[Basis (∂/∂x,∂/∂y) on the Tangent space at Point p on the
|
|
1354
|
+
2-dimensional differentiable manifold M]
|
|
1355
|
+
|
|
1356
|
+
Let us consider a vector frame that is a not a coordinate one::
|
|
1357
|
+
|
|
1358
|
+
sage: aut = M.automorphism_field()
|
|
1359
|
+
sage: aut[:] = [[1+y^2, 0], [0, 2]]
|
|
1360
|
+
sage: f = e.new_frame(aut, 'f') ; f
|
|
1361
|
+
Vector frame (M, (f_0,f_1))
|
|
1362
|
+
sage: fp = f.at(p) ; fp
|
|
1363
|
+
Basis (f_0,f_1) on the Tangent space at Point p on the
|
|
1364
|
+
2-dimensional differentiable manifold M
|
|
1365
|
+
|
|
1366
|
+
There are now two bases on the tangent space::
|
|
1367
|
+
|
|
1368
|
+
sage: Tp.bases()
|
|
1369
|
+
[Basis (∂/∂x,∂/∂y) on the Tangent space at Point p on the
|
|
1370
|
+
2-dimensional differentiable manifold M,
|
|
1371
|
+
Basis (f_0,f_1) on the Tangent space at Point p on the
|
|
1372
|
+
2-dimensional differentiable manifold M]
|
|
1373
|
+
|
|
1374
|
+
Moreover, the changes of bases in the tangent space have been
|
|
1375
|
+
computed from the known relation between the frames ``e`` and
|
|
1376
|
+
``f`` (field of automorphisms ``aut`` defined above)::
|
|
1377
|
+
|
|
1378
|
+
sage: Tp.change_of_basis(ep, fp)
|
|
1379
|
+
Automorphism of the Tangent space at Point p on the 2-dimensional
|
|
1380
|
+
differentiable manifold M
|
|
1381
|
+
sage: Tp.change_of_basis(ep, fp).display()
|
|
1382
|
+
5 ∂/∂x⊗dx + 2 ∂/∂y⊗dy
|
|
1383
|
+
sage: Tp.change_of_basis(fp, ep)
|
|
1384
|
+
Automorphism of the Tangent space at Point p on the 2-dimensional
|
|
1385
|
+
differentiable manifold M
|
|
1386
|
+
sage: Tp.change_of_basis(fp, ep).display()
|
|
1387
|
+
1/5 ∂/∂x⊗dx + 1/2 ∂/∂y⊗dy
|
|
1388
|
+
|
|
1389
|
+
The dual bases::
|
|
1390
|
+
|
|
1391
|
+
sage: e.coframe()
|
|
1392
|
+
Coordinate coframe (M, (dx,dy))
|
|
1393
|
+
sage: ep.dual_basis()
|
|
1394
|
+
Dual basis (dx,dy) on the Tangent space at Point p on the
|
|
1395
|
+
2-dimensional differentiable manifold M
|
|
1396
|
+
sage: ep.dual_basis() is e.coframe().at(p)
|
|
1397
|
+
True
|
|
1398
|
+
sage: f.coframe()
|
|
1399
|
+
Coframe (M, (f^0,f^1))
|
|
1400
|
+
sage: fp.dual_basis()
|
|
1401
|
+
Dual basis (f^0,f^1) on the Tangent space at Point p on the
|
|
1402
|
+
2-dimensional differentiable manifold M
|
|
1403
|
+
sage: fp.dual_basis() is f.coframe().at(p)
|
|
1404
|
+
True
|
|
1405
|
+
"""
|
|
1406
|
+
# Case of a non-trivial destination map
|
|
1407
|
+
if self._from_frame is not None:
|
|
1408
|
+
if self._dest_map.is_identity(): # ! # probably not necessary
|
|
1409
|
+
raise ValueError("the destination map should not be the identity")
|
|
1410
|
+
ambient_point = self._dest_map(point)
|
|
1411
|
+
return self._from_frame.at(ambient_point)
|
|
1412
|
+
|
|
1413
|
+
# Determination of the tangent space:
|
|
1414
|
+
if point not in self._domain:
|
|
1415
|
+
raise ValueError("the {} is not a point in the ".format(point) +
|
|
1416
|
+
"domain of {}".format(self))
|
|
1417
|
+
|
|
1418
|
+
if self._dest_map.is_identity():
|
|
1419
|
+
ambient_point = point
|
|
1420
|
+
else:
|
|
1421
|
+
ambient_point = self._dest_map(point)
|
|
1422
|
+
ts = ambient_point._manifold.tangent_space(ambient_point)
|
|
1423
|
+
|
|
1424
|
+
# If the basis has already been constructed, it is simply returned:
|
|
1425
|
+
ts_frame_bases = ts._frame_bases
|
|
1426
|
+
if self in ts_frame_bases:
|
|
1427
|
+
return ts_frame_bases[self]
|
|
1428
|
+
for frame in ts_frame_bases:
|
|
1429
|
+
if self in frame._subframes or self in frame._superframes:
|
|
1430
|
+
return ts_frame_bases[frame]
|
|
1431
|
+
|
|
1432
|
+
# If this point is reached, the basis has to be constructed from
|
|
1433
|
+
# scratch.
|
|
1434
|
+
# The names of the basis vectors set to those of the frame vector
|
|
1435
|
+
# fields:
|
|
1436
|
+
basis = ts.basis(self._symbol, latex_symbol=self._latex_symbol,
|
|
1437
|
+
indices=self._indices,
|
|
1438
|
+
latex_indices=self._latex_indices,
|
|
1439
|
+
symbol_dual=self._symbol_dual,
|
|
1440
|
+
latex_symbol_dual=self._latex_symbol_dual)
|
|
1441
|
+
ts_frame_bases[self] = basis
|
|
1442
|
+
# Update of the change of bases in the tangent space:
|
|
1443
|
+
for frame_pair, automorph in self._domain._frame_changes.items():
|
|
1444
|
+
frame1 = frame_pair[0]
|
|
1445
|
+
frame2 = frame_pair[1]
|
|
1446
|
+
if frame1 is self:
|
|
1447
|
+
fr2 = None
|
|
1448
|
+
for frame in ts_frame_bases:
|
|
1449
|
+
if frame2 in frame._subframes:
|
|
1450
|
+
fr2 = frame
|
|
1451
|
+
break
|
|
1452
|
+
if fr2 is not None:
|
|
1453
|
+
basis1 = basis
|
|
1454
|
+
basis2 = ts_frame_bases[fr2]
|
|
1455
|
+
auto = ts.automorphism()
|
|
1456
|
+
for frame, comp in automorph._components.items():
|
|
1457
|
+
bas = None
|
|
1458
|
+
if frame is frame1:
|
|
1459
|
+
bas = basis1
|
|
1460
|
+
if frame is frame2:
|
|
1461
|
+
bas = basis2
|
|
1462
|
+
if bas is not None:
|
|
1463
|
+
cauto = auto.add_comp(bas)
|
|
1464
|
+
for ind, val in comp._comp.items():
|
|
1465
|
+
cauto._comp[ind] = val(point)
|
|
1466
|
+
ts._basis_changes[(basis1, basis2)] = auto
|
|
1467
|
+
if frame2 is self:
|
|
1468
|
+
fr1 = None
|
|
1469
|
+
for frame in ts_frame_bases:
|
|
1470
|
+
if frame1 in frame._subframes:
|
|
1471
|
+
fr1 = frame
|
|
1472
|
+
break
|
|
1473
|
+
if fr1 is not None:
|
|
1474
|
+
basis1 = ts_frame_bases[fr1]
|
|
1475
|
+
basis2 = basis
|
|
1476
|
+
auto = ts.automorphism()
|
|
1477
|
+
for frame, comp in automorph._components.items():
|
|
1478
|
+
bas = None
|
|
1479
|
+
if frame is frame1:
|
|
1480
|
+
bas = basis1
|
|
1481
|
+
if frame is frame2:
|
|
1482
|
+
bas = basis2
|
|
1483
|
+
if bas is not None:
|
|
1484
|
+
cauto = auto.add_comp(bas)
|
|
1485
|
+
for ind, val in comp._comp.items():
|
|
1486
|
+
cauto._comp[ind] = val(point)
|
|
1487
|
+
ts._basis_changes[(basis1, basis2)] = auto
|
|
1488
|
+
return basis
|
|
1489
|
+
|
|
1490
|
+
def set_name(self, symbol, latex_symbol=None, indices=None,
|
|
1491
|
+
latex_indices=None, index_position='down',
|
|
1492
|
+
include_domain=True):
|
|
1493
|
+
r"""
|
|
1494
|
+
Set (or change) the text name and LaTeX name of ``self``.
|
|
1495
|
+
|
|
1496
|
+
INPUT:
|
|
1497
|
+
|
|
1498
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
1499
|
+
symbols of the vector fields constituting the vector frame, or a
|
|
1500
|
+
list/tuple of strings, representing the individual symbols of the
|
|
1501
|
+
vector fields
|
|
1502
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
1503
|
+
as a common base for the LaTeX symbols of the vector fields
|
|
1504
|
+
constituting the vector frame, or a list/tuple of strings,
|
|
1505
|
+
representing the individual LaTeX symbols of the vector fields;
|
|
1506
|
+
if ``None``, ``symbol`` is used in place of ``latex_symbol``
|
|
1507
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a
|
|
1508
|
+
single string) tuple of strings representing the indices labelling
|
|
1509
|
+
the vector fields of the frame; if ``None``, the indices will be
|
|
1510
|
+
generated as integers within the range declared on ``self``
|
|
1511
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings
|
|
1512
|
+
representing the indices for the LaTeX symbols of the vector fields;
|
|
1513
|
+
if ``None``, ``indices`` is used instead
|
|
1514
|
+
- ``index_position`` -- (default: ``'down'``) determines the position
|
|
1515
|
+
of the indices labelling the vector fields of the frame; can be
|
|
1516
|
+
either ``'down'`` or ``'up'``
|
|
1517
|
+
- ``include_domain`` -- boolean (default: ``True``); determining whether
|
|
1518
|
+
the name of the domain is included in the beginning of the vector
|
|
1519
|
+
frame name
|
|
1520
|
+
|
|
1521
|
+
EXAMPLES::
|
|
1522
|
+
|
|
1523
|
+
sage: M = Manifold(2, 'M')
|
|
1524
|
+
sage: e = M.vector_frame('e'); e
|
|
1525
|
+
Vector frame (M, (e_0,e_1))
|
|
1526
|
+
sage: e.set_name('f'); e
|
|
1527
|
+
Vector frame (M, (f_0,f_1))
|
|
1528
|
+
sage: e.set_name('e', include_domain=False); e
|
|
1529
|
+
Vector frame (e_0,e_1)
|
|
1530
|
+
sage: e.set_name(['a', 'b']); e
|
|
1531
|
+
Vector frame (M, (a,b))
|
|
1532
|
+
sage: e.set_name('e', indices=['x', 'y']); e
|
|
1533
|
+
Vector frame (M, (e_x,e_y))
|
|
1534
|
+
sage: e.set_name('e', latex_symbol=r'\epsilon')
|
|
1535
|
+
sage: latex(e)
|
|
1536
|
+
\left(M, \left(\epsilon_{0},\epsilon_{1}\right)\right)
|
|
1537
|
+
sage: e.set_name('e', latex_symbol=[r'\alpha', r'\beta'])
|
|
1538
|
+
sage: latex(e)
|
|
1539
|
+
\left(M, \left(\alpha,\beta\right)\right)
|
|
1540
|
+
sage: e.set_name('e', latex_symbol='E',
|
|
1541
|
+
....: latex_indices=[r'\alpha', r'\beta'])
|
|
1542
|
+
sage: latex(e)
|
|
1543
|
+
\left(M, \left(E_{\alpha},E_{\beta}\right)\right)
|
|
1544
|
+
"""
|
|
1545
|
+
super().set_name(symbol, latex_symbol=latex_symbol,
|
|
1546
|
+
indices=indices,
|
|
1547
|
+
latex_indices=latex_indices,
|
|
1548
|
+
index_position=index_position)
|
|
1549
|
+
if include_domain:
|
|
1550
|
+
# Redefinition of the name and the LaTeX name to include the domain
|
|
1551
|
+
self._name = "({}, {})".format(self._domain._name, self._name)
|
|
1552
|
+
self._latex_name = r"\left({}, {}\right)".format(
|
|
1553
|
+
self._domain._latex_name, self._latex_name)
|
|
1554
|
+
|
|
1555
|
+
#******************************************************************************
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
class CoordCoFrame(CoFrame):
|
|
1559
|
+
r"""
|
|
1560
|
+
Coordinate coframe on a differentiable manifold.
|
|
1561
|
+
|
|
1562
|
+
By *coordinate coframe*, it is meant the `n`-tuple of the
|
|
1563
|
+
differentials of the coordinates of some chart on the manifold,
|
|
1564
|
+
with `n` being the manifold's dimension.
|
|
1565
|
+
|
|
1566
|
+
INPUT:
|
|
1567
|
+
|
|
1568
|
+
- ``coord_frame`` -- coordinate frame dual to the coordinate coframe
|
|
1569
|
+
- ``symbol`` -- either a string, to be used as a common base for the
|
|
1570
|
+
symbols of the 1-forms constituting the coframe, or a tuple of strings,
|
|
1571
|
+
representing the individual symbols of the 1-forms
|
|
1572
|
+
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
|
|
1573
|
+
as a common base for the LaTeX symbols of the 1-forms constituting the
|
|
1574
|
+
coframe, or a tuple of strings, representing the individual LaTeX symbols
|
|
1575
|
+
of the 1-forms; if ``None``, ``symbol`` is used in place of
|
|
1576
|
+
``latex_symbol``
|
|
1577
|
+
- ``indices`` -- (default: ``None``; used only if ``symbol`` is a single
|
|
1578
|
+
string) tuple of strings representing the indices labelling the 1-forms
|
|
1579
|
+
of the coframe; if ``None``, the indices will be generated as
|
|
1580
|
+
integers within the range declared on the vector frame's domain
|
|
1581
|
+
- ``latex_indices`` -- (default: ``None``) tuple of strings representing
|
|
1582
|
+
the indices for the LaTeX symbols of the 1-forms of the coframe; if
|
|
1583
|
+
``None``, ``indices`` is used instead
|
|
1584
|
+
|
|
1585
|
+
EXAMPLES:
|
|
1586
|
+
|
|
1587
|
+
Coordinate coframe on a 3-dimensional manifold::
|
|
1588
|
+
|
|
1589
|
+
sage: M = Manifold(3, 'M', start_index=1)
|
|
1590
|
+
sage: X.<x,y,z> = M.chart()
|
|
1591
|
+
sage: M.frames()
|
|
1592
|
+
[Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))]
|
|
1593
|
+
sage: M.coframes()
|
|
1594
|
+
[Coordinate coframe (M, (dx,dy,dz))]
|
|
1595
|
+
sage: dX = M.coframes()[0] ; dX
|
|
1596
|
+
Coordinate coframe (M, (dx,dy,dz))
|
|
1597
|
+
|
|
1598
|
+
The 1-forms composing the coframe are obtained via the operator ``[]``::
|
|
1599
|
+
|
|
1600
|
+
sage: dX[1]
|
|
1601
|
+
1-form dx on the 3-dimensional differentiable manifold M
|
|
1602
|
+
sage: dX[2]
|
|
1603
|
+
1-form dy on the 3-dimensional differentiable manifold M
|
|
1604
|
+
sage: dX[3]
|
|
1605
|
+
1-form dz on the 3-dimensional differentiable manifold M
|
|
1606
|
+
sage: dX[1][:]
|
|
1607
|
+
[1, 0, 0]
|
|
1608
|
+
sage: dX[2][:]
|
|
1609
|
+
[0, 1, 0]
|
|
1610
|
+
sage: dX[3][:]
|
|
1611
|
+
[0, 0, 1]
|
|
1612
|
+
|
|
1613
|
+
The coframe is the dual of the coordinate frame::
|
|
1614
|
+
|
|
1615
|
+
sage: e = X.frame() ; e
|
|
1616
|
+
Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))
|
|
1617
|
+
sage: dX[1](e[1]).expr(), dX[1](e[2]).expr(), dX[1](e[3]).expr()
|
|
1618
|
+
(1, 0, 0)
|
|
1619
|
+
sage: dX[2](e[1]).expr(), dX[2](e[2]).expr(), dX[2](e[3]).expr()
|
|
1620
|
+
(0, 1, 0)
|
|
1621
|
+
sage: dX[3](e[1]).expr(), dX[3](e[2]).expr(), dX[3](e[3]).expr()
|
|
1622
|
+
(0, 0, 1)
|
|
1623
|
+
|
|
1624
|
+
Each 1-form of a coordinate coframe is closed::
|
|
1625
|
+
|
|
1626
|
+
sage: dX[1].exterior_derivative()
|
|
1627
|
+
2-form ddx on the 3-dimensional differentiable manifold M
|
|
1628
|
+
sage: dX[1].exterior_derivative() == 0
|
|
1629
|
+
True
|
|
1630
|
+
"""
|
|
1631
|
+
def __init__(self, coord_frame, symbol, latex_symbol=None, indices=None,
|
|
1632
|
+
latex_indices=None):
|
|
1633
|
+
r"""
|
|
1634
|
+
Construct a coordinate coframe.
|
|
1635
|
+
|
|
1636
|
+
TESTS::
|
|
1637
|
+
|
|
1638
|
+
sage: M = Manifold(2, 'M')
|
|
1639
|
+
sage: X.<x,y> = M.chart()
|
|
1640
|
+
sage: from sage.manifolds.differentiable.vectorframe import CoordCoFrame
|
|
1641
|
+
sage: f = CoordCoFrame(X.frame(), 'omega'); f
|
|
1642
|
+
Coordinate coframe (M, (omega^0,omega^1))
|
|
1643
|
+
sage: TestSuite(f).run()
|
|
1644
|
+
"""
|
|
1645
|
+
if not isinstance(coord_frame, CoordFrame):
|
|
1646
|
+
raise TypeError("the first argument must be a coordinate frame")
|
|
1647
|
+
CoFrame.__init__(self, coord_frame, symbol, latex_symbol=latex_symbol,
|
|
1648
|
+
indices=indices, latex_indices=latex_indices)
|
|
1649
|
+
self._chart = coord_frame._chart
|
|
1650
|
+
|
|
1651
|
+
def _repr_(self):
|
|
1652
|
+
r"""
|
|
1653
|
+
String representation of ``self``.
|
|
1654
|
+
|
|
1655
|
+
TESTS::
|
|
1656
|
+
|
|
1657
|
+
sage: M = Manifold(2, 'M')
|
|
1658
|
+
sage: X.<x,y> = M.chart()
|
|
1659
|
+
sage: f = X.frame().coframe()
|
|
1660
|
+
sage: f._repr_()
|
|
1661
|
+
'Coordinate coframe (M, (dx,dy))'
|
|
1662
|
+
sage: repr(f) # indirect doctest
|
|
1663
|
+
'Coordinate coframe (M, (dx,dy))'
|
|
1664
|
+
sage: f # indirect doctest
|
|
1665
|
+
Coordinate coframe (M, (dx,dy))
|
|
1666
|
+
"""
|
|
1667
|
+
return "Coordinate coframe " + self._name
|
|
1668
|
+
|
|
1669
|
+
#******************************************************************************
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
class CoordFrame(VectorFrame):
|
|
1673
|
+
r"""
|
|
1674
|
+
Coordinate frame on a differentiable manifold.
|
|
1675
|
+
|
|
1676
|
+
By *coordinate frame*, it is meant a vector frame on a differentiable
|
|
1677
|
+
manifold `M` that is associated to a coordinate chart on `M`.
|
|
1678
|
+
|
|
1679
|
+
INPUT:
|
|
1680
|
+
|
|
1681
|
+
- ``chart`` -- the chart defining the coordinates
|
|
1682
|
+
|
|
1683
|
+
EXAMPLES:
|
|
1684
|
+
|
|
1685
|
+
The coordinate frame associated to spherical coordinates of the
|
|
1686
|
+
sphere `S^2`::
|
|
1687
|
+
|
|
1688
|
+
sage: M = Manifold(2, 'S^2', start_index=1) # Part of S^2 covered by spherical coord.
|
|
1689
|
+
sage: M.chart(r'th:[0,pi]:\theta ph:[0,2*pi):\phi')
|
|
1690
|
+
Chart (S^2, (th, ph))
|
|
1691
|
+
sage: b = M.default_frame()
|
|
1692
|
+
sage: b
|
|
1693
|
+
Coordinate frame (S^2, (∂/∂th,∂/∂ph))
|
|
1694
|
+
sage: b[1]
|
|
1695
|
+
Vector field ∂/∂th on the 2-dimensional differentiable manifold S^2
|
|
1696
|
+
sage: b[2]
|
|
1697
|
+
Vector field ∂/∂ph on the 2-dimensional differentiable manifold S^2
|
|
1698
|
+
sage: latex(b)
|
|
1699
|
+
\left(S^2, \left(\frac{\partial}{\partial {\theta} },\frac{\partial}{\partial {\phi} }\right)\right)
|
|
1700
|
+
"""
|
|
1701
|
+
|
|
1702
|
+
# The following class attribute must be redefined by any derived class:
|
|
1703
|
+
_cobasis_class = CoordCoFrame
|
|
1704
|
+
|
|
1705
|
+
def __init__(self, chart):
|
|
1706
|
+
r"""
|
|
1707
|
+
Construct a coordinate frame.
|
|
1708
|
+
|
|
1709
|
+
TESTS::
|
|
1710
|
+
|
|
1711
|
+
sage: M = Manifold(2, 'M')
|
|
1712
|
+
sage: X.<x,y> = M.chart()
|
|
1713
|
+
sage: from sage.manifolds.differentiable.vectorframe import CoordFrame
|
|
1714
|
+
sage: e = CoordFrame(X); e
|
|
1715
|
+
Coordinate frame (M, (∂/∂x,∂/∂y))
|
|
1716
|
+
sage: TestSuite(e).run()
|
|
1717
|
+
"""
|
|
1718
|
+
from sage.manifolds.differentiable.chart import DiffChart
|
|
1719
|
+
from sage.misc.latex import latex
|
|
1720
|
+
from sage.typeset.unicode_characters import unicode_partial
|
|
1721
|
+
if not isinstance(chart, DiffChart):
|
|
1722
|
+
raise TypeError("the first argument must be a chart")
|
|
1723
|
+
dom = chart.domain()
|
|
1724
|
+
# Some sanity check:
|
|
1725
|
+
vmodule = dom._vector_field_modules.get(dom.identity_map())
|
|
1726
|
+
if vmodule and not isinstance(vmodule, FiniteRankFreeModule):
|
|
1727
|
+
raise ValueError("the {} has already been constructed as a "
|
|
1728
|
+
"non-free module, which implies that the {} is "
|
|
1729
|
+
"not parallelizable and hence cannot be the "
|
|
1730
|
+
"domain of a coordinate chart".format(vmodule,
|
|
1731
|
+
dom))
|
|
1732
|
+
self._chart = chart
|
|
1733
|
+
coords = chart[:] # list of all coordinates
|
|
1734
|
+
symbol = tuple(f"{unicode_partial}/{unicode_partial}{x!s}"
|
|
1735
|
+
for x in coords)
|
|
1736
|
+
latex_symbol = tuple(r"\frac{\partial}{\partial" + latex(x) + "}"
|
|
1737
|
+
for x in coords)
|
|
1738
|
+
symbol_dual = tuple("d" + str(x) for x in coords)
|
|
1739
|
+
latex_symbol_dual = tuple(r"\mathrm{d}" + latex(x) for x in coords)
|
|
1740
|
+
VectorFrame.__init__(self,
|
|
1741
|
+
dom.vector_field_module(force_free=True),
|
|
1742
|
+
symbol=symbol, latex_symbol=latex_symbol,
|
|
1743
|
+
symbol_dual=symbol_dual,
|
|
1744
|
+
latex_symbol_dual=latex_symbol_dual)
|
|
1745
|
+
# In the above:
|
|
1746
|
+
# - force_free=True ensures that a free module is constructed in case
|
|
1747
|
+
# it is the first call to the vector field module on chart.domain()
|
|
1748
|
+
|
|
1749
|
+
###### Methods that must be redefined by derived classes of ######
|
|
1750
|
+
###### FreeModuleBasis ######
|
|
1751
|
+
|
|
1752
|
+
def _repr_(self):
|
|
1753
|
+
r"""
|
|
1754
|
+
String representation of ``self``.
|
|
1755
|
+
|
|
1756
|
+
TESTS::
|
|
1757
|
+
|
|
1758
|
+
sage: M = Manifold(2, 'M')
|
|
1759
|
+
sage: X.<x,y> = M.chart()
|
|
1760
|
+
sage: e = X.frame()
|
|
1761
|
+
sage: e._repr_()
|
|
1762
|
+
'Coordinate frame (M, (∂/∂x,∂/∂y))'
|
|
1763
|
+
sage: repr(e) # indirect doctest
|
|
1764
|
+
'Coordinate frame (M, (∂/∂x,∂/∂y))'
|
|
1765
|
+
sage: e # indirect doctest
|
|
1766
|
+
Coordinate frame (M, (∂/∂x,∂/∂y))
|
|
1767
|
+
"""
|
|
1768
|
+
return "Coordinate frame " + self._name
|
|
1769
|
+
|
|
1770
|
+
###### End of methods redefined by derived classes ######
|
|
1771
|
+
|
|
1772
|
+
def chart(self):
|
|
1773
|
+
r"""
|
|
1774
|
+
Return the chart defining this coordinate frame.
|
|
1775
|
+
|
|
1776
|
+
EXAMPLES::
|
|
1777
|
+
|
|
1778
|
+
sage: M = Manifold(2, 'M')
|
|
1779
|
+
sage: X.<x,y> = M.chart()
|
|
1780
|
+
sage: e = X.frame()
|
|
1781
|
+
sage: e.chart()
|
|
1782
|
+
Chart (M, (x, y))
|
|
1783
|
+
sage: U = M.open_subset('U', coord_def={X: x>0})
|
|
1784
|
+
sage: e.restrict(U).chart()
|
|
1785
|
+
Chart (U, (x, y))
|
|
1786
|
+
"""
|
|
1787
|
+
return self._chart
|
|
1788
|
+
|
|
1789
|
+
@cached_method
|
|
1790
|
+
def structure_coeff(self):
|
|
1791
|
+
r"""
|
|
1792
|
+
Return the structure coefficients associated to ``self``.
|
|
1793
|
+
|
|
1794
|
+
`n` being the manifold's dimension, the structure coefficients
|
|
1795
|
+
of the frame `(e_i)` are the `n^3` scalar fields `C^k_{\ \, ij}`
|
|
1796
|
+
defined by
|
|
1797
|
+
|
|
1798
|
+
.. MATH::
|
|
1799
|
+
|
|
1800
|
+
[e_i, e_j] = C^k_{\ \, ij} e_k.
|
|
1801
|
+
|
|
1802
|
+
In the present case, since `(e_i)` is a coordinate frame,
|
|
1803
|
+
`C^k_{\ \, ij}=0`.
|
|
1804
|
+
|
|
1805
|
+
OUTPUT:
|
|
1806
|
+
|
|
1807
|
+
- the structure coefficients `C^k_{\ \, ij}`, as a vanishing instance
|
|
1808
|
+
of :class:`~sage.tensor.modules.comp.CompWithSym` with 3 indices
|
|
1809
|
+
ordered as `(k,i,j)`
|
|
1810
|
+
|
|
1811
|
+
EXAMPLES:
|
|
1812
|
+
|
|
1813
|
+
Structure coefficients of the coordinate frame associated to
|
|
1814
|
+
spherical coordinates in the Euclidean space `\RR^3`::
|
|
1815
|
+
|
|
1816
|
+
sage: M = Manifold(3, 'R^3', r'\RR^3', start_index=1) # Part of R^3 covered by spherical coord.
|
|
1817
|
+
sage: c_spher = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi')
|
|
1818
|
+
sage: b = M.default_frame() ; b
|
|
1819
|
+
Coordinate frame (R^3, (∂/∂r,∂/∂th,∂/∂ph))
|
|
1820
|
+
sage: c = b.structure_coeff() ; c
|
|
1821
|
+
3-indices components w.r.t. Coordinate frame
|
|
1822
|
+
(R^3, (∂/∂r,∂/∂th,∂/∂ph)), with antisymmetry on the index
|
|
1823
|
+
positions (1, 2)
|
|
1824
|
+
sage: c == 0
|
|
1825
|
+
True
|
|
1826
|
+
"""
|
|
1827
|
+
from sage.tensor.modules.comp import CompWithSym
|
|
1828
|
+
# A zero CompWithSym
|
|
1829
|
+
return CompWithSym(self._fmodule._ring, self, 3,
|
|
1830
|
+
start_index=self._fmodule._sindex,
|
|
1831
|
+
output_formatter=self._fmodule._output_formatter,
|
|
1832
|
+
antisym=(1,2))
|