Curves in Manifolds¶
Given a differentiable manifold \(M\), a differentiable curve curve in \(M\) is a differentiable mapping
where \(I\) is an interval of \(\RR\).
Differentiable curves are implemented by DifferentiableCurve
.
AUTHORS:
 Eric Gourgoulhon (2015): initial version
 Travis Scrimshaw (2016): review tweaks
REFERENCES:

class
sage.manifolds.differentiable.curve.
DifferentiableCurve
(parent, coord_expression=None, name=None, latex_name=None, is_isomorphism=False, is_identity=False)¶ Bases:
sage.manifolds.differentiable.diff_map.DiffMap
Curve in a differentiable manifold.
Given a differentiable manifold \(M\), a differentiable curve in \(M\) is a differentiable map
\[\gamma: I \longrightarrow M,\]where \(I\) is an interval of \(\RR\).
INPUT:
parent
–DifferentiableCurveSet
the set of curves \(\mathrm{Hom}(I, M)\) to which the curve belongscoord_expression
– (default:None
) dictionary (possibly empty) of the functions of the curve parameter \(t\) expressing the curve in various charts of \(M\), the keys of the dictionary being the charts and the values being lists or tuples of \(n\) symbolic expressions of \(t\), where \(n\) is the dimension of \(M\)name
– (default:None
) string; symbol given to the curvelatex_name
– (default:None
) string; LaTeX symbol to denote the curve; if none is provided,name
will be usedis_isomorphism
– (default:False
) determines whether the constructed object is a diffeomorphism; if set toTrue
, then \(M\) must have dimension oneis_identity
– (default:False
) determines whether the constructed object is the identity map; if set toTrue
, then \(M\) must be the interval \(I\)
EXAMPLES:
The lemniscate of Gerono in the 2dimensional Euclidean plane:
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: t = var('t') sage: c = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi), name='c') ; c Curve c in the 2dimensional differentiable manifold M sage: type(c) <class 'sage.manifolds.differentiable.manifold_homset.DifferentiableCurveSet_with_category.element_class'>
Instead of declaring the parameter \(t\) as a symbolic variable by means of
var('t')
, it is equivalent to get it as the canonical coordinate of the real number line (seeRealLine
):sage: R.<t> = RealLine() sage: c = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi), name='c') ; c Curve c in the 2dimensional differentiable manifold M
A graphical view of the curve is provided by the method
plot()
:sage: c.plot(aspect_ratio=1) Graphics object consisting of 1 graphics primitive
Curves are considered as (manifold) morphisms from real intervals to differentiable manifolds:
sage: c.parent() Set of Morphisms from Real interval (0, 2*pi) to 2dimensional differentiable manifold M in Join of Category of subobjects of sets and Category of smooth manifolds over Real Field with 53 bits of precision sage: I = R.open_interval(0, 2*pi) sage: c.parent() is Hom(I, M) True sage: c.domain() Real interval (0, 2*pi) sage: c.domain() is I True sage: c.codomain() 2dimensional differentiable manifold M
Accordingly, all methods of
DiffMap
are available for them. In particular, the methoddisplay()
shows the coordinate representations in various charts of manifoldM
:sage: c.display() c: (0, 2*pi) > M t > (x, y) = (sin(t), 1/2*sin(2*t))
Another map method is using the usual call syntax, which returns the image of a point in the curve’s domain:
sage: t0 = pi/2 sage: I(t0) Point on the Real number line R sage: c(I(t0)) Point on the 2dimensional differentiable manifold M sage: c(I(t0)).coord(X) (1, 0)
For curves, the value of the parameter, instead of the corresponding point in the real line manifold, can be passed directly:
sage: c(t0) Point c(1/2*pi) on the 2dimensional differentiable manifold M sage: c(t0).coord(X) (1, 0) sage: c(t0) == c(I(t0)) True
Instead of a dictionary of coordinate expressions, the curve can be defined by a single coordinate expression in a given chart:
sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), chart=X, name='c') ; c Curve c in the 2dimensional differentiable manifold M sage: c.display() c: (0, 2*pi) > M t > (x, y) = (sin(t), 1/2*sin(2*t))
Since
X
is the default chart onM
, it can be omitted:sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c') ; c Curve c in the 2dimensional differentiable manifold M sage: c.display() c: (0, 2*pi) > M t > (x, y) = (sin(t), 1/2*sin(2*t))
Note that a curve in \(M\) can also be created as a differentiable map \(I \to M\):
sage: c1 = I.diff_map(M, coord_functions={X: [sin(t), sin(2*t)/2]}, ....: name='c') ; c1 Curve c in the 2dimensional differentiable manifold M sage: c1.parent() is c.parent() True sage: c1 == c True
LaTeX symbols representing a curve:
sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi)) sage: latex(c) \mbox{Curve in the 2dimensional differentiable manifold M} sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c') sage: latex(c) c sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c', ....: latex_name=r'\gamma') sage: latex(c) \gamma
The curve’s tangent vector field (velocity vector):
sage: v = c.tangent_vector_field() ; v Vector field c' along the Real interval (0, 2*pi) with values on the 2dimensional differentiable manifold M sage: v.display() c' = cos(t) d/dx + (2*cos(t)^2  1) d/dy
Plot of the curve and its tangent vector field:
sage: show(c.plot(thickness=2, aspect_ratio=1) + ....: v.plot(chart=X, number_values=17, scale=0.5))
Value of the tangent vector field at \(t = \pi\):
sage: v.at(R(pi)) Tangent vector c' at Point on the 2dimensional differentiable manifold M sage: v.at(R(pi)) in M.tangent_space(c(R(pi))) True sage: v.at(R(pi)).display() c' = d/dx + d/dy
Curves \(\RR \to \RR\) can be composed: the operator \(\circ\) is given by
*
:sage: f = R.curve(t^2, (t,oo,+oo)) sage: g = R.curve(cos(t), (t,oo,+oo)) sage: s = g*f ; s Differentiable map from the Real number line R to itself sage: s.display() R > R t > cos(t^2) sage: s = f*g ; s Differentiable map from the Real number line R to itself sage: s.display() R > R t > cos(t)^2

coord_expr
(chart=None)¶ Return the coordinate functions expressing the curve in a given chart.
INPUT:
chart
– (default:None
) chart on the curve’s codomain; ifNone
, the codomain’s default chart is assumed
OUTPUT:
 symbolic expression representing the curve in the above chart
EXAMPLES:
Cartesian and polar expression of a curve in the Euclidean plane:
sage: M = Manifold(2, 'R^2', r'\RR^2') # the Euclidean plane R^2 sage: c_xy.<x,y> = M.chart() # Cartesian coordinate on R^2 sage: U = M.open_subset('U', coord_def={c_xy: (y!=0, x<0)}) # the complement of the segment y=0 and x>0 sage: c_cart = c_xy.restrict(U) # Cartesian coordinates on U sage: c_spher.<r,ph> = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi') # spherical coordinates on U sage: # Links between spherical coordinates and Cartesian ones: sage: ch_cart_spher = c_cart.transition_map(c_spher, [sqrt(x*x+y*y), atan2(y,x)]) sage: ch_cart_spher.set_inverse(r*cos(ph), r*sin(ph)) sage: R.<t> = RealLine() sage: c = U.curve({c_spher: (1,t)}, (t, 0, 2*pi), name='c') sage: c.coord_expr(c_spher) (1, t) sage: c.coord_expr(c_cart) (cos(t), sin(t))
Since
c_cart
is the default chart onU
, it can be omitted:sage: c.coord_expr() (cos(t), sin(t))
Cartesian expression of a cardiod:
sage: c = U.curve({c_spher: (2*(1+cos(t)), t)}, (t, 0, 2*pi), name='c') sage: c.coord_expr(c_cart) (2*cos(t)^2 + 2*cos(t), 2*(cos(t) + 1)*sin(t))

plot
(chart=None, ambient_coords=None, mapping=None, prange=None, include_end_point=(True, True), end_point_offset=(0.001, 0.001), parameters=None, color='red', style='', label_axes=True, aspect_ratio='automatic', max_range=8, plot_points=75, thickness=1, **kwds)¶ Plot the current curve in a Cartesian graph based on the coordinates of some ambient chart.
The curve is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the ambient chart. The ambient chart’s domain must overlap with the curve’s codomain or with the codomain of the composite curve \(\Phi\circ c\), where \(c\) is the current curve and \(\Phi\) some manifold differential map (argument
mapping
below).INPUT:
chart
– (default:None
) the ambient chart (see above); ifNone
, the default chart of the codomain of the curve (or of the curve composed with \(\Phi\)) is usedambient_coords
– (default:None
) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; ifNone
, all the coordinates of the ambient chart are consideredmapping
– (default:None
) differentiable mapping \(\Phi\) (instance ofDiffMap
) providing the link between the curve and the ambient chartchart
(cf. above); ifNone
, the ambient chart is supposed to be defined on the codomain of the curve.prange
– (default:None
) range of the curve parameter for the plot; ifNone
, the entire parameter range declared during the curve construction is considered (with Infinity replaced bymax_range
and +Infinity bymax_range
)include_end_point
– (default:(True, True)
) determines whether the end points ofprange
are included in the plotend_point_offset
– (default:(0.001, 0.001)
) offsets from the end points when they are not included in the plot: ifinclude_end_point[0] == False
, the minimal value of the curve parameter used for the plot isprange[0] + end_point_offset[0]
, while ifinclude_end_point[1] == False
, the maximal value isprange[1]  end_point_offset[1]
.max_range
– (default: 8) numerical value substituted to +Infinity if the latter is the upper bound of the parameter range; similarlymax_range
is the numerical valued substituted for Infinityparameters
– (default:None
) dictionary giving the numerical values of the parameters that may appear in the coordinate expression of the curvecolor
– (default: ‘red’) color of the drawn curvestyle
– (default: ‘‘) color of the drawn curve; NB:style
is effective only for 2D plotsthickness
– (default: 1) thickness of the drawn curveplot_points
– (default: 75) number of points to plot the curvelabel_axes
– (default:True
) boolean determining whether the labels of the coordinate axes ofchart
shall be added to the graph; can be set toFalse
if the graph is 3D and must be superposed with another graph.aspect_ratio
– (default:'automatic'
) aspect ratio of the plot; the default value ('automatic'
) applies only for 2D plots; for 3D plots, the default value is1
instead
OUTPUT:
 a graphic object, either an instance of
Graphics
for a 2D plot (i.e. based on 2 coordinates ofchart
) or an instance ofGraphics3d
for a 3D plot (i.e. based on 3 coordinates ofchart
)
EXAMPLES:
Plot of the lemniscate of Gerono:
sage: R2 = Manifold(2, 'R^2') sage: X.<x,y> = R2.chart() sage: R.<t> = RealLine() sage: c = R2.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c') sage: c.plot() # 2D plot Graphics object consisting of 1 graphics primitive
Plot for a subinterval of the curve’s domain:
sage: c.plot(prange=(0,pi)) Graphics object consisting of 1 graphics primitive
Plot with various options:
sage: c.plot(color='green', style=':', thickness=3, aspect_ratio=1) Graphics object consisting of 1 graphics primitive
Plot via a mapping to another manifold: loxodrome of a sphere viewed in \(\RR^3\):
sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: R3 = Manifold(3, 'R^3') sage: X3.<x,y,z> = R3.chart() sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), ....: sin(th)*sin(ph), cos(th)]}, name='F') sage: F.display() F: S^2 > R^3 on U: (th, ph) > (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: c = S2.curve([2*atan(exp(t/10)), t], (t, oo, +oo), name='c') sage: graph_c = c.plot(mapping=F, max_range=40, ....: plot_points=200, thickness=2, label_axes=False) # 3D plot sage: graph_S2 = XS.plot(X3, mapping=F, number_values=11, color='black') # plot of the sphere sage: show(graph_c + graph_S2) # the loxodrome + the sphere
Example of use of the argument
parameters
: we define a curve with some symbolic parametersa
andb
:sage: a, b = var('a b') sage: c = R2.curve([a*cos(t) + b, a*sin(t)], (t, 0, 2*pi), name='c')
To make a plot, we set spectific values for
a
andb
by means of the Python dictionaryparameters
:sage: c.plot(parameters={a: 2, b: 3}, aspect_ratio=1) Graphics object consisting of 1 graphics primitive

tangent_vector_field
(name=None, latex_name=None)¶ Return the tangent vector field to the curve (velocity vector).
INPUT:
name
– (default:None
) string; symbol given to the tangent vector field; if none is provided, the primed curve symbol (if any) will be usedlatex_name
– (default:None
) string; LaTeX symbol to denote the tangent vector field; ifNone
then (i) ifname
isNone
as well, the primed curve LaTeX symbol (if any) will be used or (ii) ifname
is notNone
,name
will be used
OUTPUT:
 the tangent vector field, as an instance of
VectorField
EXAMPLES:
Tangent vector field to a circle curve in \(\RR^2\):
sage: M = Manifold(2, 'R^2') sage: X.<x,y> = M.chart() sage: R.<t> = RealLine() sage: c = M.curve([cos(t), sin(t)], (t, 0, 2*pi), name='c') sage: v = c.tangent_vector_field() ; v Vector field c' along the Real interval (0, 2*pi) with values on the 2dimensional differentiable manifold R^2 sage: v.display() c' = sin(t) d/dx + cos(t) d/dy sage: latex(v) {c'} sage: v.parent() Free module X((0, 2*pi),c) of vector fields along the Real interval (0, 2*pi) mapped into the 2dimensional differentiable manifold R^2
Value of the tangent vector field for some specific value of the curve parameter (\(t = \pi\)):
sage: R(pi) in c.domain() # pi in (0, 2*pi) True sage: vp = v.at(R(pi)) ; vp Tangent vector c' at Point on the 2dimensional differentiable manifold R^2 sage: vp.parent() is M.tangent_space(c(R(pi))) True sage: vp.display() c' = d/dy
Tangent vector field to a curve in a nonparallelizable manifold (the 2sphere \(S^2\)): first, we introduce the 2sphere:
sage: M = Manifold(2, 'M') # the 2dimensional sphere S^2 sage: U = M.open_subset('U') # complement of the North pole sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole sage: V = M.open_subset('V') # complement of the South pole sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole sage: M.declare_union(U,V) # S^2 is the union of U and V sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)), ....: intersection_name='W', restrictions1= x^2+y^2!=0, ....: restrictions2= u^2+v^2!=0) sage: uv_to_xy = xy_to_uv.inverse() sage: W = U.intersection(V) sage: A = W.open_subset('A', coord_def={c_xy.restrict(W): (y!=0, x<0)}) sage: c_spher.<th,ph> = A.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') # spherical coordinates sage: spher_to_xy = c_spher.transition_map(c_xy.restrict(A), ....: (sin(th)*cos(ph)/(1cos(th)), sin(th)*sin(ph)/(1cos(th))) ) sage: spher_to_xy.set_inverse(2*atan(1/sqrt(x^2+y^2)), atan2(y, x), check=False)
Then we define a curve (a loxodrome) by its expression in terms of spherical coordinates and evaluate the tangent vector field:
sage: R.<t> = RealLine() sage: c = M.curve({c_spher: [2*atan(exp(t/10)), t]}, (t, oo, +oo), ....: name='c') ; c Curve c in the 2dimensional differentiable manifold M sage: vc = c.tangent_vector_field() ; vc Vector field c' along the Real number line R with values on the 2dimensional differentiable manifold M sage: vc.parent() Module X(R,c) of vector fields along the Real number line R mapped into the 2dimensional differentiable manifold M sage: vc.display(c_spher.frame().along(c.restrict(R,A))) c' = 1/5*e^(1/10*t)/(e^(1/5*t) + 1) d/dth + d/dph