Tensor¶
- 
class sympy.tensor.tensor.TensorIndexType(name, metric=False, dim=None, eps_dim=None, dummy_fmt=None)[source]¶
- 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 - metricparameter can be:- metric = Falsesymmetric metric (in Riemannian geometry)- metric = Trueantisymmetric metric (for spinor calculus)- metric = Nonethere is no metric- metriccan be an object having- nameand- antisymattributes.- 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- TensorIndexfor 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 > 2they are linearly independent.- eps_dimis by default equal to- dim, if the latter is an integer; else it can be assigned (for use in naive dimensional regularization); if- eps_dimis not an integer- epsilonis- 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 epsilontensor)- dim- eps_dim- dummy_fmt- data- ((deprecated) a property to add - ndarrayvalues, to work in a specified basis.)
- 
class sympy.tensor.tensor.TensorIndex(name, tensortype, is_up=True)[source]¶
- Represents a tensor index - Parameters
- name : name of the index, or - Trueif you want it to be automatically assigned- tensortype : - TensorIndexTypeof the index- is_up : flag for contravariant index (is_up=True by default) 
 - 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. Adding- -to a covariant (is_up=False) index makes it contravariant.- Dummy indices have a name with head given by - tensortype._dummy_fmt- Similar to - symbolsmultiple contravariant indices can be created at once using- tensor_indices(s, typ), where- sis a string of names.- Examples - >>> from sympy.tensor.tensor import TensorIndexType, TensorIndex, TensorHead, tensor_indices >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> mu = TensorIndex('mu', Lorentz, is_up=False) >>> nu, rho = tensor_indices('nu, rho', Lorentz) >>> A = TensorHead('A', [Lorentz, Lorentz]) >>> A(mu, nu) A(-mu, nu) >>> A(-mu, -rho) A(mu, -rho) >>> A(mu, -mu) A(-L_0, L_0) - Attributes - name- tensortype- is_up
- 
class sympy.tensor.tensor.TensorHead(name, index_types, symmetry=None, comm=0)[source]¶
- Tensor head of the tensor - Parameters
- name : name of the tensor - index_types : list of TensorIndexType - symmetry : TensorSymmetry of the tensor - comm : commutation group number 
 - Notes - Similar to - symbolsmultiple TensorHeads can be created using- tensorhead(s, typ, sym=None, comm=0)function, where- sis the string of names and- symis the monoterm tensor symmetry (see- tensorsymmetry).- A - TensorHeadbelongs 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- commis- 0, the group of the commuting tensors.- Examples - Define a fully antisymmetric tensor of rank 2: - >>> from sympy.tensor.tensor import TensorIndexType, TensorHead, TensorSymmetry >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> asym2 = TensorSymmetry.fully_symmetric(-2) >>> A = TensorHead('A', [Lorentz, Lorentz], asym2) - Examples with ndarray values, the components data assigned to the - TensorHeadobject are assumed to be in a fully-contravariant representation. In case it is necessary to assign components data which represents the values of a non-fully covariant tensor, see the other examples.- >>> from sympy.tensor.tensor import tensor_indices >>> from sympy import diag >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> i0, i1 = tensor_indices('i0:2', Lorentz) - Specify a replacement dictionary to keep track of the arrays to use for replacements in the tensorial expression. The - TensorIndexTypeis associated to the metric used for contractions (in fully covariant form):- >>> repl = {Lorentz: diag(1, -1, -1, -1)} - Let’s see some examples of working with components with the electromagnetic tensor: - >>> from sympy import symbols >>> Ex, Ey, Ez, Bx, By, Bz = symbols('E_x E_y E_z B_x B_y B_z') >>> c = symbols('c', positive=True) - Let’s define \(F\), an antisymmetric tensor: - >>> F = TensorHead('F', [Lorentz, Lorentz], asym2) - Let’s update the dictionary to contain the matrix to use in the replacements: - >>> repl.update({F(-i0, -i1): [ ... [0, Ex/c, Ey/c, Ez/c], ... [-Ex/c, 0, -Bz, By], ... [-Ey/c, Bz, 0, -Bx], ... [-Ez/c, -By, Bx, 0]]}) - Now it is possible to retrieve the contravariant form of the Electromagnetic tensor: - >>> F(i0, i1).replace_with_arrays(repl, [i0, i1]) [[0, -E_x/c, -E_y/c, -E_z/c], [E_x/c, 0, -B_z, B_y], [E_y/c, B_z, 0, -B_x], [E_z/c, -B_y, B_x, 0]] - and the mixed contravariant-covariant form: - >>> F(i0, -i1).replace_with_arrays(repl, [i0, -i1]) [[0, E_x/c, E_y/c, E_z/c], [E_x/c, 0, B_z, -B_y], [E_y/c, -B_z, 0, B_x], [E_z/c, B_y, -B_x, 0]] - Energy-momentum of a particle may be represented as: - >>> from sympy import symbols >>> P = TensorHead('P', [Lorentz], TensorSymmetry.no_symmetry(1)) >>> E, px, py, pz = symbols('E p_x p_y p_z', positive=True) >>> repl.update({P(i0): [E, px, py, pz]}) - The contravariant and covariant components are, respectively: - >>> P(i0).replace_with_arrays(repl, [i0]) [E, p_x, p_y, p_z] >>> P(-i0).replace_with_arrays(repl, [-i0]) [E, -p_x, -p_y, -p_z] - The contraction of a 1-index tensor by itself: - >>> expr = P(i0)*P(-i0) >>> expr.replace_with_arrays(repl, []) E**2 - p_x**2 - p_y**2 - p_z**2 - Attributes - name- index_types- rank- (total number of indices) - symmetry- comm- (commutation group) 
- 
class sympy.tensor.tensor.TensExpr(*args)[source]¶
- Abstract base class for tensor expressions - Notes - A tensor expression is an expression formed by tensors; currently the sums of tensors are distributed. - A - TensExprcan be a- TensAddor a- TensMul.- TensMulobjects 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- icomp1is the position of the component tensor with contravariant index,- ipos1is the slot which the index occupies in that component tensor.- Contracted indices are therefore nameless in the internal representation. - 
get_matrix()[source]¶
- DEPRECATED: do not use. - Returns ndarray components data as a matrix, if components data are available and ndarray dimension does not exceed 2. 
 - 
replace_with_arrays(replacement_dict, indices=None)[source]¶
- Replace the tensorial expressions with arrays. The final array will correspond to the N-dimensional array with indices arranged according to - indices.- Parameters
- replacement_dict - dictionary containing the replacement rules for tensors. - indices - the index order with respect to which the array is read. The original index order will be used if no value is passed. 
 - Examples - >>> from sympy.tensor.tensor import TensorIndexType, tensor_indices >>> from sympy.tensor.tensor import TensorHead >>> from sympy import symbols, diag - >>> L = TensorIndexType("L") >>> i, j = tensor_indices("i j", L) >>> A = TensorHead("A", [L]) >>> A(i).replace_with_arrays({A(i): [1, 2]}, [i]) [1, 2] - Since ‘indices’ is optional, we can also call replace_with_arrays by this way if no specific index order is needed: - >>> A(i).replace_with_arrays({A(i): [1, 2]}) [1, 2] - >>> expr = A(i)*A(j) >>> expr.replace_with_arrays({A(i): [1, 2]}) [[1, 2], [2, 4]] - For contractions, specify the metric of the - TensorIndexType, which in this case is- L, in its covariant form:- >>> expr = A(i)*A(-i) >>> expr.replace_with_arrays({A(i): [1, 2], L: diag(1, -1)}) -3 - Symmetrization of an array: - >>> H = TensorHead("H", [L, L]) >>> a, b, c, d = symbols("a b c d") >>> expr = H(i, j)/2 + H(j, i)/2 >>> expr.replace_with_arrays({H(i, j): [[a, b], [c, d]]}) [[a, b/2 + c/2], [b/2 + c/2, d]] - Anti-symmetrization of an array: - >>> expr = H(i, j)/2 - H(j, i)/2 >>> repl = {H(i, j): [[a, b], [c, d]]} >>> expr.replace_with_arrays(repl) [[0, b/2 - c/2], [-b/2 + c/2, 0]] - The same expression can be read as the transpose by inverting - iand- j:- >>> expr.replace_with_arrays(repl, [j, i]) [[0, -b/2 + c/2], [b/2 - c/2, 0]] 
 
- 
- 
class sympy.tensor.tensor.TensAdd(*args, **kw_args)[source]¶
- Sum of tensors - Parameters
- free_args : list of the free indices 
 - Examples - >>> from sympy.tensor.tensor import TensorIndexType, tensor_heads, tensor_indices >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> a, b = tensor_indices('a,b', Lorentz) >>> p, q = tensor_heads('p,q', [Lorentz]) >>> t = p(a) + q(a); t p(a) + q(a) - Examples with components data added to the tensor expression: - >>> from sympy import symbols, diag >>> x, y, z, t = symbols("x y z t") >>> repl = {} >>> repl[Lorentz] = diag(1, -1, -1, -1) >>> repl[p(a)] = [1, 2, 3, 4] >>> repl[q(a)] = [x, y, z, t] - The following are: 2**2 - 3**2 - 2**2 - 7**2 ==> -58 - >>> expr = p(a) + q(a) >>> expr.replace_with_arrays(repl, [a]) [x + 1, y + 2, z + 3, t + 4] - Attributes - args- (tuple of addends) - rank- (rank of the tensor) - free_args- (list of the free indices in sorted order) 
- 
class sympy.tensor.tensor.TensMul(*args, **kw_args)[source]¶
- Product of tensors - Parameters
- coeff : SymPy coefficient of the tensor - args 
 - Notes - args[0]list of- TensorHeadof the component tensors.- args[1]list of- (ind, ipos, icomp)where- indis a free index,- iposis the slot position of- indin 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- ipos2slot position in the- icomp2-th component tensor.- Attributes - components- (list of - TensorHeadof 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- ( - Trueif the tensor in in canonical form)- 
canon_bp()[source]¶
- Canonicalize using the Butler-Portugal algorithm for canonicalization under monoterm symmetries. - Examples - >>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, TensorSymmetry >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz) >>> A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(-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 
 - 
contract_metric(g)[source]¶
- Raise or lower indices with the metric - g- Parameters
- g : metric 
 - Notes - see the - TensorIndexTypedocstring for the contraction conventions- Examples - >>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz) >>> g = Lorentz.metric >>> p, q = tensor_heads('p,q', [Lorentz]) >>> 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) 
 - 
get_free_indices()[source]¶
- Returns the list of free indices of the tensor - The indices are listed in the order in which they appear in the component tensors. - Examples - >>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz) >>> g = Lorentz.metric >>> p, q = tensor_heads('p,q', [Lorentz]) >>> t = p(m1)*g(m0,m2) >>> t.get_free_indices() [m1, m0, m2] >>> t2 = p(m1)*g(-m1, m2) >>> t2.get_free_indices() [m2] 
 - 
get_indices()[source]¶
- 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, tensor_heads >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> m0, m1, m2 = tensor_indices('m0,m1,m2', Lorentz) >>> g = Lorentz.metric >>> p, q = tensor_heads('p,q', [Lorentz]) >>> t = p(m1)*g(m0,m2) >>> t.get_indices() [m1, m0, m2] >>> t2 = p(m1)*g(-m1, m2) >>> t2.get_indices() [L_0, -L_0, m2] 
 - 
perm2tensor(g, is_canon_bp=False)[source]¶
- Returns the tensor corresponding to the permutation - g- For further details, see the method in - TIDSwith the same name.
 - 
split()[source]¶
- 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, tensor_heads, TensorSymmetry >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> a, b, c, d = tensor_indices('a,b,c,d', Lorentz) >>> A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(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)] 
 
- 
sympy.tensor.tensor.canon_bp(p)[source]¶
- Butler-Portugal canonicalization. See - tensor_can.pyfrom the combinatorics module for the details.
- 
sympy.tensor.tensor.riemann_cyclic_replace(t_r)[source]¶
- 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)
- 
sympy.tensor.tensor.riemann_cyclic(t2)[source]¶
- 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, TensorSymmetry >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> i, j, k, l = tensor_indices('i,j,k,l', Lorentz) >>> R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann()) >>> t = R(i,j,k,l)*(R(-i,-j,-k,-l) - 2*R(-i,-k,-j,-l)) >>> riemann_cyclic(t) 0 
- 
class sympy.tensor.tensor.TensorSymmetry(*args, **kw_args)[source]¶
- Monoterm symmetry of a tensor (i.e. any symmetric or anti-symmetric index permutation). For the relevant terminology see - tensor_can.pysection of the combinatorics module.- 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 (i.e., Bianchi identity), are not covered. See combinatorics module for information on how to generate BSGS for a general index permutation group. Simple symmetries can be generated using built-in methods. - Examples - Define a symmetric tensor of rank 2 - >>> from sympy.tensor.tensor import TensorIndexType, TensorSymmetry, get_symmetric_group_sgs, TensorHead >>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L') >>> sym = TensorSymmetry(get_symmetric_group_sgs(2)) >>> T = TensorHead('T', [Lorentz]*2, sym) - Note, that the same can also be done using built-in TensorSymmetry methods - >>> sym2 = TensorSymmetry.fully_symmetric(2) >>> sym == sym2 True - Attributes - base- (base of the BSGS) - generators- (generators of the BSGS) - rank- (rank of the tensor) - 
classmethod direct_product(*args)[source]¶
- Returns a TensorSymmetry object that is being a direct product of fully (anti-)symmetric index permutation groups. - Notes - Some examples for different values of - (*args):- (1)vector, equivalent to- TensorSymmetry.fully_symmetric(1)- (2)tensor with 2 symmetric indices, equivalent to- .fully_symmetric(2)- (-2)tensor with 2 antisymmetric indices, equivalent to- .fully_symmetric(-2)- (2, -2)tensor with the first 2 indices commuting and the last 2 anticommuting- (1, 1, 1)tensor with 3 indices without any symmetry
 
- 
sympy.tensor.tensor.tensorsymmetry(*args)[source]¶
- Returns a - TensorSymmetryobject. This method is deprecated, use- TensorSymmetry.direct_product()or- .riemann()instead.- One can represent a tensor with any monoterm slot symmetry group using a BSGS. - argscan be a BSGS- args[0]base- args[1]sgs- Usually tensors are in (direct products of) representations of the symmetric group; - argscan be a list of lists representing the shapes of Young tableaux- Notes - For instance: - [[1]]vector- [[1]*n]symmetric tensor of rank- n- [[n]]antisymmetric tensor of rank- n- [[2, 2]]monoterm slot symmetry of the Riemann tensor- [[1],[1]]vector*vector- [[2],[1],[1](antisymmetric tensor)*vector*vector- Notice that with the shape - [2, 2]we associate only the monoterm symmetries of the Riemann tensor; this is an abuse of notation, since the shape- [2, 2]corresponds usually to the irreducible representation characterized by the monoterm symmetries and by the cyclic symmetry.
- 
class sympy.tensor.tensor.TensorType(index_types, symmetry, **kw_args)[source]¶
- Class of tensor types. Deprecated, use tensor_heads() instead. - Parameters
- index_types : list of - TensorIndexTypeof the tensor indices- symmetry : - TensorSymmetryof the tensor
 - Attributes - index_types- symmetry- types- (list of - TensorIndexTypewithout repetitions)
- 
class sympy.tensor.tensor._TensorManager[source]¶
- Class to manage tensor properties. - Notes - Tensors belong to tensor commutation groups; each group has a label - comm; there are predefined labels:- 0tensors commuting with any other tensor- 1tensors anticommuting among themselves- 2tensors 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.- 
comm_symbols2i(i)[source]¶
- get the commutation group number corresponding to - i- ican be a symbol or a number or a string- If - iis not already defined its commutation group number is set.
 - 
get_comm(i, j)[source]¶
- Return the commutation parameter for commutation group numbers - i, j- see - _TensorManager.set_comm
 - 
set_comm(i, j, c)[source]¶
- set the commutation parameter - cfor commutation groups- i, j- Parameters
- i, j : symbols representing commutation groups - c : group commutation number 
 - Notes - i, jcan be symbols, strings or numbers, apart from- 0, 1and- 2which 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 - cis assigned in correspondence to the group commutation symbols; it can be- 0 commuting - 1 anticommuting - None no commutation property - Examples - Gand- GHdo not commute with themselves and commute with each other; A is commuting.- >>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, TensorManager, TensorSymmetry >>> Lorentz = TensorIndexType('Lorentz') >>> i0,i1,i2,i3,i4 = tensor_indices('i0:5', Lorentz) >>> A = TensorHead('A', [Lorentz]) >>> G = TensorHead('G', [Lorentz], TensorSymmetry.no_symmetry(1), 'Gcomm') >>> GH = TensorHead('GH', [Lorentz], TensorSymmetry.no_symmetry(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) 
 
- 
