Vector Fields¶
Given two differentiable manifolds and
over the same topological field
and a differentiable map
we define a vector field along with values on
to be a
differentiable map
( being the tangent bundle of
) such that
The standard case of vector fields on a differentiable manifold corresponds
to and
. Other common cases are
being an immersion and
being a curve in
(
is then an open
interval of
).
Vector fields are implemented via two classes: VectorFieldParal
and
VectorField
, depending respectively whether the manifold
is parallelizable or not, i.e. whether the bundle
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:
- [KN1963]
- [Lee2013]
- [ONe1983]
- [BG1988]
-
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
with values on a differentiable manifold
, via a differentiable map
. More precisely, given a differentiable map
a vector field along
with values on
is a differentiable map
(
being the tangent bundle of
) such that
The standard case of vector fields on a differentiable manifold corresponds to
and
. Other common cases are
being an immersion and
being a curve in
(
is then an open interval of
).
Note
If
is parallelizable, then
VectorFieldParal
must be used instead.INPUT:
vector_field_module
– moduleof vector fields along
with values on
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 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
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, expressed in terms on the coordinates covering
:
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
(or their images
by some differentiable mapping
) 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 mapproviding the link between the vector field’s domain and the ambient chart
chart
; 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 (with-Infinity
replaced by-max_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
); 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, 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 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
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 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
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 2-sphere viewed in
:
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
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_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
with values on a parallelizable manifold
, via a differentiable map
. More precisely, given a differentiable map
a vector field along
with values on
is a differentiable map
(
being the tangent bundle of
) such that
The standard case of vector fields on a differentiable manifold corresponds to
and
. Other common cases are
being an immersion and
being a curve in
(
is then an open interval of
).
Note
If
is not parallelizable, then
VectorField
must be used instead.INPUT:
vector_field_module
– free moduleof vector fields along
with values on
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 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
:
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
:
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 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 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
; a vector field along a curve in
:
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