passagemath-symbolics 10.6.37__cp310-cp310-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.
Files changed (171) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.6.37.dist-info/METADATA +187 -0
  3. passagemath_symbolics-10.6.37.dist-info/RECORD +171 -0
  4. passagemath_symbolics-10.6.37.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.6.37.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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-310-x86_64-linux-gnu.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,1028 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Curves in Manifolds
4
+
5
+ Given a differentiable manifold `M`, a *differentiable curve* in
6
+ `M` is a differentiable mapping
7
+
8
+ .. MATH::
9
+
10
+ \gamma: I \longrightarrow M,
11
+
12
+ where `I` is an interval of `\RR`.
13
+
14
+ Differentiable curves are implemented by :class:`DifferentiableCurve`.
15
+
16
+ AUTHORS:
17
+
18
+ - Eric Gourgoulhon (2015): initial version
19
+ - Travis Scrimshaw (2016): review tweaks
20
+
21
+ REFERENCES:
22
+
23
+ - Chap. 1 of [KN1963]_
24
+ - Chap. 3 of [Lee2013]_
25
+ """
26
+
27
+ #*****************************************************************************
28
+ # Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@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
+ # http://www.gnu.org/licenses/
34
+ #*****************************************************************************
35
+
36
+ from sage.manifolds.differentiable.diff_map import DiffMap
37
+ from sage.manifolds.point import ManifoldPoint
38
+ from sage.misc.decorators import options
39
+ from sage.misc.latex import latex
40
+
41
+
42
+ class DifferentiableCurve(DiffMap):
43
+ r"""
44
+ Curve in a differentiable manifold.
45
+
46
+ Given a differentiable manifold `M`, a *differentiable curve* in
47
+ `M` is a differentiable map
48
+
49
+ .. MATH::
50
+
51
+ \gamma: I \longrightarrow M,
52
+
53
+ where `I` is an interval of `\RR`.
54
+
55
+ INPUT:
56
+
57
+ - ``parent`` --
58
+ :class:`~sage.manifolds.differentiable.manifold_homset.DifferentiableCurveSet`
59
+ the set of curves `\mathrm{Hom}(I, M)` to which the curve belongs
60
+ - ``coord_expression`` -- (default: ``None``) dictionary (possibly empty)
61
+ of the functions of the curve parameter `t` expressing the curve in
62
+ various charts of `M`, the keys of the dictionary being the charts and
63
+ the values being lists or tuples of `n` symbolic expressions of `t`,
64
+ where `n` is the dimension of `M`
65
+ - ``name`` -- (default: ``None``) string; symbol given to the curve
66
+ - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote
67
+ the curve; if none is provided, ``name`` will be used
68
+ - ``is_isomorphism`` -- boolean (default: ``False``); determines whether the
69
+ constructed object is a diffeomorphism; if set to ``True``,
70
+ then `M` must have dimension one
71
+ - ``is_identity`` -- boolean (default: ``False``); determines whether the
72
+ constructed object is the identity map; if set to ``True``,
73
+ then `M` must be the interval `I`
74
+
75
+ EXAMPLES:
76
+
77
+ The lemniscate of Gerono in the 2-dimensional Euclidean plane::
78
+
79
+ sage: M = Manifold(2, 'M')
80
+ sage: X.<x,y> = M.chart()
81
+ sage: t = var('t')
82
+ sage: c = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi), name='c') ; c
83
+ Curve c in the 2-dimensional differentiable manifold M
84
+ sage: type(c)
85
+ <class 'sage.manifolds.differentiable.manifold_homset.DifferentiableCurveSet_with_category.element_class'>
86
+
87
+ Instead of declaring the parameter `t` as a symbolic variable by means
88
+ of ``var('t')``, it is equivalent to get it as the canonical coordinate
89
+ of the real number line (see
90
+ :class:`~sage.manifolds.differentiable.examples.real_line.RealLine`)::
91
+
92
+ sage: R.<t> = manifolds.RealLine()
93
+ sage: c = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi), name='c') ; c
94
+ Curve c in the 2-dimensional differentiable manifold M
95
+
96
+ A graphical view of the curve is provided by the method :meth:`plot`::
97
+
98
+ sage: c.plot(aspect_ratio=1) # needs sage.plot
99
+ Graphics object consisting of 1 graphics primitive
100
+
101
+ .. PLOT::
102
+
103
+ M = Manifold(2, 'M')
104
+ X = M.chart('x y')
105
+ t = manifolds.RealLine().canonical_coordinate()
106
+ c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
107
+ g = c.plot(aspect_ratio=1)
108
+ sphinx_plot(g)
109
+
110
+ Curves are considered as (manifold) morphisms from real intervals to
111
+ differentiable manifolds::
112
+
113
+ sage: c.parent()
114
+ Set of Morphisms from Real interval (0, 2*pi) to 2-dimensional
115
+ differentiable manifold M in Category of smooth manifolds over Real
116
+ Field with 53 bits of precision
117
+ sage: I = R.open_interval(0, 2*pi)
118
+ sage: c.parent() is Hom(I, M)
119
+ True
120
+ sage: c.domain()
121
+ Real interval (0, 2*pi)
122
+ sage: c.domain() is I
123
+ True
124
+ sage: c.codomain()
125
+ 2-dimensional differentiable manifold M
126
+
127
+ Accordingly, all methods of
128
+ :class:`~sage.manifolds.differentiable.diff_map.DiffMap` are available
129
+ for them. In particular, the method
130
+ :meth:`~sage.manifolds.continuous_map.ContinuousMap.display`
131
+ shows the coordinate representations in various charts of manifold ``M``::
132
+
133
+ sage: c.display()
134
+ c: (0, 2*pi) → M
135
+ t ↦ (x, y) = (sin(t), 1/2*sin(2*t))
136
+
137
+ Another map method is using the usual call syntax, which returns
138
+ the image of a point in the curve's domain::
139
+
140
+ sage: t0 = pi/2
141
+ sage: I(t0)
142
+ Point on the Real number line ℝ
143
+ sage: c(I(t0))
144
+ Point on the 2-dimensional differentiable manifold M
145
+ sage: c(I(t0)).coord(X)
146
+ (1, 0)
147
+
148
+ For curves, the value of the parameter, instead of the corresponding
149
+ point in the real line manifold, can be passed directly::
150
+
151
+ sage: c(t0)
152
+ Point c(1/2*pi) on the 2-dimensional differentiable manifold M
153
+ sage: c(t0).coord(X)
154
+ (1, 0)
155
+ sage: c(t0) == c(I(t0))
156
+ True
157
+
158
+ Instead of a dictionary of coordinate expressions, the curve can be
159
+ defined by a single coordinate expression in a given chart::
160
+
161
+ sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), chart=X, name='c') ; c
162
+ Curve c in the 2-dimensional differentiable manifold M
163
+ sage: c.display()
164
+ c: (0, 2*pi) → M
165
+ t ↦ (x, y) = (sin(t), 1/2*sin(2*t))
166
+
167
+ Since ``X`` is the default chart on ``M``, it can be omitted::
168
+
169
+ sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c') ; c
170
+ Curve c in the 2-dimensional differentiable manifold M
171
+ sage: c.display()
172
+ c: (0, 2*pi) → M
173
+ t ↦ (x, y) = (sin(t), 1/2*sin(2*t))
174
+
175
+ Note that a curve in `M` can also be created as a differentiable
176
+ map `I \to M`::
177
+
178
+ sage: c1 = I.diff_map(M, coord_functions={X: [sin(t), sin(2*t)/2]},
179
+ ....: name='c') ; c1
180
+ Curve c in the 2-dimensional differentiable manifold M
181
+ sage: c1.parent() is c.parent()
182
+ True
183
+ sage: c1 == c
184
+ True
185
+
186
+ LaTeX symbols representing a curve::
187
+
188
+ sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi))
189
+ sage: latex(c)
190
+ \text{Curve in the 2-dimensional differentiable manifold M}
191
+ sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
192
+ sage: latex(c)
193
+ c
194
+ sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c',
195
+ ....: latex_name=r'\gamma')
196
+ sage: latex(c)
197
+ \gamma
198
+
199
+ The curve's tangent vector field (velocity vector)::
200
+
201
+ sage: v = c.tangent_vector_field() ; v
202
+ Vector field c' along the Real interval (0, 2*pi) with values on the
203
+ 2-dimensional differentiable manifold M
204
+ sage: v.display()
205
+ c' = cos(t) ∂/∂x + (2*cos(t)^2 - 1) ∂/∂y
206
+
207
+ Plot of the curve and its tangent vector field::
208
+
209
+ sage: show(c.plot(thickness=2, aspect_ratio=1) + # needs sage.plot
210
+ ....: v.plot(chart=X, number_values=17, scale=0.5))
211
+
212
+ .. PLOT::
213
+
214
+ M = Manifold(2, 'M')
215
+ X = M.chart('x y')
216
+ t = manifolds.RealLine().canonical_coordinate()
217
+ c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
218
+ v = c.tangent_vector_field()
219
+ g = c.plot(thickness=2, aspect_ratio=1) + v.plot(chart=X, number_values=17, scale=0.5)
220
+ sphinx_plot(g)
221
+
222
+ Value of the tangent vector field at `t = \pi`::
223
+
224
+ sage: v.at(R(pi))
225
+ Tangent vector c' at Point on the 2-dimensional differentiable
226
+ manifold M
227
+ sage: v.at(R(pi)) in M.tangent_space(c(R(pi)))
228
+ True
229
+ sage: v.at(R(pi)).display()
230
+ c' = -∂/∂x + ∂/∂y
231
+
232
+ Curves `\RR \to \RR` can be composed: the operator `\circ` is
233
+ given by ``*``::
234
+
235
+ sage: f = R.curve(t^2, (t,-oo,+oo))
236
+ sage: g = R.curve(cos(t), (t,-oo,+oo))
237
+ sage: s = g*f ; s
238
+ Differentiable map from the Real number line ℝ to itself
239
+ sage: s.display()
240
+ ℝ → ℝ
241
+ t ↦ cos(t^2)
242
+ sage: s = f*g ; s
243
+ Differentiable map from the Real number line ℝ to itself
244
+ sage: s.display()
245
+ ℝ → ℝ
246
+ t ↦ cos(t)^2
247
+
248
+ .. RUBRIC:: Curvature and torsion of a curve in a Riemannian manifold
249
+
250
+ Let us consider a helix `C` in the Euclidean space `\mathbb{E}^3`
251
+ parametrized by its arc length `s`::
252
+
253
+ sage: E.<x,y,z> = EuclideanSpace()
254
+ sage: R.<s> = manifolds.RealLine()
255
+ sage: C = E.curve((2*cos(s/3), 2*sin(s/3), sqrt(5)*s/3), (s, 0, 6*pi),
256
+ ....: name='C')
257
+
258
+ Its tangent vector field is::
259
+
260
+ sage: T = C.tangent_vector_field()
261
+ sage: T.display()
262
+ C' = -2/3*sin(1/3*s) e_x + 2/3*cos(1/3*s) e_y + 1/3*sqrt(5) e_z
263
+
264
+ Since `C` is parametrized by its arc length `s`, `T` is a unit vector (with
265
+ respect to the Euclidean metric of `\mathbb{E}^3`)::
266
+
267
+ sage: norm(T)
268
+ Scalar field |C'| on the Real interval (0, 6*pi)
269
+ sage: norm(T).display()
270
+ |C'|: (0, 6*pi) → ℝ
271
+ s ↦ 1
272
+
273
+ Vector fields along `C` are defined by the method
274
+ :meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.vector_field`
275
+ of the domain of `C` with the keyword argument ``dest_map`` set to `C`. For
276
+ instance the derivative vector `T'=\mathrm{d}T/\mathrm{d}s` is::
277
+
278
+ sage: I = C.domain(); I
279
+ Real interval (0, 6*pi)
280
+ sage: Tp = I.vector_field([diff(T[i], s) for i in E.irange()], dest_map=C,
281
+ ....: name="T'")
282
+ sage: Tp.display()
283
+ T' = -2/9*cos(1/3*s) e_x - 2/9*sin(1/3*s) e_y
284
+
285
+ The norm of `T'` is the curvature of the helix::
286
+
287
+ sage: kappa = norm(Tp)
288
+ sage: kappa
289
+ Scalar field |T'| on the Real interval (0, 6*pi)
290
+ sage: kappa.expr()
291
+ 2/9
292
+
293
+ The unit normal vector along `C` is::
294
+
295
+ sage: N = Tp / kappa
296
+ sage: N.display()
297
+ -cos(1/3*s) e_x - sin(1/3*s) e_y
298
+
299
+ while the binormal vector along `C` is `B = T \times N`::
300
+
301
+ sage: B = T.cross_product(N)
302
+ sage: B
303
+ Vector field along the Real interval (0, 6*pi) with values on the
304
+ Euclidean space E^3
305
+ sage: B.display()
306
+ 1/3*sqrt(5)*sin(1/3*s) e_x - 1/3*sqrt(5)*cos(1/3*s) e_y + 2/3 e_z
307
+
308
+ The three vector fields `(T, N, B)` form the **Frenet-Serret frame** along
309
+ `C`::
310
+
311
+ sage: FS = I.vector_frame(('T', 'N', 'B'), (T, N, B),
312
+ ....: symbol_dual=('t', 'n', 'b'))
313
+ sage: FS
314
+ Vector frame ((0, 6*pi), (T,N,B)) with values on the Euclidean space E^3
315
+
316
+ The Frenet-Serret frame is orthonormal::
317
+
318
+ sage: matrix([[u.dot(v).expr() for v in FS] for u in FS])
319
+ [1 0 0]
320
+ [0 1 0]
321
+ [0 0 1]
322
+
323
+ The derivative vectors `N'` and `B'`::
324
+
325
+ sage: Np = I.vector_field([diff(N[i], s) for i in E.irange()],
326
+ ....: dest_map=C, name="N'")
327
+ sage: Np.display()
328
+ N' = 1/3*sin(1/3*s) e_x - 1/3*cos(1/3*s) e_y
329
+ sage: Bp = I.vector_field([diff(B[i], s) for i in E.irange()],
330
+ ....: dest_map=C, name="B'")
331
+ sage: Bp.display()
332
+ B' = 1/9*sqrt(5)*cos(1/3*s) e_x + 1/9*sqrt(5)*sin(1/3*s) e_y
333
+
334
+ The Frenet-Serret formulas::
335
+
336
+ sage: for v in (Tp, Np, Bp):
337
+ ....: v.display(FS)
338
+ ....:
339
+ T' = 2/9 N
340
+ N' = -2/9 T + 1/9*sqrt(5) B
341
+ B' = -1/9*sqrt(5) N
342
+
343
+ The torsion of `C` is obtained as the third component of `N'` in the
344
+ Frenet-Serret frame::
345
+
346
+ sage: tau = Np[FS, 3]
347
+ sage: tau
348
+ 1/9*sqrt(5)
349
+ """
350
+ def __init__(self, parent, coord_expression=None, name=None,
351
+ latex_name=None, is_isomorphism=False, is_identity=False):
352
+ r"""
353
+ Construct a curve.
354
+
355
+ TESTS::
356
+
357
+ sage: M = Manifold(2, 'M')
358
+ sage: X.<x,y> = M.chart()
359
+ sage: R.<t> = manifolds.RealLine()
360
+ sage: I = R.open_interval(0, 2*pi)
361
+ sage: c = Hom(I,M)({X: (cos(t), sin(2*t))}, name='c') ; c
362
+ Curve c in the 2-dimensional differentiable manifold M
363
+ sage: TestSuite(c).run()
364
+
365
+ The identity of interval ``I``::
366
+
367
+ sage: c = Hom(I,I)({}, is_identity=True) ; c
368
+ Identity map Id_(0, 2*pi) of the Real interval (0, 2*pi)
369
+ sage: TestSuite(c).run()
370
+ """
371
+ if coord_expression is None:
372
+ coord_functions = None
373
+ else:
374
+ if not isinstance(coord_expression, dict):
375
+ raise TypeError("{} is not a dictionary".format(
376
+ coord_expression))
377
+ param_chart = parent.domain().canonical_chart()
378
+ coord_functions = {}
379
+ for chart, expr in coord_expression.items():
380
+ if isinstance(chart, tuple):
381
+ # a pair of charts is passed:
382
+ coord_functions[chart] = expr
383
+ else:
384
+ coord_functions[(param_chart, chart)] = expr
385
+ DiffMap.__init__(self, parent, coord_functions=coord_functions,
386
+ name=name, latex_name=latex_name,
387
+ is_isomorphism=is_isomorphism,
388
+ is_identity=is_identity)
389
+
390
+ def _repr_(self):
391
+ r"""
392
+ Return a string representation of ``self``.
393
+
394
+ TESTS::
395
+
396
+ sage: M = Manifold(2, 'M')
397
+ sage: X.<x,y> = M.chart()
398
+ sage: R.<t> = manifolds.RealLine()
399
+ sage: M.curve([cos(t), sin(2*t)], (t, 0, 2*pi))
400
+ Curve in the 2-dimensional differentiable manifold M
401
+ sage: M.curve([cos(t), sin(2*t)], (t, 0, 2*pi), name='c')
402
+ Curve c in the 2-dimensional differentiable manifold M
403
+ """
404
+ if self._codomain._dim == 1:
405
+ return DiffMap._repr_(self)
406
+ description = "Curve "
407
+ if self._name is not None:
408
+ description += self._name + " "
409
+ description += "in the {}".format(self._codomain)
410
+ return description
411
+
412
+ def __reduce__(self):
413
+ r"""
414
+ Reduction function for the pickle protocole.
415
+
416
+ TESTS::
417
+
418
+ sage: M = Manifold(2, 'M')
419
+ sage: X.<x,y> = M.chart()
420
+ sage: R.<t> = manifolds.RealLine()
421
+ sage: c = M.curve([cos(t), sin(2*t)], (t, 0, 2*pi))
422
+ sage: c.__reduce__()
423
+ (<class 'sage.manifolds.differentiable.manifold_homset.DifferentiableCurveSet_with_category.element_class'>,
424
+ (Set of Morphisms from Real interval (0, 2*pi) to 2-dimensional
425
+ differentiable manifold M in Category of smooth manifolds over
426
+ Real Field with 53 bits of precision,
427
+ None,
428
+ None,
429
+ None,
430
+ False,
431
+ False))
432
+
433
+ Test of pickling::
434
+
435
+ sage: loads(dumps(c))
436
+ Curve in the 2-dimensional differentiable manifold M
437
+ """
438
+ return (type(self), (self.parent(), None, self._name, self._latex_name,
439
+ self._is_isomorphism, self._is_identity))
440
+
441
+ def coord_expr(self, chart=None):
442
+ r"""
443
+ Return the coordinate functions expressing the curve in a given chart.
444
+
445
+ INPUT:
446
+
447
+ - ``chart`` -- (default: ``None``) chart on the curve's codomain; if
448
+ ``None``, the codomain's default chart is assumed
449
+
450
+ OUTPUT: symbolic expression representing the curve in the above chart
451
+
452
+ EXAMPLES:
453
+
454
+ Cartesian and polar expression of a curve in the Euclidean plane::
455
+
456
+ sage: M = Manifold(2, 'R^2', r'\RR^2') # the Euclidean plane R^2
457
+ sage: c_xy.<x,y> = M.chart() # Cartesian coordinate on R^2
458
+ sage: U = M.open_subset('U', coord_def={c_xy: (y!=0, x<0)}) # the complement of the segment y=0 and x>0
459
+ sage: c_cart = c_xy.restrict(U) # Cartesian coordinates on U
460
+ sage: c_spher.<r,ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi') # spherical coordinates on U
461
+
462
+ Links between spherical coordinates and Cartesian ones::
463
+
464
+ sage: ch_cart_spher = c_cart.transition_map(c_spher, [sqrt(x*x+y*y), atan2(y,x)])
465
+ sage: ch_cart_spher.set_inverse(r*cos(ph), r*sin(ph))
466
+ Check of the inverse coordinate transformation:
467
+ x == x *passed*
468
+ y == y *passed*
469
+ r == r *passed*
470
+ ph == arctan2(r*sin(ph), r*cos(ph)) **failed**
471
+ NB: a failed report can reflect a mere lack of simplification.
472
+ sage: R.<t> = manifolds.RealLine()
473
+ sage: c = U.curve({c_spher: (1,t)}, (t, 0, 2*pi), name='c')
474
+ sage: c.coord_expr(c_spher)
475
+ (1, t)
476
+ sage: c.coord_expr(c_cart)
477
+ (cos(t), sin(t))
478
+
479
+ Since ``c_cart`` is the default chart on ``U``, it can be omitted::
480
+
481
+ sage: c.coord_expr()
482
+ (cos(t), sin(t))
483
+
484
+ Cartesian expression of a cardioid::
485
+
486
+ sage: c = U.curve({c_spher: (2*(1+cos(t)), t)}, (t, 0, 2*pi), name='c')
487
+ sage: c.coord_expr(c_cart)
488
+ (2*cos(t)^2 + 2*cos(t), 2*(cos(t) + 1)*sin(t))
489
+ """
490
+ return self.expr(chart1=self._domain.canonical_chart(), chart2=chart)
491
+
492
+ def __call__(self, t, simplify=True):
493
+ r"""
494
+ Image for a given value of the curve parameter.
495
+
496
+ This is a redefinition of :meth:`sage.categories.map.Map.__call__`
497
+ to allow for the direct call with some value of the parameter
498
+ (numerical value or symbolic expression) instead of the element
499
+ (ManifoldPoint) of the domain corresponding to that value.
500
+
501
+ EXAMPLES:
502
+
503
+ Points on circle in the Euclidean plane::
504
+
505
+ sage: M = Manifold(2, 'M')
506
+ sage: X.<x,y> = M.chart()
507
+ sage: R.<t> = manifolds.RealLine()
508
+ sage: c = M.curve([cos(t), sin(t)], (t, 0, 2*pi), name='c')
509
+ sage: c(0)
510
+ Point c(0) on the 2-dimensional differentiable manifold M
511
+ sage: c(0) in M
512
+ True
513
+ sage: c(0).coord(X)
514
+ (1, 0)
515
+ sage: c(pi/4).coord(X)
516
+ (1/2*sqrt(2), 1/2*sqrt(2))
517
+ sage: c(t)
518
+ Point c(t) on the 2-dimensional differentiable manifold M
519
+ sage: c(t).coord(X)
520
+ (cos(t), sin(t))
521
+ """
522
+ # Case of a point in the domain:
523
+ if isinstance(t, ManifoldPoint):
524
+ return DiffMap.__call__(self, t)
525
+
526
+ # Case of a value of the canonical coordinate in the domain:
527
+ codom = self._codomain
528
+ canon_chart = self._domain._canon_chart
529
+ canon_coord = canon_chart._xx[0]
530
+ if (canon_chart, codom._def_chart) in self._coord_expression:
531
+ chart_pair = (canon_chart, codom._def_chart)
532
+ else:
533
+ chart_pair = next(iter(self._coord_expression.keys()))
534
+ # a chart is picked at random
535
+ coord_functions = self._coord_expression[chart_pair]._functions
536
+ n = codom._dim
537
+ dict_subs = {canon_coord: t}
538
+ coords = [coord_functions[i].expr().substitute(dict_subs)
539
+ for i in range(n)]
540
+ if simplify:
541
+ coords = [chart_pair[0].simplify(coords[i]) for i in range(n)]
542
+ if self._name is not None:
543
+ name = "{}({})".format(self._name, t)
544
+ else:
545
+ name = None
546
+ if self._latex_name is not None:
547
+ latex_name = r"{}\left({}\right)".format(self._latex_name, latex(t))
548
+ else:
549
+ latex_name = None
550
+ return codom.element_class(codom, coords=coords, chart=chart_pair[1],
551
+ name=name, latex_name=latex_name,
552
+ check_coords=False)
553
+
554
+ def tangent_vector_field(self, name=None, latex_name=None):
555
+ r"""
556
+ Return the tangent vector field to the curve (velocity vector).
557
+
558
+ INPUT:
559
+
560
+ - ``name`` -- (default: ``None``) string; symbol given to the tangent
561
+ vector field; if none is provided, the primed curve symbol (if any)
562
+ will be used
563
+ - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote
564
+ the tangent vector field; if ``None`` then (i) if ``name`` is
565
+ ``None`` as well, the primed curve LaTeX symbol (if any) will be
566
+ used or (ii) if ``name`` is not ``None``, ``name`` will be used
567
+
568
+ OUTPUT:
569
+
570
+ - the tangent vector field, as an instance of
571
+ :class:`~sage.manifolds.differentiable.vectorfield.VectorField`
572
+
573
+ EXAMPLES:
574
+
575
+ Tangent vector field to a circle curve in `\RR^2`::
576
+
577
+ sage: M = Manifold(2, 'R^2')
578
+ sage: X.<x,y> = M.chart()
579
+ sage: R.<t> = manifolds.RealLine()
580
+ sage: c = M.curve([cos(t), sin(t)], (t, 0, 2*pi), name='c')
581
+ sage: v = c.tangent_vector_field() ; v
582
+ Vector field c' along the Real interval (0, 2*pi) with values on
583
+ the 2-dimensional differentiable manifold R^2
584
+ sage: v.display()
585
+ c' = -sin(t) ∂/∂x + cos(t) ∂/∂y
586
+ sage: latex(v)
587
+ {c'}
588
+ sage: v.parent()
589
+ Free module X((0, 2*pi),c) of vector fields along the Real interval
590
+ (0, 2*pi) mapped into the 2-dimensional differentiable manifold R^2
591
+
592
+ Value of the tangent vector field for some specific value of the
593
+ curve parameter (`t = \pi`)::
594
+
595
+ sage: R(pi) in c.domain() # pi in (0, 2*pi)
596
+ True
597
+ sage: vp = v.at(R(pi)) ; vp
598
+ Tangent vector c' at Point on the 2-dimensional differentiable
599
+ manifold R^2
600
+ sage: vp.parent() is M.tangent_space(c(R(pi)))
601
+ True
602
+ sage: vp.display()
603
+ c' = -∂/∂y
604
+
605
+ Tangent vector field to a curve in a non-parallelizable manifold (the
606
+ 2-sphere `S^2`): first, we introduce the 2-sphere::
607
+
608
+ sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
609
+ sage: U = M.open_subset('U') # complement of the North pole
610
+ sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
611
+ sage: V = M.open_subset('V') # complement of the South pole
612
+ sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
613
+ sage: M.declare_union(U,V) # S^2 is the union of U and V
614
+ sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
615
+ ....: intersection_name='W', restrictions1= x^2+y^2!=0,
616
+ ....: restrictions2= u^2+v^2!=0)
617
+ sage: uv_to_xy = xy_to_uv.inverse()
618
+ sage: W = U.intersection(V)
619
+ sage: A = W.open_subset('A', coord_def={c_xy.restrict(W): (y!=0, x<0)})
620
+ sage: c_spher.<th,ph> = A.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') # spherical coordinates
621
+ sage: spher_to_xy = c_spher.transition_map(c_xy.restrict(A),
622
+ ....: (sin(th)*cos(ph)/(1-cos(th)), sin(th)*sin(ph)/(1-cos(th))) )
623
+ sage: spher_to_xy.set_inverse(2*atan(1/sqrt(x^2+y^2)), atan2(y, x), check=False)
624
+
625
+ Then we define a curve (a loxodrome) by its expression in terms of
626
+ spherical coordinates and evaluate the tangent vector field::
627
+
628
+ sage: R.<t> = manifolds.RealLine()
629
+ sage: c = M.curve({c_spher: [2*atan(exp(-t/10)), t]}, (t, -oo, +oo),
630
+ ....: name='c') ; c
631
+ Curve c in the 2-dimensional differentiable manifold M
632
+ sage: vc = c.tangent_vector_field() ; vc
633
+ Vector field c' along the Real number line ℝ with values on
634
+ the 2-dimensional differentiable manifold M
635
+ sage: vc.parent()
636
+ Module X(ℝ,c) of vector fields along the Real number line ℝ
637
+ mapped into the 2-dimensional differentiable manifold M
638
+ sage: vc.display(c_spher.frame().along(c.restrict(R,A)))
639
+ c' = -1/5*e^(1/10*t)/(e^(1/5*t) + 1) ∂/∂th + ∂/∂ph
640
+ """
641
+ vmodule = self._domain.vector_field_module(dest_map=self)
642
+ if latex_name is None:
643
+ if name is None:
644
+ if self._latex_name is not None:
645
+ latex_name = r"{%s'}" % (self._latex_name)
646
+ else:
647
+ latex_name = name
648
+ if name is None and self._name is not None:
649
+ name = self._name + "'"
650
+ resu = vmodule.element_class(vmodule, name=name, latex_name=latex_name)
651
+ canon_chart = self._domain.canonical_chart()
652
+ codom = self._codomain
653
+ dim = codom._dim
654
+ codom_top_charts = codom._top_charts
655
+ for chart in codom_top_charts:
656
+ try:
657
+ jacob = self.differential_functions(canon_chart, chart)
658
+ restrict = self.restrict(canon_chart.domain(),
659
+ subcodomain=chart.domain())
660
+ fmodule = restrict._domain.vector_field_module(dest_map=restrict)
661
+ frame = fmodule.basis(from_frame=chart.frame())
662
+ resu_rest = resu.restrict(canon_chart.domain(), dest_map=restrict)
663
+ resu_rest.add_comp(frame)[:, canon_chart] = [jacob[i][0]
664
+ for i in range(dim)]
665
+ except ValueError:
666
+ pass
667
+ return resu
668
+
669
+ @options(thickness=1, plot_points=75, max_range=8, aspect_ratio='automatic')
670
+ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None,
671
+ include_end_point=(True, True), end_point_offset=(0.001, 0.001),
672
+ parameters=None, color='red', style='-', label_axes=True, **kwds):
673
+ r"""
674
+ Plot the current curve in a Cartesian graph based on the
675
+ coordinates of some ambient chart.
676
+
677
+ The curve is drawn in terms of two (2D graphics) or three (3D graphics)
678
+ coordinates of a given chart, called hereafter the *ambient chart*.
679
+ The ambient chart's domain must overlap with the curve's codomain or
680
+ with the codomain of the composite curve `\Phi\circ c`, where `c` is
681
+ the current curve and `\Phi` some manifold differential map (argument
682
+ ``mapping`` below).
683
+
684
+ INPUT:
685
+
686
+ - ``chart`` -- (default: ``None``) the ambient chart (see above);
687
+ if ``None``, the default chart of the codomain of the curve (or of
688
+ the curve composed with `\Phi`) is used
689
+
690
+ - ``ambient_coords`` -- (default: ``None``) tuple containing the 2
691
+ or 3 coordinates of the ambient chart in terms of which the plot
692
+ is performed; if ``None``, all the coordinates of the ambient chart
693
+ are considered
694
+
695
+ - ``mapping`` -- (default: ``None``) differentiable mapping `\Phi`
696
+ (instance of
697
+ :class:`~sage.manifolds.differentiable.diff_map.DiffMap`)
698
+ providing the link between the curve and the ambient chart ``chart``
699
+ (cf. above); if ``None``, the ambient chart is supposed to be defined
700
+ on the codomain of the curve.
701
+
702
+ - ``prange`` -- (default: ``None``) range of the curve parameter for
703
+ the plot; if ``None``, the entire parameter range declared during the
704
+ curve construction is considered (with -Infinity
705
+ replaced by ``-max_range`` and +Infinity by ``max_range``)
706
+
707
+ - ``include_end_point`` -- (default: ``(True, True)``) determines
708
+ whether the end points of ``prange`` are included in the plot
709
+
710
+ - ``end_point_offset`` -- (default: ``(0.001, 0.001)``) offsets from
711
+ the end points when they are not included in the plot: if
712
+ ``include_end_point[0] == False``, the minimal value of the curve
713
+ parameter used for the plot is ``prange[0] + end_point_offset[0]``,
714
+ while if ``include_end_point[1] == False``, the maximal value is
715
+ ``prange[1] - end_point_offset[1]``.
716
+
717
+ - ``max_range`` -- (default: 8) numerical value substituted to
718
+ +Infinity if the latter is the upper bound of the parameter range;
719
+ similarly ``-max_range`` is the numerical valued substituted for
720
+ -Infinity
721
+
722
+ - ``parameters`` -- (default: ``None``) dictionary giving the numerical
723
+ values of the parameters that may appear in the coordinate expression
724
+ of the curve
725
+
726
+ - ``color`` -- (default: ``'red'``) color of the drawn curve
727
+
728
+ - ``style`` -- (default: ``'-'``) color of the drawn curve; NB: ``style``
729
+ is effective only for 2D plots
730
+
731
+ - ``thickness`` -- (default: 1) thickness of the drawn curve
732
+
733
+ - ``plot_points`` -- (default: 75) number of points to plot the curve
734
+
735
+ - ``label_axes`` -- boolean (default: ``True``); determining whether the
736
+ labels of the coordinate axes of ``chart`` shall be added to the
737
+ graph; can be set to ``False`` if the graph is 3D and must be
738
+ superposed with another graph.
739
+
740
+ - ``aspect_ratio`` -- (default: ``'automatic'``) aspect ratio of the
741
+ plot; the default value (``'automatic'``) applies only for 2D plots;
742
+ for 3D plots, the default value is ``1`` instead
743
+
744
+ OUTPUT:
745
+
746
+ - a graphic object, either an instance of
747
+ :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
748
+ 2 coordinates of ``chart``) or an instance of
749
+ :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
750
+ based on 3 coordinates of ``chart``)
751
+
752
+ EXAMPLES:
753
+
754
+ Plot of the lemniscate of Gerono::
755
+
756
+ sage: R2 = Manifold(2, 'R^2')
757
+ sage: X.<x,y> = R2.chart()
758
+ sage: R.<t> = manifolds.RealLine()
759
+ sage: c = R2.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
760
+ sage: c.plot() # 2D plot # needs sage.plot
761
+ Graphics object consisting of 1 graphics primitive
762
+
763
+ .. PLOT::
764
+
765
+ R2 = Manifold(2, 'R^2')
766
+ X = R2.chart('x y')
767
+ t = manifolds.RealLine().canonical_coordinate()
768
+ c = R2.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
769
+ g = c.plot()
770
+ sphinx_plot(g)
771
+
772
+ Plot for a subinterval of the curve's domain::
773
+
774
+ sage: c.plot(prange=(0,pi)) # needs sage.plot
775
+ Graphics object consisting of 1 graphics primitive
776
+
777
+ .. PLOT::
778
+
779
+ R2 = Manifold(2, 'R^2')
780
+ X = R2.chart('x y')
781
+ t = manifolds.RealLine().canonical_coordinate()
782
+ c = R2.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
783
+ g = c.plot(prange=(0,pi))
784
+ sphinx_plot(g)
785
+
786
+ Plot with various options::
787
+
788
+ sage: c.plot(color='green', style=':', thickness=3, aspect_ratio=1) # needs sage.plot
789
+ Graphics object consisting of 1 graphics primitive
790
+
791
+ .. PLOT::
792
+
793
+ R2 = Manifold(2, 'R^2')
794
+ X = R2.chart('x y')
795
+ t = manifolds.RealLine().canonical_coordinate()
796
+ c = R2.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
797
+ g = c.plot(color='green', style=':', thickness=3, aspect_ratio=1)
798
+ sphinx_plot(g)
799
+
800
+ Cardioid defined in terms of polar coordinates and plotted with respect
801
+ to Cartesian coordinates, as an example of use of the optional argument
802
+ ``chart``::
803
+
804
+ sage: E.<r,ph> = EuclideanSpace(coordinates='polar')
805
+ sage: c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi))
806
+ sage: c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1) # needs sage.plot
807
+ Graphics object consisting of 1 graphics primitive
808
+
809
+ .. PLOT::
810
+
811
+ E = EuclideanSpace(2, coordinates='polar')
812
+ r, ph = E.polar_coordinates()[:]
813
+ c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi))
814
+ g = c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1)
815
+ sphinx_plot(g)
816
+
817
+ Plot via a mapping to another manifold: loxodrome of a sphere viewed
818
+ in `\RR^3`::
819
+
820
+ sage: S2 = Manifold(2, 'S^2')
821
+ sage: U = S2.open_subset('U')
822
+ sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
823
+ sage: R3 = Manifold(3, 'R^3')
824
+ sage: X3.<x,y,z> = R3.chart()
825
+ sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph),
826
+ ....: sin(th)*sin(ph), cos(th)]}, name='F')
827
+ sage: F.display()
828
+ F: S^2 → R^3
829
+ on U: (th, ph) ↦ (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
830
+ sage: c = S2.curve([2*atan(exp(-t/10)), t], (t, -oo, +oo), name='c')
831
+ sage: graph_c = c.plot(mapping=F, max_range=40, # needs sage.plot
832
+ ....: plot_points=200, thickness=2, label_axes=False) # 3D plot
833
+ sage: graph_S2 = XS.plot(X3, mapping=F, # plot of the sphere # needs sage.plot
834
+ ....: number_values=11, color='black')
835
+ sage: show(graph_c + graph_S2) # the loxodrome + the sphere # needs sage.plot
836
+
837
+ .. PLOT::
838
+
839
+ S2 = Manifold(2, 'S^2')
840
+ U = S2.open_subset('U')
841
+ XS = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
842
+ th, ph = XS[:]
843
+ R3 = Manifold(3, 'R^3')
844
+ X3 = R3.chart('x y z')
845
+ F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), sin(th)*sin(ph),
846
+ cos(th)]}, name='F')
847
+ t = manifolds.RealLine().canonical_coordinate()
848
+ c = S2.curve([2*atan(exp(-t/10)), t], (t, -oo, +oo), name='c')
849
+ graph_c = c.plot(mapping=F, max_range=40, plot_points=200,
850
+ thickness=2, label_axes=False)
851
+ graph_S2 = XS.plot(X3, mapping=F, number_values=11, color='black')
852
+ sphinx_plot(graph_c + graph_S2)
853
+
854
+ Example of use of the argument ``parameters``: we define a curve with
855
+ some symbolic parameters ``a`` and ``b``::
856
+
857
+ sage: a, b = var('a b')
858
+ sage: c = R2.curve([a*cos(t) + b, a*sin(t)], (t, 0, 2*pi), name='c')
859
+
860
+ To make a plot, we set specific values for ``a`` and ``b`` by means
861
+ of the Python dictionary ``parameters``::
862
+
863
+ sage: c.plot(parameters={a: 2, b: -3}, aspect_ratio=1) # needs sage.plot
864
+ Graphics object consisting of 1 graphics primitive
865
+
866
+ .. PLOT::
867
+
868
+ R2 = Manifold(2, 'R^2')
869
+ X = R2.chart('x y')
870
+ t = manifolds.RealLine().canonical_coordinate()
871
+ a, b = var('a b')
872
+ c = R2.curve([a*cos(t) + b, a*sin(t)], (t, 0, 2*pi), name='c')
873
+ g = c.plot(parameters={a: 2, b: -3}, aspect_ratio=1)
874
+ sphinx_plot(g)
875
+ """
876
+ from sage.manifolds.chart import RealChart
877
+ from sage.misc.functional import numerical_approx
878
+ from sage.rings.infinity import Infinity
879
+
880
+ #
881
+ # Get the @options from kwds
882
+ #
883
+ thickness = kwds.pop('thickness')
884
+ plot_points = kwds.pop('plot_points')
885
+ max_range = kwds.pop('max_range')
886
+ aspect_ratio = kwds.pop('aspect_ratio')
887
+ #
888
+ # The "effective" curve to be plotted
889
+ #
890
+ if mapping is None:
891
+ eff_curve = self
892
+ else:
893
+ eff_curve = mapping.restrict(self.codomain()) * self
894
+ #
895
+ # The chart w.r.t. which the curve is plotted
896
+ #
897
+ if chart is None:
898
+ chart = eff_curve._codomain.default_chart()
899
+ elif not isinstance(chart, RealChart):
900
+ raise TypeError("{} is not a real chart".format(chart))
901
+ #
902
+ # Coordinates of the above chart w.r.t. which the curve is plotted
903
+ #
904
+ if ambient_coords is None:
905
+ ambient_coords = chart[:] # all chart coordinates are used
906
+ n_pc = len(ambient_coords)
907
+ if n_pc != 2 and n_pc != 3:
908
+ raise ValueError("the number of coordinates involved in the " +
909
+ "plot must be either 2 or 3, not {}".format(n_pc))
910
+ # indices of plot coordinates
911
+ ind_pc = [chart[:].index(pc) for pc in ambient_coords]
912
+ #
913
+ # Parameter range for the plot
914
+ #
915
+ if prange is None:
916
+ prange = (self._domain.lower_bound(), self._domain.upper_bound())
917
+ elif not isinstance(prange, (tuple, list)):
918
+ raise TypeError("{} is neither a tuple nor a list".format(prange))
919
+ elif len(prange) != 2:
920
+ raise ValueError("the argument prange must be a tuple/list " +
921
+ "of 2 elements")
922
+ tmin = prange[0]
923
+ tmax = prange[1]
924
+ if tmin == -Infinity:
925
+ tmin = -max_range
926
+ elif not include_end_point[0]:
927
+ tmin = tmin + end_point_offset[0]
928
+ if tmax == Infinity:
929
+ tmax = max_range
930
+ elif not include_end_point[1]:
931
+ tmax = tmax - end_point_offset[1]
932
+ tmin = numerical_approx(tmin)
933
+ tmax = numerical_approx(tmax)
934
+ #
935
+ # The coordinate expression of the effective curve
936
+ #
937
+ transf = eff_curve.coord_functions(chart1=self._domain.canonical_chart(),
938
+ chart2=chart)
939
+ #
940
+ # List of points for the plot curve
941
+ #
942
+ plot_curve = []
943
+ dt = (tmax - tmin) / (plot_points - 1)
944
+ t = tmin
945
+ if parameters is None:
946
+ for i in range(plot_points):
947
+ x = transf(t, simplify=False)
948
+ plot_curve.append( [numerical_approx(x[j]) for j in ind_pc] )
949
+ t += dt
950
+ else:
951
+ for i in range(plot_points):
952
+ x = transf(t, simplify=False)
953
+ plot_curve.append(
954
+ [numerical_approx( x[j].substitute(parameters) )
955
+ for j in ind_pc] )
956
+ t += dt
957
+
958
+ return self._graphics(plot_curve, ambient_coords,
959
+ thickness=thickness,
960
+ aspect_ratio=aspect_ratio, color=color,
961
+ style=style, label_axes=label_axes)
962
+
963
+ def _graphics(self, plot_curve, ambient_coords, thickness=1,
964
+ aspect_ratio='automatic', color='red', style='-',
965
+ label_axes=True):
966
+ r"""
967
+ Plot a 2D or 3D curve in a Cartesian graph with axes labeled by
968
+ the ambient coordinates; it is invoked by the methods
969
+ :meth:`plot` of
970
+ :class:`~sage.manifolds.differentiable.curve.DifferentiableCurve`,
971
+ and its subclasses
972
+ (:class:`~sage.manifolds.differentiable.integrated_curve.IntegratedCurve`,
973
+ :class:`~sage.manifolds.differentiable.integrated_curve.IntegratedAutoparallelCurve`,
974
+ and
975
+ :class:`~sage.manifolds.differentiable.integrated_curve.IntegratedGeodesic`).
976
+
977
+ TESTS::
978
+
979
+ sage: # needs sage.plot
980
+ sage: M = Manifold(2, 'R^2')
981
+ sage: X.<x,y> = M.chart()
982
+ sage: R.<t> = manifolds.RealLine()
983
+ sage: c = M.curve([cos(t), sin(t)], (t, 0, 2*pi), name='c')
984
+ sage: graph = c._graphics([[1,2], [3,4]], [x,y])
985
+ sage: graph._objects[0].xdata == [1,3]
986
+ True
987
+ sage: graph._objects[0].ydata == [2,4]
988
+ True
989
+ sage: graph._objects[0]._options['thickness'] == 1
990
+ True
991
+ sage: graph._extra_kwds['aspect_ratio'] == 'automatic'
992
+ True
993
+ sage: graph._objects[0]._options['rgbcolor'] == 'red'
994
+ True
995
+ sage: graph._objects[0]._options['linestyle'] == '-'
996
+ True
997
+ sage: l = [r'$'+latex(x)+r'$', r'$'+latex(y)+r'$']
998
+ sage: graph._extra_kwds['axes_labels'] == l
999
+ True
1000
+ """
1001
+ from sage.manifolds.utilities import set_axes_labels
1002
+ from sage.plot.graphics import Graphics
1003
+ from sage.plot.line import line
1004
+
1005
+ #
1006
+ # The plot
1007
+ #
1008
+ n_pc = len(ambient_coords)
1009
+ resu = Graphics()
1010
+ resu += line(plot_curve, color=color, linestyle=style,
1011
+ thickness=thickness)
1012
+ if n_pc == 2: # 2D graphic
1013
+ resu.set_aspect_ratio(aspect_ratio)
1014
+ if label_axes:
1015
+ # We update the dictionary _extra_kwds (options to be passed
1016
+ # to show()), instead of using the method
1017
+ # Graphics.axes_labels() since the latter is not robust w.r.t.
1018
+ # graph addition
1019
+ resu._extra_kwds['axes_labels'] = [r'$'+latex(pc)+r'$'
1020
+ for pc in ambient_coords]
1021
+ else: # 3D graphic
1022
+ if aspect_ratio == 'automatic':
1023
+ aspect_ratio = 1
1024
+ resu.aspect_ratio(aspect_ratio)
1025
+ if label_axes:
1026
+ labels = [str(pc) for pc in ambient_coords]
1027
+ resu = set_axes_labels(resu, *labels)
1028
+ return resu