Vector Fields¶
Given two differentiable manifolds \(U\) and \(M\) over the same topological field \(K\) and a differentiable map
we define a vector field along \(U\) with values on \(M\) to be a differentiable map
(\(TM\) being the tangent bundle of \(M\)) such that
The standard case of vector fields on a differentiable manifold corresponds to \(U = M\) and \(\Phi = \mathrm{Id}_M\). Other common cases are \(\Phi\) being an immersion and \(\Phi\) being a curve in \(M\) (\(U\) is then an open interval of \(\RR\)).
Vector fields are implemented via two classes: VectorFieldParal
and
VectorField
, depending respectively whether the manifold \(M\)
is parallelizable or not, i.e. whether the bundle \(TM\) is trivial or not.
AUTHORS:
 Eric Gourgoulhon, Michal Bejger (20132015) : initial version
 Marco Mancini (2015): parallelization of vector field plots
 Travis Scrimshaw (2016): review tweaks
 Eric Gourgoulhon (2017): vector fields inherit from multivector fields
REFERENCES:

class
sage.manifolds.differentiable.vectorfield.
VectorField
(vector_field_module, name=None, latex_name=None)¶ Bases:
sage.manifolds.differentiable.multivectorfield.MultivectorField
Vector field along a differentiable manifold.
An instance of this class is a vector field along a differentiable manifold \(U\) with values on a differentiable manifold \(M\), via a differentiable map \(U \rightarrow M\). More precisely, given a differentiable map
\[\Phi:\ U \longrightarrow M,\]a vector field along \(U\) with values on \(M\) is a differentiable map
\[v:\ U \longrightarrow TM\](\(TM\) being the tangent bundle of \(M\)) such that
\[\forall p \in U,\ v(p) \in T_{\Phi(p)}M.\]The standard case of vector fields on a differentiable manifold corresponds to \(U = M\) and \(\Phi = \mathrm{Id}_M\). Other common cases are \(\Phi\) being an immersion and \(\Phi\) being a curve in \(M\) (\(U\) is then an open interval of \(\RR\)).
Note
If \(M\) is parallelizable, then
VectorFieldParal
must be used instead.INPUT:
vector_field_module
– module \(\mathfrak{X}(U,\Phi)\) of vector fields along \(U\) with values on \(M\supset\Phi(U)\)name
– (default:None
) name given to the vector fieldlatex_name
– (default:None
) LaTeX symbol to denote the vector field; if none is provided, the LaTeX symbol is set toname
EXAMPLES:
A vector field on a nonparallelizable 2dimensional manifold:
sage: M = Manifold(2, 'M') sage: U = M.open_subset('U') ; V = M.open_subset('V') sage: M.declare_union(U,V) # M is the union of U and V sage: c_xy.<x,y> = U.chart() ; c_tu.<t,u> = V.chart() sage: transf = c_xy.transition_map(c_tu, (x+y, xy), intersection_name='W', ....: restrictions1= x>0, restrictions2= t+u>0) sage: inv = transf.inverse() sage: W = U.intersection(V) sage: eU = c_xy.frame() ; eV = c_tu.frame() sage: c_tuW = c_tu.restrict(W) ; eVW = c_tuW.frame() sage: v = M.vector_field('v') ; v Vector field v on the 2dimensional differentiable manifold M sage: v.parent() Module X(M) of vector fields on the 2dimensional differentiable manifold M
The vector field is first defined on the domain \(U\) by means of its components with respect to the frame
eU
:sage: v[eU,:] = [y, 1+x]
The components with respect to the frame
eV
are then deduced by continuation of the components with respect to the frameeVW
on the domain \(W = U \cap V\), expressed in terms on the coordinates covering \(V\):sage: v[eV,0] = v[eVW,0,c_tuW].expr() sage: v[eV,1] = v[eVW,1,c_tuW].expr()
At this stage, the vector field is fully defined on the whole manifold:
sage: v.display(eU) v = y d/dx + (x + 1) d/dy sage: v.display(eV) v = (u + 1) d/dt + (t  1) d/du
The vector field acting on scalar fields:
sage: f = M.scalar_field({c_xy: (x+y)^2, c_tu: t^2}, name='f') sage: s = v(f) ; s Scalar field v(f) on the 2dimensional differentiable manifold M sage: s.display() v(f): M > R on U: (x, y) > 2*x^2  2*y^2 + 2*x + 2*y on V: (t, u) > 2*t*u + 2*t
Some checks:
sage: v(f) == f.differential()(v) True sage: v(f) == f.lie_der(v) True
The result is defined on the intersection of the vector field’s domain and the scalar field’s one:
sage: s = v(f.restrict(U)) ; s Scalar field v(f) on the Open subset U of the 2dimensional differentiable manifold M sage: s == v(f).restrict(U) True sage: s = v(f.restrict(W)) ; s Scalar field v(f) on the Open subset W of the 2dimensional differentiable manifold M sage: s.display() v(f): W > R (x, y) > 2*x^2  2*y^2 + 2*x + 2*y (t, u) > 2*t*u + 2*t sage: s = v.restrict(U)(f) ; s Scalar field v(f) on the Open subset U of the 2dimensional differentiable manifold M sage: s.display() v(f): U > R (x, y) > 2*x^2  2*y^2 + 2*x + 2*y on W: (t, u) > 2*t*u + 2*t sage: s = v.restrict(U)(f.restrict(V)) ; s Scalar field v(f) on the Open subset W of the 2dimensional differentiable manifold M sage: s.display() v(f): W > R (x, y) > 2*x^2  2*y^2 + 2*x + 2*y (t, u) > 2*t*u + 2*t

bracket
(other)¶ Return the Lie bracket
[self, other]
.INPUT:
other
– aVectorField
OUTPUT:
 the
VectorField
[self, other]
EXAMPLES:
sage: M = Manifold(3, 'M') sage: X.<x,y,z> = M.chart() sage: v = X.frame()[0] + 2*X.frame()[1]  (x^2  y)*X.frame()[2] sage: w = (z + y) * X.frame()[1]  X.frame()[2] sage: vw = v.bracket(w); vw Vector field on the 3dimensional differentiable manifold M sage: vw.display() (x^2 + y + 2) d/dy + (y  z) d/dz
Some checks:
sage: vw ==  w.bracket(v) True sage: f = M.scalar_field({X: x+y*z}) sage: vw(f) == v(w(f))  w(v(f)) True sage: vw == w.lie_derivative(v) True

plot
(chart=None, ambient_coords=None, mapping=None, chart_domain=None, fixed_coords=None, ranges=None, number_values=None, steps=None, parameters=None, label_axes=True, color='blue', max_range=8, scale=1, **extra_options)¶ Plot the vector field in a Cartesian graph based on the coordinates of some ambient chart.
The vector field is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the ambient chart. The vector field’s base points \(p\) (or their images \(\Phi(p)\) by some differentiable mapping \(\Phi\)) must lie in the ambient chart’s domain.
INPUT:
chart
– (default:None
) the ambient chart (see above); ifNone
, the default chart of the vector field’s domain 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
–DiffMap
(default:None
); differentiable map \(\Phi\) providing the link between the vector field’s domain and the ambient chartchart
; ifNone
, the identity map is assumedchart_domain
– (default:None
) chart on the vector field’s domain to define the points at which vector arrows are to be plotted; ifNone
, the default chart of the vector field’s domain is usedfixed_coords
– (default:None
) dictionary with keys the coordinates ofchart_domain
that are kept fixed and with values the value of these coordinates; ifNone
, all the coordinates ofchart_domain
are usedranges
– (default:None
) dictionary with keys the coordinates ofchart_domain
to be used and values tuples(x_min, x_max)
specifying the coordinate range for the plot; ifNone
, the entire coordinate range declared during the construction ofchart_domain
is considered (withInfinity
replaced bymax_range
and+Infinity
bymax_range
)number_values
– (default:None
) either an integer or a dictionary with keys the coordinates ofchart_domain
to be used and values the number of values of the coordinate for sampling the part of the vector field’s domain involved in the plot ; ifnumber_values
is a single integer, it represents the number of values for all coordinates; ifnumber_values
isNone
, it is set to 9 for a 2D plot and to 5 for a 3D plotsteps
– (default:None
) dictionary with keys the coordinates ofchart_domain
to be used and values the step between each constant value of the coordinate; ifNone
, the step is computed from the coordinate range (specified inranges
) andnumber_values
; on the contrary, if the step is provided for some coordinate, the corresponding number of values is deduced from it and the coordinate rangeparameters
– (default:None
) dictionary giving the numerical values of the parameters that may appear in the coordinate expression of the vector field (see example below)label_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 graphcolor
– (default: ‘blue’) color of the arrows representing the vectorsmax_range
– (default: 8) numerical value substituted to+Infinity
if the latter is the upper bound of the range of a coordinate for which the plot is performed over the entire coordinate range (i.e. for which no specific plot range has been set inranges
); similarlymax_range
is the numerical valued substituted forInfinity
scale
– (default: 1) value by which the lengths of the arrows representing the vectors is multiplied**extra_options
– extra options for the arrow plot, likelinestyle
,width
orarrowsize
(seearrow2d()
andarrow3d()
for details)
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 a vector field on a 2dimensional manifold:
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: v = M.vector_field(name='v') sage: v[:] = y, x ; v.display() v = y d/dx + x d/dy sage: v.plot() Graphics object consisting of 80 graphics primitives
Plot with various options:
sage: v.plot(scale=0.5, color='green', linestyle='', width=1, ....: arrowsize=6) Graphics object consisting of 80 graphics primitives
sage: v.plot(max_range=4, number_values=5, scale=0.5) Graphics object consisting of 24 graphics primitives
Plot using parallel computation:
sage: Parallelism().set(nproc=2) sage: v.plot(scale=0.5, number_values=10, linestyle='', width=1, ....: arrowsize=6) Graphics object consisting of 100 graphics primitives
sage: Parallelism().set(nproc=1) # switch off parallelization
Plots along a line of fixed coordinate:
sage: v.plot(fixed_coords={x: 2}) Graphics object consisting of 9 graphics primitives
sage: v.plot(fixed_coords={y: 1}) Graphics object consisting of 9 graphics primitives
Let us now consider a vector field on a 4dimensional manifold:
sage: M = Manifold(4, 'M') sage: X.<t,x,y,z> = M.chart() sage: v = M.vector_field(name='v') sage: v[:] = (t/8)^2, t*y/4, t*x/4, t*z/4 ; v.display() v = 1/64*t^2 d/dt  1/4*t*y d/dx + 1/4*t*x d/dy + 1/4*t*z d/dz
We cannot make a 4D plot directly:
sage: v.plot() Traceback (most recent call last): ... ValueError: the number of ambient coordinates must be either 2 or 3, not 4
Rather, we have to select some coordinates for the plot, via the argument
ambient_coords
. For instance, for a 3D plot:sage: v.plot(ambient_coords=(x, y, z), fixed_coords={t: 1}, # long time ....: number_values=4) Graphics3d Object
sage: v.plot(ambient_coords=(x, y, t), fixed_coords={z: 0}, # long time ....: ranges={x: (2,2), y: (2,2), t: (1, 4)}, ....: number_values=4) Graphics3d Object
or, for a 2D plot:
sage: v.plot(ambient_coords=(x, y), fixed_coords={t: 1, z: 0}) # long time Graphics object consisting of 80 graphics primitives
sage: v.plot(ambient_coords=(x, t), fixed_coords={y: 1, z: 0}) # long time Graphics object consisting of 72 graphics primitives
An example of plot via a differential mapping: plot of a vector field tangent to a 2sphere viewed in \(\RR^3\):
sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') # the open set covered by spherical coord. 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() # the standard embedding of S^2 into R^3 F: S^2 > R^3 on U: (th, ph) > (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: v = XS.frame()[1] ; v # the coordinate vector d/dphi Vector field d/dph on the Open subset U of the 2dimensional differentiable manifold S^2 sage: graph_v = v.plot(chart=X3, mapping=F, label_axes=False) sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) sage: graph_v + graph_S2 Graphics3d Object
Note that the default values of some arguments of the method
plot
are stored in the dictionaryplot.options
:sage: v.plot.options # random (dictionary output) {'color': 'blue', 'max_range': 8, 'scale': 1}
so that they can be adjusted by the user:
sage: v.plot.options['color'] = 'red'
From now on, all plots of vector fields will use red as the default color. To restore the original default options, it suffices to type:
sage: v.plot.reset()

class
sage.manifolds.differentiable.vectorfield.
VectorFieldParal
(vector_field_module, name=None, latex_name=None)¶ Bases:
sage.tensor.modules.free_module_element.FiniteRankFreeModuleElement
,sage.manifolds.differentiable.multivectorfield.MultivectorFieldParal
,sage.manifolds.differentiable.vectorfield.VectorField
Vector field along a differentiable manifold, with values on a parallelizable manifold.
An instance of this class is a vector field along a differentiable manifold \(U\) with values on a parallelizable manifold \(M\), via a differentiable map \(\Phi: U \rightarrow M\). More precisely, given a differentiable map
\[\Phi:\ U \longrightarrow M,\]a vector field along \(U\) with values on \(M\) is a differentiable map
\[v:\ U \longrightarrow TM\](\(TM\) being the tangent bundle of \(M\)) such that
\[\forall p \in U,\ v(p) \in T_{\Phi(p)}M.\]The standard case of vector fields on a differentiable manifold corresponds to \(U = M\) and \(\Phi = \mathrm{Id}_M\). Other common cases are \(\Phi\) being an immersion and \(\Phi\) being a curve in \(M\) (\(U\) is then an open interval of \(\RR\)).
Note
If \(M\) is not parallelizable, then
VectorField
must be used instead.INPUT:
vector_field_module
– free module \(\mathfrak{X}(U,\Phi)\) of vector fields along \(U\) with values on \(M\supset\Phi(U)\)name
– (default:None
) name given to the vector fieldlatex_name
– (default:None
) LaTeX symbol to denote the vector field; if none is provided, the LaTeX symbol is set toname
EXAMPLES:
A vector field on a parallelizable 3dimensional manifold:
sage: M = Manifold(3, 'M') sage: c_xyz.<x,y,z> = M.chart() sage: v = M.vector_field('V') ; v Vector field V on the 3dimensional differentiable manifold M sage: latex(v) V
Vector fields are considered as elements of a module over the ring (algebra) of scalar fields on \(M\):
sage: v.parent() Free module X(M) of vector fields on the 3dimensional differentiable manifold M sage: v.parent().base_ring() Algebra of differentiable scalar fields on the 3dimensional differentiable manifold M sage: v.parent() is M.vector_field_module() True
A vector field is a tensor field of rank 1 and of type \((1,0)\):
sage: v.tensor_rank() 1 sage: v.tensor_type() (1, 0)
Components of a vector field with respect to a given frame:
sage: e = M.vector_frame('e') ; M.set_default_frame(e) sage: v[0], v[1], v[2] = (1, 4, 9) # components on M's default frame (e) sage: v.comp() 1index components w.r.t. Vector frame (M, (e_0,e_1,e_2))
The totality of the components are accessed via the operator
[:]
:sage: v[:] = (1, 4, 9) # equivalent to v[0], v[1], v[2] = (1, 4, 9) sage: v[:] [1, 4, 9]
The components are also read on the expansion on the frame
e
, as provided by the methoddisplay()
:sage: v.display() # displays the expansion in the default frame V = e_0 + 4 e_1 + 9 e_2
A subset of the components can be accessed by using slice notation:
sage: v[1:] = (2, 3) sage: v[:] [1, 2, 3] sage: v[:2] [1, 2]
Components in another frame:
sage: f = M.vector_frame('f') sage: for i in range(3): ....: v.set_comp(f)[i] = (i+1)**3 ....: sage: v.comp(f)[2] 27 sage: v[f, 2] # equivalent to above 27 sage: v.display(f) V = f_0 + 8 f_1 + 27 f_2
The range of the indices depends on the convention set for the manifold:
sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: e = M.vector_frame('e') ; M.set_default_frame(e) sage: v = M.vector_field('V') sage: (v[1], v[2], v[3]) = (1, 4, 9) sage: v[0] Traceback (most recent call last): ... IndexError: index out of range: 0 not in [1, 3]
A vector field acts on scalar fields (derivation along the vector field):
sage: M = Manifold(2, 'M') sage: c_cart.<x,y> = M.chart() sage: f = M.scalar_field(x*y^2, name='f') sage: v = M.vector_field('v') sage: v[:] = (y, x) sage: v.display() v = y d/dx + x d/dy sage: v(f) Scalar field v(f) on the 2dimensional differentiable manifold M sage: v(f).expr() 2*x^2*y  y^3 sage: latex(v(f)) v\left(f\right)
Example of a vector field associated with a nontrivial map \(\Phi\); a vector field along a curve in \(M\):
sage: R = Manifold(1, 'R') sage: T.<t> = R.chart() # canonical chart on R sage: Phi = R.diff_map(M, [cos(t), sin(t)], name='Phi') ; Phi Differentiable map Phi from the 1dimensional differentiable manifold R to the 2dimensional differentiable manifold M sage: Phi.display() Phi: R > M t > (x, y) = (cos(t), sin(t)) sage: w = R.vector_field('w', dest_map=Phi) ; w Vector field w along the 1dimensional differentiable manifold R with values on the 2dimensional differentiable manifold M sage: w.parent() Free module X(R,Phi) of vector fields along the 1dimensional differentiable manifold R mapped into the 2dimensional differentiable manifold M sage: w[:] = (sin(t), cos(t)) sage: w.display() w = sin(t) d/dx + cos(t) d/dy
Value at a given point:
sage: p = R((0,), name='p') ; p Point p on the 1dimensional differentiable manifold R sage: w.at(p) Tangent vector w at Point Phi(p) on the 2dimensional differentiable manifold M sage: w.at(p).display() w = d/dy sage: w.at(p) == v.at(Phi(p)) True