Affine Connections¶
The class AffineConnection implements affine connections on
smooth manifolds.
AUTHORS:
- Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version 
- Marco Mancini (2015) : parallelization of some computations 
- Florentin Jaffredo (2018) : series expansion with respect to a given parameter 
REFERENCES:
- class sage.manifolds.differentiable.affine_connection.AffineConnection(domain, name, latex_name=None)[source]¶
- Bases: - SageObject- Affine connection on a smooth manifold. - Let \(M\) be a differentiable manifold of class \(C^\infty\) (smooth manifold) over a non-discrete topological field \(K\) (in most applications \(K=\RR\) or \(K=\CC\)), let \(C^\infty(M)\) be the algebra of smooth functions \(M\rightarrow K\) (cf. - DiffScalarFieldAlgebra) and let \(\mathfrak{X}(M)\) be the \(C^\infty(M)\)-module of vector fields on \(M\) (cf.- VectorFieldModule). An affine connection on \(M\) is an operator\[\begin{split}\begin{array}{cccc} \nabla: & \mathfrak{X}(M)\times \mathfrak{X}(M) & \longrightarrow & \mathfrak{X}(M) \\ & (u,v) & \longmapsto & \nabla_u v \end{array}\end{split}\]- that - is \(K\)-bilinear, i.e. is bilinear when considering \(\mathfrak{X}(M)\) as a vector space over \(K\) 
- is \(C^\infty(M)\)-linear w.r.t. the first argument: \(\forall f\in C^\infty(M),\ \nabla_{fu} v = f\nabla_u v\) 
- obeys Leibniz rule w.r.t. the second argument: \(\forall f\in C^\infty(M),\ \nabla_u (f v) = \mathrm{d}f(u)\, v + f \nabla_u v\) 
 - The affine connection \(\nabla\) gives birth to the covariant derivative operator acting on tensor fields, denoted by the same symbol: \[\begin{split}\begin{array}{cccc} \nabla: & T^{(k,l)}(M) & \longrightarrow & T^{(k,l+1)}(M)\\ & t & \longmapsto & \nabla t \end{array}\end{split}\]- where \(T^{(k,l)}(M)\) stands for the \(C^\infty(M)\)-module of tensor fields of type \((k,l)\) on \(M\) (cf. - TensorFieldModule), with the convention \(T^{(0,0)}(M):=C^\infty(M)\). For a vector field \(v\), the covariant derivative \(\nabla v\) is a type-(1,1) tensor field such that\[\forall u \in\mathfrak{X}(M), \ \nabla_u v = \nabla v(., u)\]- More generally for any tensor field \(t\in T^{(k,l)}(M)\), we have \[\forall u \in\mathfrak{X}(M), \ \nabla_u t = \nabla t(\ldots, u)\]- Note - The above convention means that, in terms of index notation, the “derivation index” in \(\nabla t\) is the last one: \[\nabla_c t^{a_1\ldots a_k}_{\quad\quad b_1\ldots b_l} = (\nabla t)^{a_1\ldots a_k}_{\quad\quad b_1\ldots b_l c}\]- INPUT: - domain– the manifold on which the connection is defined (must be an instance of class- DifferentiableManifold)
- name– name given to the affine connection
- latex_name– (default:- None) LaTeX symbol to denote the affine connection; if- None, it is set to- name
 - EXAMPLES: - Affine connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M - A just-created connection has no connection coefficients: - sage: nab._coefficients {} - >>> from sage.all import * >>> nab._coefficients {} - The connection coefficients relative to the manifold’s default frame [here \((\partial/\partial x, \partial/\partial y, \partial/\partial z)\)], are created by providing the relevant indices inside square brackets: - sage: nab[1,1,2], nab[3,2,3] = x^2, y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz sage: nab._coefficients {Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)): 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))} - >>> from sage.all import * >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz >>> nab._coefficients {Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)): 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))} - If not the default one, the vector frame w.r.t. which the connection coefficients are defined can be specified as the first argument inside the square brackets; hence the above definition is equivalent to: - sage: nab[c_xyz.frame(), 1,1,2], nab[c_xyz.frame(),3,2,3] = x^2, y*z sage: nab._coefficients {Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)): 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))} - >>> from sage.all import * >>> nab[c_xyz.frame(), Integer(1),Integer(1),Integer(2)], nab[c_xyz.frame(),Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z >>> nab._coefficients {Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)): 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z))} - Unset components are initialized to zero: - sage: nab[:] # list of coefficients relative to the manifold's default vector frame [[[0, x^2, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, y*z], [0, 0, 0]]] - >>> from sage.all import * >>> nab[:] # list of coefficients relative to the manifold's default vector frame [[[0, x^2, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, y*z], [0, 0, 0]]] - The treatment of connection coefficients in a given vector frame is similar to that of tensor components; see therefore the class - TensorFieldfor the documentation. In particular, the square brackets return the connection coefficients as instances of- ChartFunction, while the double square brackets return a scalar field:- sage: nab[1,1,2] x^2 sage: nab[1,1,2].display() (x, y, z) ↦ x^2 sage: type(nab[1,1,2]) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'> sage: nab[[1,1,2]] Scalar field on the 3-dimensional differentiable manifold M sage: nab[[1,1,2]].display() M → ℝ (x, y, z) ↦ x^2 sage: nab[[1,1,2]].coord_function() is nab[1,1,2] True - >>> from sage.all import * >>> nab[Integer(1),Integer(1),Integer(2)] x^2 >>> nab[Integer(1),Integer(1),Integer(2)].display() (x, y, z) ↦ x^2 >>> type(nab[Integer(1),Integer(1),Integer(2)]) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'> >>> nab[[Integer(1),Integer(1),Integer(2)]] Scalar field on the 3-dimensional differentiable manifold M >>> nab[[Integer(1),Integer(1),Integer(2)]].display() M → ℝ (x, y, z) ↦ x^2 >>> nab[[Integer(1),Integer(1),Integer(2)]].coord_function() is nab[Integer(1),Integer(1),Integer(2)] True - Action on a scalar field: - sage: f = M.scalar_field(x^2 - y^2, name='f') sage: Df = nab(f) ; Df 1-form df on the 3-dimensional differentiable manifold M sage: Df[:] [2*x, -2*y, 0] - >>> from sage.all import * >>> f = M.scalar_field(x**Integer(2) - y**Integer(2), name='f') >>> Df = nab(f) ; Df 1-form df on the 3-dimensional differentiable manifold M >>> Df[:] [2*x, -2*y, 0] - The action of an affine connection on a scalar field must coincide with the differential: - sage: Df == f.differential() True - >>> from sage.all import * >>> Df == f.differential() True - A generic affine connection has some torsion: - sage: DDf = nab(Df) ; DDf Tensor field nabla(df) of type (0,2) on the 3-dimensional differentiable manifold M sage: DDf.antisymmetrize()[:] # nabla does not commute on scalar fields: [ 0 -x^3 0] [ x^3 0 0] [ 0 0 0] - >>> from sage.all import * >>> DDf = nab(Df) ; DDf Tensor field nabla(df) of type (0,2) on the 3-dimensional differentiable manifold M >>> DDf.antisymmetrize()[:] # nabla does not commute on scalar fields: [ 0 -x^3 0] [ x^3 0 0] [ 0 0 0] - Let us check the standard formula \[\nabla_j \nabla_i \, f - \nabla_i \nabla_j \, f = T^k_{\ \, ij} \nabla_k \, f ,\]- where the \(T^k_{\ \, ij}\)’s are the components of the connection’s torsion tensor: - sage: 2*DDf.antisymmetrize() == nab.torsion().contract(0,Df) True - >>> from sage.all import * >>> Integer(2)*DDf.antisymmetrize() == nab.torsion().contract(Integer(0),Df) True - The connection acting on a vector field: - sage: v = M.vector_field(y*z, x*z, x*y, name='v') sage: Dv = nab(v) ; Dv Tensor field nabla(v) of type (1,1) on the 3-dimensional differentiable manifold M sage: Dv[:] [ 0 (x^2*y + 1)*z y] [ z 0 x] [ y x x*y*z^2] - >>> from sage.all import * >>> v = M.vector_field(y*z, x*z, x*y, name='v') >>> Dv = nab(v) ; Dv Tensor field nabla(v) of type (1,1) on the 3-dimensional differentiable manifold M >>> Dv[:] [ 0 (x^2*y + 1)*z y] [ z 0 x] [ y x x*y*z^2] - Another example: connection on a non-parallelizable 2-dimensional manifold: - sage: M = Manifold(2, 'M') sage: U = M.open_subset('U') ; V = M.open_subset('V') sage: M.declare_union(U,V) # M is the union of U and V sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() sage: transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ....: restrictions1= x>0, restrictions2= u+v>0) sage: inv = transf.inverse() sage: W = U.intersection(V) sage: eU = c_xy.frame() ; eV = c_uv.frame() sage: c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) sage: eUW = c_xyW.frame() ; eVW = c_uvW.frame() sage: nab = M.affine_connection('nabla', r'\nabla') - >>> from sage.all import * >>> M = Manifold(Integer(2), 'M') >>> U = M.open_subset('U') ; V = M.open_subset('V') >>> M.declare_union(U,V) # M is the union of U and V >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ... restrictions1= x>Integer(0), restrictions2= u+v>Integer(0)) >>> inv = transf.inverse() >>> W = U.intersection(V) >>> eU = c_xy.frame() ; eV = c_uv.frame() >>> c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) >>> eUW = c_xyW.frame() ; eVW = c_uvW.frame() >>> nab = M.affine_connection('nabla', r'\nabla') - The connection is first defined on the open subset U by means of its coefficients w.r.t. the frame eU (the manifold’s default frame): - sage: nab[0,0,0], nab[1,0,1] = x, x*y - >>> from sage.all import * >>> nab[Integer(0),Integer(0),Integer(0)], nab[Integer(1),Integer(0),Integer(1)] = x, x*y - The coefficients w.r.t the frame eV are deduced by continuation of the coefficients w.r.t. the frame eVW on the open subset \(W=U\cap V\): - sage: for i in M.irange(): ....: for j in M.irange(): ....: for k in M.irange(): ....: nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() - >>> from sage.all import * >>> for i in M.irange(): ... for j in M.irange(): ... for k in M.irange(): ... nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() - At this stage, the connection is fully defined on all the manifold: - sage: nab.coef(eU)[:] [[[x, 0], [0, 0]], [[0, x*y], [0, 0]]] sage: nab.coef(eV)[:] [[[1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v, -1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v], [1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v, -1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v]], [[-1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v, 1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v], [-1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v, 1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v]]] - >>> from sage.all import * >>> nab.coef(eU)[:] [[[x, 0], [0, 0]], [[0, x*y], [0, 0]]] >>> nab.coef(eV)[:] [[[1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v, -1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v], [1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v, -1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v]], [[-1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v, 1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v], [-1/16*u^2 + 1/16*v^2 + 1/8*u + 1/8*v, 1/16*u^2 - 1/16*v^2 + 1/8*u + 1/8*v]]] - We may let it act on a vector field defined globally on \(M\): - sage: a = M.vector_field({eU: [-y,x]}, name='a') sage: a.add_comp_by_continuation(eV, W, c_uv) sage: a.display(eU) a = -y ∂/∂x + x ∂/∂y sage: a.display(eV) a = v ∂/∂u - u ∂/∂v sage: da = nab(a) ; da Tensor field nabla(a) of type (1,1) on the 2-dimensional differentiable manifold M sage: da.display(eU) nabla(a) = -x*y ∂/∂x⊗dx - ∂/∂x⊗dy + ∂/∂y⊗dx - x*y^2 ∂/∂y⊗dy sage: da.display(eV) nabla(a) = (-1/16*u^3 + 1/16*u^2*v + 1/16*(u + 2)*v^2 - 1/16*v^3 - 1/8*u^2) ∂/∂u⊗du + (1/16*u^3 - 1/16*u^2*v - 1/16*(u - 2)*v^2 + 1/16*v^3 - 1/8*u^2 + 1) ∂/∂u⊗dv + (1/16*u^3 - 1/16*u^2*v - 1/16*(u - 2)*v^2 + 1/16*v^3 - 1/8*u^2 - 1) ∂/∂v⊗du + (-1/16*u^3 + 1/16*u^2*v + 1/16*(u + 2)*v^2 - 1/16*v^3 - 1/8*u^2) ∂/∂v⊗dv - >>> from sage.all import * >>> a = M.vector_field({eU: [-y,x]}, name='a') >>> a.add_comp_by_continuation(eV, W, c_uv) >>> a.display(eU) a = -y ∂/∂x + x ∂/∂y >>> a.display(eV) a = v ∂/∂u - u ∂/∂v >>> da = nab(a) ; da Tensor field nabla(a) of type (1,1) on the 2-dimensional differentiable manifold M >>> da.display(eU) nabla(a) = -x*y ∂/∂x⊗dx - ∂/∂x⊗dy + ∂/∂y⊗dx - x*y^2 ∂/∂y⊗dy >>> da.display(eV) nabla(a) = (-1/16*u^3 + 1/16*u^2*v + 1/16*(u + 2)*v^2 - 1/16*v^3 - 1/8*u^2) ∂/∂u⊗du + (1/16*u^3 - 1/16*u^2*v - 1/16*(u - 2)*v^2 + 1/16*v^3 - 1/8*u^2 + 1) ∂/∂u⊗dv + (1/16*u^3 - 1/16*u^2*v - 1/16*(u - 2)*v^2 + 1/16*v^3 - 1/8*u^2 - 1) ∂/∂v⊗du + (-1/16*u^3 + 1/16*u^2*v + 1/16*(u + 2)*v^2 - 1/16*v^3 - 1/8*u^2) ∂/∂v⊗dv - A few tests: - sage: nab(a.restrict(V)) == da.restrict(V) True sage: nab.restrict(V)(a) == da.restrict(V) True sage: nab.restrict(V)(a.restrict(U)) == da.restrict(W) True sage: nab.restrict(U)(a.restrict(V)) == da.restrict(W) # long time True - >>> from sage.all import * >>> nab(a.restrict(V)) == da.restrict(V) True >>> nab.restrict(V)(a) == da.restrict(V) True >>> nab.restrict(V)(a.restrict(U)) == da.restrict(W) True >>> nab.restrict(U)(a.restrict(V)) == da.restrict(W) # long time True - Same examples with SymPy as the engine for symbolic calculus: - sage: M.set_calculus_method('sympy') sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[0,0,0], nab[1,0,1] = x, x*y sage: for i in M.irange(): ....: for j in M.irange(): ....: for k in M.irange(): ....: nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() - >>> from sage.all import * >>> M.set_calculus_method('sympy') >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(0),Integer(0),Integer(0)], nab[Integer(1),Integer(0),Integer(1)] = x, x*y >>> for i in M.irange(): ... for j in M.irange(): ... for k in M.irange(): ... nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() - At this stage, the connection is fully defined on all the manifold: - sage: nab.coef(eU)[:] [[[x, 0], [0, 0]], [[0, x*y], [0, 0]]] sage: nab.coef(eV)[:] [[[u**2/16 + u/8 - v**2/16 + v/8, -u**2/16 + u/8 + v**2/16 + v/8], [u**2/16 + u/8 - v**2/16 + v/8, -u**2/16 + u/8 + v**2/16 + v/8]], [[-u**2/16 + u/8 + v**2/16 + v/8, u**2/16 + u/8 - v**2/16 + v/8], [-u**2/16 + u/8 + v**2/16 + v/8, u**2/16 + u/8 - v**2/16 + v/8]]] - >>> from sage.all import * >>> nab.coef(eU)[:] [[[x, 0], [0, 0]], [[0, x*y], [0, 0]]] >>> nab.coef(eV)[:] [[[u**2/16 + u/8 - v**2/16 + v/8, -u**2/16 + u/8 + v**2/16 + v/8], [u**2/16 + u/8 - v**2/16 + v/8, -u**2/16 + u/8 + v**2/16 + v/8]], [[-u**2/16 + u/8 + v**2/16 + v/8, u**2/16 + u/8 - v**2/16 + v/8], [-u**2/16 + u/8 + v**2/16 + v/8, u**2/16 + u/8 - v**2/16 + v/8]]] - We may let it act on a vector field defined globally on \(M\): - sage: a = M.vector_field({eU: [-y,x]}, name='a') sage: a.add_comp_by_continuation(eV, W, c_uv) sage: a.display(eU) a = -y ∂/∂x + x ∂/∂y sage: a.display(eV) a = v ∂/∂u - u ∂/∂v sage: da = nab(a) ; da Tensor field nabla(a) of type (1,1) on the 2-dimensional differentiable manifold M sage: da.display(eU) nabla(a) = -x*y ∂/∂x⊗dx - ∂/∂x⊗dy + ∂/∂y⊗dx - x*y**2 ∂/∂y⊗dy sage: da.display(eV) nabla(a) = (-u**3/16 + u**2*v/16 - u**2/8 + u*v**2/16 - v**3/16 + v**2/8) ∂/∂u⊗du + (u**3/16 - u**2*v/16 - u**2/8 - u*v**2/16 + v**3/16 + v**2/8 + 1) ∂/∂u⊗dv + (u**3/16 - u**2*v/16 - u**2/8 - u*v**2/16 + v**3/16 + v**2/8 - 1) ∂/∂v⊗du + (-u**3/16 + u**2*v/16 - u**2/8 + u*v**2/16 - v**3/16 + v**2/8) ∂/∂v⊗dv - >>> from sage.all import * >>> a = M.vector_field({eU: [-y,x]}, name='a') >>> a.add_comp_by_continuation(eV, W, c_uv) >>> a.display(eU) a = -y ∂/∂x + x ∂/∂y >>> a.display(eV) a = v ∂/∂u - u ∂/∂v >>> da = nab(a) ; da Tensor field nabla(a) of type (1,1) on the 2-dimensional differentiable manifold M >>> da.display(eU) nabla(a) = -x*y ∂/∂x⊗dx - ∂/∂x⊗dy + ∂/∂y⊗dx - x*y**2 ∂/∂y⊗dy >>> da.display(eV) nabla(a) = (-u**3/16 + u**2*v/16 - u**2/8 + u*v**2/16 - v**3/16 + v**2/8) ∂/∂u⊗du + (u**3/16 - u**2*v/16 - u**2/8 - u*v**2/16 + v**3/16 + v**2/8 + 1) ∂/∂u⊗dv + (u**3/16 - u**2*v/16 - u**2/8 - u*v**2/16 + v**3/16 + v**2/8 - 1) ∂/∂v⊗du + (-u**3/16 + u**2*v/16 - u**2/8 + u*v**2/16 - v**3/16 + v**2/8) ∂/∂v⊗dv - To make affine connections hashable, they have to be set immutable before: - sage: nab.is_immutable() False sage: nab.set_immutable() sage: nab.is_immutable() True - >>> from sage.all import * >>> nab.is_immutable() False >>> nab.set_immutable() >>> nab.is_immutable() True - Immutable connections cannot be changed anymore: - sage: nab.set_coef(eU) Traceback (most recent call last): ... ValueError: the coefficients of an immutable element cannot be changed - >>> from sage.all import * >>> nab.set_coef(eU) Traceback (most recent call last): ... ValueError: the coefficients of an immutable element cannot be changed - However, they can now be used as keys for dictionaries: - sage: {nab: 1}[nab] 1 - >>> from sage.all import * >>> {nab: Integer(1)}[nab] 1 - The immutability process cannot be made undone. If a connection is needed to be changed again, a copy has to be created: - sage: nab_copy = nab.copy('nablo'); nab_copy Affine connection nablo on the 2-dimensional differentiable manifold M sage: nab_copy is nab False sage: nab_copy == nab True sage: nab_copy.is_immutable() False - >>> from sage.all import * >>> nab_copy = nab.copy('nablo'); nab_copy Affine connection nablo on the 2-dimensional differentiable manifold M >>> nab_copy is nab False >>> nab_copy == nab True >>> nab_copy.is_immutable() False - add_coef(frame=None)[source]¶
- Return the connection coefficients in a given frame for assignment, keeping the coefficients in other frames. - See method - coef()for details about the definition of the connection coefficients.- To delete the connection coefficients in other frames, use the method - set_coef()instead.- INPUT: - frame– (default:- None) vector frame in which the connection coefficients are defined; if- None, the default frame of the connection’s domain is assumed.
 - Warning - If the connection has already coefficients in other frames, it is the user’s responsibility to make sure that the coefficients to be added are consistent with them. - OUTPUT: - connection coefficients in the given frame, as an instance of the class - Components; if such connection coefficients did not exist previously, they are created. See method- coef()for the storage convention of the connection coefficients.
 - EXAMPLES: - Setting the coefficients of an affine connection w.r.t. some coordinate frame: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: eX = X.frame(); eX Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.add_coef(eX) 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.add_coef(eX)[1,2,1] = x*y sage: nab.display(eX) Gam^x_yx = x*y - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> eX = X.frame(); eX Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.add_coef(eX) 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.add_coef(eX)[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.display(eX) Gam^x_yx = x*y - Since - eXis the manifold’s default vector frame, its mention may be omitted:- sage: nab.add_coef()[1,2,1] = x*y sage: nab.add_coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.add_coef()[1,2,1] = x*y sage: nab.display() Gam^x_yx = x*y - >>> from sage.all import * >>> nab.add_coef()[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.add_coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.add_coef()[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.display() Gam^x_yx = x*y - Adding connection coefficients w.r.t. to another vector frame: - sage: e = M.vector_frame('e') sage: nab.add_coef(e) 3-indices components w.r.t. Vector frame (M, (e_1,e_2)) sage: nab.add_coef(e)[2,1,1] = x+y sage: nab.add_coef(e)[2,1,2] = x-y sage: nab.display(e) Gam^2_11 = x + y Gam^2_12 = x - y - >>> from sage.all import * >>> e = M.vector_frame('e') >>> nab.add_coef(e) 3-indices components w.r.t. Vector frame (M, (e_1,e_2)) >>> nab.add_coef(e)[Integer(2),Integer(1),Integer(1)] = x+y >>> nab.add_coef(e)[Integer(2),Integer(1),Integer(2)] = x-y >>> nab.display(e) Gam^2_11 = x + y Gam^2_12 = x - y - The coefficients w.r.t. the frame - eXhave been kept:- sage: nab.display(eX) Gam^x_yx = x*y - >>> from sage.all import * >>> nab.display(eX) Gam^x_yx = x*y - To delete them, use the method - set_coef()instead.
 - coef(frame=None)[source]¶
- Return the connection coefficients relative to the given frame. - \(n\) being the manifold’s dimension, the connection coefficients relative to the vector frame \((e_i)\) are the \(n^3\) scalar fields \(\Gamma^k_{\ \, ij}\) defined by \[\nabla_{e_j} e_i = \Gamma^k_{\ \, ij} e_k\]- If the connection coefficients are not known already, they are computed from the above formula. - INPUT: - frame– (default:- None) vector frame relative to which the connection coefficients are required; if none is provided, the domain’s default frame is assumed
 - OUTPUT: - connection coefficients relative to the frame - frame, as an instance of the class- Componentswith 3 indices ordered as \((k,i,j)\)
 - EXAMPLES: - Connection coefficient of an affine connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,2], nab[3,2,3] = x^2, y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz sage: nab.coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) sage: type(nab.coef()) <class 'sage.tensor.modules.comp.Components'> sage: M.default_frame() Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) sage: nab.coef() is nab.coef(c_xyz.frame()) True sage: nab.coef()[:] # full list of coefficients: [[[0, x^2, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, y*z], [0, 0, 0]]] - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz >>> nab.coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) >>> type(nab.coef()) <class 'sage.tensor.modules.comp.Components'> >>> M.default_frame() Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) >>> nab.coef() is nab.coef(c_xyz.frame()) True >>> nab.coef()[:] # full list of coefficients: [[[0, x^2, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, y*z], [0, 0, 0]]] 
 - connection_form(i, j, frame=None)[source]¶
- Return the connection 1-form corresponding to the given index and vector frame. - The connection 1-forms with respect to the frame \((e_i)\) are the \(n^2\) 1-forms \(\omega^i_{\ \, j}\) defined by \[\nabla_v e_j = \langle \omega^i_{\ \, j}, v \rangle \, e_i\]- for any vector \(v\). - The components of \(\omega^i_{\ \, j}\) in the coframe \((e^i)\) dual to \((e_i)\) are nothing but the connection coefficients \(\Gamma^i_{\ \, jk}\) relative to the frame \((e_i)\): \[\omega^i_{\ \, j} = \Gamma^i_{\ \, jk} e^k\]- INPUT: - i,- j– indices identifying the 1-form \(\omega^i_{\ \, j}\)
- frame– (default:- None) vector frame relative to which the connection 1-forms are defined; if- None, the default frame of the connection’s domain is assumed.
 - OUTPUT: - the 1-form \(\omega^i_{\ \, j}\), as an instance of - DiffForm
 - EXAMPLES: - Connection 1-forms on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,1], nab[1,1,2], nab[1,1,3] = x*y*z, x^2, -y*z sage: nab[1,2,3], nab[1,3,1], nab[1,3,2] = -x^3, y^2*z, y^2-x^2 sage: nab[2,1,1], nab[2,1,2], nab[2,2,1] = z^2, x*y*z^2, -x^2 sage: nab[2,3,1], nab[2,3,3], nab[3,1,2] = x^2+y^2+z^2, y^2-z^2, x*y+z^2 sage: nab[3,2,1], nab[3,2,2], nab[3,3,3] = x*y+z, z^3 -y^2, x*z^2 - z*y^2 sage: nab.connection_form(1,1) # connection 1-form (i,j)=(1,1) w.r.t. M's default frame 1-form nabla connection 1-form (1,1) on the 3-dimensional differentiable manifold M sage: nab.connection_form(1,1)[:] [x*y*z, x^2, -y*z] - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(1)], nab[Integer(1),Integer(1),Integer(2)], nab[Integer(1),Integer(1),Integer(3)] = x*y*z, x**Integer(2), -y*z >>> nab[Integer(1),Integer(2),Integer(3)], nab[Integer(1),Integer(3),Integer(1)], nab[Integer(1),Integer(3),Integer(2)] = -x**Integer(3), y**Integer(2)*z, y**Integer(2)-x**Integer(2) >>> nab[Integer(2),Integer(1),Integer(1)], nab[Integer(2),Integer(1),Integer(2)], nab[Integer(2),Integer(2),Integer(1)] = z**Integer(2), x*y*z**Integer(2), -x**Integer(2) >>> nab[Integer(2),Integer(3),Integer(1)], nab[Integer(2),Integer(3),Integer(3)], nab[Integer(3),Integer(1),Integer(2)] = x**Integer(2)+y**Integer(2)+z**Integer(2), y**Integer(2)-z**Integer(2), x*y+z**Integer(2) >>> nab[Integer(3),Integer(2),Integer(1)], nab[Integer(3),Integer(2),Integer(2)], nab[Integer(3),Integer(3),Integer(3)] = x*y+z, z**Integer(3) -y**Integer(2), x*z**Integer(2) - z*y**Integer(2) >>> nab.connection_form(Integer(1),Integer(1)) # connection 1-form (i,j)=(1,1) w.r.t. M's default frame 1-form nabla connection 1-form (1,1) on the 3-dimensional differentiable manifold M >>> nab.connection_form(Integer(1),Integer(1))[:] [x*y*z, x^2, -y*z] - The result is cached (until the connection is modified via - set_coef()or- add_coef()):- sage: nab.connection_form(1,1) is nab.connection_form(1,1) True - >>> from sage.all import * >>> nab.connection_form(Integer(1),Integer(1)) is nab.connection_form(Integer(1),Integer(1)) True - Connection 1-forms w.r.t. a non-holonomic frame: - sage: ch_basis = M.automorphism_field() sage: ch_basis[1,1], ch_basis[2,2], ch_basis[3,3] = y, z, x sage: e = M.default_frame().new_frame(ch_basis, 'e') sage: e[1][:], e[2][:], e[3][:] ([y, 0, 0], [0, z, 0], [0, 0, x]) sage: nab.connection_form(1,1,e) 1-form nabla connection 1-form (1,1) on the 3-dimensional differentiable manifold M sage: nab.connection_form(1,1,e).comp(e)[:] [x*y^2*z, (x^2*y + 1)*z/y, -x*y*z] - >>> from sage.all import * >>> ch_basis = M.automorphism_field() >>> ch_basis[Integer(1),Integer(1)], ch_basis[Integer(2),Integer(2)], ch_basis[Integer(3),Integer(3)] = y, z, x >>> e = M.default_frame().new_frame(ch_basis, 'e') >>> e[Integer(1)][:], e[Integer(2)][:], e[Integer(3)][:] ([y, 0, 0], [0, z, 0], [0, 0, x]) >>> nab.connection_form(Integer(1),Integer(1),e) 1-form nabla connection 1-form (1,1) on the 3-dimensional differentiable manifold M >>> nab.connection_form(Integer(1),Integer(1),e).comp(e)[:] [x*y^2*z, (x^2*y + 1)*z/y, -x*y*z] - Check of the formula \(\omega^i_{\ \, j} = \Gamma^i_{\ \, jk} e^k\): - First on the manifold’s default frame (∂/∂x, ∂/∂y, d:dz): - sage: dx = M.default_frame().coframe() ; dx Coordinate coframe (M, (dx,dy,dz)) sage: check = [] sage: for i in M.irange(): ....: for j in M.irange(): ....: check.append( nab.connection_form(i,j) == \ ....: sum( nab[[i,j,k]]*dx[k] for k in M.irange() ) ) sage: check [True, True, True, True, True, True, True, True, True] - >>> from sage.all import * >>> dx = M.default_frame().coframe() ; dx Coordinate coframe (M, (dx,dy,dz)) >>> check = [] >>> for i in M.irange(): ... for j in M.irange(): ... check.append( nab.connection_form(i,j) == sum( nab[[i,j,k]]*dx[k] for k in M.irange() ) ) >>> check [True, True, True, True, True, True, True, True, True] - Then on the frame e: - sage: ef = e.coframe() ; ef Coframe (M, (e^1,e^2,e^3)) sage: check = [] sage: for i in M.irange(): ....: for j in M.irange(): ....: s = nab.connection_form(i,j,e).comp(c_xyz.frame(), from_basis=e) ....: check.append( nab.connection_form(i,j,e) == sum( nab.coef(e)[[i,j,k]]*ef[k] for k in M.irange() ) ) sage: check [True, True, True, True, True, True, True, True, True] - >>> from sage.all import * >>> ef = e.coframe() ; ef Coframe (M, (e^1,e^2,e^3)) >>> check = [] >>> for i in M.irange(): ... for j in M.irange(): ... s = nab.connection_form(i,j,e).comp(c_xyz.frame(), from_basis=e) ... check.append( nab.connection_form(i,j,e) == sum( nab.coef(e)[[i,j,k]]*ef[k] for k in M.irange() ) ) >>> check [True, True, True, True, True, True, True, True, True] - Check of the formula \(\nabla_v e_j = \langle \omega^i_{\ \, j}, v \rangle e_i\): - sage: v = M.vector_field() sage: v[:] = (x*y, z^2-3*x, z+2*y) sage: b = M.default_frame() sage: for j in M.irange(): # check on M's default frame # long time ....: nab(b[j]).contract(v) == \ ....: sum( nab.connection_form(i,j)(v)*b[i] for i in M.irange()) True True True sage: for j in M.irange(): # check on frame e # long time ....: nab(e[j]).contract(v) == \ ....: sum( nab.connection_form(i,j,e)(v)*e[i] for i in M.irange()) True True True - >>> from sage.all import * >>> v = M.vector_field() >>> v[:] = (x*y, z**Integer(2)-Integer(3)*x, z+Integer(2)*y) >>> b = M.default_frame() >>> for j in M.irange(): # check on M's default frame # long time ... nab(b[j]).contract(v) == sum( nab.connection_form(i,j)(v)*b[i] for i in M.irange()) True True True >>> for j in M.irange(): # check on frame e # long time ... nab(e[j]).contract(v) == sum( nab.connection_form(i,j,e)(v)*e[i] for i in M.irange()) True True True 
 - copy(name, latex_name=None)[source]¶
- Return an exact copy of - self.- INPUT: - name– name given to the copy
- latex_name– (default:- None) LaTeX symbol to denote the copy; if none is provided, the LaTeX symbol is set to- name
 - Note - The name and the derived quantities are not copied. - EXAMPLES: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: eX = X.frame() sage: nab.set_coef(eX)[1,2,1] = x*y sage: nab.set_coef(eX)[1,2,2] = x+y sage: nab.display() Gam^x_yx = x*y Gam^x_yy = x + y sage: nab_copy = nab.copy(name='nabla_1', latex_name=r'\nabla_1') sage: nab is nab_copy False sage: nab == nab_copy True sage: nab_copy.display() Gam^x_yx = x*y Gam^x_yy = x + y - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> eX = X.frame() >>> nab.set_coef(eX)[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.set_coef(eX)[Integer(1),Integer(2),Integer(2)] = x+y >>> nab.display() Gam^x_yx = x*y Gam^x_yy = x + y >>> nab_copy = nab.copy(name='nabla_1', latex_name=r'\nabla_1') >>> nab is nab_copy False >>> nab == nab_copy True >>> nab_copy.display() Gam^x_yx = x*y Gam^x_yy = x + y 
 - curvature_form(i, j, frame=None)[source]¶
- Return the curvature 2-form corresponding to the given index and vector frame. - The curvature 2-forms with respect to the frame \((e_i)\) are the \(n^2\) 2-forms \(\Omega^i_{\ \, j}\) defined by \[\Omega^i_{\ \, j}(u,v) = R(e^i, e_j, u, v)\]- where \(R\) is the connection’s Riemann curvature tensor (cf. - riemann()), \((e^i)\) is the coframe dual to \((e_i)\) and \((u,v)\) is a generic pair of vectors.- INPUT: - i,- j– indices identifying the 2-form \(\Omega^i_{\ \, j}\)
- frame– (default:- None) vector frame relative to which the curvature 2-forms are defined; if- None, the default frame of the connection’s domain is assumed.
 - OUTPUT: - the 2-form \(\Omega^i_{\ \, j}\), as an instance of - DiffForm
 - EXAMPLES: - Curvature 2-forms on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,1], nab[1,1,2], nab[1,1,3] = x*y*z, x^2, -y*z sage: nab[1,2,3], nab[1,3,1], nab[1,3,2] = -x^3, y^2*z, y^2-x^2 sage: nab[2,1,1], nab[2,1,2], nab[2,2,1] = z^2, x*y*z^2, -x^2 sage: nab[2,3,1], nab[2,3,3], nab[3,1,2] = x^2+y^2+z^2, y^2-z^2, x*y+z^2 sage: nab[3,2,1], nab[3,2,2], nab[3,3,3] = x*y+z, z^3 -y^2, x*z^2 - z*y^2 sage: nab.curvature_form(1,1) # long time 2-form curvature (1,1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) on the 3-dimensional differentiable manifold M sage: nab.curvature_form(1,1).display() # long time (if above is skipped) curvature (1,1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) = (y^2*z^3 + (x*y^3 - x)*z + 2*x) dx∧dy + (x^3*z^2 - x*y) dx∧dz + (x^4*y*z^2 - z) dy∧dz - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(1)], nab[Integer(1),Integer(1),Integer(2)], nab[Integer(1),Integer(1),Integer(3)] = x*y*z, x**Integer(2), -y*z >>> nab[Integer(1),Integer(2),Integer(3)], nab[Integer(1),Integer(3),Integer(1)], nab[Integer(1),Integer(3),Integer(2)] = -x**Integer(3), y**Integer(2)*z, y**Integer(2)-x**Integer(2) >>> nab[Integer(2),Integer(1),Integer(1)], nab[Integer(2),Integer(1),Integer(2)], nab[Integer(2),Integer(2),Integer(1)] = z**Integer(2), x*y*z**Integer(2), -x**Integer(2) >>> nab[Integer(2),Integer(3),Integer(1)], nab[Integer(2),Integer(3),Integer(3)], nab[Integer(3),Integer(1),Integer(2)] = x**Integer(2)+y**Integer(2)+z**Integer(2), y**Integer(2)-z**Integer(2), x*y+z**Integer(2) >>> nab[Integer(3),Integer(2),Integer(1)], nab[Integer(3),Integer(2),Integer(2)], nab[Integer(3),Integer(3),Integer(3)] = x*y+z, z**Integer(3) -y**Integer(2), x*z**Integer(2) - z*y**Integer(2) >>> nab.curvature_form(Integer(1),Integer(1)) # long time 2-form curvature (1,1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) on the 3-dimensional differentiable manifold M >>> nab.curvature_form(Integer(1),Integer(1)).display() # long time (if above is skipped) curvature (1,1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) = (y^2*z^3 + (x*y^3 - x)*z + 2*x) dx∧dy + (x^3*z^2 - x*y) dx∧dz + (x^4*y*z^2 - z) dy∧dz - Curvature 2-forms w.r.t. a non-holonomic frame: - sage: ch_basis = M.automorphism_field() sage: ch_basis[1,1], ch_basis[2,2], ch_basis[3,3] = y, z, x sage: e = M.default_frame().new_frame(ch_basis, 'e') sage: e[1].display(), e[2].display(), e[3].display() (e_1 = y ∂/∂x, e_2 = z ∂/∂y, e_3 = x ∂/∂z) sage: ef = e.coframe() sage: ef[1].display(), ef[2].display(), ef[3].display() (e^1 = 1/y dx, e^2 = 1/z dy, e^3 = 1/x dz) sage: nab.curvature_form(1,1,e) # long time 2-form curvature (1,1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) on the 3-dimensional differentiable manifold M sage: nab.curvature_form(1,1,e).display(e) # long time (if above is skipped) curvature (1,1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) = (y^3*z^4 + 2*x*y*z + (x*y^4 - x*y)*z^2) e^1∧e^2 + (x^4*y*z^2 - x^2*y^2) e^1∧e^3 + (x^5*y*z^3 - x*z^2) e^2∧e^3 - >>> from sage.all import * >>> ch_basis = M.automorphism_field() >>> ch_basis[Integer(1),Integer(1)], ch_basis[Integer(2),Integer(2)], ch_basis[Integer(3),Integer(3)] = y, z, x >>> e = M.default_frame().new_frame(ch_basis, 'e') >>> e[Integer(1)].display(), e[Integer(2)].display(), e[Integer(3)].display() (e_1 = y ∂/∂x, e_2 = z ∂/∂y, e_3 = x ∂/∂z) >>> ef = e.coframe() >>> ef[Integer(1)].display(), ef[Integer(2)].display(), ef[Integer(3)].display() (e^1 = 1/y dx, e^2 = 1/z dy, e^3 = 1/x dz) >>> nab.curvature_form(Integer(1),Integer(1),e) # long time 2-form curvature (1,1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) on the 3-dimensional differentiable manifold M >>> nab.curvature_form(Integer(1),Integer(1),e).display(e) # long time (if above is skipped) curvature (1,1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) = (y^3*z^4 + 2*x*y*z + (x*y^4 - x*y)*z^2) e^1∧e^2 + (x^4*y*z^2 - x^2*y^2) e^1∧e^3 + (x^5*y*z^3 - x*z^2) e^2∧e^3 - Cartan’s second structure equation is \[\Omega^i_{\ \, j} = \mathrm{d} \omega^i_{\ \, j} + \omega^i_{\ \, k} \wedge \omega^k_{\ \, j}\]- where the \(\omega^i_{\ \, j}\)’s are the connection 1-forms (cf. - connection_form()). Let us check it on the frame e:- sage: omega = nab.connection_form sage: check = [] sage: for i in M.irange(): # long time ....: for j in M.irange(): ....: check.append( nab.curvature_form(i,j,e) == \ ....: omega(i,j,e).exterior_derivative() + \ ....: sum( omega(i,k,e).wedge(omega(k,j,e)) for k in M.irange()) ) sage: check # long time [True, True, True, True, True, True, True, True, True] - >>> from sage.all import * >>> omega = nab.connection_form >>> check = [] >>> for i in M.irange(): # long time ... for j in M.irange(): ... check.append( nab.curvature_form(i,j,e) == omega(i,j,e).exterior_derivative() + sum( omega(i,k,e).wedge(omega(k,j,e)) for k in M.irange()) ) >>> check # long time [True, True, True, True, True, True, True, True, True] 
 - del_other_coef(frame=None)[source]¶
- Delete all the coefficients but those corresponding to - frame.- INPUT: - frame– (default:- None) vector frame, the connection coefficients w.r.t. which are to be kept; if- None, the default frame of the connection’s domain is assumed.
 - EXAMPLES: - We first create two sets of connection coefficients: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: eX = X.frame() sage: nab.set_coef(eX)[1,2,1] = x*y sage: e = M.vector_frame('e') sage: nab.add_coef(e)[2,1,1] = x+y sage: nab.display(eX) Gam^x_yx = x*y sage: nab.display(e) Gam^2_11 = x + y - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> eX = X.frame() >>> nab.set_coef(eX)[Integer(1),Integer(2),Integer(1)] = x*y >>> e = M.vector_frame('e') >>> nab.add_coef(e)[Integer(2),Integer(1),Integer(1)] = x+y >>> nab.display(eX) Gam^x_yx = x*y >>> nab.display(e) Gam^2_11 = x + y - Let us delete the connection coefficients w.r.t. all frames except for frame - eX:- sage: nab.del_other_coef(eX) sage: nab.display(eX) Gam^x_yx = x*y - >>> from sage.all import * >>> nab.del_other_coef(eX) >>> nab.display(eX) Gam^x_yx = x*y - The connection coefficients w.r.t. frame - ehave indeed been deleted:- sage: nab.display(e) Traceback (most recent call last): ... ValueError: no common frame found for the computation - >>> from sage.all import * >>> nab.display(e) Traceback (most recent call last): ... ValueError: no common frame found for the computation 
 - display(frame=None, chart=None, symbol=None, latex_symbol=None, index_labels=None, index_latex_labels=None, coordinate_labels=True, only_nonzero=True, only_nonredundant=False)[source]¶
- Display all the connection coefficients w.r.t. 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 relative to which the connection coefficients are defined; if- None, the default frame of the connection’s domain is used
- chart– (default:- None) chart specifying the coordinate expression of the connection coefficients; if- None, the default chart of the domain of- frameis used
- symbol– (default:- None) string specifying the symbol of the connection coefficients; if- None, ‘Gam’ is used
- latex_symbol– (default:- None) string specifying the LaTeX symbol for the components; if- None, ‘\Gamma’ is used
- index_labels– (default:- None) list of strings representing the labels of each index; if- None, integer labels are used, except if- frameis a coordinate frame and- coordinate_symbolsis set to- True, in which case the coordinate symbols are used
- index_latex_labels– (default:- None) list of strings representing the LaTeX labels of each index; if- None, integer labels are used, except if- frameis a coordinate frame and- coordinate_symbolsis set to- True, in which case the coordinate LaTeX symbols are 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 connection coefficients are displayed
- only_nonredundant– boolean (default:- False); if- True, only nonredundant connection coefficients are displayed in case of symmetries
 - EXAMPLES: - Coefficients of a connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,2], nab[3,2,3] = x^2, y*z - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z - By default, only the nonzero connection coefficients are displayed: - sage: nab.display() Gam^x_xy = x^2 Gam^z_yz = y*z sage: latex(nab.display()) \begin{array}{lcl} \Gamma_{ \phantom{\, x} \, x \, y }^{ \, x \phantom{\, x} \phantom{\, y} } & = & x^{2} \\ \Gamma_{ \phantom{\, z} \, y \, z }^{ \, z \phantom{\, y} \phantom{\, z} } & = & y z \end{array} - >>> from sage.all import * >>> nab.display() Gam^x_xy = x^2 Gam^z_yz = y*z >>> latex(nab.display()) \begin{array}{lcl} \Gamma_{ \phantom{\, x} \, x \, y }^{ \, x \phantom{\, x} \phantom{\, y} } & = & x^{2} \\ \Gamma_{ \phantom{\, z} \, y \, z }^{ \, z \phantom{\, y} \phantom{\, z} } & = & y z \end{array} - By default, the displayed connection coefficients are those w.r.t. to the default frame of the connection’s domain, so the above is equivalent to: - sage: nab.display(frame=M.default_frame()) Gam^x_xy = x^2 Gam^z_yz = y*z - >>> from sage.all import * >>> nab.display(frame=M.default_frame()) Gam^x_xy = x^2 Gam^z_yz = y*z - Since the default frame is a coordinate frame, coordinate symbols are used to label the indices, but one may ask for integers instead: - sage: M.default_frame() is c_xyz.frame() True sage: nab.display(coordinate_labels=False) Gam^1_12 = x^2 Gam^3_23 = y*z - >>> from sage.all import * >>> M.default_frame() is c_xyz.frame() True >>> nab.display(coordinate_labels=False) Gam^1_12 = x^2 Gam^3_23 = y*z - The index labels can also be customized: - sage: nab.display(index_labels=['(1)', '(2)', '(3)']) Gam^(1)_(1),(2) = x^2 Gam^(3)_(2),(3) = y*z - >>> from sage.all import * >>> nab.display(index_labels=['(1)', '(2)', '(3)']) Gam^(1)_(1),(2) = x^2 Gam^(3)_(2),(3) = y*z - The symbol ‘Gam’ can be changed: - sage: nab.display(symbol='C', latex_symbol='C') C^x_xy = x^2 C^z_yz = y*z sage: latex(nab.display(symbol='C', latex_symbol='C')) \begin{array}{lcl} C_{ \phantom{\, x} \, x \, y }^{ \, x \phantom{\, x} \phantom{\, y} } & = & x^{2} \\ C_{ \phantom{\, z} \, y \, z }^{ \, z \phantom{\, y} \phantom{\, z} } & = & y z \end{array} - >>> from sage.all import * >>> nab.display(symbol='C', latex_symbol='C') C^x_xy = x^2 C^z_yz = y*z >>> latex(nab.display(symbol='C', latex_symbol='C')) \begin{array}{lcl} C_{ \phantom{\, x} \, x \, y }^{ \, x \phantom{\, x} \phantom{\, y} } & = & x^{2} \\ C_{ \phantom{\, z} \, y \, z }^{ \, z \phantom{\, y} \phantom{\, z} } & = & y z \end{array} - Display of Christoffel symbols, skipping the redundancy associated with the symmetry of the last two indices: - sage: M = Manifold(3, 'R^3', start_index=1) sage: c_spher.<r,th,ph> = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') sage: g = M.metric('g') sage: g[1,1], g[2,2], g[3,3] = 1, r^2 , (r*sin(th))^2 sage: g.display() g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph sage: g.connection().display(only_nonredundant=True) Gam^r_th,th = -r Gam^r_ph,ph = -r*sin(th)^2 Gam^th_r,th = 1/r Gam^th_ph,ph = -cos(th)*sin(th) Gam^ph_r,ph = 1/r Gam^ph_th,ph = cos(th)/sin(th) - >>> from sage.all import * >>> M = Manifold(Integer(3), 'R^3', start_index=Integer(1)) >>> c_spher = M.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi', names=('r', 'th', 'ph',)); (r, th, ph,) = c_spher._first_ngens(3) >>> g = M.metric('g') >>> g[Integer(1),Integer(1)], g[Integer(2),Integer(2)], g[Integer(3),Integer(3)] = Integer(1), r**Integer(2) , (r*sin(th))**Integer(2) >>> g.display() g = dr⊗dr + r^2 dth⊗dth + r^2*sin(th)^2 dph⊗dph >>> g.connection().display(only_nonredundant=True) Gam^r_th,th = -r Gam^r_ph,ph = -r*sin(th)^2 Gam^th_r,th = 1/r Gam^th_ph,ph = -cos(th)*sin(th) Gam^ph_r,ph = 1/r Gam^ph_th,ph = cos(th)/sin(th) - By default, the parameter - only_nonredundantis set to- False:- sage: g.connection().display() Gam^r_th,th = -r Gam^r_ph,ph = -r*sin(th)^2 Gam^th_r,th = 1/r Gam^th_th,r = 1/r Gam^th_ph,ph = -cos(th)*sin(th) Gam^ph_r,ph = 1/r Gam^ph_th,ph = cos(th)/sin(th) Gam^ph_ph,r = 1/r Gam^ph_ph,th = cos(th)/sin(th) - >>> from sage.all import * >>> g.connection().display() Gam^r_th,th = -r Gam^r_ph,ph = -r*sin(th)^2 Gam^th_r,th = 1/r Gam^th_th,r = 1/r Gam^th_ph,ph = -cos(th)*sin(th) Gam^ph_r,ph = 1/r Gam^ph_th,ph = cos(th)/sin(th) Gam^ph_ph,r = 1/r Gam^ph_ph,th = cos(th)/sin(th) 
 - domain()[source]¶
- Return the manifold subset on which the affine connection is defined. - OUTPUT: - instance of class - DifferentiableManifoldrepresenting the manifold on which- selfis defined.
 - EXAMPLES: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab.domain() 3-dimensional differentiable manifold M sage: U = M.open_subset('U', coord_def={c_xyz: x>0}) sage: nabU = U.affine_connection('D') sage: nabU.domain() Open subset U of the 3-dimensional differentiable manifold M - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab.domain() 3-dimensional differentiable manifold M >>> U = M.open_subset('U', coord_def={c_xyz: x>Integer(0)}) >>> nabU = U.affine_connection('D') >>> nabU.domain() Open subset U of the 3-dimensional differentiable manifold M 
 - is_immutable()[source]¶
- Return - Trueif this object is immutable, i.e. its coefficients cannot be chanced, and- Falseif it is not.- To set an affine connection immutable, use - set_immutable().- EXAMPLES: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: nab.is_immutable() False sage: nab.set_immutable() sage: nab.is_immutable() True - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> nab.is_immutable() False >>> nab.set_immutable() >>> nab.is_immutable() True 
 - is_mutable()[source]¶
- Return - Trueif this object is mutable, i.e. its coefficients can be changed, and- Falseif it is not.- EXAMPLES: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: nab.is_mutable() True sage: nab.set_immutable() sage: nab.is_mutable() False - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> nab.is_mutable() True >>> nab.set_immutable() >>> nab.is_mutable() False 
 - restrict(subdomain)[source]¶
- Return the restriction of the connection to some subdomain. - If such restriction has not been defined yet, it is constructed here. - INPUT: - subdomain– open subset \(U\) of the connection’s domain (must be an instance of- DifferentiableManifold)
 - OUTPUT: instance of - AffineConnectionrepresenting the restriction- EXAMPLES: - Restriction of a connection on a 2-dimensional manifold: - sage: M = Manifold(2, 'M', start_index=1) sage: c_xy.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,2], nab[2,1,1] = x^2, x+y sage: nab[:] [[[0, x^2], [0, 0]], [[x + y, 0], [0, 0]]] sage: U = M.open_subset('U', coord_def={c_xy: x>0}) sage: nabU = nab.restrict(U) ; nabU Affine connection nabla on the Open subset U of the 2-dimensional differentiable manifold M sage: nabU.domain() Open subset U of the 2-dimensional differentiable manifold M sage: nabU[:] [[[0, x^2], [0, 0]], [[x + y, 0], [0, 0]]] - >>> 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) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(2),Integer(1),Integer(1)] = x**Integer(2), x+y >>> nab[:] [[[0, x^2], [0, 0]], [[x + y, 0], [0, 0]]] >>> U = M.open_subset('U', coord_def={c_xy: x>Integer(0)}) >>> nabU = nab.restrict(U) ; nabU Affine connection nabla on the Open subset U of the 2-dimensional differentiable manifold M >>> nabU.domain() Open subset U of the 2-dimensional differentiable manifold M >>> nabU[:] [[[0, x^2], [0, 0]], [[x + y, 0], [0, 0]]] - The result is cached: - sage: nab.restrict(U) is nabU True - >>> from sage.all import * >>> nab.restrict(U) is nabU True - until the connection is modified: - sage: nab[1,2,2] = -y sage: nab.restrict(U) is nabU False sage: nab.restrict(U)[:] [[[0, x^2], [0, -y]], [[x + y, 0], [0, 0]]] - >>> from sage.all import * >>> nab[Integer(1),Integer(2),Integer(2)] = -y >>> nab.restrict(U) is nabU False >>> nab.restrict(U)[:] [[[0, x^2], [0, -y]], [[x + y, 0], [0, 0]]] 
 - ricci()[source]¶
- Return the connection’s Ricci tensor. - The Ricci tensor is the tensor field \(Ric\) of type (0,2) defined from the Riemann curvature tensor \(R\) by \[Ric(u, v) = R(e^i, u, e_i, v)\]- for any vector fields \(u\) and \(v\), \((e_i)\) being any vector frame and \((e^i)\) the dual coframe. - OUTPUT: - the Ricci tensor \(Ric\), as an instance of - TensorField
 - EXAMPLES: - Ricci tensor of an affine connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M sage: nab[1,1,2], nab[3,2,3] = x^2, y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz sage: r = nab.ricci() ; r Tensor field of type (0,2) on the 3-dimensional differentiable manifold M sage: r[:] [ 0 2*x 0] [ 0 -z 0] [ 0 0 0] - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz >>> r = nab.ricci() ; r Tensor field of type (0,2) on the 3-dimensional differentiable manifold M >>> r[:] [ 0 2*x 0] [ 0 -z 0] [ 0 0 0] - The result is cached (until the connection is modified via - set_coef()or- add_coef()):- sage: nab.ricci() is r True - >>> from sage.all import * >>> nab.ricci() is r True 
 - riemann()[source]¶
- Return the connection’s Riemann curvature tensor. - The Riemann curvature tensor is the tensor field \(R\) of type (1,3) defined by \[R(\omega, w, u, v) = \left\langle \omega, \nabla_u \nabla_v w - \nabla_v \nabla_u w - \nabla_{[u, v]} w \right\rangle\]- for any 1-form \(\omega\) and any vector fields \(u\), \(v\) and \(w\). - OUTPUT: - the Riemann curvature tensor \(R\), as an instance of - TensorField
 - EXAMPLES: - Curvature of an affine connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M sage: nab[1,1,2], nab[3,2,3] = x^2, y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz sage: r = nab.riemann() ; r Tensor field of type (1,3) on the 3-dimensional differentiable manifold M sage: r.parent() Free module T^(1,3)(M) of type-(1,3) tensors fields on the 3-dimensional differentiable manifold M - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') ; nab Affine connection nabla on the 3-dimensional differentiable manifold M >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz >>> r = nab.riemann() ; r Tensor field of type (1,3) on the 3-dimensional differentiable manifold M >>> r.parent() Free module T^(1,3)(M) of type-(1,3) tensors fields on the 3-dimensional differentiable manifold M - By construction, the Riemann tensor is antisymmetric with respect to its last two arguments (denoted \(u\) and \(v\) in the definition above), which are at positions 2 and 3 (the first argument being at position 0): - sage: r.symmetries() no symmetry; antisymmetry: (2, 3) - >>> from sage.all import * >>> r.symmetries() no symmetry; antisymmetry: (2, 3) - The components: - sage: r[:] [[[[0, 2*x, 0], [-2*x, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, z], [0, -z, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]] - >>> from sage.all import * >>> r[:] [[[[0, 2*x, 0], [-2*x, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, z], [0, -z, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]] - The result is cached (until the connection is modified via - set_coef()or- add_coef()):- sage: nab.riemann() is r True - >>> from sage.all import * >>> nab.riemann() is r True - Another example: Riemann curvature tensor of some connection on a non-parallelizable 2-dimensional manifold: - sage: M = Manifold(2, 'M') sage: U = M.open_subset('U') ; V = M.open_subset('V') sage: M.declare_union(U,V) # M is the union of U and V sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() sage: transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ....: restrictions1= x>0, restrictions2= u+v>0) sage: inv = transf.inverse() sage: W = U.intersection(V) sage: eU = c_xy.frame() ; eV = c_uv.frame() sage: c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) sage: eUW = c_xyW.frame() ; eVW = c_uvW.frame() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[0,0,0], nab[0,1,0], nab[1,0,1] = x, x-y, x*y sage: for i in M.irange(): ....: for j in M.irange(): ....: for k in M.irange(): ....: nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() sage: r = nab.riemann() ; r # long time Tensor field of type (1,3) on the 2-dimensional differentiable manifold M sage: r.parent() # long time Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M sage: r.display(eU) # long time (x^2*y - x*y^2) ∂/∂x⊗dx⊗dx⊗dy + (-x^2*y + x*y^2) ∂/∂x⊗dx⊗dy⊗dx + ∂/∂x⊗dy⊗dx⊗dy - ∂/∂x⊗dy⊗dy⊗dx - (x^2 - 1)*y ∂/∂y⊗dx⊗dx⊗dy + (x^2 - 1)*y ∂/∂y⊗dx⊗dy⊗dx + (-x^2*y + x*y^2) ∂/∂y⊗dy⊗dx⊗dy + (x^2*y - x*y^2) ∂/∂y⊗dy⊗dy⊗dx sage: r.display(eV) # long time (1/32*u^3 - 1/32*u*v^2 - 1/32*v^3 + 1/32*(u^2 + 4)*v - 1/8*u - 1/4) ∂/∂u⊗du⊗du⊗dv + (-1/32*u^3 + 1/32*u*v^2 + 1/32*v^3 - 1/32*(u^2 + 4)*v + 1/8*u + 1/4) ∂/∂u⊗du⊗dv⊗du + (1/32*u^3 - 1/32*u*v^2 + 3/32*v^3 - 1/32*(3*u^2 - 4)*v - 1/8*u + 1/4) ∂/∂u⊗dv⊗du⊗dv + (-1/32*u^3 + 1/32*u*v^2 - 3/32*v^3 + 1/32*(3*u^2 - 4)*v + 1/8*u - 1/4) ∂/∂u⊗dv⊗dv⊗du + (-1/32*u^3 + 1/32*u*v^2 + 5/32*v^3 - 1/32*(5*u^2 + 4)*v + 1/8*u - 1/4) ∂/∂v⊗du⊗du⊗dv + (1/32*u^3 - 1/32*u*v^2 - 5/32*v^3 + 1/32*(5*u^2 + 4)*v - 1/8*u + 1/4) ∂/∂v⊗du⊗dv⊗du + (-1/32*u^3 + 1/32*u*v^2 + 1/32*v^3 - 1/32*(u^2 + 4)*v + 1/8*u + 1/4) ∂/∂v⊗dv⊗du⊗dv + (1/32*u^3 - 1/32*u*v^2 - 1/32*v^3 + 1/32*(u^2 + 4)*v - 1/8*u - 1/4) ∂/∂v⊗dv⊗dv⊗du - >>> from sage.all import * >>> M = Manifold(Integer(2), 'M') >>> U = M.open_subset('U') ; V = M.open_subset('V') >>> M.declare_union(U,V) # M is the union of U and V >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ... restrictions1= x>Integer(0), restrictions2= u+v>Integer(0)) >>> inv = transf.inverse() >>> W = U.intersection(V) >>> eU = c_xy.frame() ; eV = c_uv.frame() >>> c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) >>> eUW = c_xyW.frame() ; eVW = c_uvW.frame() >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(0),Integer(0),Integer(0)], nab[Integer(0),Integer(1),Integer(0)], nab[Integer(1),Integer(0),Integer(1)] = x, x-y, x*y >>> for i in M.irange(): ... for j in M.irange(): ... for k in M.irange(): ... nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() >>> r = nab.riemann() ; r # long time Tensor field of type (1,3) on the 2-dimensional differentiable manifold M >>> r.parent() # long time Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M >>> r.display(eU) # long time (x^2*y - x*y^2) ∂/∂x⊗dx⊗dx⊗dy + (-x^2*y + x*y^2) ∂/∂x⊗dx⊗dy⊗dx + ∂/∂x⊗dy⊗dx⊗dy - ∂/∂x⊗dy⊗dy⊗dx - (x^2 - 1)*y ∂/∂y⊗dx⊗dx⊗dy + (x^2 - 1)*y ∂/∂y⊗dx⊗dy⊗dx + (-x^2*y + x*y^2) ∂/∂y⊗dy⊗dx⊗dy + (x^2*y - x*y^2) ∂/∂y⊗dy⊗dy⊗dx >>> r.display(eV) # long time (1/32*u^3 - 1/32*u*v^2 - 1/32*v^3 + 1/32*(u^2 + 4)*v - 1/8*u - 1/4) ∂/∂u⊗du⊗du⊗dv + (-1/32*u^3 + 1/32*u*v^2 + 1/32*v^3 - 1/32*(u^2 + 4)*v + 1/8*u + 1/4) ∂/∂u⊗du⊗dv⊗du + (1/32*u^3 - 1/32*u*v^2 + 3/32*v^3 - 1/32*(3*u^2 - 4)*v - 1/8*u + 1/4) ∂/∂u⊗dv⊗du⊗dv + (-1/32*u^3 + 1/32*u*v^2 - 3/32*v^3 + 1/32*(3*u^2 - 4)*v + 1/8*u - 1/4) ∂/∂u⊗dv⊗dv⊗du + (-1/32*u^3 + 1/32*u*v^2 + 5/32*v^3 - 1/32*(5*u^2 + 4)*v + 1/8*u - 1/4) ∂/∂v⊗du⊗du⊗dv + (1/32*u^3 - 1/32*u*v^2 - 5/32*v^3 + 1/32*(5*u^2 + 4)*v - 1/8*u + 1/4) ∂/∂v⊗du⊗dv⊗du + (-1/32*u^3 + 1/32*u*v^2 + 1/32*v^3 - 1/32*(u^2 + 4)*v + 1/8*u + 1/4) ∂/∂v⊗dv⊗du⊗dv + (1/32*u^3 - 1/32*u*v^2 - 1/32*v^3 + 1/32*(u^2 + 4)*v - 1/8*u - 1/4) ∂/∂v⊗dv⊗dv⊗du - The same computation parallelized on 2 cores: - sage: Parallelism().set(nproc=2) sage: r_backup = r # long time sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[0,0,0], nab[0,1,0], nab[1,0,1] = x, x-y, x*y sage: for i in M.irange(): ....: for j in M.irange(): ....: for k in M.irange(): ....: nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() sage: r = nab.riemann() ; r # long time Tensor field of type (1,3) on the 2-dimensional differentiable manifold M sage: r.parent() # long time Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M sage: r == r_backup # long time True sage: Parallelism().set(nproc=1) # switch off parallelization - >>> from sage.all import * >>> Parallelism().set(nproc=Integer(2)) >>> r_backup = r # long time >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(0),Integer(0),Integer(0)], nab[Integer(0),Integer(1),Integer(0)], nab[Integer(1),Integer(0),Integer(1)] = x, x-y, x*y >>> for i in M.irange(): ... for j in M.irange(): ... for k in M.irange(): ... nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() >>> r = nab.riemann() ; r # long time Tensor field of type (1,3) on the 2-dimensional differentiable manifold M >>> r.parent() # long time Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M >>> r == r_backup # long time True >>> Parallelism().set(nproc=Integer(1)) # switch off parallelization 
 - set_calc_order(symbol, order, truncate=False)[source]¶
- Trigger a series expansion with respect to a small parameter in computations involving - self.- This property is propagated by usual operations. The internal representation must be - SRfor this to take effect.- INPUT: - symbol– symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the connection coefficients 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 connection coefficients are 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: h = 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: h[0, 1] = x sage: g.set(g + e*h) sage: g[:] [ -1 e*x 0 0] [e*x 1 0 0] [ 0 0 1 0] [ 0 0 0 1] sage: nab = g.connection() sage: nab[0, 1, 1] -e/(e^2*x^2 + 1) sage: nab.set_calc_order(e, 1, truncate=True) sage: nab[0, 1, 1] -e - >>> 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() >>> h = 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) >>> h[Integer(0), Integer(1)] = x >>> g.set(g + e*h) >>> g[:] [ -1 e*x 0 0] [e*x 1 0 0] [ 0 0 1 0] [ 0 0 0 1] >>> nab = g.connection() >>> nab[Integer(0), Integer(1), Integer(1)] -e/(e^2*x^2 + 1) >>> nab.set_calc_order(e, Integer(1), truncate=True) >>> nab[Integer(0), Integer(1), Integer(1)] -e 
 - set_coef(frame=None)[source]¶
- Return the connection coefficients in a given frame for assignment. - See method - coef()for details about the definition of the connection coefficients.- The connection coefficients with respect to other frames are deleted, in order to avoid any inconsistency. To keep them, use the method - add_coef()instead.- INPUT: - frame– (default:- None) vector frame in which the connection coefficients are defined; if- None, the default frame of the connection’s domain is assumed.
 - OUTPUT: - connection coefficients in the given frame, as an instance of the class - Components; if such connection coefficients did not exist previously, they are created. See method- coef()for the storage convention of the connection coefficients.
 - EXAMPLES: - Setting the coefficients of an affine connection w.r.t. some coordinate frame: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: eX = X.frame(); eX Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.set_coef(eX) 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.set_coef(eX)[1,2,1] = x*y sage: nab.display(eX) Gam^x_yx = x*y - >>> 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) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> eX = X.frame(); eX Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.set_coef(eX) 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.set_coef(eX)[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.display(eX) Gam^x_yx = x*y - Since - eXis the manifold’s default vector frame, its mention may be omitted:- sage: nab.set_coef()[1,2,1] = x*y sage: nab.set_coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) sage: nab.set_coef()[1,2,1] = x*y sage: nab.display() Gam^x_yx = x*y - >>> from sage.all import * >>> nab.set_coef()[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.set_coef() 3-indices components w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y)) >>> nab.set_coef()[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.display() Gam^x_yx = x*y - To set the coefficients in the default frame, one can even bypass the method - set_coef()and call directly the operator- []on the connection object:- sage: nab[1,2,1] = x*y sage: nab.display() Gam^x_yx = x*y - >>> from sage.all import * >>> nab[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.display() Gam^x_yx = x*y - Setting the connection coefficients w.r.t. to another vector frame: - sage: e = M.vector_frame('e') sage: nab.set_coef(e) 3-indices components w.r.t. Vector frame (M, (e_1,e_2)) sage: nab.set_coef(e)[2,1,1] = x+y sage: nab.set_coef(e)[2,1,2] = x-y sage: nab.display(e) Gam^2_11 = x + y Gam^2_12 = x - y - >>> from sage.all import * >>> e = M.vector_frame('e') >>> nab.set_coef(e) 3-indices components w.r.t. Vector frame (M, (e_1,e_2)) >>> nab.set_coef(e)[Integer(2),Integer(1),Integer(1)] = x+y >>> nab.set_coef(e)[Integer(2),Integer(1),Integer(2)] = x-y >>> nab.display(e) Gam^2_11 = x + y Gam^2_12 = x - y - The coefficients w.r.t. the frame - eXhave been deleted:- sage: nab.display(eX) Traceback (most recent call last): ... ValueError: no common frame found for the computation - >>> from sage.all import * >>> nab.display(eX) Traceback (most recent call last): ... ValueError: no common frame found for the computation - To keep them, use the method - add_coef()instead.
 - set_immutable()[source]¶
- Set - selfand all restrictions of- selfimmutable.- EXAMPLES: - An affine connection can be set immutable: - sage: M = Manifold(2, 'M', start_index=1) sage: X.<x,y> = M.chart() sage: U = M.open_subset('U', coord_def={X: x^2+y^2<1}) sage: nab = M.affine_connection('nabla', latex_name=r'\nabla') sage: eX = X.frame() sage: nab.set_coef(eX)[1,2,1] = x*y sage: nab.is_immutable() False sage: nab.set_immutable() sage: nab.is_immutable() True - >>> 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) >>> U = M.open_subset('U', coord_def={X: x**Integer(2)+y**Integer(2)<Integer(1)}) >>> nab = M.affine_connection('nabla', latex_name=r'\nabla') >>> eX = X.frame() >>> nab.set_coef(eX)[Integer(1),Integer(2),Integer(1)] = x*y >>> nab.is_immutable() False >>> nab.set_immutable() >>> nab.is_immutable() True - The coefficients of immutable elements cannot be changed: - sage: nab.add_coef(eX)[2,1,1] = x+y Traceback (most recent call last): ... ValueError: the coefficients of an immutable element cannot be changed - >>> from sage.all import * >>> nab.add_coef(eX)[Integer(2),Integer(1),Integer(1)] = x+y Traceback (most recent call last): ... ValueError: the coefficients of an immutable element cannot be changed - The restriction are set immutable as well: - sage: nabU = nab.restrict(U) sage: nabU.is_immutable() True - >>> from sage.all import * >>> nabU = nab.restrict(U) >>> nabU.is_immutable() True 
 - torsion()[source]¶
- Return the connection’s torsion tensor. - The torsion tensor is the tensor field \(T\) of type (1,2) defined by \[T(\omega, u, v) = \left\langle \omega, \nabla_u v - \nabla_v u - [u, v] \right\rangle\]- for any 1-form \(\omega\) and any vector fields \(u\) and \(v\). - OUTPUT: - the torsion tensor \(T\), as an instance of - TensorField
 - EXAMPLES: - Torsion of an affine connection on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,2], nab[3,2,3] = x^2, y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz sage: t = nab.torsion() ; t Tensor field of type (1,2) on the 3-dimensional differentiable manifold M sage: t.symmetries() no symmetry; antisymmetry: (1, 2) sage: t[:] [[[0, -x^2, 0], [x^2, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, -y*z], [0, y*z, 0]]] - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(2)], nab[Integer(3),Integer(2),Integer(3)] = x**Integer(2), y*z # Gamma^1_{12} = x^2, Gamma^3_{23} = yz >>> t = nab.torsion() ; t Tensor field of type (1,2) on the 3-dimensional differentiable manifold M >>> t.symmetries() no symmetry; antisymmetry: (1, 2) >>> t[:] [[[0, -x^2, 0], [x^2, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, -y*z], [0, y*z, 0]]] - The torsion expresses the lack of commutativity of two successive derivatives of a scalar field: - sage: f = M.scalar_field(x*z^2 + y^2 - z^2, name='f') sage: DDf = nab(nab(f)) ; DDf Tensor field nabla(df) of type (0,2) on the 3-dimensional differentiable manifold M sage: DDf.antisymmetrize()[:] # two successive derivatives do not commute: [ 0 -1/2*x^2*z^2 0] [ 1/2*x^2*z^2 0 -(x - 1)*y*z^2] [ 0 (x - 1)*y*z^2 0] sage: 2*DDf.antisymmetrize() == nab.torsion().contract(0,nab(f)) True - >>> from sage.all import * >>> f = M.scalar_field(x*z**Integer(2) + y**Integer(2) - z**Integer(2), name='f') >>> DDf = nab(nab(f)) ; DDf Tensor field nabla(df) of type (0,2) on the 3-dimensional differentiable manifold M >>> DDf.antisymmetrize()[:] # two successive derivatives do not commute: [ 0 -1/2*x^2*z^2 0] [ 1/2*x^2*z^2 0 -(x - 1)*y*z^2] [ 0 (x - 1)*y*z^2 0] >>> Integer(2)*DDf.antisymmetrize() == nab.torsion().contract(Integer(0),nab(f)) True - The above identity is the standard formula \[\nabla_j \nabla_i \, f - \nabla_i \nabla_j \, f = T^k_{\ \, ij} \nabla_k \, f ,\]- where the \(T^k_{\ \, ij}\)’s are the components of the torsion tensor. - The result is cached: - sage: nab.torsion() is t True - >>> from sage.all import * >>> nab.torsion() is t True - as long as the connection remains unchanged: - sage: nab[2,1,3] = 1+x # changing the connection sage: nab.torsion() is t # a new computation of the torsion has been made False sage: (nab.torsion() - t).display() (-x - 1) ∂/∂y⊗dx⊗dz + (x + 1) ∂/∂y⊗dz⊗dx - >>> from sage.all import * >>> nab[Integer(2),Integer(1),Integer(3)] = Integer(1)+x # changing the connection >>> nab.torsion() is t # a new computation of the torsion has been made False >>> (nab.torsion() - t).display() (-x - 1) ∂/∂y⊗dx⊗dz + (x + 1) ∂/∂y⊗dz⊗dx - Another example: torsion of some connection on a non-parallelizable 2-dimensional manifold: - sage: M = Manifold(2, 'M') sage: U = M.open_subset('U') ; V = M.open_subset('V') sage: M.declare_union(U,V) # M is the union of U and V sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() sage: transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ....: restrictions1= x>0, restrictions2= u+v>0) sage: inv = transf.inverse() sage: W = U.intersection(V) sage: eU = c_xy.frame() ; eV = c_uv.frame() sage: c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) sage: eUW = c_xyW.frame() ; eVW = c_uvW.frame() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[0,0,0], nab[0,1,0], nab[1,0,1] = x, x-y, x*y sage: for i in M.irange(): ....: for j in M.irange(): ....: for k in M.irange(): ....: nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() sage: t = nab.torsion() ; t Tensor field of type (1,2) on the 2-dimensional differentiable manifold M sage: t.parent() Module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M sage: t[eU,:] [[[0, x - y], [-x + y, 0]], [[0, -x*y], [x*y, 0]]] sage: t[eV,:] [[[0, 1/8*u^2 - 1/8*v^2 - 1/2*v], [-1/8*u^2 + 1/8*v^2 + 1/2*v, 0]], [[0, -1/8*u^2 + 1/8*v^2 - 1/2*v], [1/8*u^2 - 1/8*v^2 + 1/2*v, 0]]] - >>> from sage.all import * >>> M = Manifold(Integer(2), 'M') >>> U = M.open_subset('U') ; V = M.open_subset('V') >>> M.declare_union(U,V) # M is the union of U and V >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> transf = c_xy.transition_map(c_uv, (x+y, x-y), intersection_name='W', ... restrictions1= x>Integer(0), restrictions2= u+v>Integer(0)) >>> inv = transf.inverse() >>> W = U.intersection(V) >>> eU = c_xy.frame() ; eV = c_uv.frame() >>> c_xyW = c_xy.restrict(W) ; c_uvW = c_uv.restrict(W) >>> eUW = c_xyW.frame() ; eVW = c_uvW.frame() >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(0),Integer(0),Integer(0)], nab[Integer(0),Integer(1),Integer(0)], nab[Integer(1),Integer(0),Integer(1)] = x, x-y, x*y >>> for i in M.irange(): ... for j in M.irange(): ... for k in M.irange(): ... nab.add_coef(eV)[i,j,k] = nab.coef(eVW)[i,j,k,c_uvW].expr() >>> t = nab.torsion() ; t Tensor field of type (1,2) on the 2-dimensional differentiable manifold M >>> t.parent() Module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M >>> t[eU,:] [[[0, x - y], [-x + y, 0]], [[0, -x*y], [x*y, 0]]] >>> t[eV,:] [[[0, 1/8*u^2 - 1/8*v^2 - 1/2*v], [-1/8*u^2 + 1/8*v^2 + 1/2*v, 0]], [[0, -1/8*u^2 + 1/8*v^2 - 1/2*v], [1/8*u^2 - 1/8*v^2 + 1/2*v, 0]]] - Check of the torsion formula: - sage: f = M.scalar_field({c_xy: (x+y)^2, c_uv: u^2}, name='f') sage: DDf = nab(nab(f)) ; DDf Tensor field nabla(df) of type (0,2) on the 2-dimensional differentiable manifold M sage: DDf.antisymmetrize().display(eU) (-x^2*y - (x + 1)*y^2 + x^2) dx∧dy sage: DDf.antisymmetrize().display(eV) (1/8*u^3 - 1/8*u*v^2 - 1/2*u*v) du∧dv sage: 2*DDf.antisymmetrize() == nab(f).contract(nab.torsion()) True - >>> from sage.all import * >>> f = M.scalar_field({c_xy: (x+y)**Integer(2), c_uv: u**Integer(2)}, name='f') >>> DDf = nab(nab(f)) ; DDf Tensor field nabla(df) of type (0,2) on the 2-dimensional differentiable manifold M >>> DDf.antisymmetrize().display(eU) (-x^2*y - (x + 1)*y^2 + x^2) dx∧dy >>> DDf.antisymmetrize().display(eV) (1/8*u^3 - 1/8*u*v^2 - 1/2*u*v) du∧dv >>> Integer(2)*DDf.antisymmetrize() == nab(f).contract(nab.torsion()) True 
 - torsion_form(i, frame=None)[source]¶
- Return the torsion 2-form corresponding to the given index and vector frame. - The torsion 2-forms with respect to the frame \((e_i)\) are the \(n\) 2-forms \(\theta^i\) defined by \[\theta^i(u,v) = T(e^i, u, v)\]- where \(T\) is the connection’s torsion tensor (cf. - torsion()), \((e^i)\) is the coframe dual to \((e_i)\) and \((u,v)\) is a generic pair of vectors.- INPUT: - i– index identifying the 2-form \(\theta^i\)
- frame– (default:- None) vector frame relative to which the torsion 2-forms are defined; if- None, the default frame of the connection’s domain is assumed.
 - OUTPUT: - the 2-form \(\theta^i\), as an instance of - DiffForm
 - EXAMPLES: - Torsion 2-forms on a 3-dimensional manifold: - sage: M = Manifold(3, 'M', start_index=1) sage: c_xyz.<x,y,z> = M.chart() sage: nab = M.affine_connection('nabla', r'\nabla') sage: nab[1,1,1], nab[1,1,2], nab[1,1,3] = x*y*z, x^2, -y*z sage: nab[1,2,3], nab[1,3,1], nab[1,3,2] = -x^3, y^2*z, y^2-x^2 sage: nab[2,1,1], nab[2,1,2], nab[2,2,1] = z^2, x*y*z^2, -x^2 sage: nab[2,3,1], nab[2,3,3], nab[3,1,2] = x^2+y^2+z^2, y^2-z^2, x*y+z^2 sage: nab[3,2,1], nab[3,2,2], nab[3,3,3] = x*y+z, z^3 -y^2, x*z^2 - z*y^2 sage: nab.torsion_form(1) 2-form torsion (1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) on the 3-dimensional differentiable manifold M sage: nab.torsion_form(1)[:] [ 0 -x^2 (y^2 + y)*z] [ x^2 0 x^3 - x^2 + y^2] [ -(y^2 + y)*z -x^3 + x^2 - y^2 0] - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', start_index=Integer(1)) >>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3) >>> nab = M.affine_connection('nabla', r'\nabla') >>> nab[Integer(1),Integer(1),Integer(1)], nab[Integer(1),Integer(1),Integer(2)], nab[Integer(1),Integer(1),Integer(3)] = x*y*z, x**Integer(2), -y*z >>> nab[Integer(1),Integer(2),Integer(3)], nab[Integer(1),Integer(3),Integer(1)], nab[Integer(1),Integer(3),Integer(2)] = -x**Integer(3), y**Integer(2)*z, y**Integer(2)-x**Integer(2) >>> nab[Integer(2),Integer(1),Integer(1)], nab[Integer(2),Integer(1),Integer(2)], nab[Integer(2),Integer(2),Integer(1)] = z**Integer(2), x*y*z**Integer(2), -x**Integer(2) >>> nab[Integer(2),Integer(3),Integer(1)], nab[Integer(2),Integer(3),Integer(3)], nab[Integer(3),Integer(1),Integer(2)] = x**Integer(2)+y**Integer(2)+z**Integer(2), y**Integer(2)-z**Integer(2), x*y+z**Integer(2) >>> nab[Integer(3),Integer(2),Integer(1)], nab[Integer(3),Integer(2),Integer(2)], nab[Integer(3),Integer(3),Integer(3)] = x*y+z, z**Integer(3) -y**Integer(2), x*z**Integer(2) - z*y**Integer(2) >>> nab.torsion_form(Integer(1)) 2-form torsion (1) of connection nabla w.r.t. Coordinate frame (M, (∂/∂x,∂/∂y,∂/∂z)) on the 3-dimensional differentiable manifold M >>> nab.torsion_form(Integer(1))[:] [ 0 -x^2 (y^2 + y)*z] [ x^2 0 x^3 - x^2 + y^2] [ -(y^2 + y)*z -x^3 + x^2 - y^2 0] - Torsion 2-forms w.r.t. a non-holonomic frame: - sage: ch_basis = M.automorphism_field() sage: ch_basis[1,1], ch_basis[2,2], ch_basis[3,3] = y, z, x sage: e = M.default_frame().new_frame(ch_basis, 'e') sage: e[1][:], e[2][:], e[3][:] ([y, 0, 0], [0, z, 0], [0, 0, x]) sage: ef = e.coframe() sage: ef[1][:], ef[2][:], ef[3][:] ([1/y, 0, 0], [0, 1/z, 0], [0, 0, 1/x]) sage: nab.torsion_form(1, e) # long time 2-form torsion (1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) on the 3-dimensional differentiable manifold M sage: nab.torsion_form(1, e).comp(e)[:] # long time [ 0 -x^2*z (x*y^2 + x*y)*z] [ x^2*z 0 (x^4 - x^3 + x*y^2)*z/y] [ -(x*y^2 + x*y)*z -(x^4 - x^3 + x*y^2)*z/y 0] - >>> from sage.all import * >>> ch_basis = M.automorphism_field() >>> ch_basis[Integer(1),Integer(1)], ch_basis[Integer(2),Integer(2)], ch_basis[Integer(3),Integer(3)] = y, z, x >>> e = M.default_frame().new_frame(ch_basis, 'e') >>> e[Integer(1)][:], e[Integer(2)][:], e[Integer(3)][:] ([y, 0, 0], [0, z, 0], [0, 0, x]) >>> ef = e.coframe() >>> ef[Integer(1)][:], ef[Integer(2)][:], ef[Integer(3)][:] ([1/y, 0, 0], [0, 1/z, 0], [0, 0, 1/x]) >>> nab.torsion_form(Integer(1), e) # long time 2-form torsion (1) of connection nabla w.r.t. Vector frame (M, (e_1,e_2,e_3)) on the 3-dimensional differentiable manifold M >>> nab.torsion_form(Integer(1), e).comp(e)[:] # long time [ 0 -x^2*z (x*y^2 + x*y)*z] [ x^2*z 0 (x^4 - x^3 + x*y^2)*z/y] [ -(x*y^2 + x*y)*z -(x^4 - x^3 + x*y^2)*z/y 0] - Cartan’s first structure equation is \[\theta^i = \mathrm{d} e^i + \omega^i_{\ \, j} \wedge e^j\]- where the \(\omega^i_{\ \, j}\)’s are the connection 1-forms (cf. - connection_form()). Let us check it on the frame e:- sage: for i in M.irange(): # long time ....: nab.torsion_form(i, e) == ef[i].exterior_derivative() + \ ....: sum(nab.connection_form(i,j,e).wedge(ef[j]) for j in M.irange()) True True True - >>> from sage.all import * >>> for i in M.irange(): # long time ... nab.torsion_form(i, e) == ef[i].exterior_derivative() + sum(nab.connection_form(i,j,e).wedge(ef[j]) for j in M.irange()) True True True