passagemath-symbolics 10.6.43__cp314-cp314t-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-symbolics might be problematic. Click here for more details.

Files changed (171) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.6.43.dist-info/METADATA +187 -0
  3. passagemath_symbolics-10.6.43.dist-info/RECORD +171 -0
  4. passagemath_symbolics-10.6.43.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.6.43.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 +2826 -0
  9. sage/calculus/desolvers.py +1866 -0
  10. sage/calculus/predefined.py +51 -0
  11. sage/calculus/tests.py +225 -0
  12. sage/calculus/var.cpython-314t-x86_64-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-x86_64-linux-musl.so +0 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -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 +743 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -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 +3017 -0
  44. sage/interfaces/magma_free.py +92 -0
  45. sage/interfaces/maple.py +1397 -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 +555 -0
  54. sage/manifolds/catalog.py +437 -0
  55. sage/manifolds/chart.py +4019 -0
  56. sage/manifolds/chart_func.py +3419 -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 +1671 -0
  70. sage/manifolds/differentiable/diff_form.py +1658 -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 +1520 -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 +910 -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 +1728 -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 +2764 -0
  118. sage/manifolds/subsets/all.py +1 -0
  119. sage/manifolds/subsets/closure.py +131 -0
  120. sage/manifolds/subsets/pullback.py +885 -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 +1342 -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-x86_64-linux-musl.so +0 -0
  129. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  130. sage/matrix/matrix_symbolic_dense.pyx +1022 -0
  131. sage/matrix/matrix_symbolic_sparse.cpython-314t-x86_64-linux-musl.so +0 -0
  132. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  133. sage/matrix/matrix_symbolic_sparse.pyx +1029 -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 +4153 -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 +5237 -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 +985 -0
  150. sage/symbolic/benchmark.py +93 -0
  151. sage/symbolic/callable.py +459 -0
  152. sage/symbolic/complexity_measures.py +35 -0
  153. sage/symbolic/constants.py +1287 -0
  154. sage/symbolic/expression_conversion_algebraic.py +310 -0
  155. sage/symbolic/expression_conversion_sympy.py +317 -0
  156. sage/symbolic/expression_conversions.py +1713 -0
  157. sage/symbolic/function_factory.py +355 -0
  158. sage/symbolic/integration/all.py +1 -0
  159. sage/symbolic/integration/external.py +270 -0
  160. sage/symbolic/integration/integral.py +1115 -0
  161. sage/symbolic/maxima_wrapper.py +162 -0
  162. sage/symbolic/operators.py +267 -0
  163. sage/symbolic/random_tests.py +462 -0
  164. sage/symbolic/relation.py +1907 -0
  165. sage/symbolic/ring.cpython-314t-x86_64-linux-musl.so +0 -0
  166. sage/symbolic/ring.pxd +5 -0
  167. sage/symbolic/ring.pyx +1396 -0
  168. sage/symbolic/subring.py +1025 -0
  169. sage/symbolic/symengine.py +19 -0
  170. sage/symbolic/tests.py +40 -0
  171. sage/symbolic/units.py +1470 -0
@@ -0,0 +1,1186 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Spheres smoothly embedded in Euclidean Space
4
+
5
+ Let `E^{n+1}` be a Euclidean space of dimension `n+1` and `c \in E^{n+1}`. An
6
+ `n`-sphere with radius `r` and centered at `c`, usually denoted by
7
+ `\mathbb{S}^n_r(c)`, smoothly embedded in the Euclidean space `E^{n+1}` is an
8
+ `n`-dimensional smooth manifold together with a smooth embedding
9
+
10
+ .. MATH::
11
+
12
+ \iota \colon \mathbb{S}^n_r \to E^{n+1}
13
+
14
+ whose image consists of all points having the same Euclidean distance to the
15
+ fixed point `c`. If we choose Cartesian coordinates `(x_1, \ldots, x_{n+1})` on
16
+ `E^{n+1}` with `x(c)=0` then the above translates to
17
+
18
+ .. MATH::
19
+
20
+ \iota(\mathbb{S}^n_r(c)) = \left\{ p \in E^{n+1} : \lVert x(p) \rVert = r \right\}.
21
+
22
+ This corresponds to the standard `n`-sphere of radius `r` centered at `c`.
23
+
24
+ AUTHORS:
25
+
26
+ - Michael Jung (2020): initial version
27
+
28
+ REFERENCES:
29
+
30
+ - \M. Berger: *Geometry I&II* [Ber1987]_, [Ber1987a]_
31
+ - \J. Lee: *Introduction to Smooth Manifolds* [Lee2013]_
32
+
33
+ EXAMPLES:
34
+
35
+ We start by defining a 2-sphere of unspecified radius `r`::
36
+
37
+ sage: r = var('r')
38
+ sage: S2_r = manifolds.Sphere(2, radius=r); S2_r
39
+ 2-sphere S^2_r of radius r smoothly embedded in the Euclidean space E^3
40
+
41
+ The embedding `\iota` is constructed from scratch and can be returned by the
42
+ following command::
43
+
44
+ sage: i = S2_r.embedding(); i
45
+ Differentiable map iota from the 2-sphere S^2_r of radius r smoothly
46
+ embedded in the Euclidean space E^3 to the Euclidean space E^3
47
+ sage: i.display()
48
+ iota: S^2_r → E^3
49
+ on A: (theta, phi) ↦ (x, y, z) = (r*cos(phi)*sin(theta),
50
+ r*sin(phi)*sin(theta),
51
+ r*cos(theta))
52
+
53
+ As a submanifold of a Riemannian manifold, namely the Euclidean space,
54
+ the 2-sphere admits an induced metric::
55
+
56
+ sage: g = S2_r.induced_metric()
57
+ sage: g.display()
58
+ g = r^2 dtheta⊗dtheta + r^2*sin(theta)^2 dphi⊗dphi
59
+
60
+ The induced metric is also known as the *first fundamental form* (see
61
+ :meth:`~sage.manifolds.differentiable.pseudo_riemannian_submanifold.PseudoRiemannianSubmanifold.first_fundamental_form`)::
62
+
63
+ sage: g is S2_r.first_fundamental_form()
64
+ True
65
+
66
+ The *second fundamental form* encodes the extrinsic curvature of the
67
+ 2-sphere as hypersurface of Euclidean space (see
68
+ :meth:`~sage.manifolds.differentiable.pseudo_riemannian_submanifold.PseudoRiemannianSubmanifold.second_fundamental_form`)::
69
+
70
+ sage: K = S2_r.second_fundamental_form(); K
71
+ Field of symmetric bilinear forms K on the 2-sphere S^2_r of radius r
72
+ smoothly embedded in the Euclidean space E^3
73
+ sage: K.display()
74
+ K = r dtheta⊗dtheta + r*sin(theta)^2 dphi⊗dphi
75
+
76
+ One quantity that can be derived from the second fundamental form is the
77
+ Gaussian curvature::
78
+
79
+ sage: K = S2_r.gauss_curvature()
80
+ sage: K.display()
81
+ S^2_r → ℝ
82
+ on A: (theta, phi) ↦ r^(-2)
83
+
84
+ As we have seen, spherical coordinates are initialized by default. To
85
+ initialize stereographic coordinates retrospectively, we can use the following
86
+ command::
87
+
88
+ sage: S2_r.stereographic_coordinates()
89
+ Chart (S^2_r-{NP}, (y1, y2))
90
+
91
+ To get all charts corresponding to stereographic coordinates, we can use the
92
+ :meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.coordinate_charts`::
93
+
94
+ sage: stereoN, stereoS = S2_r.coordinate_charts('stereographic')
95
+ sage: stereoN, stereoS
96
+ (Chart (S^2_r-{NP}, (y1, y2)), Chart (S^2_r-{SP}, (yp1, yp2)))
97
+
98
+ .. SEEALSO::
99
+
100
+ See :meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.stereographic_coordinates`
101
+ and :meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.spherical_coordinates`
102
+ for details.
103
+
104
+ .. NOTE::
105
+
106
+ Notice that the derived quantities such as the embedding as well as the
107
+ first and second fundamental forms must be computed from scratch again
108
+ when new coordinates have been initialized. That makes the usage of
109
+ previously declared objects obsolete.
110
+
111
+ Consider now a 1-sphere with barycenter `(1,0)` in Cartesian coordinates::
112
+
113
+ sage: E2 = EuclideanSpace(2)
114
+ sage: c = E2.point((1,0), name='c')
115
+ sage: S1c.<chi> = E2.sphere(center=c); S1c
116
+ 1-sphere S^1(c) of radius 1 smoothly embedded in the Euclidean plane
117
+ E^2 centered at the Point c
118
+ sage: S1c.spherical_coordinates()
119
+ Chart (A, (chi,))
120
+
121
+ Get stereographic coordinates::
122
+
123
+ sage: stereoN, stereoS = S1c.coordinate_charts('stereographic')
124
+ sage: stereoN, stereoS
125
+ (Chart (S^1(c)-{NP}, (y1,)), Chart (S^1(c)-{SP}, (yp1,)))
126
+
127
+ The embedding takes now the following form in all coordinates::
128
+
129
+ sage: S1c.embedding().display()
130
+ iota: S^1(c) → E^2
131
+ on A: chi ↦ (x, y) = (cos(chi) + 1, sin(chi))
132
+ on S^1(c)-{NP}: y1 ↦ (x, y) = (2*y1/(y1^2 + 1) + 1, (y1^2 - 1)/(y1^2 + 1))
133
+ on S^1(c)-{SP}: yp1 ↦ (x, y) = (2*yp1/(yp1^2 + 1) + 1, -(yp1^2 - 1)/(yp1^2 + 1))
134
+
135
+ Since the sphere is a hypersurface, we can get a normal vector field by using
136
+ ``normal``::
137
+
138
+ sage: n = S1c.normal(); n
139
+ Vector field n along the 1-sphere S^1(c) of radius 1 smoothly embedded in
140
+ the Euclidean plane E^2 centered at the Point c with values on the
141
+ Euclidean plane E^2
142
+ sage: n.display()
143
+ n = -cos(chi) e_x - sin(chi) e_y
144
+
145
+ Notice that this is just *one* normal field with arbitrary direction,
146
+ in this particular case `n` points inwards whereas `-n` points outwards.
147
+ However, the vector field `n` is indeed non-vanishing and hence the sphere
148
+ admits an orientation (as all spheres do)::
149
+
150
+ sage: orient = S1c.orientation(); orient
151
+ [Coordinate frame (S^1(c)-{SP}, (∂/∂yp1)), Vector frame (S^1(c)-{NP}, (f_1))]
152
+ sage: f = orient[1]
153
+ sage: f[1].display()
154
+ f_1 = -∂/∂y1
155
+
156
+ Notice that the orientation is chosen is such a way that `(\iota_*(f_1), -n)`
157
+ is oriented in the ambient Euclidean space, i.e. the last entry is the normal
158
+ vector field pointing outwards. Henceforth, the manifold admits
159
+ a volume form::
160
+
161
+ sage: g = S1c.induced_metric()
162
+ sage: g.display()
163
+ g = dchi⊗dchi
164
+ sage: eps = g.volume_form()
165
+ sage: eps.display()
166
+ eps_g = -dchi
167
+ """
168
+
169
+ from sage.categories.manifolds import Manifolds
170
+ from sage.categories.metric_spaces import MetricSpaces
171
+ from sage.categories.topological_spaces import TopologicalSpaces
172
+ from sage.manifolds.differentiable.examples.euclidean import EuclideanSpace
173
+ from sage.manifolds.differentiable.pseudo_riemannian_submanifold import (
174
+ PseudoRiemannianSubmanifold,
175
+ )
176
+ from sage.rings.real_mpfr import RR
177
+
178
+
179
+ class Sphere(PseudoRiemannianSubmanifold):
180
+ r"""
181
+ Sphere smoothly embedded in Euclidean Space.
182
+
183
+ An `n`-sphere of radius `r`smoothly embedded in a Euclidean space `E^{n+1}`
184
+ is a smooth `n`-dimensional manifold smoothly embedded into `E^{n+1}`,
185
+ such that the embedding constitutes a standard `n`-sphere of radius `r`
186
+ in that Euclidean space (possibly shifted by a point).
187
+
188
+ - ``n`` -- positive integer representing dimension of the sphere
189
+ - ``radius`` -- (default: ``1``) positive number that states the radius
190
+ of the sphere
191
+ - ``name`` -- (default: ``None``) string; name (symbol) given to the
192
+ sphere; if ``None``, the name will be set according to the input
193
+ (see convention above)
194
+ - ``ambient_space`` -- (default: ``None``) Euclidean space in which the
195
+ sphere should be embedded; if ``None``, a new instance of Euclidean
196
+ space is created
197
+ - ``center`` -- (default: ``None``) the barycenter of the sphere as point of
198
+ the ambient Euclidean space; if ``None`` the barycenter is set to the
199
+ origin of the ambient space's standard Cartesian coordinates
200
+ - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to
201
+ denote the space; if ``None``, it will be set according to the input
202
+ (see convention above)
203
+ - ``coordinates`` -- (default: ``'spherical'``) string describing the
204
+ type of coordinates to be initialized at the sphere's creation; allowed
205
+ values are
206
+
207
+ - ``'spherical'`` spherical coordinates (see
208
+ :meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.spherical_coordinates`))
209
+ - ``'stereographic'`` stereographic coordinates given by the
210
+ stereographic projection (see
211
+ :meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.stereographic_coordinates`)
212
+
213
+ - ``names`` -- (default: ``None``) must be a tuple containing
214
+ the coordinate symbols (this guarantees the shortcut operator
215
+ ``<,>`` to function); if ``None``, the usual conventions are used (see
216
+ examples below for details)
217
+ - ``unique_tag`` -- (default: ``None``) tag used to force the construction
218
+ of a new object when all the other arguments have been used previously
219
+ (without ``unique_tag``, the
220
+ :class:`~sage.structure.unique_representation.UniqueRepresentation`
221
+ behavior inherited from
222
+ :class:`~sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold`
223
+ would return the previously constructed object corresponding to these
224
+ arguments)
225
+
226
+ EXAMPLES:
227
+
228
+ A 2-sphere embedded in Euclidean space::
229
+
230
+ sage: S2 = manifolds.Sphere(2); S2
231
+ 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3
232
+ sage: latex(S2)
233
+ \mathbb{S}^{2}
234
+
235
+ The ambient Euclidean space is constructed incidentally::
236
+
237
+ sage: S2.ambient()
238
+ Euclidean space E^3
239
+
240
+ Another call creates another sphere and hence another Euclidean space::
241
+
242
+ sage: S2 is manifolds.Sphere(2)
243
+ False
244
+ sage: S2.ambient() is manifolds.Sphere(2).ambient()
245
+ False
246
+
247
+ By default, the barycenter is set to the coordinate origin of the
248
+ standard Cartesian coordinates in the ambient Euclidean space::
249
+
250
+ sage: c = S2.center(); c
251
+ Point on the Euclidean space E^3
252
+ sage: c.coord()
253
+ (0, 0, 0)
254
+
255
+ Each `n`-sphere is a compact manifold and a complete metric space::
256
+
257
+ sage: S2.category()
258
+ Join of Category of compact topological spaces and Category of smooth
259
+ manifolds over Real Field with 53 bits of precision and Category of
260
+ connected manifolds over Real Field with 53 bits of precision and
261
+ Category of complete metric spaces
262
+
263
+ If not stated otherwise, each `n`-sphere is automatically endowed with
264
+ spherical coordinates::
265
+
266
+ sage: S2.atlas()
267
+ [Chart (A, (theta, phi))]
268
+ sage: S2.default_chart()
269
+ Chart (A, (theta, phi))
270
+ sage: spher = S2.spherical_coordinates()
271
+ sage: spher is S2.default_chart()
272
+ True
273
+
274
+ Notice that the spherical coordinates do not cover the whole sphere. To
275
+ cover the entire sphere with charts, use stereographic coordinates instead::
276
+
277
+ sage: stereoN, stereoS = S2.coordinate_charts('stereographic')
278
+ sage: stereoN, stereoS
279
+ (Chart (S^2-{NP}, (y1, y2)), Chart (S^2-{SP}, (yp1, yp2)))
280
+ sage: list(S2.open_covers())
281
+ [Set {S^2} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3,
282
+ Set {S^2-{NP}, S^2-{SP}} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3]
283
+
284
+ .. NOTE::
285
+
286
+ Keep in mind that the initialization process of stereographic
287
+ coordinates and their transition maps is computational complex in
288
+ higher dimensions. Henceforth, high computation times are expected with
289
+ increasing dimension.
290
+ """
291
+ @staticmethod
292
+ def __classcall_private__(cls, n=None, radius=1, ambient_space=None,
293
+ center=None, name=None, latex_name=None,
294
+ coordinates='spherical', names=None,
295
+ unique_tag=None):
296
+ r"""
297
+ Determine the correct class to return based upon the input.
298
+
299
+ TESTS:
300
+
301
+ Each call gives a new instance::
302
+
303
+ sage: S2 = manifolds.Sphere(2)
304
+ sage: S2 is manifolds.Sphere(2)
305
+ False
306
+
307
+ The dimension can be determined using the ``<...>`` operator::
308
+
309
+ sage: S.<x,y> = manifolds.Sphere(coordinates='stereographic'); S
310
+ 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3
311
+ sage: S._first_ngens(2)
312
+ (x, y)
313
+ """
314
+ if n is None:
315
+ if names is None:
316
+ raise ValueError("either n or names must be specified")
317
+ n = len(names)
318
+
319
+ # Technical bit for UniqueRepresentation
320
+ from time import time
321
+
322
+ from sage.misc.prandom import getrandbits
323
+ if unique_tag is None:
324
+ unique_tag = getrandbits(128) * time()
325
+
326
+ return super().__classcall__(cls, n, radius=radius,
327
+ ambient_space=ambient_space,
328
+ center=center,
329
+ name=name, latex_name=latex_name,
330
+ coordinates=coordinates, names=names,
331
+ unique_tag=unique_tag)
332
+
333
+ def __init__(self, n, radius=1, ambient_space=None, center=None, name=None,
334
+ latex_name=None, coordinates='spherical', names=None,
335
+ category=None, init_coord_methods=None, unique_tag=None):
336
+ r"""
337
+ Construct sphere smoothly embedded in Euclidean space.
338
+
339
+ TESTS::
340
+
341
+ sage: S2 = manifolds.Sphere(2); S2
342
+ 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3
343
+ sage: S2.metric()
344
+ Riemannian metric g on the 2-sphere S^2 of radius 1 smoothly
345
+ embedded in the Euclidean space E^3
346
+ sage: TestSuite(S2).run()
347
+ """
348
+ # radius
349
+ if radius <= 0:
350
+ raise ValueError('radius must be greater than zero')
351
+ # ambient space
352
+ if ambient_space is None:
353
+ ambient_space = EuclideanSpace(n+1)
354
+ elif not isinstance(ambient_space, EuclideanSpace):
355
+ raise TypeError("the argument 'ambient_space' must be a Euclidean space")
356
+ elif ambient_space._dim != n+1:
357
+ raise ValueError("Euclidean space must have dimension {}".format(n+1))
358
+ if center is None:
359
+ cart = ambient_space.cartesian_coordinates()
360
+ c_coords = [0]*(n+1)
361
+ center = ambient_space.point(c_coords, chart=cart)
362
+ elif center not in ambient_space:
363
+ raise ValueError('{} must be an element of {}'.format(center, ambient_space))
364
+ if name is None:
365
+ name = 'S^{}'.format(n)
366
+ if radius != 1:
367
+ name += r'_{}'.format(radius)
368
+ if center._name:
369
+ name += r'({})'.format(center._name)
370
+ if latex_name is None:
371
+ latex_name = r'\mathbb{S}^{' + str(n) + r'}'
372
+ if radius != 1:
373
+ latex_name += r'_{{{}}}'.format(radius)
374
+ if center._latex_name:
375
+ latex_name += r'({})'.format(center._latex_name)
376
+ if category is None:
377
+ category = Manifolds(RR).Smooth() & MetricSpaces().Complete() & \
378
+ TopologicalSpaces().Compact().Connected()
379
+ # initialize
380
+ PseudoRiemannianSubmanifold.__init__(self, n, name,
381
+ ambient=ambient_space,
382
+ signature=n, latex_name=latex_name,
383
+ metric_name='g', start_index=1,
384
+ category=category)
385
+ # set attributes
386
+ self._radius = radius
387
+ self._center = center
388
+ self._coordinates = {} # established coordinates; values are lists
389
+ self._init_coordinates = {'spherical': self._init_spherical,
390
+ 'stereographic': self._init_stereographic}
391
+ # predefined coordinates
392
+ if init_coord_methods:
393
+ self._init_coordinates.update(init_coord_methods)
394
+ if coordinates not in self._init_coordinates:
395
+ raise ValueError('{} coordinates not available'.format(coordinates))
396
+ # up here, the actual initialization begins:
397
+ self._init_chart_domains()
398
+ self._init_embedding()
399
+ self._init_coordinates[coordinates](names)
400
+
401
+ def _init_embedding(self):
402
+ r"""
403
+ Initialize the embedding into Euclidean space.
404
+
405
+ TESTS::
406
+
407
+ sage: S2 = manifolds.Sphere(2)
408
+ sage: i = S2.embedding(); i
409
+ Differentiable map iota from the 2-sphere S^2 of radius 1 smoothly
410
+ embedded in the Euclidean space E^3 to the Euclidean space E^3
411
+ sage: i.display()
412
+ iota: S^2 → E^3
413
+ on A: (theta, phi) ↦ (x, y, z) = (cos(phi)*sin(theta),
414
+ sin(phi)*sin(theta), cos(theta))
415
+ """
416
+ name = 'iota'
417
+ latex_name = r'\iota'
418
+ iota = self.diff_map(self._ambient, name=name, latex_name=latex_name)
419
+ self.set_embedding(iota)
420
+
421
+ def _repr_(self):
422
+ r"""
423
+ Return a string representation of ``self``.
424
+
425
+ TESTS::
426
+
427
+ sage: S2_3 = manifolds.Sphere(2, radius=3)
428
+ sage: S2_3._repr_()
429
+ '2-sphere S^2_3 of radius 3 smoothly embedded in the Euclidean space E^3'
430
+ sage: S2_3 # indirect doctest
431
+ 2-sphere S^2_3 of radius 3 smoothly embedded in the Euclidean space E^3
432
+ """
433
+ s = "{}-sphere {} of radius {} smoothly embedded in " \
434
+ "the {}".format(self._dim, self._name, self._radius, self._ambient)
435
+ if self._center._name:
436
+ s += ' centered at the Point {}'.format(self._center._name)
437
+ return s
438
+
439
+ def coordinate_charts(self, coord_name, names=None):
440
+ r"""
441
+ Return a list of all charts belonging to the coordinates ``coord_name``.
442
+
443
+ INPUT:
444
+
445
+ - ``coord_name`` -- string describing the type of coordinates
446
+ - ``names`` -- (default: ``None``) must be a tuple containing
447
+ the coordinate symbols for the first chart in the list; if
448
+ ``None``, the standard convention is used
449
+
450
+ EXAMPLES:
451
+
452
+ Spherical coordinates on `S^1`::
453
+
454
+ sage: S1 = manifolds.Sphere(1)
455
+ sage: S1.coordinate_charts('spherical')
456
+ [Chart (A, (phi,))]
457
+
458
+ Stereographic coordinates on `S^1`::
459
+
460
+ sage: stereo_charts = S1.coordinate_charts('stereographic', names=['a'])
461
+ sage: stereo_charts
462
+ [Chart (S^1-{NP}, (a,)), Chart (S^1-{SP}, (ap,))]
463
+ """
464
+ if coord_name not in self._coordinates:
465
+ if coord_name not in self._init_coordinates:
466
+ raise ValueError('{} coordinates not available'.format(coord_name))
467
+ self._init_coordinates[coord_name](names)
468
+ return list(self._coordinates[coord_name])
469
+
470
+ def _first_ngens(self, n):
471
+ r"""
472
+ Return the list of coordinates of the default chart.
473
+
474
+ This is useful only for the use of Sage preparser::
475
+
476
+ sage: preparse("S3.<x,y,z> = manifolds.Sphere(coordinates='stereographic')")
477
+ "S3 = manifolds.Sphere(coordinates='stereographic', names=('x', 'y', 'z',));
478
+ (x, y, z,) = S3._first_ngens(3)"
479
+
480
+ TESTS::
481
+
482
+ sage: S2 = manifolds.Sphere(2)
483
+ sage: S2._first_ngens(2)
484
+ (theta, phi)
485
+ sage: S2.<u,v> = manifolds.Sphere(2)
486
+ sage: S2._first_ngens(2)
487
+ (u, v)
488
+ """
489
+ return self._def_chart[:]
490
+
491
+ def _init_chart_domains(self):
492
+ r"""
493
+ Construct the chart domains on ``self``.
494
+
495
+ TESTS::
496
+
497
+ sage: S2 = manifolds.Sphere(2)
498
+ sage: list(S2.open_covers())
499
+ [Set {S^2} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3,
500
+ Set {S^2-{NP}, S^2-{SP}} of open subsets of the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3]
501
+ sage: frozenset(S2.subsets()) # random
502
+ frozenset({Euclidean 2-sphere S^2 of radius 1,
503
+ Open subset A of the Euclidean 2-sphere S^2 of radius 1,
504
+ Open subset S^2-{NP,SP} of the Euclidean 2-sphere S^2 of radius 1,
505
+ Open subset S^2-{NP} of the Euclidean 2-sphere S^2 of radius 1,
506
+ Open subset S^2-{SP} of the Euclidean 2-sphere S^2 of radius 1})
507
+ """
508
+ # without north pole:
509
+ name = self._name + '-{NP}'
510
+ latex_name = self._latex_name + r'\setminus\{\mathrm{NP}\}'
511
+ self._stereoN_dom = self.open_subset(name, latex_name)
512
+ # without south pole:
513
+ name = self._name + '-{SP}'
514
+ latex_name = self._latex_name + r'\setminus\{\mathrm{SP}\}'
515
+ self._stereoS_dom = self.open_subset(name, latex_name)
516
+ # intersection:
517
+ int = self._stereoN_dom.intersection(self._stereoS_dom)
518
+ int._name = self._name + '-{NP,SP}'
519
+ int._latex_name = self._latex_name + \
520
+ r'\setminus\{\mathrm{NP}, \mathrm{SP}\}'
521
+ # without half circle:
522
+ self._spher_dom = int.open_subset('A')
523
+ # declare union:
524
+ self.declare_union(self._stereoN_dom, self._stereoS_dom)
525
+
526
+ def _shift_coords(self, coordfunc, s='+'):
527
+ r"""
528
+ Shift the coordinates ``coordfunc`` given in Cartesian coordinates to
529
+ the barycenter.
530
+
531
+ INPUT:
532
+
533
+ - ``coordfunc`` -- coordinate expression given in the standard
534
+ Cartesian coordinates of the ambient Euclidean space
535
+ - ``s`` -- either ``'+'`` or ``'-'`` depending on whether ``coordfunc``
536
+ should be shifted from the coordinate origin to the center or from
537
+ the center to the coordinate origin
538
+
539
+ TESTS::
540
+
541
+ sage: E3 = EuclideanSpace(3)
542
+ sage: c = E3.point((1,2,3), name='c')
543
+ sage: S2c = manifolds.Sphere(2, ambient_space=E3, center=c)
544
+ sage: spher = S2c.spherical_coordinates()
545
+ sage: cart = E3.cartesian_coordinates()
546
+ sage: coordfunc = S2c.embedding().expr(spher, cart); coordfunc
547
+ (cos(phi)*sin(theta) + 1, sin(phi)*sin(theta) + 2, cos(theta) + 3)
548
+ sage: S2c._shift_coords(coordfunc, s='-')
549
+ (cos(phi)*sin(theta), sin(phi)*sin(theta), cos(theta))
550
+ """
551
+ cart = self._ambient.cartesian_coordinates()
552
+ c_coords = cart(self._center)
553
+ if s == '+':
554
+ res = [x + c for x, c in zip(coordfunc, c_coords)]
555
+ elif s == '-':
556
+ res = [x - c for x, c in zip(coordfunc, c_coords)]
557
+ return tuple(res)
558
+
559
+ def _init_spherical(self, names=None):
560
+ r"""
561
+ Construct the chart of spherical coordinates.
562
+
563
+ TESTS:
564
+
565
+ Spherical coordinates on a 2-sphere::
566
+
567
+ sage: S2 = manifolds.Sphere(2)
568
+ sage: S2.spherical_coordinates()
569
+ Chart (A, (theta, phi))
570
+
571
+ Spherical coordinates on a 1-sphere::
572
+
573
+ sage: S1 = manifolds.Sphere(1, coordinates='stereographic')
574
+ sage: spher = S1.spherical_coordinates(); spher # create coords
575
+ Chart (A, (phi,))
576
+ sage: S1.atlas()
577
+ [Chart (S^1-{NP}, (y1,)),
578
+ Chart (S^1-{SP}, (yp1,)),
579
+ Chart (S^1-{NP,SP}, (y1,)),
580
+ Chart (S^1-{NP,SP}, (yp1,)),
581
+ Chart (A, (phi,)),
582
+ Chart (A, (y1,)),
583
+ Chart (A, (yp1,))]
584
+ """
585
+ # speed-up via simplification method...
586
+ self.set_simplify_function(lambda expr: expr.simplify_trig())
587
+
588
+ # get domain...
589
+ A = self._spher_dom
590
+
591
+ # initialize coordinates...
592
+ n = self._dim
593
+ if names:
594
+ # add interval:
595
+ names = tuple([x + ':(0,pi)' for x in names[:-1]] +
596
+ [names[-1] + ':(-pi,pi):periodic'])
597
+ else:
598
+ if n == 1:
599
+ names = ('phi:(-pi,pi):periodic',)
600
+ elif n == 2:
601
+ names = ('theta:(0,pi)', 'phi:(-pi,pi):periodic')
602
+ elif n == 3:
603
+ names = ('chi:(0,pi)', 'theta:(0,pi)', 'phi:(-pi,pi):periodic')
604
+ else:
605
+ names = tuple(["phi_{}:(0,pi)".format(i) for i in range(1,n)] +
606
+ ["phi_{}:(-pi,pi):periodic".format(n)])
607
+ spher = A.chart(names=names)
608
+ coord = spher[:]
609
+
610
+ # make spherical chart and frame the default ones on their domain:
611
+ A.set_default_chart(spher)
612
+ A.set_default_frame(spher.frame())
613
+
614
+ # manage embedding...
615
+ from sage.functions.trig import cos, sin
616
+ from sage.misc.misc_c import prod
617
+
618
+ R = self._radius
619
+
620
+ coordfunc = [R*cos(coord[n-1])*prod(sin(coord[i]) for i in range(n-1))]
621
+ coordfunc += [R*prod(sin(coord[i]) for i in range(n))]
622
+ for k in reversed(range(n-1)):
623
+ c = R*cos(coord[k])*prod(sin(coord[i]) for i in range(k))
624
+ coordfunc.append(c)
625
+ cart = self._ambient.cartesian_coordinates()
626
+ # shift coordinates to barycenter:
627
+ coordfunc = self._shift_coords(coordfunc, s='+')
628
+ # add expression to embedding:
629
+ self._immersion.add_expr(spher, cart, coordfunc)
630
+ self.clear_cache() # clear cache of extrinsic information
631
+
632
+ # finish process...
633
+ self._coordinates['spherical'] = [spher]
634
+
635
+ # adapt other coordinates...
636
+ if 'stereographic' in self._coordinates:
637
+ self._transition_spher_stereo()
638
+
639
+ # reset simplification method...
640
+ self.set_simplify_function('default')
641
+
642
+ def stereographic_coordinates(self, pole='north', names=None):
643
+ r"""
644
+ Return stereographic coordinates given by the stereographic
645
+ projection of ``self`` w.r.t. to a given pole.
646
+
647
+ INPUT:
648
+
649
+ - ``pole`` -- (default: ``'north'``) the pole determining the
650
+ stereographic projection; possible options are ``'north'`` and
651
+ ``'south'``
652
+ - ``names`` -- (default: ``None``) must be a tuple containing
653
+ the coordinate symbols (this guarantees the usage of the shortcut
654
+ operator ``<,>``)
655
+
656
+ OUTPUT:
657
+
658
+ - the chart of stereographic coordinates w.r.t. to the given pole,
659
+ as an instance of
660
+ :class:`~sage.manifolds.differentiable.chart.RealDiffChart`
661
+
662
+ Let `\mathbb{S}^n_r(c)` be an `n`-sphere of radius `r` smoothly
663
+ embedded in the Euclidean space `E^{n+1}` centered at `c \in E^{n+1}`.
664
+ We denote the north pole of `\mathbb{S}^n_r(c)` by `\mathrm{NP}` and the
665
+ south pole by `\mathrm{SP}`. These poles are uniquely determined by
666
+ the requirement
667
+
668
+ .. MATH::
669
+
670
+ x(\iota(\mathrm{NP})) &= (0, \ldots, 0, r) + x(c), \\
671
+ x(\iota(\mathrm{SP})) &= (0, \ldots, 0, -r) + x(c).
672
+
673
+ The coordinates `(y_1, \ldots, y_n)` (`(y'_1, \ldots, y'_n)`
674
+ respectively) define *stereographic coordinates* on `\mathbb{S}^n_r(c)`
675
+ for the Cartesian coordinates `(x_1, \ldots, x_{n+1})` on `E^{n+1}`
676
+ if they arise from the stereographic projection from
677
+ `\iota(\mathrm{NP})` (`\iota(\mathrm{SP})`) to the hypersurface
678
+ `x_n = x_n(c)`. In concrete formulas, this means:
679
+
680
+ .. MATH::
681
+
682
+ \left. x \circ \iota \right|_{\mathbb{S}^n_r(c) \setminus \{
683
+ \mathrm{NP}\}}
684
+ &= \left( \frac{2y_1r^2}{r^2+\sum^n_{i=1} y^2_i},
685
+ \ldots, \frac{2y_nr^2}{r^2+\sum^n_{i=1} y^2_i},
686
+ \frac{r\sum^n_{i=1} y^2_i-r^3}{r^2+\sum^n_{i=1} y^2_i} \right) +
687
+ x(c), \\
688
+ \left. x \circ \iota \right|_{\mathbb{S}^n_r(c) \setminus \{
689
+ \mathrm{SP}\}} &= \left( \frac{2y'_1r^2}{r^2+\sum^n_{i=1} y'^2_i},
690
+ \ldots, \frac{2y'_nr^2}{r^2+\sum^n_{i=1} y'^2_i},
691
+ \frac{r^3 - r\sum^n_{i=1} y'^2_i}{r^2+\sum^n_{i=1} y'^2_i} \right) +
692
+ x(c).
693
+
694
+ EXAMPLES:
695
+
696
+ Initialize a 1-sphere centered at `(1,0)` in the Euclidean plane
697
+ using the shortcut operator::
698
+
699
+ sage: E2 = EuclideanSpace(2)
700
+ sage: c = E2.point((1,0), name='c')
701
+ sage: S1.<a> = E2.sphere(center=c, coordinates='stereographic'); S1
702
+ 1-sphere S^1(c) of radius 1 smoothly embedded in the Euclidean plane
703
+ E^2 centered at the Point c
704
+
705
+ By default, the shortcut variables belong to the stereographic
706
+ projection from the north pole::
707
+
708
+ sage: S1.coordinate_charts('stereographic')
709
+ [Chart (S^1(c)-{NP}, (a,)), Chart (S^1(c)-{SP}, (ap,))]
710
+ sage: S1.embedding().display()
711
+ iota: S^1(c) → E^2
712
+ on S^1(c)-{NP}: a ↦ (x, y) = (2*a/(a^2 + 1) + 1, (a^2 - 1)/(a^2 + 1))
713
+ on S^1(c)-{SP}: ap ↦ (x, y) = (2*ap/(ap^2 + 1) + 1, -(ap^2 - 1)/(ap^2 + 1))
714
+
715
+ Initialize a 2-sphere from scratch::
716
+
717
+ sage: S2 = manifolds.Sphere(2)
718
+ sage: S2.atlas()
719
+ [Chart (A, (theta, phi))]
720
+
721
+ In the previous block, the stereographic coordinates have not been
722
+ initialized. This happens subsequently with the invocation of
723
+ ``stereographic_coordinates``::
724
+
725
+ sage: stereoS.<u,v> = S2.stereographic_coordinates(pole='south')
726
+ sage: S2.coordinate_charts('stereographic')
727
+ [Chart (S^2-{NP}, (up, vp)), Chart (S^2-{SP}, (u, v))]
728
+
729
+ If not specified by the user, the default coordinate names are given by
730
+ `(y_1, \ldots, y_n)` and `(y'_1, \ldots, y'_n)` respectively::
731
+
732
+ sage: S3 = manifolds.Sphere(3, coordinates='stereographic')
733
+ sage: S3.stereographic_coordinates(pole='north')
734
+ Chart (S^3-{NP}, (y1, y2, y3))
735
+ sage: S3.stereographic_coordinates(pole='south')
736
+ Chart (S^3-{SP}, (yp1, yp2, yp3))
737
+ """
738
+ coordinates = 'stereographic'
739
+ if coordinates not in self._coordinates:
740
+ self._init_coordinates[coordinates](names, default_pole=pole)
741
+ if pole == 'north':
742
+ return self._coordinates[coordinates][0]
743
+ elif pole == 'south':
744
+ return self._coordinates[coordinates][1]
745
+ else:
746
+ raise ValueError("pole must be 'north' or 'south'")
747
+
748
+ def spherical_coordinates(self, names=None):
749
+ r"""
750
+ Return the spherical coordinates of ``self``.
751
+
752
+ INPUT:
753
+
754
+ - ``names`` -- (default: ``None``) must be a tuple containing
755
+ the coordinate symbols (this guarantees the usage of the shortcut
756
+ operator ``<,>``)
757
+
758
+ OUTPUT:
759
+
760
+ - the chart of spherical coordinates, as an instance of
761
+ :class:`~sage.manifolds.differentiable.chart.RealDiffChart`
762
+
763
+ Let `\mathbb{S}^n_r(c)` be an `n`-sphere of radius `r` smoothly
764
+ embedded in the Euclidean space `E^{n+1}` centered at `c \in E^{n+1}`.
765
+ We say that `(\varphi_1, \ldots, \varphi_n)` define *spherical
766
+ coordinates* on the open subset `A \subset \mathbb{S}^n_r(c)` for the
767
+ Cartesian coordinates `(x_1, \ldots, x_{n+1})` on `E^{n+1}` (not
768
+ necessarily centered at `c`) if
769
+
770
+ .. MATH::
771
+
772
+ \begin{aligned}
773
+ \left. x_1 \circ \iota \right|_{A} &= r \cos(\varphi_n)\sin(
774
+ \varphi_{n-1}) \cdots
775
+ \sin(\varphi_1)
776
+ + x_1(c), \\
777
+ \left. x_1 \circ \iota \right|_{A} &= r \sin(\varphi_n)\sin(
778
+ \varphi_{n-1}) \cdots
779
+ \sin(\varphi_1)
780
+ + x_1(c), \\
781
+ \left. x_2 \circ \iota \right|_{A} &= r \cos(\varphi_{
782
+ n-1})\sin(\varphi_{n-2}) \cdots
783
+ \sin(\varphi_1)
784
+ + x_2(c), \\
785
+ \left. x_3 \circ \iota \right|_{A} &= r \cos(\varphi_{
786
+ n-2})\sin(\varphi_{n-3}) \cdots
787
+ \sin(\varphi_1)
788
+ + x_3(c), \\
789
+ \vdots & \\
790
+ \left. x_{n+1} \circ \iota \right|_{A} &= r \cos(\varphi_1) +
791
+ x_{n+1}(c),
792
+ \end{aligned}
793
+
794
+ where `\varphi_i` has range `(0, \pi)` for `i=1, \ldots, n-1` and
795
+ `\varphi_n` lies in `(-\pi, \pi)`. Notice that the above expressions
796
+ together with the ranges of the `\varphi_i` fully determine the open
797
+ set `A`.
798
+
799
+ .. NOTE::
800
+
801
+ Notice that our convention slightly differs from the one given on
802
+ the :wikipedia:`N-sphere#Spherical_coordinates`. The definition
803
+ above ensures that the conventions for the most common cases
804
+ `n=1` and `n=2` are maintained.
805
+
806
+ EXAMPLES:
807
+
808
+ The spherical coordinates on a 2-sphere follow the common conventions::
809
+
810
+ sage: S2 = manifolds.Sphere(2)
811
+ sage: spher = S2.spherical_coordinates(); spher
812
+ Chart (A, (theta, phi))
813
+
814
+ The coordinate range of spherical coordinates::
815
+
816
+ sage: spher.coord_range()
817
+ theta: (0, pi); phi: [-pi, pi] (periodic)
818
+
819
+ Spherical coordinates do not cover the 2-sphere entirely::
820
+
821
+ sage: A = spher.domain(); A
822
+ Open subset A of the 2-sphere S^2 of radius 1 smoothly embedded in
823
+ the Euclidean space E^3
824
+
825
+ The embedding of a 2-sphere in Euclidean space via spherical
826
+ coordinates::
827
+
828
+ sage: S2.embedding().display()
829
+ iota: S^2 → E^3
830
+ on A: (theta, phi) ↦ (x, y, z) =
831
+ (cos(phi)*sin(theta),
832
+ sin(phi)*sin(theta),
833
+ cos(theta))
834
+
835
+ Now, consider spherical coordinates on a 3-sphere::
836
+
837
+ sage: S3 = manifolds.Sphere(3)
838
+ sage: spher = S3.spherical_coordinates(); spher
839
+ Chart (A, (chi, theta, phi))
840
+ sage: S3.embedding().display()
841
+ iota: S^3 → E^4
842
+ on A: (chi, theta, phi) ↦ (x1, x2, x3, x4) =
843
+ (cos(phi)*sin(chi)*sin(theta),
844
+ sin(chi)*sin(phi)*sin(theta),
845
+ cos(theta)*sin(chi),
846
+ cos(chi))
847
+
848
+ By convention, the last coordinate is periodic::
849
+
850
+ sage: spher.coord_range()
851
+ chi: (0, pi); theta: (0, pi); phi: [-pi, pi] (periodic)
852
+ """
853
+ coordinates = 'spherical'
854
+ if coordinates not in self._coordinates:
855
+ self._init_coordinates[coordinates](names)
856
+ return self._coordinates[coordinates][0]
857
+
858
+ def _init_stereographic(self, names, default_pole='north'):
859
+ r"""
860
+ Construct the charts of stereographic coordinates.
861
+
862
+ TESTS:
863
+
864
+ Stereographic coordinates on the 2-sphere::
865
+
866
+ sage: S2.<x,y> = manifolds.Sphere(2, coordinates='stereographic')
867
+ sage: S2.atlas()
868
+ [Chart (S^2-{NP}, (x, y)),
869
+ Chart (S^2-{SP}, (xp, yp)),
870
+ Chart (S^2-{NP,SP}, (x, y)),
871
+ Chart (S^2-{NP,SP}, (xp, yp))]
872
+
873
+ Stereographic coordinates on the 1-sphere::
874
+
875
+ sage: S1 = manifolds.Sphere(1)
876
+ sage: stereoS.<x> = S1.stereographic_coordinates(pole='south')
877
+ sage: S1.atlas()
878
+ [Chart (A, (phi,)),
879
+ Chart (S^1-{NP}, (xp,)),
880
+ Chart (S^1-{SP}, (x,)),
881
+ Chart (S^1-{NP,SP}, (xp,)),
882
+ Chart (S^1-{NP,SP}, (x,)),
883
+ Chart (A, (xp,)),
884
+ Chart (A, (x,))]
885
+
886
+ The stereographic chart is the default one on its domain::
887
+
888
+ sage: V = stereoS.domain()
889
+ sage: V.default_chart()
890
+ Chart (S^1-{SP}, (x,))
891
+
892
+ Accordingly, we have::
893
+
894
+ sage: S1.metric().restrict(V).display()
895
+ g = 4/(x^4 + 2*x^2 + 1) dx⊗dx
896
+
897
+ while the spherical chart is still the default one on ``S1``::
898
+
899
+ sage: S1.metric().display()
900
+ g = dphi⊗dphi
901
+ """
902
+ # speed-up via simplification method...
903
+ self.set_simplify_function(lambda expr: expr.simplify_rational())
904
+ # TODO: More speed-up?
905
+
906
+ # get domains...
907
+ U = self._stereoN_dom
908
+ V = self._stereoS_dom
909
+
910
+ # initialize coordinates...
911
+ symbols_N = ''
912
+ symbols_S = ''
913
+ if names:
914
+ for x in names:
915
+ if default_pole == 'north':
916
+ symbols_N += x + ' '
917
+ symbols_S += "{}p".format(x) + ":{}' ".format(x)
918
+ elif default_pole == 'south':
919
+ symbols_S += x + ' '
920
+ symbols_N += "{}p".format(x) + ":{}' ".format(x)
921
+ else:
922
+ for i in self.irange():
923
+ symbols_N += "y{}".format(i) + r":y_{" + str(i) + r"} "
924
+ symbols_S += "yp{}".format(i) + r":y'_{" + str(i) + r"} "
925
+ symbols_N = symbols_N[:-1]
926
+ symbols_S = symbols_S[:-1]
927
+ stereoN = U.chart(coordinates=symbols_N)
928
+ stereoS = V.chart(coordinates=symbols_S)
929
+ coordN = stereoN[:]
930
+ coordS = stereoS[:]
931
+
932
+ # make stereographic charts and frames the default ones on their
933
+ # respective domains:
934
+ U.set_default_chart(stereoN)
935
+ V.set_default_chart(stereoS)
936
+ U.set_default_frame(stereoN.frame())
937
+ V.set_default_frame(stereoS.frame())
938
+
939
+ # predefine variables...
940
+ r2_N = sum(y ** 2 for y in coordN)
941
+ r2_S = sum(yp ** 2 for yp in coordS)
942
+ R = self._radius
943
+ R2 = R**2
944
+
945
+ # define transition map...
946
+ coordN_to_S = tuple(R*y/r2_N for y in coordN)
947
+ coordS_to_N = tuple(R*yp/r2_S for yp in coordS)
948
+ stereoN_to_S = stereoN.transition_map(stereoS, coordN_to_S,
949
+ restrictions1=r2_N != 0,
950
+ restrictions2=r2_S != 0)
951
+ stereoN_to_S.set_inverse(*coordS_to_N, check=False)
952
+
953
+ # manage embedding...
954
+ coordfuncN = [2*y*R2 / (R2+r2_N) for y in coordN]
955
+ coordfuncN += [(R*r2_N-R*R2)/(R2+r2_N)]
956
+ coordfuncS = [2*yp*R2 / (R2+r2_S) for yp in coordS]
957
+ coordfuncS += [(R*R2-R*r2_S)/(R2+r2_S)]
958
+ cart = self._ambient.cartesian_coordinates()
959
+ # shift coordinates to barycenter:
960
+ coordfuncN = self._shift_coords(coordfuncN, s='+')
961
+ coordfuncS = self._shift_coords(coordfuncS, s='+')
962
+ # add expressions to embedding:
963
+ self._immersion.add_expr(stereoN, cart, coordfuncN)
964
+ self._immersion.add_expr(stereoS, cart, coordfuncS)
965
+ self.clear_cache() # clear cache of extrinsic information
966
+
967
+ # define orientation...
968
+ eN = stereoN.frame()
969
+ eS = stereoS.frame() # oriented w.r.t. embedding
970
+ frame_comp = list(eN[:])
971
+ frame_comp[0] = -frame_comp[0] # reverse orientation
972
+ f = U.vector_frame('f', frame_comp)
973
+ self.set_orientation([eS, f])
974
+
975
+ # finish process...
976
+ self._coordinates['stereographic'] = [stereoN, stereoS]
977
+
978
+ # adapt other coordinates...
979
+ if 'spherical' in self._coordinates:
980
+ self._transition_spher_stereo()
981
+
982
+ # reset simplification method...
983
+ self.set_simplify_function('default')
984
+
985
+ def _transition_spher_stereo(self):
986
+ r"""
987
+ Initialize the transition map between spherical and stereographic
988
+ coordinates.
989
+
990
+ TESTS::
991
+
992
+ sage: S1 = manifolds.Sphere(1)
993
+ sage: spher = S1.spherical_coordinates(); spher
994
+ Chart (A, (phi,))
995
+ sage: A = spher.domain()
996
+ sage: stereoN = S1.stereographic_coordinates(pole='north'); stereoN
997
+ Chart (S^1-{NP}, (y1,))
998
+ sage: S1.coord_change(spher, stereoN.restrict(A))
999
+ Change of coordinates from Chart (A, (phi,)) to Chart (A, (y1,))
1000
+ """
1001
+ # speed-up via simplification method...
1002
+ self.set_simplify_function(lambda expr: expr.simplify())
1003
+
1004
+ # configure preexisting charts...
1005
+ W = self._stereoN_dom.intersection(self._stereoS_dom)
1006
+ A = self._spher_dom
1007
+ stereoN, stereoS = self._coordinates['stereographic'][:]
1008
+ coordN = stereoN[:]
1009
+ coordS = stereoS[:]
1010
+ rstN = (coordN[0] != 0,)
1011
+ rstS = (coordS[0] != 0,)
1012
+ if self._dim > 1:
1013
+ rstN += (coordN[0] > 0,)
1014
+ rstS += (coordS[0] > 0,)
1015
+ stereoN_A = stereoN.restrict(A, rstN)
1016
+ stereoS_A = stereoS.restrict(A, rstS)
1017
+ self._coord_changes[(stereoN.restrict(W),
1018
+ stereoS.restrict(W))].restrict(A)
1019
+ self._coord_changes[(stereoS.restrict(W),
1020
+ stereoN.restrict(W))].restrict(A)
1021
+ spher = self._coordinates['spherical'][0]
1022
+
1023
+ R = self._radius
1024
+ n = self._dim
1025
+
1026
+ # transition: spher to stereoN...
1027
+ imm = self.embedding()
1028
+ cart = self._ambient.cartesian_coordinates()
1029
+ # get ambient coordinates and shift to coordinate origin:
1030
+ x = self._shift_coords(imm.expr(spher, cart), s='-')
1031
+ coordfunc = [(R*x[i])/(R-x[-1]) for i in range(n)]
1032
+ # define transition map:
1033
+ spher_to_stereoN = spher.transition_map(stereoN_A, coordfunc)
1034
+
1035
+ # transition: stereoN to spher...
1036
+ from sage.functions.trig import acos, atan2
1037
+ from sage.misc.functional import sqrt
1038
+ # get ambient coordinates and shift to coordinate origin:
1039
+ x = self._shift_coords(imm.expr(stereoN, cart), s='-')
1040
+ coordfunc = [atan2(x[1],x[0])]
1041
+ for k in range(2, n+1):
1042
+ c = acos(x[k]/sqrt(sum(x[i]**2 for i in range(k+1))))
1043
+ coordfunc.append(c)
1044
+ coordfunc = reversed(coordfunc)
1045
+ spher_to_stereoN.set_inverse(*coordfunc, check=False)
1046
+
1047
+ # transition spher <-> stereoS...
1048
+ stereoN_to_S_A = self.coord_change(stereoN_A, stereoS_A)
1049
+ stereoN_to_S_A * spher_to_stereoN # generates spher_to_stereoS
1050
+ stereoS_to_N_A = self.coord_change(stereoS_A, stereoN_A)
1051
+ spher_to_stereoN.inverse() * stereoS_to_N_A # generates stereoS_to_spher
1052
+
1053
+ def dist(self, p, q):
1054
+ r"""
1055
+ Return the great circle distance between the points ``p`` and ``q`` on
1056
+ ``self``.
1057
+
1058
+ INPUT:
1059
+
1060
+ - ``p`` -- an element of ``self``
1061
+ - ``q`` -- an element of ``self``
1062
+
1063
+ OUTPUT:
1064
+
1065
+ - the great circle distance `d(p, q)` on ``self``
1066
+
1067
+ The great circle distance `d(p, q)` of the points
1068
+ `p, q \in \mathbb{S}^n_r(c)` is the length of the shortest great circle
1069
+ segment on `\mathbb{S}^n_r(c)` that joins `p` and `q`. If we choose
1070
+ Cartesian coordinates `(x_1, \ldots, x_{n+1})` of the ambient Euclidean
1071
+ space such that the center lies in the coordinate origin, i.e.
1072
+ `x(c)=0`, the great circle distance can be expressed in terms of the
1073
+ following formula:
1074
+
1075
+ .. MATH::
1076
+
1077
+ d(p,q) = r \, \arccos\left(\frac{x(\iota(p)) \cdot
1078
+ x(\iota(q))}{r^2}\right).
1079
+
1080
+ EXAMPLES:
1081
+
1082
+ Define a 2-sphere with unspecified radius::
1083
+
1084
+ sage: r = var('r')
1085
+ sage: S2_r = manifolds.Sphere(2, radius=r); S2_r
1086
+ 2-sphere S^2_r of radius r smoothly embedded in the Euclidean space E^3
1087
+
1088
+ Given two antipodal points in spherical coordinates::
1089
+
1090
+ sage: p = S2_r.point((pi/2, pi/2), name='p'); p
1091
+ Point p on the 2-sphere S^2_r of radius r smoothly embedded in the
1092
+ Euclidean space E^3
1093
+ sage: q = S2_r.point((pi/2, -pi/2), name='q'); q
1094
+ Point q on the 2-sphere S^2_r of radius r smoothly embedded in the
1095
+ Euclidean space E^3
1096
+
1097
+ The distance is determined as the length of the half great circle::
1098
+
1099
+ sage: S2_r.dist(p, q)
1100
+ pi*r
1101
+ """
1102
+ from sage.functions.trig import acos
1103
+ # get Euclidean points:
1104
+ x = self._immersion(p)
1105
+ y = self._immersion(q)
1106
+ cart = self._ambient.cartesian_coordinates()
1107
+ # get ambient coordinates and shift to coordinate origin:
1108
+ x_coord = self._shift_coords(x.coord(chart=cart), s='-')
1109
+ y_coord = self._shift_coords(y.coord(chart=cart), s='-')
1110
+
1111
+ n = self._dim + 1
1112
+ r = self._radius
1113
+ inv_angle = sum(x_coord[i]*y_coord[i] for i in range(n)) / r**2
1114
+ return (r * acos(inv_angle)).simplify()
1115
+
1116
+ def radius(self):
1117
+ r"""
1118
+ Return the radius of ``self``.
1119
+
1120
+ EXAMPLES:
1121
+
1122
+ 3-sphere with radius 3::
1123
+
1124
+ sage: S3_2 = manifolds.Sphere(3, radius=2); S3_2
1125
+ 3-sphere S^3_2 of radius 2 smoothly embedded in the 4-dimensional
1126
+ Euclidean space E^4
1127
+ sage: S3_2.radius()
1128
+ 2
1129
+
1130
+ 2-sphere with unspecified radius::
1131
+
1132
+ sage: r = var('r')
1133
+ sage: S2_r = manifolds.Sphere(3, radius=r); S2_r
1134
+ 3-sphere S^3_r of radius r smoothly embedded in the 4-dimensional
1135
+ Euclidean space E^4
1136
+ sage: S2_r.radius()
1137
+ r
1138
+ """
1139
+ return self._radius
1140
+
1141
+ def minimal_triangulation(self):
1142
+ r"""
1143
+ Return the minimal triangulation of ``self`` as a simplicial complex.
1144
+
1145
+ EXAMPLES:
1146
+
1147
+ Minimal triangulation of the 2-sphere::
1148
+
1149
+ sage: S2 = manifolds.Sphere(2)
1150
+ sage: S = S2.minimal_triangulation(); S # needs sage.graphs
1151
+ Minimal triangulation of the 2-sphere
1152
+
1153
+ The Euler characteristic of a 2-sphere::
1154
+
1155
+ sage: S.euler_characteristic() # needs sage.graphs
1156
+ 2
1157
+ """
1158
+ from sage.topology.simplicial_complex_examples import Sphere as SymplicialSphere
1159
+ return SymplicialSphere(self._dim)
1160
+
1161
+ def center(self):
1162
+ r"""
1163
+ Return the barycenter of ``self`` in the ambient Euclidean space.
1164
+
1165
+ EXAMPLES:
1166
+
1167
+ 2-sphere embedded in Euclidean space centered at `(1,2,3)` in
1168
+ Cartesian coordinates::
1169
+
1170
+ sage: E3 = EuclideanSpace(3)
1171
+ sage: c = E3.point((1,2,3), name='c')
1172
+ sage: S2c = manifolds.Sphere(2, ambient_space=E3, center=c); S2c
1173
+ 2-sphere S^2(c) of radius 1 smoothly embedded in the Euclidean space
1174
+ E^3 centered at the Point c
1175
+ sage: S2c.center()
1176
+ Point c on the Euclidean space E^3
1177
+
1178
+ We can see that the embedding is shifted accordingly::
1179
+
1180
+ sage: S2c.embedding().display()
1181
+ iota: S^2(c) → E^3
1182
+ on A: (theta, phi) ↦ (x, y, z) = (cos(phi)*sin(theta) + 1,
1183
+ sin(phi)*sin(theta) + 2,
1184
+ cos(theta) + 3)
1185
+ """
1186
+ return self._center