# Tensor¶

class sympy.tensor.tensor.TIDS(components, free, dum)[source]

Tensor internal data structure. This contains internal data about components of a tensor expression, its free and dummy indices.

To create a $$TIDS$$ object via the standard constructor, the required arguments are

components $$TensorHead$$ objects representing the components
of the tensor expression.

free Free indices in their internal representation.

dum Dummy indices in their internal representation.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TIDS, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> T = tensorhead('T', [Lorentz]*4, [[1]*4])
>>> TIDS([T], [(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])
TIDS([T(Lorentz,Lorentz,Lorentz,Lorentz)], [(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])


Details

In short, this has created the components, free and dummy indices for the internal representation of a tensor T(m0, m1, -m1, m3).

Free indices are represented as a list of triplets. The elements of each triplet identify a single free index and are

1. TensorIndex object
2. position inside the component
3. component number

Dummy indices are represented as a list of 4-plets. Each 4-plet stands for couple for contracted indices, their original TensorIndex is not stored as it is no longer required. The four elements of the 4-plet are

1. position inside the component of the first index.
2. position inside the component of the second index.
3. component number of the first index.
4. component number of the second index.
canon_args()[source]

Returns (g, dummies, msym, v), the entries of canonicalize

see canonicalize in tensor_can.py

static free_dum_from_indices(*indices)[source]

Convert indices into free, dum for single component tensor

free list of tuples (index, pos, 0),
where pos is the position of index in the list of indices formed by the component tensors

dum list of tuples (pos_contr, pos_cov, 0, 0)

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TIDS
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> TIDS.free_dum_from_indices(m0, m1, -m1, m3)
([(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])

static from_components_and_indices(components, indices)[source]

Create a new $$TIDS$$ object from $$components$$ and $$indices$$

components $$TensorHead$$ objects representing the components
of the tensor expression.
indices $$TensorIndex$$ objects, the indices. Contractions are
detected upon construction.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TIDS, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> T = tensorhead('T', [Lorentz]*4, [[1]*4])
>>> TIDS.from_components_and_indices([T], [m0, m1, -m1, m3])
TIDS([T(Lorentz,Lorentz,Lorentz,Lorentz)], [(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)])


In case of many components the same indices have slightly different indexes:

>>> A = tensorhead('A', [Lorentz], [[1]])
>>> TIDS.from_components_and_indices([A]*4, [m0, m1, -m1, m3])
TIDS([A(Lorentz), A(Lorentz), A(Lorentz), A(Lorentz)], [(m0, 0, 0), (m3, 0, 3)], [(0, 0, 1, 2)])

get_components_with_free_indices()[source]

Get a list of components with their associated indices.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TIDS, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> T = tensorhead('T', [Lorentz]*4, [[1]*4])
>>> A = tensorhead('A', [Lorentz], [[1]])
>>> t = TIDS.from_components_and_indices([T], [m0, m1, -m1, m3])
>>> t.get_components_with_free_indices()
[(T(Lorentz,Lorentz,Lorentz,Lorentz), [(m0, 0, 0), (m3, 3, 0)])]
>>> t2 = (A(m0)*A(-m0))._tids
>>> t2.get_components_with_free_indices()
[(A(Lorentz), []), (A(Lorentz), [])]
>>> t3 = (A(m0)*A(-m1)*A(-m0)*A(m1))._tids
>>> t3.get_components_with_free_indices()
[(A(Lorentz), []), (A(Lorentz), []), (A(Lorentz), []), (A(Lorentz), [])]
>>> t4 = (A(m0)*A(m1)*A(-m0))._tids
>>> t4.get_components_with_free_indices()
[(A(Lorentz), []), (A(Lorentz), [(m1, 0, 1)]), (A(Lorentz), [])]
>>> t5 = (A(m0)*A(m1)*A(m2))._tids
>>> t5.get_components_with_free_indices()
[(A(Lorentz), [(m0, 0, 0)]), (A(Lorentz), [(m1, 0, 1)]), (A(Lorentz), [(m2, 0, 2)])]

static mul(f, g)[source]

The algorithms performing the multiplication of two TIDS instances.

In short, it forms a new TIDS object, joining components and indices, checking that abstract indices are compatible, and possibly contracting them.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, TIDS, tensorhead
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> T = tensorhead('T', [Lorentz]*4, [[1]*4])
>>> A = tensorhead('A', [Lorentz], [[1]])
>>> tids_1 = TIDS.from_components_and_indices([T], [m0, m1, -m1, m3])
>>> tids_2 = TIDS.from_components_and_indices([A], [m2])
>>> tids_1 * tids_2
TIDS([T(Lorentz,Lorentz,Lorentz,Lorentz), A(Lorentz)],            [(m0, 0, 0), (m3, 3, 0), (m2, 0, 1)], [(1, 2, 0, 0)])


In this case no contraction has been performed.

>>> tids_3 = TIDS.from_components_and_indices([A], [-m3])
>>> tids_1 * tids_3
TIDS([T(Lorentz,Lorentz,Lorentz,Lorentz), A(Lorentz)],            [(m0, 0, 0)], [(1, 2, 0, 0), (3, 0, 0, 1)])


Free indices m3 and -m3 are identified as a contracted couple, and are therefore transformed into dummy indices.

A wrong index construction (for example, trying to contract two contravariant indices or using indices multiple times) would result in an exception:

>>> tids_4 = TIDS.from_components_and_indices([A], [m3])
>>> # This raises an exception:
>>> # tids_1 * tids_4

perm2tensor(g, canon_bp=False)[source]

Returns a $$TIDS$$ instance corresponding to the permutation g

g permutation corresponding 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

sorted_components()[source]

Returns a TIDS with sorted components

The sorting is done taking into account the commutation group of the component tensors.

to_indices()[source]

Get a list of indices, creating new tensor indices to complete dummy indices.

class sympy.tensor.tensor.VTIDS(components, free, dum, data)[source]

This class handles a VTIDS object, which is a TIDS object with an attached numpy ndarray.

To create a $$TIDS$$ object via the standard constructor, the required arguments are

components $$TensorHead$$ objects representing the components
of the tensor expression.

free Free indices in their internal representation.

dum Dummy indices in their internal representation.

data Data as a numpy ndarray.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, VTIDS, tensorhead
>>> import numpy
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> m0, m1, m2, m3 = tensor_indices('m0,m1,m2,m3', Lorentz)
>>> T = tensorhead('T', [Lorentz]*4, [[1]*4])
>>> data = numpy.array([2,9,6,-5]).reshape(2, 2)
>>> VTIDS([T], [(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)], data)
VTIDS([T(Lorentz,Lorentz,Lorentz,Lorentz)], [(m0, 0, 0), (m3, 3, 0)], [(1, 2, 0, 0)], [[ 2  9]
[ 6 -5]])

correct_signature_from_indices(data, indices, free, dum)[source]

Utility function to correct the values inside the data ndarray according to whether indices are covariant or contravariant.

It uses the metric matrix to lower values of covariant indices.

static mul(f, g)[source]

Multiplies two VTIDS objects, it first calls its super method on TIDS, then creates a new VTIDS object, adding ndarray data according to the metric contractions of indices.

static parse_data(data)[source]

Transform data to a numpy ndarray.

Examples

>>> from sympy.tensor.tensor import VTIDS
>>> VTIDS.parse_data([1, 3, -6, 12])
[1 3 -6 12]

>>> VTIDS.parse_data([[1, 2], [4, 7]])
[[1 2]
[4 7]]

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:

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.

clear()[source]

Clear the TensorManager.

comm_i2symbol(i)[source]

Returns the symbol corresponding to the commutation group number.

comm_symbols2i(i)[source]

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.

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 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 correspondence 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)

set_comms(*args)[source]

set the commutation group numbers c for symbols i, j

Parameters : args : sequence of (i, j, c)
class sympy.tensor.tensor.TensorIndexType[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 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)


Examples with metric data added, this means it is working on a fixed basis:

>>> Lorentz.data = [1, -1, -1, -1]
>>> Lorentz
TensorIndexType(Lorentz, 0)
>>> Lorentz.data
[[1 0 0 0]
[0 -1 0 0]
[0 0 -1 0]
[0 0 0 -1]]


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 data a property to add ndarray values, to work in a specified basis.
class sympy.tensor.tensor.TensorIndex[source]

Represents an abstract tensor index.

Parameters : name : name of the index, or True if you want it to be automatically assigned 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)


If you want the index name to be automatically assigned, just put True in the name field, it will be generated using the reserved character _ in front of its name, in order to avoid conflicts with possible existing indices:

>>> i0 = TensorIndex(True, Lorentz)
>>> i0
_i0
>>> i1 = TensorIndex(True, Lorentz)
>>> i1
_i1
>>> A(i0)*B(-i1)
A(_i0)*B(-_i1)
>>> A(i0)*B(-i0)
A(L_0)*B(-L_0)


Attributes

 name tensortype is_up
sympy.tensor.tensor.tensor_indices(s, typ)[source]

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)

class sympy.tensor.tensor.TensorSymmetry[source]

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 sympy.tensor.tensor.TensorType[source]

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

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')


Examples with ndarray values:

>>> from sympy.tensor.tensor import tensor_indices, tensorhead
>>> Lorentz.data = [1, -1, -1, -1]
>>> i0, i1 = tensor_indices('i0:2', Lorentz)
>>> A.data = [[j+2*i for j in range(4)] for i in range(4)]


in order to retrieve data, it is also necessary to specify abstract indices enclosed by round brackets, then numerical indices inside square brackets.

>>> A(i0, i1)[0, 0]
0
>>> A(i0, i1)[2, 3] == 3+2*2
True


Notice that square brackets create a valued tensor expression instance:

>>> A(i0, i1)
A(i0, i1)


To view the data, just type:

>>> A.data
[[0 1 2 3]
[2 3 4 5]
[4 5 6 7]
[6 7 8 9]]


Turning to a tensor expression, covariant indices get the corresponding data corrected by the metric:

>>> A(i0, -i1).data
[[0 -1 -2 -3]
[2 -3 -4 -5]
[4 -5 -6 -7]
[6 -7 -8 -9]]

>>> A(-i0, -i1).data
[[0 -1 -2 -3]
[-2 3 4 5]
[-4 5 6 7]
[-6 7 8 9]]


while if all indices are contravariant, the ndarray remains the same

>>> A(i0, i1).data
[[0 1 2 3]
[2 3 4 5]
[4 5 6 7]
[6 7 8 9]]


When all indices are contracted and data are added to the tensor, it will return a scalar resulting from all contractions:

>>> A(i0, -i0)
-18


Attributes

 name index_types rank types equal to typ.types symmetry equal to typ.symmetry comm commutation group
commutes_with(other)[source]

Returns 0 if self and other commute, 1 if they anticommute.

Returns None if self and other neither commute nor anticommute.

strip()[source]

Return an identical TensorHead, just with ndarray data removed.

class sympy.tensor.tensor.TensExpr[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 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.

get_matrix()[source]

Returns ndarray data as a matrix, if data are available and ndarray dimension does not exceed 2.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensorsymmetry, TensorType
>>> from sympy import ones
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> sym2 = tensorsymmetry([1]*2)
>>> S2 = TensorType([Lorentz]*2, sym2)
>>> A = S2('A')

>>> from sympy.tensor.tensor import tensor_indices, tensorhead
>>> Lorentz.data = [1, -1, -1, -1]
>>> i0, i1 = tensor_indices('i0:2', Lorentz)
>>> A.data = [[j+2*i for j in range(4)] for i in range(4)]
>>> A(i0, i1).get_matrix()
Matrix([
[0, 1, 2, 3],
[2, 3, 4, 5],
[4, 5, 6, 7],
[6, 7, 8, 9]])


It is possible to perform usual operation on matrices, such as the matrix multiplication:

>>> A(i0, i1).get_matrix()*ones(4, 1)
Matrix([
[ 6],
[14],
[22],
[30]])

strip()[source]

Return an identical tensor expression, just with ndarray data removed.

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)


Examples with data added to the tensor expression:

>>> from sympy import eye
>>> Lorentz.data = [1, -1, -1, -1]
>>> a, b = tensor_indices('a, b', Lorentz)
>>> p.data = [2, 3, -2, 7]
>>> q.data = [2, 3, -2, 7]
>>> t = p(a) + q(a); t
p(a) + q(a)

>>> t(b)
p(b) + q(b)


The following are: 2**2 - 3**2 - 2**2 - 7**2 ==> -58

>>> p(a)*p(-a)
-58

>>> p(a)**2
-58


Attributes

 args tuple of addends rank rank of the tensor free_args list of the free indices in sorted order
applyfunc(func)[source]

Return a new TensAdd object, whose data ndarray will be the elementwise map of the current data ndarray by function func.

canon_bp()[source]

canonicalize using the Butler-Portugal algorithm for canonicalization under monoterm symmetries.

contract_metric(g)[source]

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

static from_TIDS_list(coeff, tids_list)[source]

Given a list of coefficients and a list of $$TIDS$$ objects, construct a $$TensAdd$$ instance, equivalent to the one that would result from creating single instances of $$TensMul$$ and then adding them.

Examples

>>> from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensorhead, TensAdd
>>> Lorentz = TensorIndexType('Lorentz', dummy_fmt='L')
>>> i, j = tensor_indices('i,j', Lorentz)
>>> A, B = tensorhead('A,B', [Lorentz]*2, [[1]*2])
>>> eA = 3*A(i, j)
>>> eB = 2*B(j, i)
>>> t1 = eA._tids
>>> t2 = eB._tids
>>> c1 = eA.coeff
>>> c2 = eB.coeff
2*B(i, j) + 3*A(i, j)


If the coefficient parameter is a scalar, then it will be applied as a coefficient on all $$TIDS$$ objects.

>>> TensAdd.from_TIDS_list(4, [t1, t2])
4*A(i, j) + 4*B(i, j)

fun_eval(*index_tuples)[source]

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)

substitute_indices(*index_tuples)[source]

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)

class sympy.tensor.tensor.TensMul[source]

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
applyfunc(func)[source]

Return a new TensAdd object, whose data ndarray will be the elementwise map of the current data ndarray by function func.

canon_bp()[source]

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

contract_metric(g)[source]

Raise or lower indices with the metric g

g metric

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)

fun_eval(*index_tuples)[source]

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)

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, 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]

perm2tensor(g, canon_bp=False)[source]

Returns the tensor corresponding to the permutation g

For further details, see the method in $$TIDS$$ with the same name.

sorted_components()[source]

Returns a tensor with sorted components calling the corresponding method in a $$TIDS$$ object.

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, 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)]

substitute_indices(*index_tuples)[source]

Return a tensor with free indices substituted according to index_tuples

index_types list of tuples (old_index, new_index)

Note: this method will neither raise or lower the indices, it will just replace their symbol.

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)

sympy.tensor.tensor.canon_bp(p)[source]

Butler-Portugal canonicalization

sympy.tensor.tensor.tensor_mul(*a)[source]

product of tensors

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
>>> 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


Methods

Utilities