Vector Fields

Given two differentiable manifolds \(U\) and \(M\) over the same topological field \(K\) and a differentiable map

\[\Phi:\ U \longrightarrow M,\]

we define a vector field along \(U\) with values on \(M\) to be 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\)).

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 (2013-2015) : initial version
  • Marco Mancini (2015): parallelization of vector field plots
  • Travis Scrimshaw (2016): review tweaks

REFERENCES:

class sage.manifolds.differentiable.vectorfield.VectorField(vector_field_module, name=None, latex_name=None)

Bases: sage.manifolds.differentiable.tensorfield.TensorField

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 \(\mathcal{X}(U,\Phi)\) of vector fields along \(U\) with values on \(M\supset\Phi(U)\)
  • name – (default: None) name given to the vector field
  • latex_name – (default: None) LaTeX symbol to denote the vector field; if none is provided, the LaTeX symbol is set to name

EXAMPLES:

A vector field on a non-parallelizable 2-dimensional 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, x-y), 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 2-dimensional differentiable manifold M
sage: v.parent()
Module X(M) of vector fields on the 2-dimensional 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 frame eVW 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 2-dimensional 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 2-dimensional
 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 2-dimensional
 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 2-dimensional
 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 2-dimensional
 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].

EXAMPLES:

sage: M = Manifold(3, 'M', structure='smooth')
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 3-dimensional differentiable manifold M
sage: vw.display()
(-x^2 + y + 2) d/dy + (-y - z) d/dz
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); if None, the default chart of the vector field’s domain is used
  • ambient_coords – (default: None) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if None, all the coordinates of the ambient chart are considered
  • mappingDiffMap (default: None); differentiable map \(\Phi\) providing the link between the vector field’s domain and the ambient chart chart; if None, the identity map is assumed
  • chart_domain – (default: None) chart on the vector field’s domain to define the points at which vector arrows are to be plotted; if None, the default chart of the vector field’s domain is used
  • fixed_coords – (default: None) dictionary with keys the coordinates of chart_domain that are kept fixed and with values the value of these coordinates; if None, all the coordinates of chart_domain are used
  • ranges – (default: None) dictionary with keys the coordinates of chart_domain to be used and values tuples (x_min, x_max) specifying the coordinate range for the plot; if None, the entire coordinate range declared during the construction of chart_domain is considered (with -Infinity replaced by -max_range and +Infinity by max_range)
  • number_values – (default: None) either an integer or a dictionary with keys the coordinates of chart_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 ; if number_values is a single integer, it represents the number of values for all coordinates; if number_values is None, it is set to 9 for a 2D plot and to 5 for a 3D plot
  • steps – (default: None) dictionary with keys the coordinates of chart_domain to be used and values the step between each constant value of the coordinate; if None, the step is computed from the coordinate range (specified in ranges) and number_values; on the contrary, if the step is provided for some coordinate, the corresponding number of values is deduced from it and the coordinate range
  • parameters – (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 of chart shall be added to the graph; can be set to False if the graph is 3D and must be superposed with another graph
  • color – (default: ‘blue’) color of the arrows representing the vectors
  • max_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 in ranges); similarly -max_range is the numerical valued substituted for -Infinity
  • scale – (default: 1) value by which the lengths of the arrows representing the vectors is multiplied
  • **extra_options – extra options for the arrow plot, like linestyle, width or arrowsize (see arrow2d() and arrow3d() for details)

OUTPUT:

  • a graphic object, either an instance of Graphics for a 2D plot (i.e. based on 2 coordinates of chart) or an instance of Graphics3d for a 3D plot (i.e. based on 3 coordinates of chart)

EXAMPLES:

Plot of a vector field on a 2-dimensional 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
../../../_images/vectorfield-1.png

Plot with various options:

sage: v.plot(scale=0.5, color='green', linestyle='--', width=1,
....:        arrowsize=6)
Graphics object consisting of 80 graphics primitives
../../../_images/vectorfield-2.png
sage: v.plot(max_range=4, number_values=5, scale=0.5)
Graphics object consisting of 24 graphics primitives
../../../_images/vectorfield-3.png

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
../../../_images/vectorfield-4.png
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
../../../_images/vectorfield-5.png
sage: v.plot(fixed_coords={y: 1})
Graphics object consisting of 9 graphics primitives
../../../_images/vectorfield-6.png

Let us now consider a vector field on a 4-dimensional 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
../../../_images/vectorfield-7.png
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
../../../_images/vectorfield-8.png

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
../../../_images/vectorfield-9.png
sage: v.plot(ambient_coords=(x, t), fixed_coords={y: 1, z: 0})  # long time
Graphics object consisting of 72 graphics primitives
../../../_images/vectorfield-10.png

An example of plot via a differential mapping: plot of a vector field tangent to a 2-sphere 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 2-dimensional
 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
../../../_images/vectorfield-11.png

Note that the default values of some arguments of the method plot are stored in the dictionary plot.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_tensor.FiniteRankFreeModuleElement, sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal, 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 \(\mathcal{X}(U,\Phi)\) of vector fields along \(U\) with values on \(M\supset\Phi(U)\)
  • name – (default: None) name given to the vector field
  • latex_name – (default: None) LaTeX symbol to denote the vector field; if none is provided, the LaTeX symbol is set to name

EXAMPLES:

A vector field on a parallelizable 3-dimensional 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 3-dimensional 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 3-dimensional differentiable
 manifold M
sage: v.parent().base_ring()
Algebra of differentiable scalar fields on the 3-dimensional
 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()
1-index 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 method display():

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 2-dimensional 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 non-trivial 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 1-dimensional differentiable manifold R
 to the 2-dimensional 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 1-dimensional differentiable manifold R with
 values on the 2-dimensional differentiable manifold M
sage: w.parent()
Free module X(R,Phi) of vector fields along the 1-dimensional
 differentiable manifold R mapped into the 2-dimensional 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 1-dimensional differentiable manifold R
sage: w.at(p)
Tangent vector w at Point Phi(p) on the 2-dimensional differentiable
 manifold M
sage: w.at(p).display()
w = d/dy
sage: w.at(p) == v.at(Phi(p))
True