passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  6. sage/all__sagemath_symbolics.py +17 -0
  7. sage/calculus/all.py +14 -0
  8. sage/calculus/calculus.py +2838 -0
  9. sage/calculus/desolvers.py +1864 -0
  10. sage/calculus/predefined.py +51 -0
  11. sage/calculus/tests.py +225 -0
  12. sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
  13. sage/calculus/var.pyx +401 -0
  14. sage/dynamics/all__sagemath_symbolics.py +6 -0
  15. sage/dynamics/complex_dynamics/all.py +5 -0
  16. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  17. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  19. sage/ext/all__sagemath_symbolics.py +1 -0
  20. sage/ext_data/kenzo/CP2.txt +45 -0
  21. sage/ext_data/kenzo/CP3.txt +349 -0
  22. sage/ext_data/kenzo/CP4.txt +4774 -0
  23. sage/ext_data/kenzo/README.txt +49 -0
  24. sage/ext_data/kenzo/S4.txt +20 -0
  25. sage/ext_data/magma/latex/latex.m +1021 -0
  26. sage/ext_data/magma/latex/latex.spec +1 -0
  27. sage/ext_data/magma/sage/basic.m +356 -0
  28. sage/ext_data/magma/sage/sage.spec +1 -0
  29. sage/ext_data/magma/spec +9 -0
  30. sage/geometry/all__sagemath_symbolics.py +8 -0
  31. sage/geometry/hyperbolic_space/all.py +5 -0
  32. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  39. sage/geometry/riemannian_manifolds/all.py +7 -0
  40. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  41. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  42. sage/interfaces/all__sagemath_symbolics.py +1 -0
  43. sage/interfaces/magma.py +2991 -0
  44. sage/interfaces/magma_free.py +90 -0
  45. sage/interfaces/maple.py +1402 -0
  46. sage/interfaces/mathematica.py +1345 -0
  47. sage/interfaces/mathics.py +1312 -0
  48. sage/interfaces/sympy.py +1398 -0
  49. sage/interfaces/sympy_wrapper.py +197 -0
  50. sage/interfaces/tides.py +938 -0
  51. sage/libs/all__sagemath_symbolics.py +6 -0
  52. sage/manifolds/all.py +7 -0
  53. sage/manifolds/calculus_method.py +553 -0
  54. sage/manifolds/catalog.py +437 -0
  55. sage/manifolds/chart.py +4010 -0
  56. sage/manifolds/chart_func.py +3416 -0
  57. sage/manifolds/continuous_map.py +2183 -0
  58. sage/manifolds/continuous_map_image.py +155 -0
  59. sage/manifolds/differentiable/affine_connection.py +2475 -0
  60. sage/manifolds/differentiable/all.py +1 -0
  61. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  62. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  63. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  64. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  65. sage/manifolds/differentiable/chart.py +1241 -0
  66. sage/manifolds/differentiable/curve.py +1028 -0
  67. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  68. sage/manifolds/differentiable/degenerate.py +559 -0
  69. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  70. sage/manifolds/differentiable/diff_form.py +1660 -0
  71. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  72. sage/manifolds/differentiable/diff_map.py +1315 -0
  73. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  74. sage/manifolds/differentiable/examples/all.py +1 -0
  75. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  76. sage/manifolds/differentiable/examples/real_line.py +897 -0
  77. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  78. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  79. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  80. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  81. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  82. sage/manifolds/differentiable/manifold.py +4254 -0
  83. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  84. sage/manifolds/differentiable/metric.py +3032 -0
  85. sage/manifolds/differentiable/mixed_form.py +1507 -0
  86. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  87. sage/manifolds/differentiable/multivector_module.py +800 -0
  88. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  89. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  90. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  91. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  92. sage/manifolds/differentiable/scalarfield.py +1343 -0
  93. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  94. sage/manifolds/differentiable/symplectic_form.py +912 -0
  95. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  96. sage/manifolds/differentiable/tangent_space.py +412 -0
  97. sage/manifolds/differentiable/tangent_vector.py +616 -0
  98. sage/manifolds/differentiable/tensorfield.py +4665 -0
  99. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  100. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  101. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  102. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  103. sage/manifolds/differentiable/vectorfield.py +1717 -0
  104. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  105. sage/manifolds/differentiable/vectorframe.py +1832 -0
  106. sage/manifolds/family.py +270 -0
  107. sage/manifolds/local_frame.py +1490 -0
  108. sage/manifolds/manifold.py +3090 -0
  109. sage/manifolds/manifold_homset.py +452 -0
  110. sage/manifolds/operators.py +359 -0
  111. sage/manifolds/point.py +994 -0
  112. sage/manifolds/scalarfield.py +3718 -0
  113. sage/manifolds/scalarfield_algebra.py +629 -0
  114. sage/manifolds/section.py +3111 -0
  115. sage/manifolds/section_module.py +831 -0
  116. sage/manifolds/structure.py +229 -0
  117. sage/manifolds/subset.py +2721 -0
  118. sage/manifolds/subsets/all.py +1 -0
  119. sage/manifolds/subsets/closure.py +131 -0
  120. sage/manifolds/subsets/pullback.py +883 -0
  121. sage/manifolds/topological_submanifold.py +891 -0
  122. sage/manifolds/trivialization.py +733 -0
  123. sage/manifolds/utilities.py +1348 -0
  124. sage/manifolds/vector_bundle.py +1347 -0
  125. sage/manifolds/vector_bundle_fiber.py +332 -0
  126. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  127. sage/matrix/all__sagemath_symbolics.py +1 -0
  128. sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
  129. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  130. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  131. sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
  132. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  133. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  134. sage/modules/all__sagemath_symbolics.py +1 -0
  135. sage/modules/vector_callable_symbolic_dense.py +105 -0
  136. sage/modules/vector_symbolic_dense.py +116 -0
  137. sage/modules/vector_symbolic_sparse.py +118 -0
  138. sage/rings/all__sagemath_symbolics.py +4 -0
  139. sage/rings/asymptotic/all.py +6 -0
  140. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  141. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  142. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  143. sage/rings/asymptotic/growth_group.py +5373 -0
  144. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  145. sage/rings/asymptotic/term_monoid.py +5205 -0
  146. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  147. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  148. sage/symbolic/all.py +15 -0
  149. sage/symbolic/assumptions.py +987 -0
  150. sage/symbolic/benchmark.py +93 -0
  151. sage/symbolic/callable.py +456 -0
  152. sage/symbolic/callable.pyi +66 -0
  153. sage/symbolic/comparison_impl.pyi +38 -0
  154. sage/symbolic/complexity_measures.py +35 -0
  155. sage/symbolic/constants.py +1286 -0
  156. sage/symbolic/constants_c_impl.pyi +10 -0
  157. sage/symbolic/expression_conversion_algebraic.py +310 -0
  158. sage/symbolic/expression_conversion_sympy.py +317 -0
  159. sage/symbolic/expression_conversions.py +1727 -0
  160. sage/symbolic/function_factory.py +355 -0
  161. sage/symbolic/function_factory.pyi +41 -0
  162. sage/symbolic/getitem_impl.pyi +24 -0
  163. sage/symbolic/integration/all.py +1 -0
  164. sage/symbolic/integration/external.py +271 -0
  165. sage/symbolic/integration/integral.py +1075 -0
  166. sage/symbolic/maxima_wrapper.py +162 -0
  167. sage/symbolic/operators.py +267 -0
  168. sage/symbolic/operators.pyi +61 -0
  169. sage/symbolic/pynac_constant_impl.pyi +13 -0
  170. sage/symbolic/pynac_function_impl.pyi +8 -0
  171. sage/symbolic/random_tests.py +461 -0
  172. sage/symbolic/relation.py +2062 -0
  173. sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  174. sage/symbolic/ring.pxd +5 -0
  175. sage/symbolic/ring.pyi +110 -0
  176. sage/symbolic/ring.pyx +1393 -0
  177. sage/symbolic/series_impl.pyi +10 -0
  178. sage/symbolic/subring.py +1025 -0
  179. sage/symbolic/symengine.py +19 -0
  180. sage/symbolic/tests.py +40 -0
  181. sage/symbolic/units.py +1468 -0
@@ -0,0 +1,1315 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Differentiable Maps between Differentiable Manifolds
4
+
5
+ The class :class:`DiffMap` implements differentiable maps from a differentiable
6
+ manifold `M` to a differentiable manifold `N` over the same topological field
7
+ `K` as `M` (in most applications, `K = \RR` or `K = \CC`):
8
+
9
+ .. MATH::
10
+
11
+ \Phi: M \longrightarrow N
12
+
13
+
14
+ AUTHORS:
15
+
16
+ - Eric Gourgoulhon, Michal Bejger (2013-2015): initial version
17
+ - Marco Mancini (2018): pullback parallelization
18
+
19
+ REFERENCES:
20
+
21
+ - Chap. 1 of [KN1963]_
22
+ - Chaps. 2 and 3 of [Lee2013]_
23
+ """
24
+
25
+ # ****************************************************************************
26
+ # Copyright (C) 2015-2021 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
27
+ # Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
28
+ # Copyright (C) 2018 Marco Mancini <marco.mancini@obspm.fr>
29
+ #
30
+ # Distributed under the terms of the GNU General Public License (GPL)
31
+ # as published by the Free Software Foundation; either version 2 of
32
+ # the License, or (at your option) any later version.
33
+ # https://www.gnu.org/licenses/
34
+ # ****************************************************************************
35
+ from __future__ import annotations
36
+
37
+ from typing import TYPE_CHECKING
38
+
39
+ from sage.manifolds.continuous_map import ContinuousMap
40
+ from sage.parallel.decorate import parallel
41
+ from sage.parallel.parallelism import Parallelism
42
+
43
+ if TYPE_CHECKING:
44
+ from sage.manifolds.point import ManifoldPoint
45
+ from sage.tensor.modules.free_module_morphism import FiniteRankFreeModuleMorphism
46
+
47
+
48
+ class DiffMap(ContinuousMap):
49
+ r"""
50
+ Differentiable map between two differentiable manifolds.
51
+
52
+ This class implements differentiable maps of the type
53
+
54
+ .. MATH::
55
+
56
+ \Phi: M \longrightarrow N
57
+
58
+ where `M` and `N` are differentiable manifolds over the same topological
59
+ field `K` (in most applications, `K = \RR` or `K = \CC`).
60
+
61
+ Differentiable maps are the *morphisms* of the *category* of
62
+ differentiable manifolds. The set of all differentiable maps from `M` to
63
+ `N` is therefore the homset between `M` and `N`, which is denoted by
64
+ `\mathrm{Hom}(M,N)`.
65
+
66
+ The class :class:`DiffMap` is a Sage *element* class, whose *parent*
67
+ class is
68
+ :class:`~sage.manifolds.differentiable.manifold_homset.DifferentiableManifoldHomset`.
69
+ It inherits from the class
70
+ :class:`~sage.manifolds.continuous_map.ContinuousMap` since a
71
+ differentiable map is obviously a continuous one.
72
+
73
+ INPUT:
74
+
75
+ - ``parent`` -- homset `\mathrm{Hom}(M,N)` to which the differentiable
76
+ map belongs
77
+ - ``coord_functions`` -- (default: ``None``) if not ``None``, must be
78
+ a dictionary of the coordinate expressions (as lists (or tuples) of the
79
+ coordinates of the image expressed in terms of the coordinates of
80
+ the considered point) with the pairs of charts (chart1, chart2)
81
+ as keys (chart1 being a chart on `M` and chart2 a chart on `N`).
82
+ If the dimension of the map's codomain is 1, a single coordinate
83
+ expression can be passed instead of a tuple with a single element
84
+ - ``name`` -- (default: ``None``) name given to the differentiable map
85
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
86
+ differentiable map; if ``None``, the LaTeX symbol is set to ``name``
87
+ - ``is_isomorphism`` -- boolean (default: ``False``); determines whether the
88
+ constructed object is a isomorphism (i.e. a diffeomorphism). If set to
89
+ ``True``, then the manifolds `M` and `N` must have the same dimension.
90
+ - ``is_identity`` -- boolean (default: ``False``); determines whether the
91
+ constructed object is the identity map. If set to ``True``,
92
+ then `N` must be `M` and the entry ``coord_functions`` is not used.
93
+
94
+ .. NOTE::
95
+
96
+ If the information passed by means of the argument ``coord_functions``
97
+ is not sufficient to fully specify the differentiable map,
98
+ further coordinate expressions, in other charts, can be subsequently
99
+ added by means of the method
100
+ :meth:`~sage.manifolds.continuous_map.ContinuousMap.add_expr`
101
+
102
+ EXAMPLES:
103
+
104
+ The standard embedding of the sphere `S^2` into `\RR^3`::
105
+
106
+ sage: M = Manifold(2, 'S^2') # the 2-dimensional sphere S^2
107
+ sage: U = M.open_subset('U') # complement of the North pole
108
+ sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
109
+ sage: V = M.open_subset('V') # complement of the South pole
110
+ sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
111
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
112
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
113
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
114
+ ....: restrictions2= u^2+v^2!=0)
115
+ sage: uv_to_xy = xy_to_uv.inverse()
116
+ sage: N = Manifold(3, 'R^3', r'\RR^3') # R^3
117
+ sage: c_cart.<X,Y,Z> = N.chart() # Cartesian coordinates on R^3
118
+ sage: Phi = M.diff_map(N,
119
+ ....: {(c_xy, c_cart): [2*x/(1+x^2+y^2), 2*y/(1+x^2+y^2), (x^2+y^2-1)/(1+x^2+y^2)],
120
+ ....: (c_uv, c_cart): [2*u/(1+u^2+v^2), 2*v/(1+u^2+v^2), (1-u^2-v^2)/(1+u^2+v^2)]},
121
+ ....: name='Phi', latex_name=r'\Phi')
122
+ sage: Phi
123
+ Differentiable map Phi from the 2-dimensional differentiable manifold
124
+ S^2 to the 3-dimensional differentiable manifold R^3
125
+ sage: Phi.parent()
126
+ Set of Morphisms from 2-dimensional differentiable manifold S^2 to
127
+ 3-dimensional differentiable manifold R^3 in Category of smooth
128
+ manifolds over Real Field with 53 bits of precision
129
+ sage: Phi.parent() is Hom(M, N)
130
+ True
131
+ sage: type(Phi)
132
+ <class 'sage.manifolds.differentiable.manifold_homset.DifferentiableManifoldHomset_with_category.element_class'>
133
+ sage: Phi.display()
134
+ Phi: S^2 → R^3
135
+ on U: (x, y) ↦ (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1),
136
+ (x^2 + y^2 - 1)/(x^2 + y^2 + 1))
137
+ on V: (u, v) ↦ (X, Y, Z) = (2*u/(u^2 + v^2 + 1), 2*v/(u^2 + v^2 + 1),
138
+ -(u^2 + v^2 - 1)/(u^2 + v^2 + 1))
139
+
140
+ It is possible to create the map via the method
141
+ :meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.diff_map`
142
+ only in a single pair of charts: the argument ``coord_functions`` is then
143
+ a mere list of coordinate expressions (and not a dictionary) and the
144
+ arguments ``chart1`` and ``chart2`` have to be provided if the charts
145
+ differ from the default ones on the domain and/or the codomain::
146
+
147
+ sage: Phi1 = M.diff_map(N, [2*x/(1+x^2+y^2), 2*y/(1+x^2+y^2),
148
+ ....: (x^2+y^2-1)/(1+x^2+y^2)],
149
+ ....: chart1=c_xy, chart2=c_cart, name='Phi',
150
+ ....: latex_name=r'\Phi')
151
+
152
+ Since ``c_xy`` and ``c_cart`` are the default charts on respectively ``M``
153
+ and ``N``, they can be omitted, so that the above declaration is equivalent
154
+ to::
155
+
156
+ sage: Phi1 = M.diff_map(N, [2*x/(1+x^2+y^2), 2*y/(1+x^2+y^2),
157
+ ....: (x^2+y^2-1)/(1+x^2+y^2)],
158
+ ....: name='Phi', latex_name=r'\Phi')
159
+
160
+ With such a declaration, the differentiable map is only partially defined
161
+ on the manifold `S^2`, being known in only one chart::
162
+
163
+ sage: Phi1.display()
164
+ Phi: S^2 → R^3
165
+ on U: (x, y) ↦ (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1),
166
+ (x^2 + y^2 - 1)/(x^2 + y^2 + 1))
167
+
168
+ The definition can be completed by means of the method
169
+ :meth:`~sage.manifolds.continuous_map.ContinuousMap.add_expr`::
170
+
171
+ sage: Phi1.add_expr(c_uv, c_cart, [2*u/(1+u^2+v^2), 2*v/(1+u^2+v^2),
172
+ ....: (1-u^2-v^2)/(1+u^2+v^2)])
173
+ sage: Phi1.display()
174
+ Phi: S^2 → R^3
175
+ on U: (x, y) ↦ (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1),
176
+ (x^2 + y^2 - 1)/(x^2 + y^2 + 1))
177
+ on V: (u, v) ↦ (X, Y, Z) = (2*u/(u^2 + v^2 + 1), 2*v/(u^2 + v^2 + 1),
178
+ -(u^2 + v^2 - 1)/(u^2 + v^2 + 1))
179
+
180
+ At this stage, ``Phi1`` and ``Phi`` are fully equivalent::
181
+
182
+ sage: Phi1 == Phi
183
+ True
184
+
185
+ The test suite is passed::
186
+
187
+ sage: TestSuite(Phi).run()
188
+ sage: TestSuite(Phi1).run()
189
+
190
+ The map acts on points::
191
+
192
+ sage: np = M.point((0,0), chart=c_uv, name='N') # the North pole
193
+ sage: Phi(np)
194
+ Point Phi(N) on the 3-dimensional differentiable manifold R^3
195
+ sage: Phi(np).coord() # Cartesian coordinates
196
+ (0, 0, 1)
197
+ sage: sp = M.point((0,0), chart=c_xy, name='S') # the South pole
198
+ sage: Phi(sp).coord() # Cartesian coordinates
199
+ (0, 0, -1)
200
+
201
+ The differential `\mathrm{d}\Phi` of the map `\Phi` at the North pole and
202
+ at the South pole::
203
+
204
+ sage: Phi.differential(np)
205
+ Generic morphism:
206
+ From: Tangent space at Point N on the 2-dimensional differentiable manifold S^2
207
+ To: Tangent space at Point Phi(N) on the 3-dimensional differentiable manifold R^3
208
+ sage: Phi.differential(sp)
209
+ Generic morphism:
210
+ From: Tangent space at Point S on the 2-dimensional differentiable manifold S^2
211
+ To: Tangent space at Point Phi(S) on the 3-dimensional differentiable manifold R^3
212
+
213
+ The matrix of the linear map `\mathrm{d}\Phi_N` with respect to the default
214
+ bases of `T_N S^2` and `T_{\Phi(N)} \RR^3`::
215
+
216
+ sage: Phi.differential(np).matrix()
217
+ [2 0]
218
+ [0 2]
219
+ [0 0]
220
+
221
+ the default bases being::
222
+
223
+ sage: Phi.differential(np).domain().default_basis()
224
+ Basis (∂/∂u,∂/∂v) on the Tangent space at Point N on the 2-dimensional
225
+ differentiable manifold S^2
226
+ sage: Phi.differential(np).codomain().default_basis()
227
+ Basis (∂/∂X,∂/∂Y,∂/∂Z) on the Tangent space at Point Phi(N) on the
228
+ 3-dimensional differentiable manifold R^3
229
+
230
+ A convenient way to display the matrix of the differential::
231
+
232
+ sage: Phi.differential(np).display()
233
+ ∂/∂u ∂/∂v
234
+ ∂/∂X⎛ 2 0⎞
235
+ ∂/∂Y⎜ 0 2⎟
236
+ ∂/∂Z⎝ 0 0⎠
237
+
238
+ Differentiable maps can be composed by means of the operator ``*``: let
239
+ us introduce the map `\RR^3\rightarrow \RR^2` corresponding to
240
+ the projection from the point `(X,Y,Z)=(0,0,1)` onto the equatorial plane
241
+ `Z=0`::
242
+
243
+ sage: P = Manifold(2, 'R^2', r'\RR^2') # R^2 (equatorial plane)
244
+ sage: cP.<xP, yP> = P.chart()
245
+ sage: Psi = N.diff_map(P, (X/(1-Z), Y/(1-Z)), name='Psi',
246
+ ....: latex_name=r'\Psi')
247
+ sage: Psi
248
+ Differentiable map Psi from the 3-dimensional differentiable manifold
249
+ R^3 to the 2-dimensional differentiable manifold R^2
250
+ sage: Psi.display()
251
+ Psi: R^3 → R^2
252
+ (X, Y, Z) ↦ (xP, yP) = (-X/(Z - 1), -Y/(Z - 1))
253
+
254
+ Then we compose ``Psi`` with ``Phi``, thereby getting a map
255
+ `S^2\rightarrow \RR^2`::
256
+
257
+ sage: ster = Psi*Phi ; ster
258
+ Differentiable map from the 2-dimensional differentiable manifold S^2
259
+ to the 2-dimensional differentiable manifold R^2
260
+
261
+ Let us test on the South pole (``sp``) that ``ster`` is indeed the
262
+ composite of ``Psi`` and ``Phi``::
263
+
264
+ sage: ster(sp) == Psi(Phi(sp))
265
+ True
266
+
267
+ Actually ``ster`` is the stereographic projection from the North pole, as
268
+ its coordinate expression reveals::
269
+
270
+ sage: ster.display()
271
+ S^2 → R^2
272
+ on U: (x, y) ↦ (xP, yP) = (x, y)
273
+ on V: (u, v) ↦ (xP, yP) = (u/(u^2 + v^2), v/(u^2 + v^2))
274
+
275
+ If its codomain is 1-dimensional, a differentiable map must be
276
+ defined by a single symbolic expression for each pair of charts, and not
277
+ by a list/tuple with a single element::
278
+
279
+ sage: N = Manifold(1, 'N')
280
+ sage: c_N = N.chart('X')
281
+ sage: Phi = M.diff_map(N, {(c_xy, c_N): x^2+y^2,
282
+ ....: (c_uv, c_N): 1/(u^2+v^2)}) # not ...[1/(u^2+v^2)] or (1/(u^2+v^2),)
283
+
284
+ An example of differentiable map `\RR \rightarrow \RR^2`::
285
+
286
+ sage: R = Manifold(1, 'R') # field R
287
+ sage: T.<t> = R.chart() # canonical chart on R
288
+ sage: R2 = Manifold(2, 'R^2') # R^2
289
+ sage: c_xy.<x,y> = R2.chart() # Cartesian coordinates on R^2
290
+ sage: Phi = R.diff_map(R2, [cos(t), sin(t)], name='Phi') ; Phi
291
+ Differentiable map Phi from the 1-dimensional differentiable manifold R
292
+ to the 2-dimensional differentiable manifold R^2
293
+ sage: Phi.parent()
294
+ Set of Morphisms from 1-dimensional differentiable manifold R to
295
+ 2-dimensional differentiable manifold R^2 in Category of smooth
296
+ manifolds over Real Field with 53 bits of precision
297
+ sage: Phi.parent() is Hom(R, R2)
298
+ True
299
+ sage: Phi.display()
300
+ Phi: R → R^2
301
+ t ↦ (x, y) = (cos(t), sin(t))
302
+
303
+ An example of diffeomorphism between the unit open disk and the Euclidean
304
+ plane `\RR^2`::
305
+
306
+ sage: D = R2.open_subset('D', coord_def={c_xy: x^2+y^2<1}) # the open unit disk
307
+ sage: Phi = D.diffeomorphism(R2, [x/sqrt(1-x^2-y^2), y/sqrt(1-x^2-y^2)],
308
+ ....: name='Phi', latex_name=r'\Phi')
309
+ sage: Phi
310
+ Diffeomorphism Phi from the Open subset D of the 2-dimensional
311
+ differentiable manifold R^2 to the 2-dimensional differentiable
312
+ manifold R^2
313
+ sage: Phi.parent()
314
+ Set of Morphisms from Open subset D of the 2-dimensional differentiable
315
+ manifold R^2 to 2-dimensional differentiable manifold R^2 in Category
316
+ of smooth manifolds over Real Field with 53 bits of precision
317
+ sage: Phi.parent() is Hom(D, R2)
318
+ True
319
+ sage: Phi.display()
320
+ Phi: D → R^2
321
+ (x, y) ↦ (x, y) = (x/sqrt(-x^2 - y^2 + 1), y/sqrt(-x^2 - y^2 + 1))
322
+
323
+ The image of a point::
324
+
325
+ sage: p = D.point((1/2,0))
326
+ sage: q = Phi(p) ; q
327
+ Point on the 2-dimensional differentiable manifold R^2
328
+ sage: q.coord()
329
+ (1/3*sqrt(3), 0)
330
+
331
+ The inverse diffeomorphism is computed by means of the method
332
+ :meth:`~sage.manifolds.continuous_map.ContinuousMap.inverse`::
333
+
334
+ sage: Phi.inverse()
335
+ Diffeomorphism Phi^(-1) from the 2-dimensional differentiable manifold R^2
336
+ to the Open subset D of the 2-dimensional differentiable manifold R^2
337
+ sage: Phi.inverse().display()
338
+ Phi^(-1): R^2 → D
339
+ (x, y) ↦ (x, y) = (x/sqrt(x^2 + y^2 + 1), y/sqrt(x^2 + y^2 + 1))
340
+
341
+ Equivalently, one may use the notations ``^(-1)`` or ``~`` to get the
342
+ inverse::
343
+
344
+ sage: Phi^(-1) is Phi.inverse()
345
+ True
346
+ sage: ~Phi is Phi.inverse()
347
+ True
348
+
349
+ Check that ``~Phi`` is indeed the inverse of ``Phi``::
350
+
351
+ sage: (~Phi)(q) == p
352
+ True
353
+ sage: Phi * ~Phi == R2.identity_map()
354
+ True
355
+ sage: ~Phi * Phi == D.identity_map()
356
+ True
357
+
358
+ The coordinate expression of the inverse diffeomorphism::
359
+
360
+ sage: (~Phi).display()
361
+ Phi^(-1): R^2 → D
362
+ (x, y) ↦ (x, y) = (x/sqrt(x^2 + y^2 + 1), y/sqrt(x^2 + y^2 + 1))
363
+
364
+ A special case of diffeomorphism: the identity map of the open unit disk::
365
+
366
+ sage: id = D.identity_map() ; id
367
+ Identity map Id_D of the Open subset D of the 2-dimensional
368
+ differentiable manifold R^2
369
+ sage: latex(id)
370
+ \mathrm{Id}_{D}
371
+ sage: id.parent()
372
+ Set of Morphisms from Open subset D of the 2-dimensional differentiable
373
+ manifold R^2 to Open subset D of the 2-dimensional differentiable
374
+ manifold R^2 in Join of Category of subobjects of sets and Category of
375
+ smooth manifolds over Real Field with 53 bits of precision
376
+ sage: id.parent() is Hom(D, D)
377
+ True
378
+ sage: id is Hom(D,D).one() # the identity element of the monoid Hom(D,D)
379
+ True
380
+
381
+ The identity map acting on a point::
382
+
383
+ sage: id(p)
384
+ Point on the 2-dimensional differentiable manifold R^2
385
+ sage: id(p) == p
386
+ True
387
+ sage: id(p) is p
388
+ True
389
+
390
+ The coordinate expression of the identity map::
391
+
392
+ sage: id.display()
393
+ Id_D: D → D
394
+ (x, y) ↦ (x, y)
395
+
396
+ The identity map is its own inverse::
397
+
398
+ sage: id^(-1) is id
399
+ True
400
+ sage: ~id is id
401
+ True
402
+ """
403
+ def __init__(self, parent, coord_functions=None, name=None,
404
+ latex_name=None, is_isomorphism=False, is_identity=False):
405
+ r"""
406
+ Construct a differentiable map.
407
+
408
+ TESTS::
409
+
410
+ sage: M = Manifold(2, 'M')
411
+ sage: X.<x,y> = M.chart()
412
+ sage: N = Manifold(3, 'N')
413
+ sage: Y.<u,v,w> = N.chart()
414
+ sage: f = Hom(M,N)({(X,Y): (x+y, x*y, x-y)}, name='f') ; f
415
+ Differentiable map f from the 2-dimensional differentiable manifold
416
+ M to the 3-dimensional differentiable manifold N
417
+ sage: f.display()
418
+ f: M → N
419
+ (x, y) ↦ (u, v, w) = (x + y, x*y, x - y)
420
+ sage: TestSuite(f).run()
421
+
422
+ The identity map::
423
+
424
+ sage: f = Hom(M,M)({}, is_identity=True) ; f
425
+ Identity map Id_M of the 2-dimensional differentiable manifold M
426
+ sage: f.display()
427
+ Id_M: M → M
428
+ (x, y) ↦ (x, y)
429
+ sage: TestSuite(f).run()
430
+ """
431
+ ContinuousMap.__init__(self, parent, coord_functions=coord_functions,
432
+ name=name, latex_name=latex_name,
433
+ is_isomorphism=is_isomorphism,
434
+ is_identity=is_identity)
435
+
436
+ #
437
+ # SageObject methods
438
+ #
439
+
440
+ def _repr_(self):
441
+ r"""
442
+ String representation of the object.
443
+
444
+ TESTS::
445
+
446
+ sage: M = Manifold(2, 'M')
447
+ sage: X.<x,y> = M.chart()
448
+ sage: N = Manifold(2, 'N')
449
+ sage: Y.<u,v> = N.chart()
450
+ sage: f = Hom(M,N)({(X,Y): (x+y,x*y)})
451
+ sage: f._repr_()
452
+ 'Differentiable map from the 2-dimensional differentiable manifold M to
453
+ the 2-dimensional differentiable manifold N'
454
+ sage: f = Hom(M,N)({(X,Y): (x+y,x*y)}, name='f')
455
+ sage: f._repr_()
456
+ 'Differentiable map f from the 2-dimensional differentiable manifold M to
457
+ the 2-dimensional differentiable manifold N'
458
+ sage: f = Hom(M,N)({(X,Y): (x+y,x-y)}, name='f', is_isomorphism=True)
459
+ sage: f._repr_()
460
+ 'Diffeomorphism f from the 2-dimensional differentiable manifold M to
461
+ the 2-dimensional differentiable manifold N'
462
+ sage: f = Hom(M,M)({(X,X): (x+y,x-y)}, name='f', is_isomorphism=True)
463
+ sage: f._repr_()
464
+ 'Diffeomorphism f of the 2-dimensional differentiable manifold M'
465
+ sage: f = Hom(M,M)({}, name='f', is_identity=True)
466
+ sage: f._repr_()
467
+ 'Identity map f of the 2-dimensional differentiable manifold M'
468
+ """
469
+ if self._is_identity:
470
+ return "Identity map " + self._name + \
471
+ " of the {}".format(self._domain)
472
+ if self._is_isomorphism:
473
+ description = "Diffeomorphism"
474
+ else:
475
+ description = "Differentiable map"
476
+ if self._name is not None:
477
+ description += " " + self._name
478
+ if self._domain == self._codomain:
479
+ if self._is_isomorphism:
480
+ description += " of the {}".format(self._domain)
481
+ else:
482
+ description += " from the {} to itself".format(self._domain)
483
+ else:
484
+ description += " from the {} to the {}".format(self._domain,
485
+ self._codomain)
486
+ return description
487
+
488
+ def _init_derived(self):
489
+ r"""
490
+ Initialize the derived quantities.
491
+
492
+ TESTS::
493
+
494
+ sage: M = Manifold(2, 'M')
495
+ sage: X.<x,y> = M.chart()
496
+ sage: f = M.diffeomorphism(M, [x+y, x-y])
497
+ sage: f._init_derived()
498
+ sage: f._restrictions
499
+ {}
500
+ sage: f._inverse
501
+ """
502
+ ContinuousMap._init_derived(self)
503
+ # derived quantities of the mother class
504
+ self._diff = {}
505
+ # dict. of the coord. expressions of the differential
506
+ # keys: pair of charts
507
+
508
+ def _del_derived(self):
509
+ r"""
510
+ Delete the derived quantities.
511
+
512
+ TESTS::
513
+
514
+ sage: M = Manifold(2, 'M')
515
+ sage: X.<x,y> = M.chart()
516
+ sage: f = M.diffeomorphism(M, [x+y, x-y])
517
+ sage: f^(-1)
518
+ Diffeomorphism of the 2-dimensional differentiable manifold M
519
+ sage: f._inverse # was set by f^(-1)
520
+ Diffeomorphism of the 2-dimensional differentiable manifold M
521
+ sage: f._del_derived()
522
+ sage: f._inverse # has been set to None by _del_derived()
523
+ """
524
+ ContinuousMap._del_derived(self) # derived quantities of the mother
525
+ # class
526
+ self._diff.clear()
527
+
528
+ def differential(self, point: ManifoldPoint) -> FiniteRankFreeModuleMorphism:
529
+ r"""
530
+ Return the differential of ``self`` at a given point.
531
+
532
+ If the differentiable map ``self`` is
533
+
534
+ .. MATH::
535
+
536
+ \Phi: M \longrightarrow N,
537
+
538
+ where `M` and `N` are differentiable manifolds, the *differential*
539
+ of `\Phi` at a point `p \in M` is the tangent space linear map:
540
+
541
+ .. MATH::
542
+
543
+ \mathrm{d}\Phi_p: T_p M \longrightarrow T_{\Phi(p)} N
544
+
545
+ defined by
546
+
547
+ .. MATH::
548
+
549
+ \begin{array}{rccc}
550
+ \forall v\in T_p M,\quad \mathrm{d}\Phi_p(v) :
551
+ & C^k(N) & \longrightarrow & \mathbb{R} \\
552
+ & f & \longmapsto & v(f\circ \Phi)
553
+ \end{array}
554
+
555
+ INPUT:
556
+
557
+ - ``point`` -- point `p` in the domain `M` of the differentiable
558
+ map `\Phi`
559
+
560
+ OUTPUT:
561
+
562
+ - `\mathrm{d}\Phi_p`, the differential of `\Phi` at `p`, as a
563
+ :class:`~sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleMorphism`
564
+
565
+ EXAMPLES:
566
+
567
+ Differential of a differentiable map between a 2-dimensional manifold
568
+ and a 3-dimensional one::
569
+
570
+ sage: M = Manifold(2, 'M')
571
+ sage: X.<x,y> = M.chart()
572
+ sage: N = Manifold(3, 'N')
573
+ sage: Y.<u,v,w> = N.chart()
574
+ sage: Phi = M.diff_map(N, {(X,Y): (x-2*y, x*y, x^2-y^3)}, name='Phi',
575
+ ....: latex_name = r'\Phi')
576
+ sage: p = M.point((2,-1), name='p')
577
+ sage: dPhip = Phi.differential(p) ; dPhip
578
+ Generic morphism:
579
+ From: Tangent space at Point p on the 2-dimensional differentiable manifold M
580
+ To: Tangent space at Point Phi(p) on the 3-dimensional differentiable manifold N
581
+ sage: latex(dPhip)
582
+ {\mathrm{d}\Phi}_{p}
583
+ sage: dPhip.parent()
584
+ Set of Morphisms from Tangent space at Point p on the 2-dimensional
585
+ differentiable manifold M to Tangent space at Point Phi(p) on the
586
+ 3-dimensional differentiable manifold N in Category of finite
587
+ dimensional vector spaces over Symbolic Ring
588
+
589
+ The matrix of `\mathrm{d}\Phi_p` w.r.t. to the default bases of
590
+ `T_p M` and `T_{\Phi(p)} N`::
591
+
592
+ sage: dPhip.matrix()
593
+ [ 1 -2]
594
+ [-1 2]
595
+ [ 4 -3]
596
+ """
597
+ image_point = self(point)
598
+ tsp_image = image_point._manifold.tangent_space(image_point)
599
+ tsp_source = point._manifold.tangent_space(point)
600
+ # Search for a common chart to perform the computation
601
+ chartp = None
602
+
603
+ # 1/ Search without any extra computation
604
+ for chart in point._coordinates:
605
+ for chart_pair in self._diff:
606
+ if chart == chart_pair[0]:
607
+ chartp = chart_pair
608
+ break
609
+ if chartp is not None:
610
+ break
611
+ else:
612
+ # 2/ Search with a coordinate transformation on the point
613
+ for chart_pair in self._diff:
614
+ try:
615
+ point.coord(chart_pair[0])
616
+ chartp = chart_pair
617
+ except ValueError:
618
+ pass
619
+
620
+ if chartp is None:
621
+ # 3/ Search with a coordinate evaluation of self
622
+ for chart1 in point._coordinates:
623
+ for chart2 in self._codomain.atlas():
624
+ try:
625
+ self.differential_functions(chart1, chart2)
626
+ chartp = (chart1, chart2)
627
+ break
628
+ except ValueError:
629
+ pass
630
+ if chartp is not None:
631
+ break
632
+
633
+ if chartp is None:
634
+ raise ValueError("no common chart have been found for the " +
635
+ "coordinate expressions of {} and {}".format(self, point))
636
+
637
+ diff_funct = self.differential_functions(*chartp)
638
+ chart1 = chartp[0]
639
+ chart2 = chartp[1]
640
+ coord_point = point.coord(chart1)
641
+ n1 = self._domain.dim()
642
+ n2 = self._codomain.dim()
643
+ matrix = [[diff_funct[i][j](*coord_point) for j in range(n1)]
644
+ for i in range(n2)]
645
+ bases = (chart1.frame().at(point), chart2.frame().at(image_point))
646
+ if self._name is not None and point._name is not None:
647
+ name = 'd%s_%s' % (self._name, point._name)
648
+ else:
649
+ name = None
650
+ if self._latex_name is not None and point._latex_name is not None:
651
+ latex_name = r'{\mathrm{d}%s}_{%s}' % (self._latex_name,
652
+ point._latex_name)
653
+ else:
654
+ latex_name = None
655
+ return tsp_source.hom(tsp_image, matrix, bases=bases,
656
+ name=name, latex_name=latex_name)
657
+
658
+ def differential_functions(self, chart1=None, chart2=None):
659
+ r"""
660
+ Return the coordinate expression of the differential of the
661
+ differentiable map with respect to a pair of charts.
662
+
663
+ If the differentiable map is
664
+
665
+ .. MATH::
666
+
667
+ \Phi: M \longrightarrow N,
668
+
669
+ where `M` and `N` are differentiable manifolds, the *differential*
670
+ of `\Phi` at a point `p \in M` is the tangent space linear map:
671
+
672
+ .. MATH::
673
+
674
+ \mathrm{d}\Phi_p: T_p M \longrightarrow T_{\Phi(p)} N
675
+
676
+ defined by
677
+
678
+ .. MATH::
679
+
680
+ \begin{array}{rccc}
681
+ \forall v\in T_p M,\quad \mathrm{d}\Phi_p(v) : & C^k(N) &
682
+ \longrightarrow & \mathbb{R}, \\
683
+ & f & \longmapsto & v(f\circ \Phi).
684
+ \end{array}
685
+
686
+ If the coordinate expression of `\Phi` is
687
+
688
+ .. MATH::
689
+
690
+ y^i = Y^i(x^1, \ldots, x^n), \quad 1 \leq i \leq m,
691
+
692
+ where `(x^1, \ldots, x^n)` are coordinates of a chart on `M` and
693
+ `(y^1, \ldots, y^m)` are coordinates of a chart on `\Phi(M)`, the
694
+ expression of the differential of `\Phi` with respect to these
695
+ coordinates is
696
+
697
+ .. MATH::
698
+
699
+ J_{ij} = \frac{\partial Y^i}{\partial x^j} \quad 1\leq i \leq m,
700
+ \qquad 1 \leq j \leq n.
701
+
702
+ `\left. J_{ij} \right|_p` is then the matrix of the linear map
703
+ `\mathrm{d}\Phi_p` with respect to the bases of `T_p M` and
704
+ `T_{\Phi(p)} N` associated to the above charts:
705
+
706
+ .. MATH::
707
+
708
+ \mathrm{d}\Phi_p\left( \left. \frac{\partial}{\partial x^j}
709
+ \right|_p \right) = \left. J_{ij} \right|_p \;
710
+ \left. \frac{\partial}{\partial y^i} \right| _{\Phi(p)}.
711
+
712
+ INPUT:
713
+
714
+ - ``chart1`` -- (default: ``None``) chart on the domain `M` of `\Phi`
715
+ (coordinates denoted by `(x^j)` above); if ``None``, the domain's
716
+ default chart is assumed
717
+ - ``chart2`` -- (default: ``None``) chart on the codomain of `\Phi`
718
+ (coordinates denoted by `(y^i)` above); if ``None``, the codomain's
719
+ default chart is assumed
720
+
721
+ OUTPUT:
722
+
723
+ - the functions `J_{ij}` as a double array, `J_{ij}` being
724
+ the element ``[i][j]`` represented by a
725
+ :class:`~sage.manifolds.chart_func.ChartFunction`
726
+
727
+ To get symbolic expressions, use the method
728
+ :meth:`jacobian_matrix` instead.
729
+
730
+ EXAMPLES:
731
+
732
+ Differential functions of a map between a 2-dimensional manifold
733
+ and a 3-dimensional one::
734
+
735
+ sage: M = Manifold(2, 'M')
736
+ sage: X.<x,y> = M.chart()
737
+ sage: N = Manifold(3, 'N')
738
+ sage: Y.<u,v,w> = N.chart()
739
+ sage: Phi = M.diff_map(N, {(X,Y): (x-2*y, x*y, x^2-y^3)}, name='Phi',
740
+ ....: latex_name = r'\Phi')
741
+ sage: J = Phi.differential_functions(X, Y) ; J
742
+ [ 1 -2]
743
+ [ y x]
744
+ [ 2*x -3*y^2]
745
+
746
+ The result is cached::
747
+
748
+ sage: Phi.differential_functions(X, Y) is J
749
+ True
750
+
751
+ The elements of ``J`` are functions of the coordinates of
752
+ the chart ``X``::
753
+
754
+ sage: J[2][0]
755
+ 2*x
756
+ sage: type(J[2][0])
757
+ <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'>
758
+
759
+ sage: J[2][0].display()
760
+ (x, y) ↦ 2*x
761
+
762
+ In contrast, the method :meth:`jacobian_matrix` leads directly to
763
+ symbolic expressions::
764
+
765
+ sage: JJ = Phi.jacobian_matrix(X,Y) ; JJ
766
+ [ 1 -2]
767
+ [ y x]
768
+ [ 2*x -3*y^2]
769
+ sage: JJ[2,0]
770
+ 2*x
771
+ sage: type(JJ[2,0])
772
+ <class 'sage.symbolic.expression.Expression'>
773
+ sage: bool( JJ[2,0] == J[2][0].expr() )
774
+ True
775
+ """
776
+ dom1 = self._domain
777
+ dom2 = self._codomain
778
+ if chart1 is None:
779
+ chart1 = dom1._def_chart
780
+ if chart2 is None:
781
+ chart2 = dom2._def_chart
782
+ if (chart1, chart2) not in self._diff:
783
+ funct = self.coord_functions(chart1, chart2)
784
+ self._diff[(chart1, chart2)] = funct.jacobian()
785
+ return self._diff[(chart1, chart2)]
786
+
787
+ def jacobian_matrix(self, chart1=None, chart2=None):
788
+ r"""
789
+ Return the Jacobian matrix resulting from the coordinate expression
790
+ of the differentiable map with respect to a pair of charts.
791
+
792
+ If `\Phi` is the current differentiable map and its coordinate
793
+ expression is
794
+
795
+ .. MATH::
796
+
797
+ y^i = Y^i(x^1, \ldots, x^n), \quad 1 \leq i \leq m,
798
+
799
+ where `(x^1, \ldots, x^n)` are coordinates of a chart `X` on the
800
+ domain of `\Phi` and `(y^1, \ldots, y^m)` are coordinates of a chart
801
+ `Y` on the codomain of `\Phi`, the *Jacobian matrix* of the
802
+ differentiable map `\Phi` w.r.t. to charts `X` and `Y` is
803
+
804
+ .. MATH::
805
+
806
+ J = \left( \frac{\partial Y^i}{\partial x^j}
807
+ \right)_{\substack{1 \leq i \leq m \\ 1 \leq j \leq n}},
808
+
809
+ where `i` is the row index and `j` the column one.
810
+
811
+ INPUT:
812
+
813
+ - ``chart1`` -- (default: ``None``) chart `X` on the domain of
814
+ `\Phi`; if none is provided, the domain's default chart is assumed
815
+ - ``chart2`` -- (default: ``None``) chart `Y` on the codomain of
816
+ `\Phi`; if none is provided, the codomain's default chart is
817
+ assumed
818
+
819
+ OUTPUT: the matrix `J` defined above
820
+
821
+ EXAMPLES:
822
+
823
+ Jacobian matrix of a map between a 2-dimensional manifold and a
824
+ 3-dimensional one::
825
+
826
+ sage: M = Manifold(2, 'M')
827
+ sage: X.<x,y> = M.chart()
828
+ sage: N = Manifold(3, 'N')
829
+ sage: Y.<u,v,w> = N.chart()
830
+ sage: Phi = M.diff_map(N, {(X,Y): (x-2*y, x*y, x^2-y^3)}, name='Phi',
831
+ ....: latex_name = r'\Phi')
832
+ sage: Phi.display()
833
+ Phi: M → N
834
+ (x, y) ↦ (u, v, w) = (x - 2*y, x*y, -y^3 + x^2)
835
+ sage: J = Phi.jacobian_matrix(X, Y) ; J
836
+ [ 1 -2]
837
+ [ y x]
838
+ [ 2*x -3*y^2]
839
+ sage: J.parent()
840
+ Full MatrixSpace of 3 by 2 dense matrices over Symbolic Ring
841
+ """
842
+ from sage.matrix.constructor import matrix
843
+ diff_funct = self.differential_functions(chart1, chart2)
844
+ n1 = self._domain.dim()
845
+ n2 = self._codomain.dim()
846
+ return matrix([[diff_funct[i][j].expr() for j in range(n1)]
847
+ for i in range(n2)])
848
+
849
+ def pullback(self, tensor_or_codomain_subset, name=None, latex_name=None):
850
+ r"""
851
+ Pullback operator associated with ``self``.
852
+
853
+ In what follows, let `\Phi` denote a differentiable map ``self``,
854
+ `M` its domain and `N` its codomain.
855
+
856
+ INPUT:
857
+
858
+ One of the following:
859
+
860
+ - ``tensor_or_codomain_subset`` -- one of the following:
861
+
862
+ - a :class:`~sage.manifolds.differentiable.tensorfield.TensorField`;
863
+ a fully covariant tensor field `T` on `N`, i.e. a tensor
864
+ field of type `(0, p)`, with `p` a positive or zero integer; the
865
+ case `p = 0` corresponds to a scalar field
866
+ - a :class:`~sage.manifolds.subset.ManifoldSubset` `S`
867
+
868
+ OUTPUT:
869
+
870
+ - (if the input is a tensor field `T`)
871
+ a :class:`~sage.manifolds.differentiable.tensorfield.TensorField`
872
+ representing a fully covariant tensor field on `M` that is the
873
+ pullback of `T` by `\Phi`
874
+ - (if the input is a manifold subset `S`)
875
+ a :class:`~sage.manifolds.subset.ManifoldSubset` that is the
876
+ preimage `\Phi^{-1}(S)`; same as :meth:`preimage`
877
+
878
+ EXAMPLES:
879
+
880
+ Pullback on `S^2` of a scalar field defined on `R^3`::
881
+
882
+ sage: M = Manifold(2, 'S^2', start_index=1)
883
+ sage: U = M.open_subset('U') # the complement of a meridian (domain of spherical coordinates)
884
+ sage: c_spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') # spherical coord. on U
885
+ sage: N = Manifold(3, 'R^3', r'\RR^3', start_index=1)
886
+ sage: c_cart.<x,y,z> = N.chart() # Cartesian coord. on R^3
887
+ sage: Phi = U.diff_map(N, (sin(th)*cos(ph), sin(th)*sin(ph), cos(th)),
888
+ ....: name='Phi', latex_name=r'\Phi')
889
+ sage: f = N.scalar_field(x*y*z, name='f') ; f
890
+ Scalar field f on the 3-dimensional differentiable manifold R^3
891
+ sage: f.display()
892
+ f: R^3 → ℝ
893
+ (x, y, z) ↦ x*y*z
894
+ sage: pf = Phi.pullback(f) ; pf
895
+ Scalar field Phi^*(f) on the Open subset U of the 2-dimensional
896
+ differentiable manifold S^2
897
+ sage: pf.display()
898
+ Phi^*(f): U → ℝ
899
+ (th, ph) ↦ cos(ph)*cos(th)*sin(ph)*sin(th)^2
900
+
901
+ Pullback on `S^2` of the standard Euclidean metric on `R^3`::
902
+
903
+ sage: g = N.sym_bilin_form_field(name='g')
904
+ sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1
905
+ sage: g.display()
906
+ g = dx⊗dx + dy⊗dy + dz⊗dz
907
+ sage: pg = Phi.pullback(g) ; pg
908
+ Field of symmetric bilinear forms Phi^*(g) on the Open subset U of
909
+ the 2-dimensional differentiable manifold S^2
910
+ sage: pg.display()
911
+ Phi^*(g) = dth⊗dth + sin(th)^2 dph⊗dph
912
+
913
+ Parallel computation::
914
+
915
+ sage: Parallelism().set('tensor', nproc=2)
916
+ sage: pg = Phi.pullback(g) ; pg
917
+ Field of symmetric bilinear forms Phi^*(g) on the Open subset U of
918
+ the 2-dimensional differentiable manifold S^2
919
+ sage: pg.display()
920
+ Phi^*(g) = dth⊗dth + sin(th)^2 dph⊗dph
921
+ sage: Parallelism().set('tensor', nproc=1) # switch off parallelization
922
+
923
+
924
+ Pullback on `S^2` of a 3-form on `R^3`::
925
+
926
+ sage: a = N.diff_form(3, name='A')
927
+ sage: a[1,2,3] = f
928
+ sage: a.display()
929
+ A = x*y*z dx∧dy∧dz
930
+ sage: pa = Phi.pullback(a) ; pa
931
+ 3-form Phi^*(A) on the Open subset U of the 2-dimensional
932
+ differentiable manifold S^2
933
+ sage: pa.display() # should be zero (as any 3-form on a 2-dimensional manifold)
934
+ Phi^*(A) = 0
935
+
936
+ TESTS:
937
+
938
+ Check that :issue:`31904` is fixed::
939
+
940
+ sage: E.<x,y> = EuclideanSpace()
941
+ sage: polar.<r,ph> = E.polar_coordinates()
942
+ sage: g = E.metric()
943
+ sage: M = Manifold(1, 'M')
944
+ sage: Ct.<t> = M.chart()
945
+ sage: F = M.diff_map(E, coord_functions={(Ct, polar): (1 + cos(t), t)})
946
+ sage: gM = F.pullback(g)
947
+ sage: gM.display()
948
+ (2*cos(t) + 2) dt⊗dt
949
+ """
950
+ if not hasattr(tensor_or_codomain_subset, '_domain'):
951
+ return super().pullback(tensor_or_codomain_subset,
952
+ name=name, latex_name=latex_name)
953
+ tensor = tensor_or_codomain_subset
954
+
955
+ from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
956
+ from sage.tensor.modules.comp import (
957
+ CompFullyAntiSym,
958
+ CompFullySym,
959
+ Components,
960
+ CompWithSym,
961
+ )
962
+
963
+ def _pullback_chart(diff_map, tensor, chart1, chart2):
964
+ r"""
965
+ Helper function performing the pullback on chart domains
966
+ only.
967
+
968
+ INPUT:
969
+
970
+ - ``diff_map`` -- a restriction of ``self``, whose both
971
+ domain and codomain are chart domains, corresponding
972
+ respectively to ``chart1`` and ``chart2``
973
+ - ``tensor`` -- a covariant tensor field, whose domain is
974
+ the codomain of ``diff_map`` and whose components are known
975
+ in ``chart2.frame()``
976
+ - ``chart1`` -- chart on the domain of ``diff_map``
977
+ - ``chart2`` -- chart on the codomain of ``diff_map``
978
+
979
+ OUTPUT: the pull back of ``tensor`` by ``diff_map``
980
+ """
981
+ dom1 = diff_map._domain
982
+ dom2 = diff_map._codomain
983
+ ncov = tensor._tensor_type[1]
984
+ resu_name = None
985
+ resu_latex_name = None
986
+ if diff_map._name is not None and tensor._name is not None:
987
+ resu_name = diff_map._name + '^*(' + tensor._name + ')'
988
+ if (diff_map._latex_name is not None and
989
+ tensor._latex_name is not None):
990
+ resu_latex_name = '{' + diff_map._latex_name + '}^*' \
991
+ + tensor._latex_name
992
+ fmodule1 = dom1.vector_field_module()
993
+ ring1 = fmodule1._ring
994
+ si1 = fmodule1._sindex
995
+ of1 = fmodule1._output_formatter
996
+ si2 = dom2._sindex
997
+ resu = fmodule1.tensor((0, ncov), name=resu_name,
998
+ latex_name=resu_latex_name, sym=tensor._sym,
999
+ antisym=tensor._antisym)
1000
+
1001
+ nproc = Parallelism().get('tensor')
1002
+ ind_old_list = list(dom2.manifold().index_generator(ncov))
1003
+
1004
+ frame1 = chart1.frame()
1005
+ frame2 = chart2.frame()
1006
+
1007
+ tcomp = tensor._components[frame2]
1008
+ if isinstance(tcomp, CompFullySym):
1009
+ ptcomp = CompFullySym(ring1, frame1, ncov, start_index=si1,
1010
+ output_formatter=of1)
1011
+ elif isinstance(tcomp, CompFullyAntiSym):
1012
+ ptcomp = CompFullyAntiSym(ring1, frame1, ncov, start_index=si1,
1013
+ output_formatter=of1)
1014
+ elif isinstance(tcomp, CompWithSym):
1015
+ ptcomp = CompWithSym(ring1, frame1, ncov, start_index=si1,
1016
+ output_formatter=of1, sym=tcomp.sym,
1017
+ antisym=tcomp.antisym)
1018
+ else:
1019
+ ptcomp = Components(ring1, frame1, ncov, start_index=si1,
1020
+ output_formatter=of1)
1021
+ phi = diff_map._coord_expression[(chart1, chart2)]
1022
+ jacob = phi.jacobian()
1023
+ # X2 coordinates expressed in terms of X1 ones via the diff. map:
1024
+ coord2_1 = phi(*(chart1._xx))
1025
+
1026
+ if nproc != 1:
1027
+ # Parallel computation
1028
+ lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)]
1029
+ ind_list = list(ptcomp.non_redundant_index_generator())
1030
+ ind_step = max(1, (len(ind_list) // nproc) // 2)
1031
+ local_list = lol(ind_list, ind_step)
1032
+ # list of input parameters
1033
+ listParalInput = [(tcomp, chart1, chart2, coord2_1, jacob,
1034
+ ind_old_list, si1, si2, ncov, ind_part)
1035
+ for ind_part in local_list]
1036
+
1037
+ @parallel(p_iter='multiprocessing', ncpus=nproc)
1038
+ def paral_comp(tcomp, chart1, chart2, coord2_1, jacob,
1039
+ ind_old_list, si1, si2, ncov, local_list_ind):
1040
+ partial = []
1041
+ for ind_new in local_list_ind:
1042
+ res = 0
1043
+ for ind_old in ind_old_list:
1044
+ ff = tcomp[[ind_old]].coord_function(chart2)
1045
+ t = chart1.function(ff(*coord2_1))
1046
+ for i in range(ncov):
1047
+ t *= jacob[ind_old[i]-si2, ind_new[i]-si1]
1048
+ res += t
1049
+ partial.append([ind_new, res])
1050
+ return partial
1051
+
1052
+ for ii, val in paral_comp(listParalInput):
1053
+ for jj in val:
1054
+ ptcomp[[jj[0]]] = jj[1]
1055
+
1056
+ else:
1057
+ # Sequential computation
1058
+ for ind_new in ptcomp.non_redundant_index_generator():
1059
+ res = 0
1060
+ for ind_old in ind_old_list:
1061
+ ff = tcomp[[ind_old]].coord_function(chart2)
1062
+ t = chart1.function(ff(*coord2_1))
1063
+ for i in range(ncov):
1064
+ t *= jacob[ind_old[i]-si2, ind_new[i]-si1]
1065
+ res += t
1066
+ ptcomp[ind_new] = res
1067
+
1068
+ resu._components[frame1] = ptcomp
1069
+ return resu
1070
+ # End of function _pullback_chart
1071
+
1072
+ # Special case of the identity map:
1073
+ if self._is_identity:
1074
+ return tensor # no test for efficiency
1075
+ # Generic case:
1076
+ dom1 = self._domain
1077
+ dom2 = self._codomain
1078
+ tdom = tensor._domain
1079
+ if not tdom.is_subset(dom2):
1080
+ raise ValueError("the tensor field is not defined on the map codomain")
1081
+ (ncon, ncov) = tensor._tensor_type
1082
+ if ncon != 0:
1083
+ raise TypeError("the pullback cannot be taken on a tensor " +
1084
+ "with some contravariant part")
1085
+ resu_name = None
1086
+ resu_latex_name = None
1087
+ if self._name is not None and tensor._name is not None:
1088
+ resu_name = self._name + '^*(' + tensor._name + ')'
1089
+ if self._latex_name is not None and tensor._latex_name is not None:
1090
+ resu_latex_name = '{' + self._latex_name + '}^*' \
1091
+ + tensor._latex_name
1092
+ if ncov == 0:
1093
+ # Case of a scalar field
1094
+ resu_fc = []
1095
+ for chart2 in tensor._express:
1096
+ for chart1 in dom1._atlas:
1097
+ if (chart1, chart2) in self._coord_expression:
1098
+ phi = self._coord_expression[(chart1, chart2)]
1099
+ coord1 = chart1._xx
1100
+ ff = tensor._express[chart2]
1101
+ resu_fc.append( chart1.function(ff(*(phi(*coord1)))) )
1102
+ dom_resu = resu_fc[0].parent()._chart.domain()
1103
+ for fc in resu_fc[1:]:
1104
+ dom_resu = dom_resu.union(fc.parent()._chart.domain())
1105
+ resu = dom_resu.scalar_field(name=resu_name,
1106
+ latex_name=resu_latex_name)
1107
+ for fc in resu_fc:
1108
+ resu._express[fc.parent()._chart] = fc
1109
+ else:
1110
+ # Case of tensor field of rank >= 1
1111
+ if tensor._vmodule._dest_map is not tdom.identity_map():
1112
+ raise TypeError("the pullback is defined only for tensor " +
1113
+ "fields on {}".format(dom2))
1114
+ resu_rst = []
1115
+ for chart_pair in self._coord_expression:
1116
+ chart1 = chart_pair[0]
1117
+ chart2 = chart_pair[1]
1118
+ ch2dom = chart2._domain
1119
+ if ch2dom.is_subset(tdom):
1120
+ self_r = self.restrict(chart1._domain, subcodomain=ch2dom)
1121
+ tensor_r = tensor.restrict(ch2dom)
1122
+ if chart2.frame() in tensor_r._components:
1123
+ resu_rst.append(_pullback_chart(self_r, tensor_r,
1124
+ chart1, chart2))
1125
+ dom_resu = resu_rst[0]._domain
1126
+ for rst in resu_rst[1:]:
1127
+ dom_resu = dom_resu.union(rst._domain)
1128
+ resu = dom_resu.tensor_field(0, ncov, name=resu_name,
1129
+ latex_name=resu_latex_name,
1130
+ sym=resu_rst[0]._sym,
1131
+ antisym=resu_rst[0]._antisym)
1132
+ for rst in resu_rst:
1133
+ if rst._domain is not resu._domain:
1134
+ resu._restrictions[rst._domain] = rst
1135
+ if isinstance(resu, TensorFieldParal):
1136
+ for rst in resu_rst:
1137
+ if rst._domain is resu._domain:
1138
+ for frame, comp in rst._components.items():
1139
+ resu._components[frame] = comp
1140
+ return resu
1141
+
1142
+ def pushforward(self, tensor):
1143
+ r"""
1144
+ Pushforward operator associated with ``self``.
1145
+
1146
+ In what follows, let `\Phi` denote the differentiable map, `M` its
1147
+ domain and `N` its codomain.
1148
+
1149
+ INPUT:
1150
+
1151
+ - ``tensor`` --
1152
+ :class:`~sage.manifolds.differentiable.tensorfield.TensorField`;
1153
+ a fully contrariant tensor field `T` on `M`, i.e. a tensor
1154
+ field of type `(p, 0)`, with `p` a positive integer
1155
+
1156
+ OUTPUT:
1157
+
1158
+ - a :class:`~sage.manifolds.differentiable.tensorfield.TensorField`
1159
+ representing a fully contravariant tensor field along `M` with
1160
+ values in `N`, which is the pushforward of `T` by `\Phi`
1161
+
1162
+ EXAMPLES:
1163
+
1164
+ Pushforward of a vector field on the 2-sphere `S^2` to the Euclidean
1165
+ 3-space `\RR^3`, via the standard embedding of `S^2`::
1166
+
1167
+ sage: S2 = Manifold(2, 'S^2', start_index=1)
1168
+ sage: U = S2.open_subset('U') # domain of spherical coordinates
1169
+ sage: spher.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
1170
+ sage: R3 = Manifold(3, 'R^3', start_index=1)
1171
+ sage: cart.<x,y,z> = R3.chart()
1172
+ sage: Phi = U.diff_map(R3, {(spher, cart): [sin(th)*cos(ph),
1173
+ ....: sin(th)*sin(ph), cos(th)]}, name='Phi', latex_name=r'\Phi')
1174
+ sage: v = U.vector_field(name='v')
1175
+ sage: v[:] = 0, 1
1176
+ sage: v.display()
1177
+ v = ∂/∂ph
1178
+ sage: pv = Phi.pushforward(v); pv
1179
+ Vector field Phi_*(v) along the Open subset U of the 2-dimensional
1180
+ differentiable manifold S^2 with values on the 3-dimensional
1181
+ differentiable manifold R^3
1182
+ sage: pv.display()
1183
+ Phi_*(v) = -sin(ph)*sin(th) ∂/∂x + cos(ph)*sin(th) ∂/∂y
1184
+
1185
+ Pushforward of a vector field on the real line to the `\RR^3`, via a
1186
+ helix embedding::
1187
+
1188
+ sage: R.<t> = manifolds.RealLine()
1189
+ sage: Psi = R.diff_map(R3, [cos(t), sin(t), t], name='Psi',
1190
+ ....: latex_name=r'\Psi')
1191
+ sage: u = R.vector_field(name='u')
1192
+ sage: u[0] = 1
1193
+ sage: u.display()
1194
+ u = ∂/∂t
1195
+ sage: pu = Psi.pushforward(u); pu
1196
+ Vector field Psi_*(u) along the Real number line ℝ with values on
1197
+ the 3-dimensional differentiable manifold R^3
1198
+ sage: pu.display()
1199
+ Psi_*(u) = -sin(t) ∂/∂x + cos(t) ∂/∂y + ∂/∂z
1200
+ """
1201
+ from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
1202
+ from sage.tensor.modules.comp import (
1203
+ CompFullyAntiSym,
1204
+ CompFullySym,
1205
+ Components,
1206
+ CompWithSym,
1207
+ )
1208
+ vmodule = tensor.base_module()
1209
+ dest_map = vmodule.destination_map()
1210
+ dom1 = tensor.domain()
1211
+ ambient_dom1 = dest_map.codomain()
1212
+ if not ambient_dom1.is_subset(self._domain):
1213
+ raise ValueError("the {} does not take its ".format(tensor) +
1214
+ "values on the domain of the {}".format(self))
1215
+ (ncon, ncov) = tensor.tensor_type()
1216
+ if ncov != 0:
1217
+ raise ValueError("the pushforward cannot be taken on a tensor " +
1218
+ "with some covariant part")
1219
+ if ncon == 0:
1220
+ raise ValueError("the pushforward cannot be taken on a scalar " +
1221
+ "field")
1222
+ if dest_map != dom1.identity_map():
1223
+ raise NotImplementedError("the case of a non-trivial destination" +
1224
+ " map is not implemented yet")
1225
+ if not isinstance(tensor, TensorFieldParal):
1226
+ raise NotImplementedError("the case of a non-parallelizable " +
1227
+ "domain is not implemented yet")
1228
+ # A pair of charts (chart1, chart2) where the computation
1229
+ # is feasible is searched, privileging the default chart of the
1230
+ # map's domain for chart1
1231
+ chart1 = None
1232
+ chart2 = None
1233
+ def_chart1 = dom1.default_chart()
1234
+ def_chart2 = self._codomain.default_chart()
1235
+ if (def_chart1._frame in tensor._components
1236
+ and (def_chart1, def_chart2) in self._coord_expression):
1237
+ chart1 = def_chart1
1238
+ chart2 = def_chart2
1239
+ else:
1240
+ for (chart1n, chart2n) in self._coord_expression:
1241
+ if (chart2n == def_chart2
1242
+ and chart1n._frame in tensor._components):
1243
+ chart1 = chart1n
1244
+ chart2 = def_chart2
1245
+ break
1246
+ if chart2 is None:
1247
+ # It is not possible to have def_chart2 as chart for
1248
+ # expressing the result; any other chart is then looked for:
1249
+ for (chart1n, chart2n) in self._coord_expression:
1250
+ if chart1n._frame in tensor._components:
1251
+ chart1 = chart1n
1252
+ chart2 = chart2n
1253
+ break
1254
+ if chart1 is None:
1255
+ # Computations of components are attempted
1256
+ chart1 = dom1.default_chart()
1257
+ tensor.comp(chart1.frame())
1258
+ for chart2n in self._codomain.atlas():
1259
+ try:
1260
+ self.coord_functions(chart1, chart2n)
1261
+ chart2 = chart2n
1262
+ break
1263
+ except ValueError:
1264
+ pass
1265
+ else:
1266
+ raise ValueError("no pair of charts could be found to " +
1267
+ "compute the pushforward of " +
1268
+ "the {} by the {}".format(tensor, self))
1269
+ # Vector field module for the result:
1270
+ fmodule2 = dom1.vector_field_module(dest_map=self)
1271
+
1272
+ frame2 = fmodule2.basis(from_frame=chart2.frame())
1273
+ si1 = dom1.start_index()
1274
+ si2 = fmodule2._sindex
1275
+ ring2 = fmodule2._ring
1276
+ of2 = fmodule2._output_formatter
1277
+ # Computation at the component level:
1278
+ tcomp = tensor._components[chart1.frame()]
1279
+ # Construction of the pushforward components (ptcomp):
1280
+ if isinstance(tcomp, CompFullySym):
1281
+ ptcomp = CompFullySym(ring2, frame2, ncon, start_index=si2,
1282
+ output_formatter=of2)
1283
+ elif isinstance(tcomp, CompFullyAntiSym):
1284
+ ptcomp = CompFullyAntiSym(ring2, frame2, ncon, start_index=si2,
1285
+ output_formatter=of2)
1286
+ elif isinstance(tcomp, CompWithSym):
1287
+ ptcomp = CompWithSym(ring2, frame2, ncon, start_index=si2,
1288
+ output_formatter=of2, sym=tcomp._sym,
1289
+ antisym=tcomp._antisym)
1290
+ else:
1291
+ ptcomp = Components(ring2, frame2, ncon, start_index=si2,
1292
+ output_formatter=of2)
1293
+ # Computation of the pushforward components:
1294
+ jacob = self.differential_functions(chart1=chart1, chart2=chart2)
1295
+ si2 = chart2.domain().start_index()
1296
+ for ind_new in ptcomp.non_redundant_index_generator():
1297
+ res = 0
1298
+ for ind_old in dom1.index_generator(ncon):
1299
+ t = tcomp[[ind_old]].coord_function(chart1)
1300
+ for i in range(ncon):
1301
+ t *= jacob[ind_new[i]-si2, ind_old[i]-si1]
1302
+ res += t
1303
+ ptcomp[ind_new] = res
1304
+ # Name of the result:
1305
+ resu_name = None
1306
+ resu_latex_name = None
1307
+ if self._name is not None and tensor._name is not None:
1308
+ resu_name = self._name + '_*(' + tensor._name + ')'
1309
+ if self._latex_name is not None and tensor._latex_name is not None:
1310
+ resu_latex_name = '{' + self._latex_name + '}_*' \
1311
+ + tensor._latex_name
1312
+ # Creation of the result with the components obtained above:
1313
+ resu = fmodule2.tensor_from_comp((ncon, 0), ptcomp, name=resu_name,
1314
+ latex_name=resu_latex_name)
1315
+ return resu