Smooth manifolds, vector fields and tensor fields
This woksheet accompanies the lecture Symbolic tensor calculus on manifolds at JNCF 2018.
Click here to download the worksheet file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, via the command sage -n jupyter
Let us restore the 2-sphere manifold constructed in the preceeding worksheet:
We also reconstruct the point :
and the embedding :
Finally we reconstruct the scalar field :
and assign the Python variable CM
to the algebra of scalar fields:
Tangent vectors
The tangent space at the point introduced above is generated by
It is a vector space over , which is represented by Sage's Symbolic Ring:
The dimension of is the same as that of :
Tangent spaces are implemented as a class inherited from TangentSpace
via the category framework:
The class TangentSpace
actually inherits from the generic class FiniteRankFreeModule
, which, in SageMath, is devoted to free modules of finite rank without any distinguished basis:
Two bases of are already available: those generated by the derivations at along the coordinates of charts XU
and XV
respectively:
None of these bases is distinguished, but one if the default one, which simply means that it is the basis to be considered if the basis argument is skipped in some methods:
A tangent vector is created as an element of the tangent space by the standard SageMath procedure new\_element = parent(...)
, where ...
stands for some material sufficient to construct the element:
Since the basis is not specified, the pair refers to components with respect to the default basis:
We have of course
As other manifold objects, tangent vectors have some plotting capabilities:
Module of vector fields
The -module of vector fields on , , is obtained as
is not a free module (at least its SageMath implementation does not belong to the class FiniteRankFreeModule
):
This is because is not a parallelizable manifold:
Via the category mechanism, the module is implemented by a dynamically-generated subclass of the class VectorFieldModule
, which is devoted to modules of vector fields on non-parallelizable manifolds:
On the contrary, the set of vector fields on is a free module of finite rank over the algebra :
This is because the open subset is a parallelizable manifold:
being a coordinate chart domain:
We can check that in the atlas of , at least one chart has for domain:
The rank of is the manifold's dimension:
Via the category mechanism, the free module is implemented by a dynamically-generated subclass of the class VectorFieldFreeModule
, which is devoted to modules of vector fields on parallelizable manifolds:
The class VectorFieldFreeModule
is itself a subclass of the generic class FiniteRankFreeModule
:
Since is a chart domain, the free module is automatically endowed with a basis: the coordinate frame associated to the chart:
Let us denote by eU
this frame. We can set eU = YU.bases()[0]
or alternatively
Another equivalent instruction would have been eU = U.default_frame()
.
Similarly, is a free module, endowed with the coordinate frame associated to stereographic coordinates from the South pole, which we denote by eV
:
If we consider the intersection , we notice its module of vector fields is endowed with two bases, reflecting the fact that is covered by two charts: and :
Let us denote by eUW
and eUV
these two bases, which are actually the restrictions of the vector frames eU
and eV
to :
The free module is also automatically endowed with automorphisms connecting the two bases, i.e. change-of-frame operators:
The first of them is
It belongs to the general linear group of the free module :
and its matrix is deduced from the Jacobian matrix of the transition map XV
XU
:
An example of vector field
We introduce a vector field on by
Notice that at this stage, we have defined only on , by setting its components in the vector frame eU
, either explicitely as scalar fields, like the component set to the restriction of to or to some symbolic expression, like for the component : the will be coerced to the constant scalar field of value . We can ask for the scalar-field value of a components via the double-bracket operator, since eU
is the default frame on , we don't have to specify it:
Note that the single bracket operator returns a chart function of the component:
The restriction of to is of course
Since we have a second vector frame on , namely eVW
, and the change-of-frame automorphisms are known, we can ask for the components of with respect to that frame:
Notice that the components are expressed in terms of the coordinates since they form the default chart on . To have them expressed in terms of the coordinates , we have to add the restriction of the chart to as the second argument of the method display()
:
We extend the expression of to the full vector frame XV
by continuation of this expression:
We have then
At this stage, the vector field is defined in all . According to the hairy ball theorem\index{hairy ball theorem}, it has to vanish somewhere. Let us show that this occurs at the North pole, by first introducing the latter, as the point of stereographic coordinates :
As a check, we verify that the image of by the canonical embedding is the point of Cartesian coordinates :
The vanishing of :
On the other hand, does not vanish at the point introduced above:
We may plot the vector field in terms of the stereographic coordinates from the North pole:
or in term of those from the South pole:
Thanks to the embedding , we may also have a 3D plot of atop of the 3D plot already obtained:
Note that the sampling, performed on the two charts XU
and XV
is not uniform on the sphere. A better sampling would be acheived by introducing spherical coordinates.
Some details about the implementation of vector fields
Since is not parallelizable, the fundamental representation of a vector field on is via its restrictions to parallelizable open subsets; they are stored in the dictionary _restrictions
, whose keys are the open subsets:
Let us consider one of these restrictions, for instance the restriction to :
Since is a parallelizable open subset, the fundamental representation of on it is via its components with respect to (possibly various) vector frames on ; they are stored in the dictionary _components
, whose keys are the vector frames:
Let us perform some algebraic operation on :
The code for the addition is defined is accessible via
As for the addition of scalar field (cf. this worksheet), we see that __add__()
is implemented at the level of the generic class Element
from which VectorField
inherits. When both operands of the addition have the same parent, as here, __add__()
invokes the method _add_()
(note the single underscore on each side of add
). This operator is implemented at the level of TensorField
, as it can be checked from the source code:
Action of a vector field on a scalar field
Tensor fields
Let us start with a 1-form, namely the differential of :
We construct a tensor of type by taking the tensor product :