Symmetries of tensors

Specifying symmetries of tensors

One of the distinctive features of tensors is the presence of symmetries. Consider symmetries under permutations of indices. Permutational symmetries in Redberry can be defined for indices of SimpleTensor and TensorField.

Let's for example define symmetries of Riemann tensor. All symmetries of Riemann tensor are: \[ R_{abcd} = R_{cdab} = - R_{bacd} = -R_{abdc} = -R_{dcab} = -R_{cdba} = R_{dcba} = R_{badc} \] Only first two symmetries can be used as generators of the corresponding PermutationGroup. The first one can be written as (2,3,0,1) in one-line notation or as (0,2)(1,3) in cycle notation. Redberry allows to input symmetries both in one-line and cycle notation. So, symmetries of e.g. Riemann tensor in Redberry can be set up in the following way:

//add first symmetry in cycle notation
addSymmetry 'R_abcd',  [[0, 2], [1, 3]].p 
//add second (anti)symmetry in one-line notation
addSymmetry 'R_abcd', -[1, 0, 2, 3].p 
Method addSymmetry have two arguments: a simple tensor (or its string representation) and a Permutation. Redberry has internal representation of permutations and permutation groups. In order to convert array to permutation one can use .p property followed after the array written in one-line or disjoint cycles notation. Minus (used in the last line) converts symmetry to antisymmetry and vice versa.

Once set, symmetries of tensor affect all further manipulations with it. For example, if Riemann symmetries are set up, then the following code automatically gives zero:

println 'R^abcd*R_efdc*R^ef_ab + R_rc^df*R_ab^rc*R_fd^ba'.t
   > 0
Here zero was returned right after parsing; this is because Redberry automatically reduced sum to the standard form and \[ R^{abcd} R_{efdc} R^{ef}{}_{ab} = -R_{rc}{}^{df} R_{ab}{}^{rc} R_{fd}{}^{ba} \] according to the specified symmetries. Such architecture requires user to set all symmetries of SimpleTensor before it will be parsed inside any complicated structure like Sum or Product. If one try to add symmetry to tensor which is already in use in some complicated expression, then the exception will be thrown.

In case of tensors with multiple types of indices it becomes useful to specify symmetry just for indices of particular type:

addSymmetry 'f_{a b \\mu \\nu}'.t, GreekLower, -[1, 0].p
println 'f_{m n \\alpha \\beta} + f_{m n \\beta \\alpha}'.t
   > 0

Internal handling of permutation groups

Internally, Redberry aggregates symmetries of SimpleTensor in a special container which can be accessed using .symmetries property of tensor indices. When all generators are specified, Redberry uses internal representation of PermutationGroup to hold and manipulate symmetries. The following lines highlights some features of permutation groups of tensor indices:

//set up symmetries of Riemann tensor
addSymmetry 'R_abcd',  [[0, 2], [1, 3]].p
addSymmetry 'R_abcd', -[1, 0, 2, 3].p

def t = 'R_abcd'.t 
//container of generators
def symmetries = t.indices.symmetries
//permutation group of Riemann tensor
def group = symmetries.permutationGroup
//total number of all permutations
println group.order()
   > 8
//compute setwise stabilizer of set [2, 3]
println  g.setwiseStabilizer(2, 3) 
   > Group( -[[0, 1]], -[[2, 3]] )
//define some other permutation group
def oth = Group(-[[0, 2, 1, 3]], -[[0, 1]], [[2, 3, 4, 5, 6]])
//compute intersections of groups
println g.intersection(oth) 
   > Group( -[[2, 3]], +[[0, 2], [1, 3]] )

One should be careful when attaching antisymmetries. Consider the following code:

def t = 'R_abcd'.t
addSymmetries t, [2, 3, 0, 1].p, -[1, 0, 2, 3].p, -[3, 2, 1, 0].p
def gr =  t.indices.symmetries.permutationGroup
println gr.order()
   > InconsistentGeneratorsException
Exception is thrown on the last line since the last attached Permutation is a combination of two previous, but its sign is different (i.e. it is antisymmetry, while to previous are symmetries). Thus, some combinations of symmetries and antisymmetries can come into conflict, which causes an exception.

Finding symmetries of complicated tensors

Redberry provides tools to find permutational symmetries of complicated tensors. Consider the following example:

addSymmetry 'R_abc', -[1, 0, 2].p
addSymmetry 'A_ab', [1, 0].p
def t = '(R_abc*A_de + R_bde*A_ac)*A^ce + R_adb'.t
def symmetries = findIndicesSymmetries('_abd'.si, t)
for (s in symmetries)
    println s
   > +[[]]
   > -[[0, 2]]
The first Permutation is identity, while the second is nontrivial. Method used in the fourth line takes SimpleIndices as the first argument in order to define the relative order of indices in tensor ('…'.si construction is used to parse SimpleIndices).

Multi-term symmetries

The so-called multi-terms symmetries (like Bianchi identities) are faintly covered or absent at all in the majority of existing systems. In fact, we know only one system — Cadabra which fully supports multi-term symmetries. The basic idea utilized by Cadabra system is usage of Young tableau projectors to reduce expressions to the simplified form. Consider the following identity (this example is taken from Section 2.2 of the Cadabra: reference guide and tutorial by Kasper Peeters, which is available on Cadabra web site): \begin{multline} W_{u}{}^{vs}{}_{w} W_{tv}{}^{qw} W_{p}{}^{t}{}_{r}{}^{u} W^{p}{}_{q}{}^{r}{}_{s} - W^{sv}{}_{u}{}^{w} W_{rvtw} W_{p}{}^{qtu} W^{p}{}_{q}{}^{r}{}_{s} = \\ = W_{s}{}^{pd}{}_{a} W^{ms}{}_{cd} W^{n}{}_{pb}{}^{c} W_{mn}{}^{ab} - \frac{1}{4} W^{n}{}_{s}{}^{d}{}_{c} W^{m}{}_{p}{}^{c}{}_{d} W^{ps}{}_{ba} W_{mn}{}^{ab} \end{multline} where $W_{abcd}$ is a Weyl tensor. In order to proof this identity using a Young projector, one need to apply the following substitution to the above expression: \begin{equation} \label{eq:WeylYoung} W_{abcd} = \frac{1}{3} \, (2\,W_{abcd}-W_{adbc}+W_{acbd}) \end{equation} This identity is derived from the Ricci cyclic identity and ordinary permutational symmetries of the Weyl tensor. The following Redberry code proofs the identity:

addSymmetries 'W_abcd', [[0, 2], [1, 3]].p, -[1, 0, 2, 3].p
def t = ('W^p_q^r_s*W_p^t_r^u*W_tv^qw*W_u^vs_w'
        + ' - W^p_q^r_s*W_p^qtu*W_rvtw*W^sv_u^w'
        + ' - W_mn^ab*W^n_pb^c*W^ms_cd*W_s^pd_a'
        + ' + 1/4*W_mn^ab*W^ps_ba*W^m_p^c_d*W^n_s^d_c').t
def s = 'W_mnpq = 1/3*(2*W_mnpq - W_mqnp + W_mpnq)'.t
def r = (s & Expand) >> t
println r
   > 0
At the moment Redberry has no built-in functionality to construct such substitutions based on the Young projectors. But, as could be seen from the above example, if one define the corresponding substitution manually, then Redberry allows to work with multi-term symmetries in the Cadabra way. The support of Young projectors is planned in the upcoming releases of Redberry.

See also