Tensor Fields with Values on a Parallelizable Manifold - Manifolds

Skip to content
Back to top
View this page
Edit this page

# Tensor Fields with Values on a Parallelizable Manifold

The class `TensorFieldParal` implements tensor fields along a differentiable manifolds with values on a parallelizable differentiable manifold. For non-parallelizable manifolds, see the class `TensorField`.

Various derived classes of `TensorFieldParal` are devoted to specific tensor fields:

- `VectorFieldParal` for vector fields (rank-1 contravariant tensor fields)

- `AutomorphismFieldParal` for fields of tangent-space automorphisms

- `DiffFormParal` for differential forms (fully antisymmetric covariant tensor fields)

- `MultivectorFieldParal` for multivector fields (fully antisymmetric contravariant tensor fields)

AUTHORS:

- Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version

- Travis Scrimshaw (2016): review tweaks

- Eric Gourgoulhon (2018): method `TensorFieldParal.along()`

- Florentin Jaffredo (2018) : series expansion with respect to a given parameter

REFERENCES:

- [KN1963]

- [Lee2013]

- [ONe1983]

EXAMPLES:

A tensor field of type \((1,1)\) on a 2-dimensional differentiable manifold:

Sage

    sage: M = Manifold(2, 'M', start_index=1)
    sage: c_xy.<x,y> = M.chart()
    sage: t = M.tensor_field(1, 1, name='T') ; t
    Tensor field T of type (1,1) on the 2-dimensional differentiable manifold M
    sage: t.tensor_type()
    (1, 1)
    sage: t.tensor_rank()
    2

Python

    >>> from sage.all import *
    >>> M = Manifold(Integer(2), 'M', start_index=Integer(1))
    >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)
    >>> t = M.tensor_field(Integer(1), Integer(1), name='T') ; t
    Tensor field T of type (1,1) on the 2-dimensional differentiable manifold M
    >>> t.tensor_type()
    (1, 1)
    >>> t.tensor_rank()
    2

Components with respect to the manifold’s default frame are created by providing the relevant indices inside square brackets:

Sage

    sage: t[1,1] = x^2

[Python]

    >>> from sage.all import *
    >>> t[Integer(1),Integer(1)] = x**Integer(2)

Unset components are initialized to zero:

Sage

    sage: t[:]  # list of components w.r.t. the manifold's default vector frame
    [x^2   0]
    [  0   0]

Python

    >>> from sage.all import *
    >>> t[:]  # list of components w.r.t. the manifold's default vector frame
    [x^2   0]
    [  0   0]

It is also possible to initialize the components at the tensor field construction:

Sage

    sage: t = M.tensor_field(1, 1, [[x^2, 0], [0, 0]], name='T')
    sage: t[:]
    [x^2   0]
    [  0   0]

[Python]

    >>> from sage.all import *
    >>> t = M.tensor_field(Integer(1), Integer(1), [[x**Integer(2), Integer(0)], [Integer(0), Integer(0)]], name='T')
    >>> t[:]
    [x^2   0]
    [  0   0]

The full set of components with respect to a given vector frame is returned by the method `comp()`:

Sage

    sage: t.comp(c_xy.frame())
    2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))

Python

    >>> from sage.all import *
    >>> t.comp(c_xy.frame())
    2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))

If no vector frame is mentioned in the argument of `comp()`, it is assumed to be the manifold’s default frame:

Sage

    sage: M.default_frame()
    Coordinate frame (M, (∂/∂x,∂/∂y))
    sage: t.comp() is t.comp(c_xy.frame())
    True

[Python]

    >>> from sage.all import *
    >>> M.default_frame()
    Coordinate frame (M, (∂/∂x,∂/∂y))
    >>> t.comp() is t.comp(c_xy.frame())
    True

Individual components with respect to the manifold’s default frame are accessed by listing their indices inside double square brackets. They are `scalar fields` on the manifold:

Sage

    sage: t[[1,1]]
    Scalar field on the 2-dimensional differentiable manifold M
    sage: t[[1,1]].display()
    M → ℝ
    (x, y) ↦ x^2
    sage: t[[1,2]]
    Scalar field zero on the 2-dimensional differentiable manifold M
    sage: t[[1,2]].display()
    zero: M → ℝ
       (x, y) ↦ 0

Python

    >>> from sage.all import *
    >>> t[[Integer(1),Integer(1)]]
    Scalar field on the 2-dimensional differentiable manifold M
    >>> t[[Integer(1),Integer(1)]].display()
    M → ℝ
    (x, y) ↦ x^2
    >>> t[[Integer(1),Integer(2)]]
    Scalar field zero on the 2-dimensional differentiable manifold M
    >>> t[[Integer(1),Integer(2)]].display()
    zero: M → ℝ
       (x, y) ↦ 0

A direct access to the coordinate expression of some component is obtained via the single square brackets:

Sage

    sage: t[1,1]
    x^2
    sage: t[1,1] is t[[1,1]].coord_function() # the coordinate function
    True
    sage: t[1,1] is t[[1,1]].coord_function(c_xy)
    True
    sage: t[1,1].expr() is t[[1,1]].expr() # the symbolic expression
    True

[Python]

    >>> from sage.all import *
    >>> t[Integer(1),Integer(1)]
    x^2
    >>> t[Integer(1),Integer(1)] is t[[Integer(1),Integer(1)]].coord_function() # the coordinate function
    True
    >>> t[Integer(1),Integer(1)] is t[[Integer(1),Integer(1)]].coord_function(c_xy)
    True
    >>> t[Integer(1),Integer(1)].expr() is t[[Integer(1),Integer(1)]].expr() # the symbolic expression
    True

Expressions in a chart different from the manifold’s default one are obtained by specifying the chart as the last argument inside the single square brackets:

Sage

    sage: c_uv.<u,v> = M.chart()
    sage: xy_to_uv = c_xy.transition_map(c_uv, [x+y, x-y])
    sage: uv_to_xy = xy_to_uv.inverse()
    sage: t[1,1, c_uv]
    1/4*u^2 + 1/2*u*v + 1/4*v^2

Python

    >>> from sage.all import *
    >>> c_uv = M.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
    >>> xy_to_uv = c_xy.transition_map(c_uv, [x+y, x-y])
    >>> uv_to_xy = xy_to_uv.inverse()
    >>> t[Integer(1),Integer(1), c_uv]
    1/4*u^2 + 1/2*u*v + 1/4*v^2

Note that `t[1,1, c_uv]` is the component of the tensor `t` with respect to the coordinate frame associated to the chart \((x,y)\) expressed in terms of the coordinates \((u,v)\). Indeed, `t[1,1, c_uv]` is a shortcut for `t.comp(c_xy.frame())[[1,1]].coord_function(c_uv)`:

Sage

    sage: t[1,1, c_uv] is t.comp(c_xy.frame())[[1,1]].coord_function(c_uv)
    True

[Python]

    >>> from sage.all import *
    >>> t[Integer(1),Integer(1), c_uv] is t.comp(c_xy.frame())[[Integer(1),Integer(1)]].coord_function(c_uv)
    True

Similarly, `t[1,1]` is a shortcut for `t.comp(c_xy.frame())[[1,1]].coord_function(c_xy)`:

Sage

    sage: t[1,1] is t.comp(c_xy.frame())[[1,1]].coord_function(c_xy)
    True
    sage: t[1,1] is t.comp()[[1,1]].coord_function()  # since c_xy.frame() and c_xy are the manifold's default values
    True

Python

    >>> from sage.all import *
    >>> t[Integer(1),Integer(1)] is t.comp(c_xy.frame())[[Integer(1),Integer(1)]].coord_function(c_xy)
    True
    >>> t[Integer(1),Integer(1)] is t.comp()[[Integer(1),Integer(1)]].coord_function()  # since c_xy.frame() and c_xy are the manifold's default values
    True

All the components can be set at once via `[:]`:

Sage

    sage: t[:] = [[1, -x], [x*y, 2]]
    sage: t[:]
    [  1  -x]
    [x*y   2]

[Python]

    >>> from sage.all import *
    >>> t[:] = [[Integer(1), -x], [x*y, Integer(2)]]
    >>> t[:]
    [  1  -x]
    [x*y   2]

To set the components in a vector frame different from the manifold’s default one, the method `set_comp()` can be employed:

Sage

    sage: e = M.vector_frame('e')
    sage: t.set_comp(e)[1,1] = x+y
    sage: t.set_comp(e)[2,1], t.set_comp(e)[2,2] = y, -3*x

Python

    >>> from sage.all import *
    >>> e = M.vector_frame('e')
    >>> t.set_comp(e)[Integer(1),Integer(1)] = x+y
    >>> t.set_comp(e)[Integer(2),Integer(1)], t.set_comp(e)[Integer(2),Integer(2)] = y, -Integer(3)*x

but, as a shortcut, one may simply specify the frame as the first argument of the square brackets:

Sage

    sage: t[e,1,1] = x+y
    sage: t[e,2,1], t[e,2,2] = y, -3*x
    sage: t.comp(e)
    2-indices components w.r.t. Vector frame (M, (e_1,e_2))
    sage: t.comp(e)[:]
    [x + y     0]
    [    y  -3*x]
    sage: t[e,:]  # a shortcut of the above
    [x + y     0]
    [    y  -3*x]

[Python]

    >>> from sage.all import *
    >>> t[e,Integer(1),Integer(1)] = x+y
    >>> t[e,Integer(2),Integer(1)], t[e,Integer(2),Integer(2)] = y, -Integer(3)*x
    >>> t.comp(e)
    2-indices components w.r.t. Vector frame (M, (e_1,e_2))
    >>> t.comp(e)[:]
    [x + y     0]
    [    y  -3*x]
    >>> t[e,:]  # a shortcut of the above
    [x + y     0]
    [    y  -3*x]

All the components in some frame can be set at once, via the operator `[:]`:

Sage

    sage: t[e,:] = [[x+y, 0], [y, -3*x]]
    sage: t[e,:]  # same as above:
    [x + y     0]
    [    y  -3*x]

Python

    >>> from sage.all import *
    >>> t[e,:] = [[x+y, Integer(0)], [y, -Integer(3)*x]]
    >>> t[e,:]  # same as above:
    [x + y     0]
    [    y  -3*x]

Equivalently, one can initialize the components in `e` at the tensor field construction:

Sage

    sage: t = M.tensor_field(1, 1, [[x+y, 0], [y, -3*x]], frame=e, name='T')
    sage: t[e,:]  # same as above:
    [x + y     0]
    [    y  -3*x]

[Python]

    >>> from sage.all import *
    >>> t = M.tensor_field(Integer(1), Integer(1), [[x+y, Integer(0)], [y, -Integer(3)*x]], frame=e, name='T')
    >>> t[e,:]  # same as above:
    [x + y     0]
    [    y  -3*x]

To avoid any inconsistency between the various components, the method `set_comp()` clears the components in other frames. To keep the other components, one must use the method `add_comp()`:

Sage

    sage: t = M.tensor_field(1, 1, name='T')  # Let us restart
    sage: t[:] = [[1, -x], [x*y, 2]]  # by first setting the components in the frame c_xy.frame()

Python

    >>> from sage.all import *
    >>> t = M.tensor_field(Integer(1), Integer(1), name='T')  # Let us restart
    >>> t[:] = [[Integer(1), -x], [x*y, Integer(2)]]  # by first setting the components in the frame c_xy.frame()

We now set the components in the frame e with add_comp:

Sage

    sage: t.add_comp(e)[:] = [[x+y, 0], [y, -3*x]]

[Python]

    >>> from sage.all import *
    >>> t.add_comp(e)[:] = [[x+y, Integer(0)], [y, -Integer(3)*x]]

The expansion of the tensor field in a given frame is obtained via the method `display`:

Sage

    sage: t.display()  # expansion in the manifold's default frame
    T = ∂/∂x⊗dx - x ∂/∂x⊗dy + x*y ∂/∂y⊗dx + 2 ∂/∂y⊗dy
    sage: t.display(e)
    T = (x + y) e_1⊗e^1 + y e_2⊗e^1 - 3*x e_2⊗e^2

Python

    >>> from sage.all import *
    >>> t.display()  # expansion in the manifold's default frame
    T = ∂/∂x⊗dx - x ∂/∂x⊗dy + x*y ∂/∂y⊗dx + 2 ∂/∂y⊗dy
    >>> t.display(e)
    T = (x + y) e_1⊗e^1 + y e_2⊗e^1 - 3*x e_2⊗e^2

See `display()` for more examples.

By definition, a tensor field acts as a multilinear map on 1-forms and vector fields; in the present case, `T` being of type \((1,1)\), it acts on pairs (1-form, vector field):

Sage

    sage: a = M.one_form(1, x, name='a')
    sage: v = M.vector_field(y, 2, name='V')
    sage: t(a,v)
    Scalar field T(a,V) on the 2-dimensional differentiable manifold M
    sage: t(a,v).display()
    T(a,V): M → ℝ
       (x, y) ↦ x^2*y^2 + 2*x + y
       (u, v) ↦ 1/16*u^4 - 1/8*u^2*v^2 + 1/16*v^4 + 3/2*u + 1/2*v
    sage: latex(t(a,v))
    T\left(a,V\right)

[Python]

    >>> from sage.all import *
    >>> a = M.one_form(Integer(1), x, name='a')
    >>> v = M.vector_field(y, Integer(2), name='V')
    >>> t(a,v)
    Scalar field T(a,V) on the 2-dimensional differentiable manifold M
    >>> t(a,v).display()
    T(a,V): M → ℝ
       (x, y) ↦ x^2*y^2 + 2*x + y
       (u, v) ↦ 1/16*u^4 - 1/8*u^2*v^2 + 1/16*v^4 + 3/2*u + 1/2*v
    >>> latex(t(a,v))
    T\left(a,V\right)

Check by means of the component expression of `t(a,v)`:

Sage

    sage: t(a,v).expr() - t[1,1]*a[1]*v[1] - t[1,2]*a[1]*v[2] \
    ....: - t[2,1]*a[2]*v[1] - t[2,2]*a[2]*v[2]
    0

Python

    >>> from sage.all import *
    >>> t(a,v).expr() - t[Integer(1),Integer(1)]*a[Integer(1)]*v[Integer(1)] - t[Integer(1),Integer(2)]*a[Integer(1)]*v[Integer(2)] - t[Integer(2),Integer(1)]*a[Integer(2)]*v[Integer(1)] - t[Integer(2),Integer(2)]*a[Integer(2)]*v[Integer(2)]
    0

A scalar field (rank-0 tensor field):

Sage

    sage: f = M.scalar_field(x*y + 2, name='f') ; f
    Scalar field f on the 2-dimensional differentiable manifold M
    sage: f.tensor_type()
    (0, 0)

[Python]

    >>> from sage.all import *
    >>> f = M.scalar_field(x*y + Integer(2), name='f') ; f
    Scalar field f on the 2-dimensional differentiable manifold M
    >>> f.tensor_type()
    (0, 0)

A scalar field acts on points on the manifold:

Sage

    sage: p = M.point((1,2))
    sage: f(p)
    4

Python

    >>> from sage.all import *
    >>> p = M.point((Integer(1),Integer(2)))
    >>> f(p)
    4

See `DiffScalarField` for more details on scalar fields.

A vector field (rank-1 contravariant tensor field):

Sage

    sage: v = M.vector_field(-x, y, name='v') ; v
    Vector field v on the 2-dimensional differentiable manifold M
    sage: v.tensor_type()
    (1, 0)
    sage: v.display()
    v = -x ∂/∂x + y ∂/∂y

[Python]

    >>> from sage.all import *
    >>> v = M.vector_field(-x, y, name='v') ; v
    Vector field v on the 2-dimensional differentiable manifold M
    >>> v.tensor_type()
    (1, 0)
    >>> v.display()
    v = -x ∂/∂x + y ∂/∂y

A field of symmetric bilinear forms:

Sage

    sage: q = M.sym_bilin_form_field(name='Q') ; q
    Field of symmetric bilinear forms Q on the 2-dimensional differentiable
     manifold M
    sage: q.tensor_type()
    (0, 2)

Python

    >>> from sage.all import *
    >>> q = M.sym_bilin_form_field(name='Q') ; q
    Field of symmetric bilinear forms Q on the 2-dimensional differentiable
     manifold M
    >>> q.tensor_type()
    (0, 2)

The components of a symmetric bilinear form are dealt by the subclass `CompFullySym` of the class `Components`, which takes into account the symmetry between the two indices:

Sage

    sage: q[1,1], q[1,2], q[2,2] = (0, -x, y) # no need to set the component (2,1)
    sage: type(q.comp())
    <class 'sage.tensor.modules.comp.CompFullySym'>
    sage: q[:] # note that the component (2,1) is equal to the component (1,2)
    [ 0 -x]
    [-x  y]
    sage: q.display()
    Q = -x dx⊗dy - x dy⊗dx + y dy⊗dy

[Python]

    >>> from sage.all import *
    >>> q[Integer(1),Integer(1)], q[Integer(1),Integer(2)], q[Integer(2),Integer(2)] = (Integer(0), -x, y) # no need to set the component (2,1)
    >>> type(q.comp())
    <class 'sage.tensor.modules.comp.CompFullySym'>
    >>> q[:] # note that the component (2,1) is equal to the component (1,2)
    [ 0 -x]
    [-x  y]
    >>> q.display()
    Q = -x dx⊗dy - x dy⊗dx + y dy⊗dy

More generally, tensor symmetries or antisymmetries can be specified via the keywords `sym` and `antisym`. For instance a rank-4 covariant tensor symmetric with respect to its first two arguments (no. 0 and no. 1) and antisymmetric with respect to its last two ones (no. 2 and no. 3) is declared as follows:

Sage

    sage: t = M.tensor_field(0, 4, name='T', sym=(0,1), antisym=(2,3))
    sage: t[1,2,1,2] = 3
    sage: t[2,1,1,2] # check of the symmetry with respect to the first 2 indices
    3
    sage: t[1,2,2,1] # check of the antisymmetry with respect to the last 2 indices
    -3

Python

    >>> from sage.all import *
    >>> t = M.tensor_field(Integer(0), Integer(4), name='T', sym=(Integer(0),Integer(1)), antisym=(Integer(2),Integer(3)))
    >>> t[Integer(1),Integer(2),Integer(1),Integer(2)] = Integer(3)
    >>> t[Integer(2),Integer(1),Integer(1),Integer(2)] # check of the symmetry with respect to the first 2 indices
    3
    >>> t[Integer(1),Integer(2),Integer(2),Integer(1)] # check of the antisymmetry with respect to the last 2 indices
    -3

class sage.manifolds.differentiable.tensorfield_paral.TensorFieldParal(vector_field_module, tensor_type, name=None, latex_name=None, sym=None, antisym=None)

  Bases: `FreeModuleTensor`, `TensorField`

  Tensor field along a differentiable manifold, with values on a parallelizable manifold.

  An instance of this class is a tensor field along a differentiable manifold \(U\) with values on a parallelizable manifold \(M\), via a differentiable map \(\Phi: U \rightarrow M\). More precisely, given two nonnegative integers \(k\) and \(l\) and a differentiable map

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

  a tensor field of type \((k,l)\) along \(U\) with values on \(M\) is a differentiable map

  \[t:\ U \longrightarrow T^{(k,l)}M\]

  (where \(T^{(k,l)}M\) is the tensor bundle of type \((k,l)\) over \(M\)) such that

  \[t(p) \in T^{(k,l)}(T_q M)\]

  for all \(p \in U\), i.e. \(t(p)\) is a tensor of type \((k,l)\) on the tangent space \(T_q M\) at the point \(q=\Phi(p)\). That is to say a multilinear map

  \[t(p):\ \underbrace{T_q^*M\times\cdots\times T_q^*M}_{k\ \; \text{times}} \times \underbrace{T_q M\times\cdots\times T_q M}_{l\ \; \text{times}} \longrightarrow K,\]

  where \(T_q^* M\) is the dual vector space to \(T_q M\) and \(K\) is the topological field over which the manifold \(M\) is defined. The integer \(k+l\) is called the tensor rank.

  The standard case of a tensor field 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, the class `TensorField` should be used instead.

  INPUT:

  - `vector_field_module` – free module \(\mathfrak{X}(U,\Phi)\) of vector fields along \(U\) associated with the map \(\Phi: U \rightarrow M\) (cf. `VectorFieldFreeModule`)

  - `tensor_type` – pair \((k,l)\) with \(k\) being the contravariant rank and \(l\) the covariant rank

  - `name` – (default: `None`) name given to the tensor field

  - `latex_name` – (default: `None`) LaTeX symbol to denote the tensor field; if none is provided, the LaTeX symbol is set to `name`

  - `sym` – (default: `None`) a symmetry or a list of symmetries among the tensor arguments: each symmetry is described by a tuple containing the positions of the involved arguments, with the convention position=0 for the first argument; for instance:

    - `sym=(0,1)` for a symmetry between the 1st and 2nd arguments

    - `sym=[(0,2),(1,3,4)]` for a symmetry between the 1st and 3rd arguments and a symmetry between the 2nd, 4th and 5th arguments

  - `antisym` – (default: `None`) antisymmetry or list of antisymmetries among the arguments, with the same convention as for `sym`

  EXAMPLES:

  A tensor field of type \((2,0)\) on a 3-dimensional parallelizable manifold:

  Sage

      sage: M = Manifold(3, 'M')
      sage: c_xyz.<x,y,z> = M.chart()  # makes M parallelizable
      sage: t = M.tensor_field(2, 0, name='T') ; t
      Tensor field T of type (2,0) on the 3-dimensional differentiable
       manifold M

  Python

      >>> from sage.all import *
      >>> M = Manifold(Integer(3), 'M')
      >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3)# makes M parallelizable
      >>> t = M.tensor_field(Integer(2), Integer(0), name='T') ; t
      Tensor field T of type (2,0) on the 3-dimensional differentiable
       manifold M

  Tensor fields are considered as elements of a module over the ring \(C^k(M)\) of scalar fields on \(M\):

  Sage

      sage: t.parent()
      Free module T^(2,0)(M) of type-(2,0) tensors fields on the
       3-dimensional differentiable manifold M
      sage: t.parent().base_ring()
      Algebra of differentiable scalar fields on the 3-dimensional
       differentiable manifold M

  [Python]

      >>> from sage.all import *
      >>> t.parent()
      Free module T^(2,0)(M) of type-(2,0) tensors fields on the
       3-dimensional differentiable manifold M
      >>> t.parent().base_ring()
      Algebra of differentiable scalar fields on the 3-dimensional
       differentiable manifold M

  The components with respect to the manifold’s default frame are set or read by means of square brackets:

  Sage

      sage: e = M.vector_frame('e') ; M.set_default_frame(e)
      sage: for i in M.irange():
      ....:     for j in M.irange():
      ....:         t[i,j] = (i+1)**(j+1)
      sage: [[ t[i,j] for j in M.irange()] for i in M.irange()]
      [[1, 1, 1], [2, 4, 8], [3, 9, 27]]

  Python

      >>> from sage.all import *
      >>> e = M.vector_frame('e') ; M.set_default_frame(e)
      >>> for i in M.irange():
      ...     for j in M.irange():
      ...         t[i,j] = (i+Integer(1))**(j+Integer(1))
      >>> [[ t[i,j] for j in M.irange()] for i in M.irange()]
      [[1, 1, 1], [2, 4, 8], [3, 9, 27]]

  A shortcut for the above is using `[:]`:

  Sage

      sage: t[:]
      [ 1  1  1]
      [ 2  4  8]
      [ 3  9 27]

  [Python]

      >>> from sage.all import *
      >>> t[:]
      [ 1  1  1]
      [ 2  4  8]
      [ 3  9 27]

  The components with respect to another frame are set via the method `set_comp()` and read via the method `comp()`; both return an instance of `Components`:

  Sage

      sage: f = M.vector_frame('f')  # a new frame defined on M, in addition to e
      sage: t.set_comp(f)[0,0] = -3
      sage: t.comp(f)
      2-indices components w.r.t. Vector frame (M, (f_0,f_1,f_2))
      sage: t.comp(f)[0,0]
      -3
      sage: t.comp(f)[:]  # the full list of components
      [-3  0  0]
      [ 0  0  0]
      [ 0  0  0]

  Python

      >>> from sage.all import *
      >>> f = M.vector_frame('f')  # a new frame defined on M, in addition to e
      >>> t.set_comp(f)[Integer(0),Integer(0)] = -Integer(3)
      >>> t.comp(f)
      2-indices components w.r.t. Vector frame (M, (f_0,f_1,f_2))
      >>> t.comp(f)[Integer(0),Integer(0)]
      -3
      >>> t.comp(f)[:]  # the full list of components
      [-3  0  0]
      [ 0  0  0]
      [ 0  0  0]

  To avoid any inconsistency between the various components, the method `set_comp()` deletes the components in other frames. Accordingly, the components in the frame `e` have been deleted:

  Sage

      sage: t._components
      {Vector frame (M, (f_0,f_1,f_2)): 2-indices components w.r.t. Vector
       frame (M, (f_0,f_1,f_2))}

  [Python]

      >>> from sage.all import *
      >>> t._components
      {Vector frame (M, (f_0,f_1,f_2)): 2-indices components w.r.t. Vector
       frame (M, (f_0,f_1,f_2))}

  To keep the other components, one must use the method `add_comp()`:

  Sage

      sage: t = M.tensor_field(2, 0, name='T')  # let us restart
      sage: t[0,0] = 2                   # sets the components in the frame e

  Python

      >>> from sage.all import *
      >>> t = M.tensor_field(Integer(2), Integer(0), name='T')  # let us restart
      >>> t[Integer(0),Integer(0)] = Integer(2)                   # sets the components in the frame e

  We now set the components in the frame f with add_comp:

  Sage

      sage: t.add_comp(f)[0,0] = -3

  [Python]

      >>> from sage.all import *
      >>> t.add_comp(f)[Integer(0),Integer(0)] = -Integer(3)

  The components w.r.t. frame e have been kept:

  Sage

      sage: t._components  # random (dictionary output)
      {Vector frame (M, (e_0,e_1,e_2)): 2-indices components w.r.t. Vector frame (M, (e_0,e_1,e_2)),
       Vector frame (M, (f_0,f_1,f_2)): 2-indices components w.r.t. Vector frame (M, (f_0,f_1,f_2))}

  Python

      >>> from sage.all import *
      >>> t._components  # random (dictionary output)
      {Vector frame (M, (e_0,e_1,e_2)): 2-indices components w.r.t. Vector frame (M, (e_0,e_1,e_2)),
       Vector frame (M, (f_0,f_1,f_2)): 2-indices components w.r.t. Vector frame (M, (f_0,f_1,f_2))}

  The basic properties of a tensor field are:

  Sage

      sage: t.domain()
      3-dimensional differentiable manifold M
      sage: t.tensor_type()
      (2, 0)

  [Python]

      >>> from sage.all import *
      >>> t.domain()
      3-dimensional differentiable manifold M
      >>> t.tensor_type()
      (2, 0)

  Symmetries and antisymmetries are declared via the keywords `sym` and `antisym`. For instance, a rank-6 covariant tensor that is symmetric with respect to its 1st and 3rd arguments and antisymmetric with respect to the 2nd, 5th and 6th arguments is set up as follows:

  Sage

      sage: a = M.tensor_field(0, 6, name='T', sym=(0,2), antisym=(1,4,5))
      sage: a[0,0,1,0,1,2] = 3
      sage: a[1,0,0,0,1,2] # check of the symmetry
      3
      sage: a[0,1,1,0,0,2], a[0,1,1,0,2,0] # check of the antisymmetry
      (-3, 3)

  Python

      >>> from sage.all import *
      >>> a = M.tensor_field(Integer(0), Integer(6), name='T', sym=(Integer(0),Integer(2)), antisym=(Integer(1),Integer(4),Integer(5)))
      >>> a[Integer(0),Integer(0),Integer(1),Integer(0),Integer(1),Integer(2)] = Integer(3)
      >>> a[Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),Integer(2)] # check of the symmetry
      3
      >>> a[Integer(0),Integer(1),Integer(1),Integer(0),Integer(0),Integer(2)], a[Integer(0),Integer(1),Integer(1),Integer(0),Integer(2),Integer(0)] # check of the antisymmetry
      (-3, 3)

  Multiple symmetries or antisymmetries are allowed; they must then be declared as a list. For instance, a rank-4 covariant tensor that is antisymmetric with respect to its 1st and 2nd arguments and with respect to its 3rd and 4th argument must be declared as:

  Sage

      sage: r = M.tensor_field(0, 4, name='T', antisym=[(0,1), (2,3)])
      sage: r[0,1,2,0] = 3
      sage: r[1,0,2,0] # first antisymmetry
      -3
      sage: r[0,1,0,2] # second antisymmetry
      -3
      sage: r[1,0,0,2] # both antisymmetries acting
      3

  [Python]

      >>> from sage.all import *
      >>> r = M.tensor_field(Integer(0), Integer(4), name='T', antisym=[(Integer(0),Integer(1)), (Integer(2),Integer(3))])
      >>> r[Integer(0),Integer(1),Integer(2),Integer(0)] = Integer(3)
      >>> r[Integer(1),Integer(0),Integer(2),Integer(0)] # first antisymmetry
      -3
      >>> r[Integer(0),Integer(1),Integer(0),Integer(2)] # second antisymmetry
      -3
      >>> r[Integer(1),Integer(0),Integer(0),Integer(2)] # both antisymmetries acting
      3

  Tensor fields of the same type can be added and subtracted:

  Sage

      sage: a = M.tensor_field(2, 0)
      sage: a[0,0], a[0,1], a[0,2] = (1,2,3)
      sage: b = M.tensor_field(2, 0)
      sage: b[0,0], b[1,1], b[2,2], b[0,2] = (4,5,6,7)
      sage: s = a + 2*b ; s
      Tensor field of type (2,0) on the 3-dimensional differentiable
       manifold M
      sage: a[:], (2*b)[:], s[:]
      (
      [1 2 3]  [ 8  0 14]  [ 9  2 17]
      [0 0 0]  [ 0 10  0]  [ 0 10  0]
      [0 0 0], [ 0  0 12], [ 0  0 12]
      )
      sage: s = a - b ; s
      Tensor field of type (2,0) on the 3-dimensional differentiable
       manifold M
      sage: a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [-3  2 -4]
      [0 0 0]  [0 5 0]  [ 0 -5  0]
      [0 0 0], [0 0 6], [ 0  0 -6]
      )

  Python

      >>> from sage.all import *
      >>> a = M.tensor_field(Integer(2), Integer(0))
      >>> a[Integer(0),Integer(0)], a[Integer(0),Integer(1)], a[Integer(0),Integer(2)] = (Integer(1),Integer(2),Integer(3))
      >>> b = M.tensor_field(Integer(2), Integer(0))
      >>> b[Integer(0),Integer(0)], b[Integer(1),Integer(1)], b[Integer(2),Integer(2)], b[Integer(0),Integer(2)] = (Integer(4),Integer(5),Integer(6),Integer(7))
      >>> s = a + Integer(2)*b ; s
      Tensor field of type (2,0) on the 3-dimensional differentiable
       manifold M
      >>> a[:], (Integer(2)*b)[:], s[:]
      (
      [1 2 3]  [ 8  0 14]  [ 9  2 17]
      [0 0 0]  [ 0 10  0]  [ 0 10  0]
      [0 0 0], [ 0  0 12], [ 0  0 12]
      )
      >>> s = a - b ; s
      Tensor field of type (2,0) on the 3-dimensional differentiable
       manifold M
      >>> a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [-3  2 -4]
      [0 0 0]  [0 5 0]  [ 0 -5  0]
      [0 0 0], [0 0 6], [ 0  0 -6]
      )

  Symmetries are preserved by the addition whenever it is possible:

  Sage

      sage: a = M.tensor_field(2, 0, sym=(0,1))
      sage: a[0,0], a[0,1], a[0,2] = (1,2,3)
      sage: s = a + b
      sage: a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [ 5  2 10]
      [2 0 0]  [0 5 0]  [ 2  5  0]
      [3 0 0], [0 0 6], [ 3  0  6]
      )
      sage: a.symmetries()
      symmetry: (0, 1);  no antisymmetry
      sage: b.symmetries()
      no symmetry;  no antisymmetry
      sage: s.symmetries()
      no symmetry;  no antisymmetry

  [Python]

      >>> from sage.all import *
      >>> a = M.tensor_field(Integer(2), Integer(0), sym=(Integer(0),Integer(1)))
      >>> a[Integer(0),Integer(0)], a[Integer(0),Integer(1)], a[Integer(0),Integer(2)] = (Integer(1),Integer(2),Integer(3))
      >>> s = a + b
      >>> a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [ 5  2 10]
      [2 0 0]  [0 5 0]  [ 2  5  0]
      [3 0 0], [0 0 6], [ 3  0  6]
      )
      >>> a.symmetries()
      symmetry: (0, 1);  no antisymmetry
      >>> b.symmetries()
      no symmetry;  no antisymmetry
      >>> s.symmetries()
      no symmetry;  no antisymmetry

  Let us now make b symmetric:

  Sage

      sage: b = M.tensor_field(2, 0, sym=(0,1))
      sage: b[0,0], b[1,1], b[2,2], b[0,2] = (4,5,6,7)
      sage: s = a + b
      sage: a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [ 5  2 10]
      [2 0 0]  [0 5 0]  [ 2  5  0]
      [3 0 0], [7 0 6], [10  0  6]
      )
      sage: s.symmetries()  # s is symmetric because both a and b are
      symmetry: (0, 1);  no antisymmetry

  Python

      >>> from sage.all import *
      >>> b = M.tensor_field(Integer(2), Integer(0), sym=(Integer(0),Integer(1)))
      >>> b[Integer(0),Integer(0)], b[Integer(1),Integer(1)], b[Integer(2),Integer(2)], b[Integer(0),Integer(2)] = (Integer(4),Integer(5),Integer(6),Integer(7))
      >>> s = a + b
      >>> a[:], b[:], s[:]
      (
      [1 2 3]  [4 0 7]  [ 5  2 10]
      [2 0 0]  [0 5 0]  [ 2  5  0]
      [3 0 0], [7 0 6], [10  0  6]
      )
      >>> s.symmetries()  # s is symmetric because both a and b are
      symmetry: (0, 1);  no antisymmetry

  The tensor product is taken with the operator `*`:

  Sage

      sage: c = a*b ; c
      Tensor field of type (4,0) on the 3-dimensional differentiable
       manifold M
      sage: c.symmetries()  # since a and b are both symmetric, a*b has two symmetries:
      symmetries: [(0, 1), (2, 3)];  no antisymmetry

  [Python]

      >>> from sage.all import *
      >>> c = a*b ; c
      Tensor field of type (4,0) on the 3-dimensional differentiable
       manifold M
      >>> c.symmetries()  # since a and b are both symmetric, a*b has two symmetries:
      symmetries: [(0, 1), (2, 3)];  no antisymmetry

  The tensor product of two fully contravariant tensors is not symmetric in general:

  Sage

      sage: a*b == b*a
      False

  Python

      >>> from sage.all import *
      >>> a*b == b*a
      False

  The tensor product of a fully contravariant tensor by a fully covariant one is symmetric:

  Sage

      sage: d = M.diff_form(2)  # a fully covariant tensor field
      sage: d[0,1], d[0,2], d[1,2] = (3, 2, 1)
      sage: s = a*d ; s
      Tensor field of type (2,2) on the 3-dimensional differentiable
       manifold M
      sage: s.symmetries()
      symmetry: (0, 1);  antisymmetry: (2, 3)
      sage: s1 = d*a ; s1
      Tensor field of type (2,2) on the 3-dimensional differentiable
       manifold M
      sage: s1.symmetries()
      symmetry: (0, 1);  antisymmetry: (2, 3)
      sage: d*a == a*d
      True

  [Python]

      >>> from sage.all import *
      >>> d = M.diff_form(Integer(2))  # a fully covariant tensor field
      >>> d[Integer(0),Integer(1)], d[Integer(0),Integer(2)], d[Integer(1),Integer(2)] = (Integer(3), Integer(2), Integer(1))
      >>> s = a*d ; s
      Tensor field of type (2,2) on the 3-dimensional differentiable
       manifold M
      >>> s.symmetries()
      symmetry: (0, 1);  antisymmetry: (2, 3)
      >>> s1 = d*a ; s1
      Tensor field of type (2,2) on the 3-dimensional differentiable
       manifold M
      >>> s1.symmetries()
      symmetry: (0, 1);  antisymmetry: (2, 3)
      >>> d*a == a*d
      True

  Example of tensor field associated with a non-trivial differentiable map \(\Phi\): tensor field along a curve in \(M\):

  Sage

      sage: R = Manifold(1, 'R')  # R as a 1-dimensional manifold
      sage: T.<t> = R.chart()  # canonical chart on R
      sage: Phi = R.diff_map(M, [cos(t), sin(t), t], name='Phi') ; Phi
      Differentiable map Phi from the 1-dimensional differentiable manifold R
       to the 3-dimensional differentiable manifold M
      sage: h = R.tensor_field(2, 0, name='h', dest_map=Phi) ; h
      Tensor field h of type (2,0) along the 1-dimensional differentiable
       manifold R with values on the 3-dimensional differentiable manifold M
      sage: h.parent()
      Free module T^(2,0)(R,Phi) of type-(2,0) tensors fields along the
       1-dimensional differentiable manifold R mapped into the 3-dimensional
       differentiable manifold M
      sage: h[0,0], h[0,1], h[2,0] = 1+t, t^2, sin(t)
      sage: h.display()
      h = (t + 1) ∂/∂x⊗∂/∂x + t^2 ∂/∂x⊗∂/∂y + sin(t) ∂/∂z⊗∂/∂x

  Python

      >>> from sage.all import *
      >>> R = Manifold(Integer(1), 'R')  # R as a 1-dimensional manifold
      >>> T = R.chart(names=('t',)); (t,) = T._first_ngens(1)# canonical chart on R
      >>> Phi = R.diff_map(M, [cos(t), sin(t), t], name='Phi') ; Phi
      Differentiable map Phi from the 1-dimensional differentiable manifold R
       to the 3-dimensional differentiable manifold M
      >>> h = R.tensor_field(Integer(2), Integer(0), name='h', dest_map=Phi) ; h
      Tensor field h of type (2,0) along the 1-dimensional differentiable
       manifold R with values on the 3-dimensional differentiable manifold M
      >>> h.parent()
      Free module T^(2,0)(R,Phi) of type-(2,0) tensors fields along the
       1-dimensional differentiable manifold R mapped into the 3-dimensional
       differentiable manifold M
      >>> h[Integer(0),Integer(0)], h[Integer(0),Integer(1)], h[Integer(2),Integer(0)] = Integer(1)+t, t**Integer(2), sin(t)
      >>> h.display()
      h = (t + 1) ∂/∂x⊗∂/∂x + t^2 ∂/∂x⊗∂/∂y + sin(t) ∂/∂z⊗∂/∂x

  add_comp(basis=None)

    Return the components of the tensor field in a given vector frame for assignment.

    The components with respect to other frames on the same domain are kept. To delete them, use the method `set_comp()` instead.

    INPUT:

    - `basis` – (default: `None`) vector frame in which the components are defined; if none is provided, the components are assumed to refer to the tensor field domain’s default frame

    OUTPUT:

    - components in the given frame, as an instance of the class `Components`; if such components did not exist previously, they are created

    EXAMPLES:

    Sage

        sage: M = Manifold(2, 'M')
        sage: X.<x,y> = M.chart()
        sage: e_xy = X.frame()
        sage: t = M.tensor_field(1,1, name='t')
        sage: t.add_comp(e_xy)
        2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        sage: t.add_comp(e_xy)[1,0] = 2
        sage: t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> e_xy = X.frame()
        >>> t = M.tensor_field(Integer(1),Integer(1), name='t')
        >>> t.add_comp(e_xy)
        2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        >>> t.add_comp(e_xy)[Integer(1),Integer(0)] = Integer(2)
        >>> t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Adding components with respect to a new frame (`e`):

    Sage

        sage: e = M.vector_frame('e')
        sage: t.add_comp(e)
        2-indices components w.r.t. Vector frame (M, (e_0,e_1))
        sage: t.add_comp(e)[0,1] = x
        sage: t.display(e)
        t = x e_0⊗e^1

    [Python]

        >>> from sage.all import *
        >>> e = M.vector_frame('e')
        >>> t.add_comp(e)
        2-indices components w.r.t. Vector frame (M, (e_0,e_1))
        >>> t.add_comp(e)[Integer(0),Integer(1)] = x
        >>> t.display(e)
        t = x e_0⊗e^1

    The components with respect to the frame `e_xy` are kept:

    Sage

        sage: t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Python

        >>> from sage.all import *
        >>> t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Adding components in a frame defined on a subdomain:

    Sage

        sage: U = M.open_subset('U', coord_def={X: x>0})
        sage: f = U.vector_frame('f')
        sage: t.add_comp(f)
        2-indices components w.r.t. Vector frame (U, (f_0,f_1))
        sage: t.add_comp(f)[0,1] = 1+y
        sage: t.display(f)
        t = (y + 1) f_0⊗f^1

    [Python]

        >>> from sage.all import *
        >>> U = M.open_subset('U', coord_def={X: x>Integer(0)})
        >>> f = U.vector_frame('f')
        >>> t.add_comp(f)
        2-indices components w.r.t. Vector frame (U, (f_0,f_1))
        >>> t.add_comp(f)[Integer(0),Integer(1)] = Integer(1)+y
        >>> t.display(f)
        t = (y + 1) f_0⊗f^1

    The components previously defined are kept:

    Sage

        sage: t.display(e_xy)
        t = 2 ∂/∂y⊗dx
        sage: t.display(e)
        t = x e_0⊗e^1

    Python

        >>> from sage.all import *
        >>> t.display(e_xy)
        t = 2 ∂/∂y⊗dx
        >>> t.display(e)
        t = x e_0⊗e^1

  along(mapping)

    Return the tensor field deduced from `self` via a differentiable map, the codomain of which is included in the domain of `self`.

    More precisely, if `self` is a tensor field \(t\) on \(M\) and if \(\Phi: U \rightarrow M\) is a differentiable map from some differentiable manifold \(U\) to \(M\), the returned object is a tensor field \(\tilde t\) along \(U\) with values on \(M\) such that

    \[\forall p \in U,\ \tilde t(p) = t(\Phi(p)).\]

    INPUT:

    - `mapping` – differentiable map \(\Phi: U \rightarrow M\)

    OUTPUT: tensor field \(\tilde t\) along \(U\) defined above

    EXAMPLES:

    Let us consider the map \(\Phi\) between the interval \(U=(0,2\pi)\) and the Euclidean plane \(M=\RR^2\) defining the lemniscate of Gerono:

    Sage

        sage: M = Manifold(2, 'M')
        sage: X.<x,y> = M.chart()
        sage: t = var('t', domain='real')
        sage: Phi = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi),
        ....:               name='Phi')
        sage: U = Phi.domain(); U
        Real interval (0, 2*pi)

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> t = var('t', domain='real')
        >>> Phi = M.curve({X: [sin(t), sin(Integer(2)*t)/Integer(2)]}, (t, Integer(0), Integer(2)*pi),
        ...               name='Phi')
        >>> U = Phi.domain(); U
        Real interval (0, 2*pi)

    and a vector field on \(M\):

    Sage

        sage: v = M.vector_field(-y , x, name='v')

    [Python]

        >>> from sage.all import *
        >>> v = M.vector_field(-y , x, name='v')

    We have then:

    Sage

        sage: vU = v.along(Phi); vU
        Vector field v along the Real interval (0, 2*pi) with values on
         the 2-dimensional differentiable manifold M
        sage: vU.display()
        v = -cos(t)*sin(t) ∂/∂x + sin(t) ∂/∂y
        sage: vU.parent()
        Free module X((0, 2*pi),Phi) of vector fields along the Real
         interval (0, 2*pi) mapped into the 2-dimensional differentiable
         manifold M
        sage: vU.parent() is Phi.tangent_vector_field().parent()
        True

    Python

        >>> from sage.all import *
        >>> vU = v.along(Phi); vU
        Vector field v along the Real interval (0, 2*pi) with values on
         the 2-dimensional differentiable manifold M
        >>> vU.display()
        v = -cos(t)*sin(t) ∂/∂x + sin(t) ∂/∂y
        >>> vU.parent()
        Free module X((0, 2*pi),Phi) of vector fields along the Real
         interval (0, 2*pi) mapped into the 2-dimensional differentiable
         manifold M
        >>> vU.parent() is Phi.tangent_vector_field().parent()
        True

    We check that the defining relation \(\tilde t(p) = t(\Phi(p))\) holds:

    Sage

        sage: p = U(t)  # a generic point of U
        sage: vU.at(p) == v.at(Phi(p))
        True

    [Python]

        >>> from sage.all import *
        >>> p = U(t)  # a generic point of U
        >>> vU.at(p) == v.at(Phi(p))
        True

    Case of a tensor field of type `(0,2)`:

    Sage

        sage: a = M.tensor_field(0, 2)
        sage: a[0,0], a[0,1], a[1,1] = x+y, x*y, x^2-y^2
        sage: aU = a.along(Phi); aU
        Tensor field of type (0,2) along the Real interval (0, 2*pi) with
         values on the 2-dimensional differentiable manifold M
        sage: aU.display()
        (cos(t) + 1)*sin(t) dx⊗dx + cos(t)*sin(t)^2 dx⊗dy + sin(t)^4 dy⊗dy
        sage: aU.parent()
        Free module T^(0,2)((0, 2*pi),Phi) of type-(0,2) tensors fields
         along the Real interval (0, 2*pi) mapped into the 2-dimensional
         differentiable manifold M
        sage: aU.at(p) == a.at(Phi(p))
        True

    Python

        >>> from sage.all import *
        >>> a = M.tensor_field(Integer(0), Integer(2))
        >>> a[Integer(0),Integer(0)], a[Integer(0),Integer(1)], a[Integer(1),Integer(1)] = x+y, x*y, x**Integer(2)-y**Integer(2)
        >>> aU = a.along(Phi); aU
        Tensor field of type (0,2) along the Real interval (0, 2*pi) with
         values on the 2-dimensional differentiable manifold M
        >>> aU.display()
        (cos(t) + 1)*sin(t) dx⊗dx + cos(t)*sin(t)^2 dx⊗dy + sin(t)^4 dy⊗dy
        >>> aU.parent()
        Free module T^(0,2)((0, 2*pi),Phi) of type-(0,2) tensors fields
         along the Real interval (0, 2*pi) mapped into the 2-dimensional
         differentiable manifold M
        >>> aU.at(p) == a.at(Phi(p))
        True

  at(point)

    Value of `self` at a point of its domain.

    If the current tensor field is

    \[t:\ U \longrightarrow T^{(k,l)} M\]

    associated with the differentiable map

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

    where \(U\) and \(M\) are two manifolds (possibly \(U = M\) and \(\Phi = \mathrm{Id}_M\)), then for any point \(p\in U\), \(t(p)\) is a tensor on the tangent space to \(M\) at the point \(\Phi(p)\).

    INPUT:

    - `point` – `ManifoldPoint` point \(p\) in the domain of the tensor field \(U\)

    OUTPUT:

    - `FreeModuleTensor` representing the tensor \(t(p)\) on the tangent vector space \(T_{\Phi(p)} M\)

    EXAMPLES:

    Vector in a tangent space of a 2-dimensional manifold:

    Sage

        sage: M = Manifold(2, 'M')
        sage: c_xy.<x,y> = M.chart()
        sage: p = M.point((-2,3), name='p')
        sage: v = M.vector_field(y, x^2, name='v')
        sage: v.display()
        v = y ∂/∂x + x^2 ∂/∂y
        sage: vp = v.at(p) ; vp
        Tangent vector v at Point p on the 2-dimensional differentiable
         manifold M
        sage: vp.parent()
        Tangent space at Point p on the 2-dimensional differentiable
         manifold M
        sage: vp.display()
        v = 3 ∂/∂x + 4 ∂/∂y

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)
        >>> p = M.point((-Integer(2),Integer(3)), name='p')
        >>> v = M.vector_field(y, x**Integer(2), name='v')
        >>> v.display()
        v = y ∂/∂x + x^2 ∂/∂y
        >>> vp = v.at(p) ; vp
        Tangent vector v at Point p on the 2-dimensional differentiable
         manifold M
        >>> vp.parent()
        Tangent space at Point p on the 2-dimensional differentiable
         manifold M
        >>> vp.display()
        v = 3 ∂/∂x + 4 ∂/∂y

    A 1-form gives birth to a linear form in the tangent space:

    Sage

        sage: w = M.one_form(-x, 1+y, name='w')
        sage: w.display()
        w = -x dx + (y + 1) dy
        sage: wp = w.at(p) ; wp
        Linear form w on the Tangent space at Point p on the 2-dimensional
         differentiable manifold M
        sage: wp.parent()
        Dual of the Tangent space at Point p on the 2-dimensional
         differentiable manifold M
        sage: wp.display()
        w = 2 dx + 4 dy

    [Python]

        >>> from sage.all import *
        >>> w = M.one_form(-x, Integer(1)+y, name='w')
        >>> w.display()
        w = -x dx + (y + 1) dy
        >>> wp = w.at(p) ; wp
        Linear form w on the Tangent space at Point p on the 2-dimensional
         differentiable manifold M
        >>> wp.parent()
        Dual of the Tangent space at Point p on the 2-dimensional
         differentiable manifold M
        >>> wp.display()
        w = 2 dx + 4 dy

    A tensor field of type \((1,1)\) yields a tensor of type \((1,1)\) in the tangent space:

    Sage

        sage: t = M.tensor_field(1, 1, name='t')
        sage: t[0,0], t[0,1], t[1,1] = 1+x, x*y, 1-y
        sage: t.display()
        t = (x + 1) ∂/∂x⊗dx + x*y ∂/∂x⊗dy + (-y + 1) ∂/∂y⊗dy
        sage: tp = t.at(p) ; tp
        Type-(1,1) tensor t on the Tangent space at Point p on the
         2-dimensional differentiable manifold M
        sage: tp.parent()
        Free module of type-(1,1) tensors on the Tangent space at Point p
         on the 2-dimensional differentiable manifold M
        sage: tp.display()
        t = -∂/∂x⊗dx - 6 ∂/∂x⊗dy - 2 ∂/∂y⊗dy

    Python

        >>> from sage.all import *
        >>> t = M.tensor_field(Integer(1), Integer(1), name='t')
        >>> t[Integer(0),Integer(0)], t[Integer(0),Integer(1)], t[Integer(1),Integer(1)] = Integer(1)+x, x*y, Integer(1)-y
        >>> t.display()
        t = (x + 1) ∂/∂x⊗dx + x*y ∂/∂x⊗dy + (-y + 1) ∂/∂y⊗dy
        >>> tp = t.at(p) ; tp
        Type-(1,1) tensor t on the Tangent space at Point p on the
         2-dimensional differentiable manifold M
        >>> tp.parent()
        Free module of type-(1,1) tensors on the Tangent space at Point p
         on the 2-dimensional differentiable manifold M
        >>> tp.display()
        t = -∂/∂x⊗dx - 6 ∂/∂x⊗dy - 2 ∂/∂y⊗dy

    A 2-form yields an alternating form of degree 2 in the tangent space:

    Sage

        sage: a = M.diff_form(2, name='a')
        sage: a[0,1] = x*y
        sage: a.display()
        a = x*y dx∧dy
        sage: ap = a.at(p) ; ap
        Alternating form a of degree 2 on the Tangent space at Point p on
         the 2-dimensional differentiable manifold M
        sage: ap.parent()
        2nd exterior power of the dual of the Tangent space at Point p on
         the 2-dimensional differentiable manifold M
        sage: ap.display()
        a = -6 dx∧dy

    [Python]

        >>> from sage.all import *
        >>> a = M.diff_form(Integer(2), name='a')
        >>> a[Integer(0),Integer(1)] = x*y
        >>> a.display()
        a = x*y dx∧dy
        >>> ap = a.at(p) ; ap
        Alternating form a of degree 2 on the Tangent space at Point p on
         the 2-dimensional differentiable manifold M
        >>> ap.parent()
        2nd exterior power of the dual of the Tangent space at Point p on
         the 2-dimensional differentiable manifold M
        >>> ap.display()
        a = -6 dx∧dy

    Example with a non trivial map \(\Phi\):

    Sage

        sage: U = Manifold(1, 'U')  # (0,2*pi) as a 1-dimensional manifold
        sage: T.<t> = U.chart(r't:(0,2*pi)')  # canonical chart on U
        sage: Phi = U.diff_map(M, [cos(t), sin(t)], name='Phi',
        ....:                  latex_name=r'\Phi')
        sage: v = U.vector_field(1+t, t^2, name='v', dest_map=Phi) ; v
        Vector field v along the 1-dimensional differentiable manifold U
         with values on the 2-dimensional differentiable manifold M
        sage: v.display()
        v = (t + 1) ∂/∂x + t^2 ∂/∂y
        sage: p = U((pi/6,))
        sage: vp = v.at(p) ; vp
        Tangent vector v at Point on the 2-dimensional differentiable
         manifold M
        sage: vp.parent() is M.tangent_space(Phi(p))
        True
        sage: vp.display()
        v = (1/6*pi + 1) ∂/∂x + 1/36*pi^2 ∂/∂y

    Python

        >>> from sage.all import *
        >>> U = Manifold(Integer(1), 'U')  # (0,2*pi) as a 1-dimensional manifold
        >>> T = U.chart(r't:(0,2*pi)', names=('t',)); (t,) = T._first_ngens(1)# canonical chart on U
        >>> Phi = U.diff_map(M, [cos(t), sin(t)], name='Phi',
        ...                  latex_name=r'\Phi')
        >>> v = U.vector_field(Integer(1)+t, t**Integer(2), name='v', dest_map=Phi) ; v
        Vector field v along the 1-dimensional differentiable manifold U
         with values on the 2-dimensional differentiable manifold M
        >>> v.display()
        v = (t + 1) ∂/∂x + t^2 ∂/∂y
        >>> p = U((pi/Integer(6),))
        >>> vp = v.at(p) ; vp
        Tangent vector v at Point on the 2-dimensional differentiable
         manifold M
        >>> vp.parent() is M.tangent_space(Phi(p))
        True
        >>> vp.display()
        v = (1/6*pi + 1) ∂/∂x + 1/36*pi^2 ∂/∂y

  comp(basis=None, from_basis=None)

    Return the components in a given vector frame.

    If the components are not known already, they are computed by the tensor change-of-basis formula from components in another vector frame.

    INPUT:

    - `basis` – (default: `None`) vector frame in which the components are required; if none is provided, the components are assumed to refer to the tensor field domain’s default frame

    - `from_basis` – (default: `None`) vector frame from which the required components are computed, via the tensor change-of-basis formula, if they are not known already in the basis `basis`

    OUTPUT:

    - components in the vector frame `basis`, as an instance of the class `Components`

    EXAMPLES:

    Sage

        sage: M = Manifold(2, 'M', start_index=1)
        sage: X.<x,y> = M.chart()
        sage: t = M.tensor_field(1,2, name='t')
        sage: t[1,2,1] = x*y
        sage: t.comp(X.frame())
        3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        sage: t.comp()  # the default frame is X.frame()
        3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        sage: t.comp()[:]
        [[[0, 0], [x*y, 0]], [[0, 0], [0, 0]]]
        sage: e = M.vector_frame('e')
        sage: t[e, 2,1,1] = x-3
        sage: t.comp(e)
        3-indices components w.r.t. Vector frame (M, (e_1,e_2))
        sage: t.comp(e)[:]
        [[[0, 0], [0, 0]], [[x - 3, 0], [0, 0]]]

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M', start_index=Integer(1))
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> t = M.tensor_field(Integer(1),Integer(2), name='t')
        >>> t[Integer(1),Integer(2),Integer(1)] = x*y
        >>> t.comp(X.frame())
        3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        >>> t.comp()  # the default frame is X.frame()
        3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        >>> t.comp()[:]
        [[[0, 0], [x*y, 0]], [[0, 0], [0, 0]]]
        >>> e = M.vector_frame('e')
        >>> t[e, Integer(2),Integer(1),Integer(1)] = x-Integer(3)
        >>> t.comp(e)
        3-indices components w.r.t. Vector frame (M, (e_1,e_2))
        >>> t.comp(e)[:]
        [[[0, 0], [0, 0]], [[x - 3, 0], [0, 0]]]

  contract(*args)

    Contraction with another tensor field, on one or more indices.

    INPUT:

    - `pos1` – positions of the indices in `self` involved in the contraction; `pos1` must be a sequence of integers, with 0 standing for the first index position, 1 for the second one, etc. If `pos1` is not provided, a single contraction on the last index position of `self` is assumed

    - `other` – the tensor field to contract with

    - `pos2` – positions of the indices in `other` involved in the contraction, with the same conventions as for `pos1`. If `pos2` is not provided, a single contraction on the first index position of `other` is assumed

    OUTPUT:

    - tensor field resulting from the contraction at the positions `pos1` and `pos2` of `self` with `other`

    EXAMPLES:

    Contraction of a tensor field of type \((2,0)\) with a tensor field of type \((1,1)\):

    Sage

        sage: M = Manifold(2, 'M')
        sage: X.<x,y> = M.chart()
        sage: a = M.tensor_field(2,0, [[1+x, 2], [y, -x^2]], name='a')
        sage: b = M.tensor_field(1,1, [[-y, 1], [x, x+y]], name='b')
        sage: s = a.contract(0, b, 1); s
        Tensor field of type (2,0) on the 2-dimensional differentiable manifold M
        sage: s.display()
        -x*y ∂/∂x⊗∂/∂x + (x^2 + x*y + y^2 + x) ∂/∂x⊗∂/∂y
         + (-x^2 - 2*y) ∂/∂y⊗∂/∂x + (-x^3 - x^2*y + 2*x) ∂/∂y⊗∂/∂y

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> a = M.tensor_field(Integer(2),Integer(0), [[Integer(1)+x, Integer(2)], [y, -x**Integer(2)]], name='a')
        >>> b = M.tensor_field(Integer(1),Integer(1), [[-y, Integer(1)], [x, x+y]], name='b')
        >>> s = a.contract(Integer(0), b, Integer(1)); s
        Tensor field of type (2,0) on the 2-dimensional differentiable manifold M
        >>> s.display()
        -x*y ∂/∂x⊗∂/∂x + (x^2 + x*y + y^2 + x) ∂/∂x⊗∂/∂y
         + (-x^2 - 2*y) ∂/∂y⊗∂/∂x + (-x^3 - x^2*y + 2*x) ∂/∂y⊗∂/∂y

    Check:

    Sage

        sage: all(s[ind] == sum(a[k, ind[0]]*b[ind[1], k] for k in [0..1])
        ....:     for ind in M.index_generator(2))
        True

    [Python]

        >>> from sage.all import *
        >>> all(s[ind] == sum(a[k, ind[Integer(0)]]*b[ind[Integer(1)], k] for k in (ellipsis_range(Integer(0),Ellipsis,Integer(1))))
        ...     for ind in M.index_generator(Integer(2)))
        True

    The same contraction with repeated index notation:

    Sage

        sage: s == a['^ki']*b['^j_k']
        True

    Python

        >>> from sage.all import *
        >>> s == a['^ki']*b['^j_k']
        True

    Contraction on the second index of `a`:

    Sage

        sage: s = a.contract(1, b, 1); s
        Tensor field of type (2,0) on the 2-dimensional differentiable manifold M
        sage: s.display()
        (-(x + 1)*y + 2) ∂/∂x⊗∂/∂x + (x^2 + 3*x + 2*y) ∂/∂x⊗∂/∂y
         + (-x^2 - y^2) ∂/∂y⊗∂/∂x + (-x^3 - (x^2 - x)*y) ∂/∂y⊗∂/∂y

    [Python]

        >>> from sage.all import *
        >>> s = a.contract(Integer(1), b, Integer(1)); s
        Tensor field of type (2,0) on the 2-dimensional differentiable manifold M
        >>> s.display()
        (-(x + 1)*y + 2) ∂/∂x⊗∂/∂x + (x^2 + 3*x + 2*y) ∂/∂x⊗∂/∂y
         + (-x^2 - y^2) ∂/∂y⊗∂/∂x + (-x^3 - (x^2 - x)*y) ∂/∂y⊗∂/∂y

    Check:

    Sage

        sage: all(s[ind] == sum(a[ind[0], k]*b[ind[1], k] for k in [0..1])
        ....:     for ind in M.index_generator(2))
        True

    Python

        >>> from sage.all import *
        >>> all(s[ind] == sum(a[ind[Integer(0)], k]*b[ind[Integer(1)], k] for k in (ellipsis_range(Integer(0),Ellipsis,Integer(1))))
        ...     for ind in M.index_generator(Integer(2)))
        True

    The same contraction with repeated index notation:

    Sage

        sage: s == a['^ik']*b['^j_k']
        True

    [Python]

        >>> from sage.all import *
        >>> s == a['^ik']*b['^j_k']
        True

    See also

    `sage.manifolds.differentiable.tensorfield.TensorField.contract()` for more examples.

  display_comp(frame=None, chart=None, coordinate_labels=True, only_nonzero=True, only_nonredundant=False)

    Display the tensor components with respect to a given frame, one per line.

    The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

    INPUT:

    - `frame` – (default: `None`) vector frame with respect to which the tensor field components are defined; if `None`, then

      - if `chart` is not `None`, the coordinate frame associated to `chart` is used

      - otherwise, the default basis of the vector field module on which the tensor field is defined is used

    - `chart` – (default: `None`) chart specifying the coordinate expression of the components; if `None`, the default chart of the tensor field domain is used

    - `coordinate_labels` – boolean (default: `True`); if `True`, coordinate symbols are used by default (instead of integers) as index labels whenever `frame` is a coordinate frame

    - `only_nonzero` – boolean (default: `True`); if `True`, only nonzero components are displayed

    - `only_nonredundant` – boolean (default: `False`); if `True`, only nonredundant components are displayed in case of symmetries

    EXAMPLES:

    Display of the components of a type-\((2,1)\) tensor field on a 2-dimensional manifold:

    Sage

        sage: M = Manifold(2, 'M')
        sage: X.<x,y> = M.chart()
        sage: t = M.tensor_field(2, 1, name='t', sym=(0,1))
        sage: t[0,0,0], t[0,1,0], t[1,1,1] = x+y, x*y, -3
        sage: t.display_comp()
        t^xx_x = x + y
        t^xy_x = x*y
        t^yx_x = x*y
        t^yy_y = -3

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> t = M.tensor_field(Integer(2), Integer(1), name='t', sym=(Integer(0),Integer(1)))
        >>> t[Integer(0),Integer(0),Integer(0)], t[Integer(0),Integer(1),Integer(0)], t[Integer(1),Integer(1),Integer(1)] = x+y, x*y, -Integer(3)
        >>> t.display_comp()
        t^xx_x = x + y
        t^xy_x = x*y
        t^yx_x = x*y
        t^yy_y = -3

    By default, only the non-vanishing components are displayed; to see all the components, the argument `only_nonzero` must be set to `False`:

    Sage

        sage: t.display_comp(only_nonzero=False)
        t^xx_x = x + y
        t^xx_y = 0
        t^xy_x = x*y
        t^xy_y = 0
        t^yx_x = x*y
        t^yx_y = 0
        t^yy_x = 0
        t^yy_y = -3

    [Python]

        >>> from sage.all import *
        >>> t.display_comp(only_nonzero=False)
        t^xx_x = x + y
        t^xx_y = 0
        t^xy_x = x*y
        t^xy_y = 0
        t^yx_x = x*y
        t^yx_y = 0
        t^yy_x = 0
        t^yy_y = -3

    `t` being symmetric with respect to its first two indices, one may ask to skip the components that can be deduced by symmetry:

    Sage

        sage: t.display_comp(only_nonredundant=True)
        t^xx_x = x + y
        t^xy_x = x*y
        t^yy_y = -3

    Python

        >>> from sage.all import *
        >>> t.display_comp(only_nonredundant=True)
        t^xx_x = x + y
        t^xy_x = x*y
        t^yy_y = -3

    Instead of coordinate labels, one may ask for integers:

    Sage

        sage: t.display_comp(coordinate_labels=False)
        t^00_0 = x + y
        t^01_0 = x*y
        t^10_0 = x*y
        t^11_1 = -3

    [Python]

        >>> from sage.all import *
        >>> t.display_comp(coordinate_labels=False)
        t^00_0 = x + y
        t^01_0 = x*y
        t^10_0 = x*y
        t^11_1 = -3

    Display in a frame different from the default one (note that since `f` is not a coordinate frame, integer are used to label the indices):

    Sage

        sage: a = M.automorphism_field()
        sage: a[:] = [[1+y^2, 0], [0, 2+x^2]]
        sage: f = X.frame().new_frame(a, 'f')
        sage: t.display_comp(frame=f)
        t^00_0 = (x + y)/(y^2 + 1)
        t^01_0 = x*y/(x^2 + 2)
        t^10_0 = x*y/(x^2 + 2)
        t^11_1 = -3/(x^2 + 2)

    Python

        >>> from sage.all import *
        >>> a = M.automorphism_field()
        >>> a[:] = [[Integer(1)+y**Integer(2), Integer(0)], [Integer(0), Integer(2)+x**Integer(2)]]
        >>> f = X.frame().new_frame(a, 'f')
        >>> t.display_comp(frame=f)
        t^00_0 = (x + y)/(y^2 + 1)
        t^01_0 = x*y/(x^2 + 2)
        t^10_0 = x*y/(x^2 + 2)
        t^11_1 = -3/(x^2 + 2)

    Display with respect to a chart different from the default one:

    Sage

        sage: Y.<u,v> = M.chart()
        sage: X_to_Y = X.transition_map(Y, [x+y, x-y])
        sage: Y_to_X = X_to_Y.inverse()
        sage: t.display_comp(chart=Y)
        t^uu_u = 1/4*u^2 - 1/4*v^2 + 1/2*u - 3/2
        t^uu_v = 1/4*u^2 - 1/4*v^2 + 1/2*u + 3/2
        t^uv_u = 1/2*u + 3/2
        t^uv_v = 1/2*u - 3/2
        t^vu_u = 1/2*u + 3/2
        t^vu_v = 1/2*u - 3/2
        t^vv_u = -1/4*u^2 + 1/4*v^2 + 1/2*u - 3/2
        t^vv_v = -1/4*u^2 + 1/4*v^2 + 1/2*u + 3/2

    [Python]

        >>> from sage.all import *
        >>> Y = M.chart(names=('u', 'v',)); (u, v,) = Y._first_ngens(2)
        >>> X_to_Y = X.transition_map(Y, [x+y, x-y])
        >>> Y_to_X = X_to_Y.inverse()
        >>> t.display_comp(chart=Y)
        t^uu_u = 1/4*u^2 - 1/4*v^2 + 1/2*u - 3/2
        t^uu_v = 1/4*u^2 - 1/4*v^2 + 1/2*u + 3/2
        t^uv_u = 1/2*u + 3/2
        t^uv_v = 1/2*u - 3/2
        t^vu_u = 1/2*u + 3/2
        t^vu_v = 1/2*u - 3/2
        t^vv_u = -1/4*u^2 + 1/4*v^2 + 1/2*u - 3/2
        t^vv_v = -1/4*u^2 + 1/4*v^2 + 1/2*u + 3/2

    Note that the frame defining the components is the coordinate frame associated with chart `Y`, i.e. we have:

    Sage

        sage: str(t.display_comp(chart=Y)) == str(t.display_comp(frame=Y.frame(), chart=Y))
        True

    Python

        >>> from sage.all import *
        >>> str(t.display_comp(chart=Y)) == str(t.display_comp(frame=Y.frame(), chart=Y))
        True

    Display of the components with respect to a specific frame, expressed in terms of a specific chart:

    Sage

        sage: t.display_comp(frame=f, chart=Y)
        t^00_0 = 4*u/(u^2 - 2*u*v + v^2 + 4)
        t^01_0 = (u^2 - v^2)/(u^2 + 2*u*v + v^2 + 8)
        t^10_0 = (u^2 - v^2)/(u^2 + 2*u*v + v^2 + 8)
        t^11_1 = -12/(u^2 + 2*u*v + v^2 + 8)

    [Python]

        >>> from sage.all import *
        >>> t.display_comp(frame=f, chart=Y)
        t^00_0 = 4*u/(u^2 - 2*u*v + v^2 + 4)
        t^01_0 = (u^2 - v^2)/(u^2 + 2*u*v + v^2 + 8)
        t^10_0 = (u^2 - v^2)/(u^2 + 2*u*v + v^2 + 8)
        t^11_1 = -12/(u^2 + 2*u*v + v^2 + 8)

  lie_der(vector)

    alias of `lie_derivative()`.

  lie_derivative(vector)

    Compute the Lie derivative with respect to a vector field.

    INPUT:

    - `vector` – vector field with respect to which the Lie derivative is to be taken

    OUTPUT:

    - the tensor field that is the Lie derivative of `self` with respect to `vector`

    EXAMPLES:

    Lie derivative of a vector:

    Sage

        sage: M = Manifold(2, 'M', start_index=1)
        sage: c_xy.<x,y> = M.chart()
        sage: v = M.vector_field(-y, x, name='v')
        sage: w = M.vector_field(2*x+y, x*y)
        sage: w.lie_derivative(v)
        Vector field on the 2-dimensional differentiable manifold M
        sage: w.lie_derivative(v).display()
        ((x - 2)*y + x) ∂/∂x + (x^2 - y^2 - 2*x - y) ∂/∂y

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M', start_index=Integer(1))
        >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)
        >>> v = M.vector_field(-y, x, name='v')
        >>> w = M.vector_field(Integer(2)*x+y, x*y)
        >>> w.lie_derivative(v)
        Vector field on the 2-dimensional differentiable manifold M
        >>> w.lie_derivative(v).display()
        ((x - 2)*y + x) ∂/∂x + (x^2 - y^2 - 2*x - y) ∂/∂y

    The result is cached:

    Sage

        sage: w.lie_derivative(v) is w.lie_derivative(v)
        True

    [Python]

        >>> from sage.all import *
        >>> w.lie_derivative(v) is w.lie_derivative(v)
        True

    An alias is `lie_der`:

    Sage

        sage: w.lie_der(v) is w.lie_derivative(v)
        True

    Python

        >>> from sage.all import *
        >>> w.lie_der(v) is w.lie_derivative(v)
        True

    The Lie derivative is antisymmetric:

    Sage

        sage: w.lie_der(v) == -v.lie_der(w)
        True

    [Python]

        >>> from sage.all import *
        >>> w.lie_der(v) == -v.lie_der(w)
        True

    For vectors, it coincides with the commutator:

    Sage

        sage: f = M.scalar_field(x^3 + x*y^2)
        sage: w.lie_der(v)(f).display()
        M → ℝ
        (x, y) ↦ -(x + 2)*y^3 + 3*x^3 - x*y^2 + 5*(x^3 - 2*x^2)*y
        sage: w.lie_der(v)(f) == v(w(f)) - w(v(f))  # rhs = commutator [v,w] acting on f
        True

    Python

        >>> from sage.all import *
        >>> f = M.scalar_field(x**Integer(3) + x*y**Integer(2))
        >>> w.lie_der(v)(f).display()
        M → ℝ
        (x, y) ↦ -(x + 2)*y^3 + 3*x^3 - x*y^2 + 5*(x^3 - 2*x^2)*y
        >>> w.lie_der(v)(f) == v(w(f)) - w(v(f))  # rhs = commutator [v,w] acting on f
        True

    Lie derivative of a 1-form:

    Sage

        sage: om = M.one_form(y^2*sin(x), x^3*cos(y))
        sage: om.lie_der(v)
        1-form on the 2-dimensional differentiable manifold M
        sage: om.lie_der(v).display()
        (-y^3*cos(x) + x^3*cos(y) + 2*x*y*sin(x)) dx
         + (-x^4*sin(y) - 3*x^2*y*cos(y) - y^2*sin(x)) dy

    [Python]

        >>> from sage.all import *
        >>> om = M.one_form(y**Integer(2)*sin(x), x**Integer(3)*cos(y))
        >>> om.lie_der(v)
        1-form on the 2-dimensional differentiable manifold M
        >>> om.lie_der(v).display()
        (-y^3*cos(x) + x^3*cos(y) + 2*x*y*sin(x)) dx
         + (-x^4*sin(y) - 3*x^2*y*cos(y) - y^2*sin(x)) dy

    Parallel computation:

    Sage

        sage: Parallelism().set('tensor', nproc=2)
        sage: om.lie_der(v)
        1-form on the 2-dimensional differentiable manifold M
        sage: om.lie_der(v).display()
        (-y^3*cos(x) + x^3*cos(y) + 2*x*y*sin(x)) dx
         + (-x^4*sin(y) - 3*x^2*y*cos(y) - y^2*sin(x)) dy
        sage: Parallelism().set('tensor', nproc=1)  # switch off parallelization

    Python

        >>> from sage.all import *
        >>> Parallelism().set('tensor', nproc=Integer(2))
        >>> om.lie_der(v)
        1-form on the 2-dimensional differentiable manifold M
        >>> om.lie_der(v).display()
        (-y^3*cos(x) + x^3*cos(y) + 2*x*y*sin(x)) dx
         + (-x^4*sin(y) - 3*x^2*y*cos(y) - y^2*sin(x)) dy
        >>> Parallelism().set('tensor', nproc=Integer(1))  # switch off parallelization

    Check of Cartan identity:

    Sage

        sage: om.lie_der(v) == (v.contract(0, om.exterior_derivative(), 0)
        ....:                   + om(v).exterior_derivative())
        True

    [Python]

        >>> from sage.all import *
        >>> om.lie_der(v) == (v.contract(Integer(0), om.exterior_derivative(), Integer(0))
        ...                   + om(v).exterior_derivative())
        True

  restrict(subdomain, dest_map=None)

    Return the restriction of `self` to some subdomain.

    If the restriction has not been defined yet, it is constructed here.

    INPUT:

    - `subdomain` – `DifferentiableManifold`; open subset \(U\) of the tensor field domain \(S\)

    - `dest_map` – `DiffMap` (default: `None`); destination map \(\Psi:\ U \rightarrow V\), where \(V\) is an open subset of the manifold \(M\) where the tensor field takes it values; if `None`, the restriction of \(\Phi\) to \(U\) is used, \(\Phi\) being the differentiable map \(S \rightarrow M\) associated with the tensor field

    OUTPUT: instance of `TensorFieldParal` representing the restriction

    EXAMPLES:

    Restriction of a vector field defined on \(\RR^2\) to a disk:

    Sage

        sage: M = Manifold(2, 'R^2')
        sage: c_cart.<x,y> = M.chart() # Cartesian coordinates on R^2
        sage: v = M.vector_field(x+y, -1+x^2, name='v')
        sage: D = M.open_subset('D') # the unit open disc
        sage: c_cart_D = c_cart.restrict(D, x^2+y^2<1)
        sage: v_D = v.restrict(D) ; v_D
        Vector field v on the Open subset D of the 2-dimensional
         differentiable manifold R^2
        sage: v_D.display()
        v = (x + y) ∂/∂x + (x^2 - 1) ∂/∂y

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'R^2')
        >>> c_cart = M.chart(names=('x', 'y',)); (x, y,) = c_cart._first_ngens(2)# Cartesian coordinates on R^2
        >>> v = M.vector_field(x+y, -Integer(1)+x**Integer(2), name='v')
        >>> D = M.open_subset('D') # the unit open disc
        >>> c_cart_D = c_cart.restrict(D, x**Integer(2)+y**Integer(2)<Integer(1))
        >>> v_D = v.restrict(D) ; v_D
        Vector field v on the Open subset D of the 2-dimensional
         differentiable manifold R^2
        >>> v_D.display()
        v = (x + y) ∂/∂x + (x^2 - 1) ∂/∂y

    The symbolic expressions of the components with respect to Cartesian coordinates are equal:

    Sage

        sage: bool( v_D[1].expr() == v[1].expr() )
        True

    [Python]

        >>> from sage.all import *
        >>> bool( v_D[Integer(1)].expr() == v[Integer(1)].expr() )
        True

    but neither the chart functions representing the components (they are defined on different charts):

    Sage

        sage: v_D[1] == v[1]
        False

    Python

        >>> from sage.all import *
        >>> v_D[Integer(1)] == v[Integer(1)]
        False

    nor the scalar fields representing the components (they are defined on different open subsets):

    Sage

        sage: v_D[[1]] == v[[1]]
        False

    [Python]

        >>> from sage.all import *
        >>> v_D[[Integer(1)]] == v[[Integer(1)]]
        False

    The restriction of the vector field to its own domain is of course itself:

    Sage

        sage: v.restrict(M) is v
        True

    Python

        >>> from sage.all import *
        >>> v.restrict(M) is v
        True

  series_expansion(symbol, order)

    Expand the tensor field in power series with respect to a small parameter.

    If the small parameter is \(\epsilon\) and \(T\) is `self`, the power series expansion to order \(n\) is

    \[T = T_0 + \epsilon T_1 + \epsilon^2 T_2 + \cdots + \epsilon^n T_n + O(\epsilon^{n+1}),\]

    where \(T_0, T_1, \ldots, T_n\) are \(n+1\) tensor fields of the same tensor type as `self` and do not depend upon \(\epsilon\).

    INPUT:

    - `symbol` – symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of `self` are expanded in power series

    - `order` – integer; the order \(n\) of the expansion, defined as the degree of the polynomial representing the truncated power series in `symbol`

    OUTPUT:

    - list of the tensor fields \(T_i\) (size `order+1`)

    EXAMPLES:

    Sage

        sage: M = Manifold(4, 'M', structure='Lorentzian')
        sage: C.<t,x,y,z> = M.chart()
        sage: e = var('e')
        sage: g = M.metric()
        sage: h1 = M.tensor_field(0,2,sym=(0,1))
        sage: h2 = M.tensor_field(0,2,sym=(0,1))
        sage: g[0, 0], g[1, 1], g[2, 2], g[3, 3] = -1, 1, 1, 1
        sage: h1[0, 1], h1[1, 2], h1[2, 3] = 1, 1, 1
        sage: h2[0, 2], h2[1, 3] = 1, 1
        sage: g.set(g + e*h1 + e^2*h2)
        sage: g_ser = g.series_expansion(e, 2); g_ser
        [Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M,
         Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M,
         Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M]
        sage: g_ser[0][:]
        [-1  0  0  0]
        [ 0  1  0  0]
        [ 0  0  1  0]
        [ 0  0  0  1]
        sage: g_ser[1][:]
        [0 1 0 0]
        [1 0 1 0]
        [0 1 0 1]
        [0 0 1 0]
        sage: g_ser[2][:]
        [0 0 1 0]
        [0 0 0 1]
        [1 0 0 0]
        [0 1 0 0]
        sage: all([g_ser[1] == h1, g_ser[2] == h2])
        True

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(4), 'M', structure='Lorentzian')
        >>> C = M.chart(names=('t', 'x', 'y', 'z',)); (t, x, y, z,) = C._first_ngens(4)
        >>> e = var('e')
        >>> g = M.metric()
        >>> h1 = M.tensor_field(Integer(0),Integer(2),sym=(Integer(0),Integer(1)))
        >>> h2 = M.tensor_field(Integer(0),Integer(2),sym=(Integer(0),Integer(1)))
        >>> g[Integer(0), Integer(0)], g[Integer(1), Integer(1)], g[Integer(2), Integer(2)], g[Integer(3), Integer(3)] = -Integer(1), Integer(1), Integer(1), Integer(1)
        >>> h1[Integer(0), Integer(1)], h1[Integer(1), Integer(2)], h1[Integer(2), Integer(3)] = Integer(1), Integer(1), Integer(1)
        >>> h2[Integer(0), Integer(2)], h2[Integer(1), Integer(3)] = Integer(1), Integer(1)
        >>> g.set(g + e*h1 + e**Integer(2)*h2)
        >>> g_ser = g.series_expansion(e, Integer(2)); g_ser
        [Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M,
         Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M,
         Field of symmetric bilinear forms on the 4-dimensional Lorentzian manifold M]
        >>> g_ser[Integer(0)][:]
        [-1  0  0  0]
        [ 0  1  0  0]
        [ 0  0  1  0]
        [ 0  0  0  1]
        >>> g_ser[Integer(1)][:]
        [0 1 0 0]
        [1 0 1 0]
        [0 1 0 1]
        [0 0 1 0]
        >>> g_ser[Integer(2)][:]
        [0 0 1 0]
        [0 0 0 1]
        [1 0 0 0]
        [0 1 0 0]
        >>> all([g_ser[Integer(1)] == h1, g_ser[Integer(2)] == h2])
        True

  set_calc_order(symbol, order, truncate=False)

    Trigger a power series expansion with respect to a small parameter in computations involving the tensor field.

    This property is propagated by usual operations. The internal representation must be `SR` for this to take effect.

    If the small parameter is \(\epsilon\) and \(T\) is `self`, the power series expansion to order \(n\) is

    \[T = T_0 + \epsilon T_1 + \epsilon^2 T_2 + \cdots + \epsilon^n T_n + O(\epsilon^{n+1}),\]

    where \(T_0, T_1, \ldots, T_n\) are \(n+1\) tensor fields of the same tensor type as `self` and do not depend upon \(\epsilon\).

    INPUT:

    - `symbol` – symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of `self` are expanded in power series

    - `order` – integer; the order \(n\) of the expansion, defined as the degree of the polynomial representing the truncated power series in `symbol`

    - `truncate` – boolean (default: `False`); determines whether the components of `self` are replaced by their expansions to the given order

    EXAMPLES:

    Sage

        sage: M = Manifold(4, 'M', structure='Lorentzian')
        sage: C.<t,x,y,z> = M.chart()
        sage: e = var('e')
        sage: g = M.metric()
        sage: h1 = M.tensor_field(0, 2, sym=(0,1))
        sage: h2 = M.tensor_field(0, 2, sym=(0,1))
        sage: g[0, 0], g[1, 1], g[2, 2], g[3, 3] = -1, 1, 1, 1
        sage: h1[0, 1], h1[1, 2], h1[2, 3] = 1, 1, 1
        sage: h2[0, 2], h2[1, 3] = 1, 1
        sage: g.set(g + e*h1 + e^2*h2)
        sage: g.set_calc_order(e, 1)
        sage: g[:]
        [ -1   e e^2   0]
        [  e   1   e e^2]
        [e^2   e   1   e]
        [  0 e^2   e   1]
        sage: g.set_calc_order(e, 1, truncate=True)
        sage: g[:]
        [-1  e  0  0]
        [ e  1  e  0]
        [ 0  e  1  e]
        [ 0  0  e  1]

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(4), 'M', structure='Lorentzian')
        >>> C = M.chart(names=('t', 'x', 'y', 'z',)); (t, x, y, z,) = C._first_ngens(4)
        >>> e = var('e')
        >>> g = M.metric()
        >>> h1 = M.tensor_field(Integer(0), Integer(2), sym=(Integer(0),Integer(1)))
        >>> h2 = M.tensor_field(Integer(0), Integer(2), sym=(Integer(0),Integer(1)))
        >>> g[Integer(0), Integer(0)], g[Integer(1), Integer(1)], g[Integer(2), Integer(2)], g[Integer(3), Integer(3)] = -Integer(1), Integer(1), Integer(1), Integer(1)
        >>> h1[Integer(0), Integer(1)], h1[Integer(1), Integer(2)], h1[Integer(2), Integer(3)] = Integer(1), Integer(1), Integer(1)
        >>> h2[Integer(0), Integer(2)], h2[Integer(1), Integer(3)] = Integer(1), Integer(1)
        >>> g.set(g + e*h1 + e**Integer(2)*h2)
        >>> g.set_calc_order(e, Integer(1))
        >>> g[:]
        [ -1   e e^2   0]
        [  e   1   e e^2]
        [e^2   e   1   e]
        [  0 e^2   e   1]
        >>> g.set_calc_order(e, Integer(1), truncate=True)
        >>> g[:]
        [-1  e  0  0]
        [ e  1  e  0]
        [ 0  e  1  e]
        [ 0  0  e  1]

  set_comp(basis=None)

    Return the components of the tensor field in a given vector frame for assignment.

    The components with respect to other frames on the same domain are deleted, in order to avoid any inconsistency. To keep them, use the method `add_comp()` instead.

    INPUT:

    - `basis` – (default: `None`) vector frame in which the components are defined; if none is provided, the components are assumed to refer to the tensor field domain’s default frame

    OUTPUT:

    - components in the given frame, as an instance of the class `Components`; if such components did not exist previously, they are created

    EXAMPLES:

    Sage

        sage: M = Manifold(2, 'M')
        sage: X.<x,y> = M.chart()
        sage: e_xy = X.frame()
        sage: t = M.tensor_field(1,1, name='t')
        sage: t.set_comp(e_xy)
        2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        sage: t.set_comp(e_xy)[1,0] = 2
        sage: t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(2), 'M')
        >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
        >>> e_xy = X.frame()
        >>> t = M.tensor_field(Integer(1),Integer(1), name='t')
        >>> t.set_comp(e_xy)
        2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
        >>> t.set_comp(e_xy)[Integer(1),Integer(0)] = Integer(2)
        >>> t.display(e_xy)
        t = 2 ∂/∂y⊗dx

    Setting components in a new frame (`e`):

    Sage

        sage: e = M.vector_frame('e')
        sage: t.set_comp(e)
        2-indices components w.r.t. Vector frame (M, (e_0,e_1))
        sage: t.set_comp(e)[0,1] = x
        sage: t.display(e)
        t = x e_0⊗e^1

    [Python]

        >>> from sage.all import *
        >>> e = M.vector_frame('e')
        >>> t.set_comp(e)
        2-indices components w.r.t. Vector frame (M, (e_0,e_1))
        >>> t.set_comp(e)[Integer(0),Integer(1)] = x
        >>> t.display(e)
        t = x e_0⊗e^1

    The components with respect to the frame `e_xy` have be erased:

    Sage

        sage: t.display(e_xy)
        Traceback (most recent call last):
        ...
        ValueError: no basis could be found for computing the components
         in the Coordinate frame (M, (∂/∂x,∂/∂y))

    Python

        >>> from sage.all import *
        >>> t.display(e_xy)
        Traceback (most recent call last):
        ...
        ValueError: no basis could be found for computing the components
         in the Coordinate frame (M, (∂/∂x,∂/∂y))

    Setting components in a frame defined on a subdomain deletes previously defined components as well:

    Sage

        sage: U = M.open_subset('U', coord_def={X: x>0})
        sage: f = U.vector_frame('f')
        sage: t.set_comp(f)
        2-indices components w.r.t. Vector frame (U, (f_0,f_1))
        sage: t.set_comp(f)[0,1] = 1+y
        sage: t.display(f)
        t = (y + 1) f_0⊗f^1
        sage: t.display(e)
        Traceback (most recent call last):
        ...
        ValueError: no basis could be found for computing the components
         in the Vector frame (M, (e_0,e_1))

    [Python]

        >>> from sage.all import *
        >>> U = M.open_subset('U', coord_def={X: x>Integer(0)})
        >>> f = U.vector_frame('f')
        >>> t.set_comp(f)
        2-indices components w.r.t. Vector frame (U, (f_0,f_1))
        >>> t.set_comp(f)[Integer(0),Integer(1)] = Integer(1)+y
        >>> t.display(f)
        t = (y + 1) f_0⊗f^1
        >>> t.display(e)
        Traceback (most recent call last):
        ...
        ValueError: no basis could be found for computing the components
         in the Vector frame (M, (e_0,e_1))

  truncate(symbol, order)

    Return the tensor field truncated at a given order in the power series expansion with respect to some small parameter.

    If the small parameter is \(\epsilon\) and \(T\) is `self`, the power series expansion to order \(n\) is

    \[T = T_0 + \epsilon T_1 + \epsilon^2 T_2 + \cdots + \epsilon^n T_n + O(\epsilon^{n+1}),\]

    where \(T_0, T_1, \ldots, T_n\) are \(n+1\) tensor fields of the same tensor type as `self` and do not depend upon \(\epsilon\).

    INPUT:

    - `symbol` – symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of `self` are expanded in power series

    - `order` – integer; the order \(n\) of the expansion, defined as the degree of the polynomial representing the truncated power series in `symbol`

    OUTPUT:

    - the tensor field \(T_0 + \epsilon T_1 + \epsilon^2 T_2 + \cdots + \epsilon^n T_n\)

    EXAMPLES:

    Sage

        sage: M = Manifold(4, 'M', structure='Lorentzian')
        sage: C.<t,x,y,z> = M.chart()
        sage: e = var('e')
        sage: g = M.metric()
        sage: h1 = M.tensor_field(0,2,sym=(0,1))
        sage: h2 = M.tensor_field(0,2,sym=(0,1))
        sage: g[0, 0], g[1, 1], g[2, 2], g[3, 3] = -1, 1, 1, 1
        sage: h1[0, 1], h1[1, 2], h1[2, 3] = 1, 1, 1
        sage: h2[0, 2], h2[1, 3] = 1, 1
        sage: g.set(g + e*h1 + e^2*h2)
        sage: g[:]
        [ -1   e e^2   0]
        [  e   1   e e^2]
        [e^2   e   1   e]
        [  0 e^2   e   1]
        sage: g.truncate(e, 1)[:]
        [-1  e  0  0]
        [ e  1  e  0]
        [ 0  e  1  e]
        [ 0  0  e  1]

    Python

        >>> from sage.all import *
        >>> M = Manifold(Integer(4), 'M', structure='Lorentzian')
        >>> C = M.chart(names=('t', 'x', 'y', 'z',)); (t, x, y, z,) = C._first_ngens(4)
        >>> e = var('e')
        >>> g = M.metric()
        >>> h1 = M.tensor_field(Integer(0),Integer(2),sym=(Integer(0),Integer(1)))
        >>> h2 = M.tensor_field(Integer(0),Integer(2),sym=(Integer(0),Integer(1)))
        >>> g[Integer(0), Integer(0)], g[Integer(1), Integer(1)], g[Integer(2), Integer(2)], g[Integer(3), Integer(3)] = -Integer(1), Integer(1), Integer(1), Integer(1)
        >>> h1[Integer(0), Integer(1)], h1[Integer(1), Integer(2)], h1[Integer(2), Integer(3)] = Integer(1), Integer(1), Integer(1)
        >>> h2[Integer(0), Integer(2)], h2[Integer(1), Integer(3)] = Integer(1), Integer(1)
        >>> g.set(g + e*h1 + e**Integer(2)*h2)
        >>> g[:]
        [ -1   e e^2   0]
        [  e   1   e e^2]
        [e^2   e   1   e]
        [  0 e^2   e   1]
        >>> g.truncate(e, Integer(1))[:]
        [-1  e  0  0]
        [ e  1  e  0]
        [ 0  e  1  e]
        [ 0  0  e  1]