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:
- VectorFieldParalfor vector fields (rank-1 contravariant tensor fields)
- AutomorphismFieldParalfor fields of tangent-space automorphisms
- DiffFormParalfor differential forms (fully antisymmetric covariant tensor fields)
- MultivectorFieldParalfor 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:
EXAMPLES:
A tensor field of type \((1,1)\) on a 2-dimensional differentiable manifold:
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
>>> 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: t[1,1] = x^2
>>> from sage.all import *
>>> t[Integer(1),Integer(1)] = x**Integer(2)
Unset components are initialized to zero:
sage: t[:]  # list of components w.r.t. the manifold's default vector frame
[x^2   0]
[  0   0]
>>> 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: t = M.tensor_field(1, 1, [[x^2, 0], [0, 0]], name='T')
sage: t[:]
[x^2   0]
[  0   0]
>>> 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: t.comp(c_xy.frame())
2-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y))
>>> 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: M.default_frame()
Coordinate frame (M, (∂/∂x,∂/∂y))
sage: t.comp() is t.comp(c_xy.frame())
True
>>> 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: 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
>>> 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: 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
>>> 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: 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
>>> 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: t[1,1, c_uv] is t.comp(c_xy.frame())[[1,1]].coord_function(c_uv)
True
>>> 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: 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
>>> 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: t[:] = [[1, -x], [x*y, 2]]
sage: t[:]
[  1  -x]
[x*y   2]
>>> 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: 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
>>> 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: 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]
>>> 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: t[e,:] = [[x+y, 0], [y, -3*x]]
sage: t[e,:]  # same as above:
[x + y     0]
[    y  -3*x]
>>> 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: 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]
>>> 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: 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()
>>> 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: t.add_comp(e)[:] = [[x+y, 0], [y, -3*x]]
>>> 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: 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
>>> 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: 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)
>>> 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: 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
>>> 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: 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)
>>> 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: p = M.point((1,2))
sage: f(p)
4
>>> 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: 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
>>> 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: 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)
>>> 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: 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
>>> 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: 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
>>> 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)[source]¶
- 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 - TensorFieldshould 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: 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 - >>> 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: 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 - >>> 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: 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]] - >>> 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: t[:] [ 1 1 1] [ 2 4 8] [ 3 9 27] - >>> 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: 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] - >>> 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- ehave been deleted:- 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))} - >>> 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: t = M.tensor_field(2, 0, name='T') # let us restart sage: t[0,0] = 2 # sets the components in the frame e - >>> 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: t.add_comp(f)[0,0] = -3 - >>> 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: 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))} - >>> 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: t.domain() 3-dimensional differentiable manifold M sage: t.tensor_type() (2, 0) - >>> from sage.all import * >>> t.domain() 3-dimensional differentiable manifold M >>> t.tensor_type() (2, 0) - Symmetries and antisymmetries are declared via the keywords - symand- 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: 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) - >>> 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: 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 - >>> 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: 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] ) - >>> 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: 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 - >>> 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: 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 - >>> 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: 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 - >>> 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: a*b == b*a False - >>> 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: 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 - >>> 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: 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 - >>> 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)[source]¶
- 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: 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 - >>> 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: 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 - >>> 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_xyare kept:- sage: t.display(e_xy) t = 2 ∂/∂y⊗dx - >>> from sage.all import * >>> t.display(e_xy) t = 2 ∂/∂y⊗dx - Adding components in a frame defined on a subdomain: - 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 - >>> 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: t.display(e_xy) t = 2 ∂/∂y⊗dx sage: t.display(e) t = x e_0⊗e^1 - >>> from sage.all import * >>> t.display(e_xy) t = 2 ∂/∂y⊗dx >>> t.display(e) t = x e_0⊗e^1 
 - along(mapping)[source]¶
- Return the tensor field deduced from - selfvia a differentiable map, the codomain of which is included in the domain of- self.- More precisely, if - selfis 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: 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) - >>> 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: v = M.vector_field(-y , x, name='v') - >>> from sage.all import * >>> v = M.vector_field(-y , x, name='v') - We have then: - 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 - >>> 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: p = U(t) # a generic point of U sage: vU.at(p) == v.at(Phi(p)) True - >>> 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: 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 - >>> 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)[source]¶
- Value of - selfat 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–- ManifoldPointpoint \(p\) in the domain of the tensor field \(U\)
 - OUTPUT: - FreeModuleTensorrepresenting 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: 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 - >>> 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: 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 - >>> 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: 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 - >>> 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: 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 - >>> 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: 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 - >>> 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)[source]¶
- 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: 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]]] - >>> 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)[source]¶
- Contraction with another tensor field, on one or more indices. - INPUT: - pos1– positions of the indices in- selfinvolved in the contraction;- pos1must be a sequence of integers, with 0 standing for the first index position, 1 for the second one, etc. If- pos1is not provided, a single contraction on the last index position of- selfis assumed
- other– the tensor field to contract with
- pos2– positions of the indices in- otherinvolved in the contraction, with the same conventions as for- pos1. If- pos2is not provided, a single contraction on the first index position of- otheris assumed
 - OUTPUT: - tensor field resulting from the contraction at the positions - pos1and- pos2of- selfwith- other
 - EXAMPLES: - Contraction of a tensor field of type \((2,0)\) with a tensor field of type \((1,1)\): - 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 - >>> 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: 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 - >>> 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: s == a['^ki']*b['^j_k'] True - >>> from sage.all import * >>> s == a['^ki']*b['^j_k'] True - Contraction on the second index of - a:- 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 - >>> 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: 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 - >>> 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: s == a['^ik']*b['^j_k'] True - >>> 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)[source]¶
- 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 - chartis not- None, the coordinate frame associated to- chartis 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- frameis 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: 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 - >>> 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_nonzeromust be set to- False:- 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 - >>> 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 - tbeing symmetric with respect to its first two indices, one may ask to skip the components that can be deduced by symmetry:- sage: t.display_comp(only_nonredundant=True) t^xx_x = x + y t^xy_x = x*y t^yy_y = -3 - >>> 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: 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 - >>> 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 - fis not a coordinate frame, integer are used to label the indices):- 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) - >>> 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: 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 - >>> 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: str(t.display_comp(chart=Y)) == str(t.display_comp(frame=Y.frame(), chart=Y)) True - >>> 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: 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) - >>> 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)[source]¶
- 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 - selfwith respect to- vector
 - EXAMPLES: - Lie derivative of a vector: - 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 - >>> 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: w.lie_derivative(v) is w.lie_derivative(v) True - >>> from sage.all import * >>> w.lie_derivative(v) is w.lie_derivative(v) True - An alias is - lie_der:- sage: w.lie_der(v) is w.lie_derivative(v) True - >>> from sage.all import * >>> w.lie_der(v) is w.lie_derivative(v) True - The Lie derivative is antisymmetric: - sage: w.lie_der(v) == -v.lie_der(w) True - >>> from sage.all import * >>> w.lie_der(v) == -v.lie_der(w) True - For vectors, it coincides with the commutator: - 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 - >>> 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: 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 - >>> 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: 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 - >>> 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: om.lie_der(v) == (v.contract(0, om.exterior_derivative(), 0) ....: + om(v).exterior_derivative()) True - >>> from sage.all import * >>> om.lie_der(v) == (v.contract(Integer(0), om.exterior_derivative(), Integer(0)) ... + om(v).exterior_derivative()) True 
 - lie_derivative(vector)[source]¶
- 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 - selfwith respect to- vector
 - EXAMPLES: - Lie derivative of a vector: - 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 - >>> 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: w.lie_derivative(v) is w.lie_derivative(v) True - >>> from sage.all import * >>> w.lie_derivative(v) is w.lie_derivative(v) True - An alias is - lie_der:- sage: w.lie_der(v) is w.lie_derivative(v) True - >>> from sage.all import * >>> w.lie_der(v) is w.lie_derivative(v) True - The Lie derivative is antisymmetric: - sage: w.lie_der(v) == -v.lie_der(w) True - >>> from sage.all import * >>> w.lie_der(v) == -v.lie_der(w) True - For vectors, it coincides with the commutator: - 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 - >>> 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: 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 - >>> 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: 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 - >>> 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: om.lie_der(v) == (v.contract(0, om.exterior_derivative(), 0) ....: + om(v).exterior_derivative()) True - >>> 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)[source]¶
- Return the restriction of - selfto 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 - TensorFieldParalrepresenting the restriction- EXAMPLES: - Restriction of a vector field defined on \(\RR^2\) to a disk: - 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 - >>> 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: bool( v_D[1].expr() == v[1].expr() ) True - >>> 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: v_D[1] == v[1] False - >>> 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: v_D[[1]] == v[[1]] False - >>> 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: v.restrict(M) is v True - >>> from sage.all import * >>> v.restrict(M) is v True 
 - series_expansion(symbol, order)[source]¶
- 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 - selfand do not depend upon \(\epsilon\).- INPUT: - symbol– symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of- selfare 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: 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 - >>> 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)[source]¶
- 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 - SRfor 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 - selfand do not depend upon \(\epsilon\).- INPUT: - symbol– symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of- selfare 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- selfare replaced by their expansions to the given order
 - EXAMPLES: - 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] - >>> 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)[source]¶
- 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: 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 - >>> 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: 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 - >>> 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_xyhave be erased:- 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)) - >>> 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: 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)) - >>> 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)[source]¶
- 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 - selfand do not depend upon \(\epsilon\).- INPUT: - symbol– symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the components of- selfare 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: 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] - >>> 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]