Class to manage tensor properties.
Notes
Tensors belong to tensor commutation groups; each group has a label comm; there are predefined labels:
0 tensors commuting with any other tensor
1 tensors anticommuting among themselves
2 tensors not commuting, apart with those with comm=0
Other groups can be defined using set_comm; tensors in those groups commute with those with comm=0; by default they do not commute with any other group.
get the commutation group number corresponding to i
i can be a symbol or a number or a string
If i is not already defined its commutation group number is set.
Return the commutation parameter for commutation group numbers i, j
see _TensorManager.set_comm
set the commutation parameter c for commutation groups i, j
Parameters : | i, j : symbols representing commutation groups c : group commutation number |
---|
Notes
i, j can be symbols, strings or numbers, apart from 0, 1 and 2 which are reserved respectively for commuting, anticommuting tensors and tensors not commuting with any other group apart with the commuting tensors. For the remaining cases, use this method to set the commutation rules; by default c=None.
The group commutation number c is assigned in corrispondence to the group commutation symbols; it can be
0 commuting
1 anticommuting
None no commutation property
Examples
G and GH do not commute with themselves and commute with each other; A is commuting.
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead, TensorManager
>>> Lorentz = TensorIndexType('Lorentz')
>>> i0,i1,i2,i3,i4 = tensor_indices('i0:5', Lorentz)
>>> A = tensorhead('A', [Lorentz], [[1]])
>>> G = tensorhead('G', [Lorentz], [[1]], 'Gcomm')
>>> GH = tensorhead('GH', [Lorentz], [[1]], 'GHcomm')
>>> TensorManager.set_comm('Gcomm', 'GHcomm', 0)
>>> (GH(i1)*G(i0)).canon_bp()
G(i0)*GH(i1)
>>> (G(i1)*G(i0)).canon_bp()
G(i1)*G(i0)
>>> (G(i1)*A(i0)).canon_bp()
A(i0)*G(i1)
A TensorIndexType is characterized by its name and its metric.
Parameters : | name : name of the tensor type metric : metric symmetry or metric object or None dim : dimension, it can be a symbol or an integer or None eps_dim : dimension of the epsilon tensor dummy_fmt : name of the head of dummy indices |
---|
Notes
The metric parameter can be: metric = False symmetric metric (in Riemannian geometry)
metric = True antisymmetric metric (for spinor calculus)
metric = None there is no metric
metric can be an object having name and antisym attributes.
If there is a metric the metric is used to raise and lower indices.
In the case of antisymmetric metric, the following raising and lowering conventions will be adopted:
psi(a) = g(a, b)*psi(-b); chi(-a) = chi(b)*g(-b, -a)
g(-a, b) = delta(-a, b); g(b, -a) = -delta(a, -b)
where delta(-a, b) = delta(b, -a) is the Kronecker delta (see TensorIndex for the conventions on indices).
If there is no metric it is not possible to raise or lower indices; e.g. the index of the defining representation of SU(N) is ‘covariant’ and the conjugate representation is ‘contravariant’; for N > 2 they are linearly independent.
eps_dim is by default equal to dim, if the latter is an integer; else it can be assigned (for use in naive dimensional regularization); if eps_dim is not an integer epsilon is None.
Examples
>>> from sympy.tensor.tensor import TensorIndexType
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> Lorentz.metric
metric(Lorentz,Lorentz)
Attributes
name | ||
metric_name | it is ‘metric’ or metric.name | |
metric_antisym | ||
metric | the metric tensor | |
delta | Kronecker delta | |
epsilon | the Levi-Civita epsilon tensor | |
dim | ||
dim_eps | ||
dummy_fmt |
Represents an abstract tensor index.
Parameters : | name : name of the index tensortype : TensorIndexType of the index is_up : flag for contravariant index |
---|
Notes
Tensor indices are contracted with the Einstein summation convention.
An index can be in contravariant or in covariant form; in the latter case it is represented prepending a - to the index name.
Dummy indices have a name with head given by tensortype.dummy_fmt
Examples
>>> from sympy.tensor.tensor import TensorIndexType, TensorIndex, TensorSymmetry, TensorType, get_symmetric_group_sgs
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i = TensorIndex('i', Lorentz); i
i
>>> sym1 = TensorSymmetry(get_symmetric_group_sgs(1))
>>> S1 = TensorType([Lorentz], sym1)
>>> A, B = S1('A,B')
>>> A(i)*B(-i)
A(L_0)*B(-L_0)
Attributes
name | |
tensortype | |
is_up |
Returns list of tensor indices given their names and their types
Parameters : | s : string of comma separated names of indices typ : list of TensorIndexType of the indices |
---|
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
Monoterm symmetry of a tensor
Parameters : | bsgs : tuple (base, sgs) BSGS of the symmetry of the tensor |
---|
Notes
A tensor can have an arbitrary monoterm symmetry provided by its BSGS. Multiterm symmetries, like the cyclic symmetry of the Riemann tensor, are not covered.
Examples
Define a symmetric tensor
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorSymmetry, TensorType, get_symmetric_group_sgs
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> sym2 = TensorSymmetry(get_symmetric_group_sgs(2))
>>> S2 = TensorType([Lorentz]*2, sym2)
>>> V = S2('V')
Attributes
base | base of the BSGS | |
generators | generators of the BSGS | |
rank | rank of the tensor |
Class of tensor types.
Parameters : | index_types : list of TensorIndexType of the tensor indices symmetry : TensorSymmetry of the tensor |
---|
Examples
Define a symmetric tensor
>>> from sympy.tensor.tensor import TensorIndexType, tensorsymmetry, TensorType
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> sym2 = tensorsymmetry([1, 1])
>>> S2 = TensorType([Lorentz]*2, sym2)
>>> V = S2('V')
Attributes
index_types | ||
symmetry | ||
types | list of TensorIndexType without repetitions |
Tensor head of the tensor
Parameters : | name : name of the tensor typ : list of TensorIndexType comm : commutation group number |
---|
Notes
A TensorHead belongs to a commutation group, defined by a symbol on number comm (see _TensorManager.set_comm); tensors in a commutation group have the same commutation properties; by default comm is 0, the group of the commuting tensors.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensorsymmetry, TensorType
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> sym2 = tensorsymmetry([1]*2)
>>> S2 = TensorType([Lorentz]*2, sym2)
>>> A = S2('A')
Attributes
name | ||
index_types | ||
rank | ||
types | equal to typ.types | |
symmetry | equal to typ.symmetry | |
comm | commutation group |
Abstract base class for tensor expressions
Notes
A tensor expression is an expression formed by tensors; currently the sums of tensors are distributed.
A TensExpr can be a TensAdd or a TensMul.
TensAdd objects are put in canonical form using the Butler-Portugal algorithm for canonicalization under monoterm symmetries.
TensMul objects are formed by products of component tensors, and include a coefficient, which is a SymPy expression.
In the internal representation contracted indices are represented by (ipos1, ipos2, icomp1, icomp2), where icomp1 is the position of the component tensor with contravariant index, ipos1 is the slot which the index occupies in that component tensor.
Contracted indices are therefore nameless in the internal representation.
Sum of tensors
Parameters : | free_args : list of the free indices |
---|
Notes
Sum of more than one tensor are put automatically in canonical form.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensorhead, tensor_indices
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> a, b = tensor_indices('a,b', Lorentz)
>>> p, q = tensorhead('p,q', [Lorentz], [[1]])
>>> t = p(a) + q(a); t
p(a) + q(a)
>>> t(b)
p(b) + q(b)
Attributes
args | tuple of addends | |
rank | rank of the tensor | |
free_args | list of the free indices in sorted order |
canonicalize using the Butler-Portugal algorithm for canonicalization under monoterm symmetries.
Raise or lower indices with the metric g
Parameters : | g : metric contract_all : if True, eliminate all g which are contracted |
---|
Notes
see the TensorIndexType docstring for the contraction conventions
Return a tensor with free indices substituted according to index_tuples
Parameters : | index_types : list of tuples (old_index, new_index) |
---|
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> t = A(i, k)*B(-k, -j) + A(i, -j)
>>> t.fun_eval((i, k),(-j, l))
A(k, L_0)*B(l, -L_0) + A(k, l)
Return a tensor with free indices substituted according to index_tuples
Parameters : | index_types : list of tuples (old_index, new_index) |
---|
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> t = A(i, k)*B(-k, -j); t
A(i, L_0)*B(-L_0, -j)
>>> t.substitute_indices((i,j), (j, k))
A(j, L_0)*B(-L_0, -k)
Product of tensors
Parameters : | coeff : SymPy coefficient of the tensor args : |
---|
Notes
args[0] list of TensorHead of the component tensors.
args[1] list of (ind, ipos, icomp) where ind is a free index, ipos is the slot position of ind in the icomp-th component tensor.
args[2] list of tuples representing dummy indices. (ipos1, ipos2, icomp1, icomp2) indicates that the contravariant dummy index is the ipos1-th slot position in the icomp1-th component tensor; the corresponding covariant index is in the ipos2 slot position in the icomp2-th component tensor.
Attributes
_components | list of TensorHead of the component tensors | |
types | list of nonrepeated TensorIndexType | |
free | list of (ind, ipos, icomp), see Notes | |
dum | list of (ipos1, ipos2, icomp1, icomp2), see Notes | |
ext_rank | rank of the tensor counting the dummy indices | |
rank | rank of the tensor | |
coeff | SymPy coefficient of the tensor | |
free_args | list of the free indices in sorted order | |
is_canon_bp | True if the tensor in in canonical form |
Returns (g, dummies, msym, v), the entries of canonicalize
see canonicalize in tensor_can.py
canonicalize using the Butler-Portugal algorithm for canonicalization under monoterm symmetries.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> A = tensorhead('A', [Lorentz]*2, [[2]])
>>> t = A(m0,-m1)*A(m1,-m0)
>>> t.canon_bp()
-A(L_0, L_1)*A(-L_0, -L_1)
>>> t = A(m0,-m1)*A(m1,-m2)*A(m2,-m0)
>>> t.canon_bp()
0
Raise or lower indices with the metric g
g metric
contract_all if True, eliminate all g which are contracted
Notes
see the TensorIndexType docstring for the contraction conventions
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensorhead('p,q', [Lorentz], [[1]])
>>> t = p(m0)*q(m1)*g(-m0, -m1)
>>> t.canon_bp()
metric(L_0, L_1)*p(-L_0)*q(-L_1)
>>> t.contract_metric(g).canon_bp()
p(L_0)*q(-L_0)
Convert indices into free, dum for single component tensor
dum list of tuples (pos_contr, pos_cov, 0, 0)
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensMul
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> TensMul.from_indices(m0, m1, -m1, m3)
([(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])
Return a tensor with free indices substituted according to index_tuples
index_types list of tuples (old_index, new_index)
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> t = A(i, k)*B(-k, -j); t
A(i, L_0)*B(-L_0, -j)
>>> t.fun_eval((i, k),(-j, l))
A(k, L_0)*B(-L_0, l)
Returns the list of indices of the tensor
The indices are listed in the order in which they appear in the component tensors. The dummy indices are given a name which does not collide with the names of the free indices.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz)
>>> g = Lorentz.metric
>>> p, q = tensorhead('p,q', [Lorentz], [[1]])
>>> t = p(m1)*g(m0,m2)
>>> t.get_indices()
[m1, m0, m2]
Returns the tensor corresponding to the permutation g
g permutation corrisponding to the tensor in the representation used in canonicalization
canon_bp if True, then g is the permutation corresponding to the canonical form of the tensor
Returns a tensor with sorted components
The sorting is done taking into account the commutation group of the component tensors.
Returns a list of tensors, whose product is self
Dummy indices contracted among different tensor components become free indices with the same name as the one used to represent the dummy indices.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> t = A(a,b)*B(-b,c)
>>> t
A(a, L_0)*B(-L_0, c)
>>> t.split()
[A(a, L_0), B(-L_0, c)]
Return a tensor with free indices substituted according to index_tuples
index_types list of tuples (old_index, new_index)
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> t = A(i, k)*B(-k, -j); t
A(i, L_0)*B(-L_0, -j)
>>> t.substitute_indices((i,j), (j, k))
A(j, L_0)*B(-L_0, -k)
replace Riemann tensor with an equivalent expression
R(m,n,p,q) -> 2/3*R(m,n,p,q) - 1/3*R(m,q,n,p) + 1/3*R(m,p,n,q)
replace each Riemann tensor with an equivalent expression satisfying the cyclic identity.
This trick is discussed in the reference guide to Cadabra.
Examples
>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead, riemann_cyclic
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz)
>>> R = tensorhead('R', [Lorentz]*4, [[2, 2]])
>>> t = R(i,j,k,l)*(R(-i,-j,-k,-l) - 2*R(-i,-k,-j,-l))
>>> riemann_cyclic(t)
0