Tensor Symmetries

Tensors of rank 2 or higher that arise in applications usually have symmetries under exchange of their slots. For example, the inertia tensor, the stress-energy tensor, or the Ricci curvature tensor are rank-2 fully symmetric tensors; the electromagnetic tensor is a rank-2 antisymmetric tensor; and the Riemann curvature tensor and the stiffness tensor are rank-4 tensors with nontrival symmetries. The Wolfram System has a general language to describe an arbitrary symmetry under permutations of the slots of any tensor and implements efficient algorithms to give those tensors a unique canonical form under those symmetries, an essential step in symbolic tensor computations.

Invariance under Phased Permutations

The basic action on a tensor is formed by a transposition by a permutation and multiplication by a root of unity. If a tensor is invariant under such action, it can be said that the tensor has symmetry.

Symmetry generators and tensor transposition.

A symmetry generator, or phased permutation, is a list containing a permutation describing how to permute the slots of a tensor and a root of unity that will simultaneously multiply the tensor:

TensorTranspose[T,{{3,4,1,2},-1}]

This rank-4 array has symmetry because it stays invariant under the action of a phased permutation:

array={{{{0,a},{-a,b}},{{a,c},{-b,d}}},{{{-a,-b},{-c,-d}},{{b,d},{-d,0}}}};

TensorTranspose[array,{Cycles[{{1,2,3,4}}],-1}]

%===array

However, it is not invariant under this other generator:

TensorTranspose[array,{Cycles[{{1,2},{3,4}}],-1}]

%===array

Successive application of generators is equivalent to a product of generators, where phases and permutations are multiplied separately. In fact, if a tensor is invariant under two phased permutations, then it will be also invariant under their product. Hence, the set of phased permutations under which a tensor is invariant form a group, the slot symmetry group of the tensor.

If an array is invariant under a generator, then it is also invariant under its powers:

gen1={{2,3,4,1},-1}
gen2={{2,3,4,1}\[PermutationProduct]{2,3,4,1},(-1)(-1)}
gen3={PermutationPower[{2,3,4,1},3],(-1)^3}
gen4={PermutationPower[{2,3,4,1},4],(-1)^4}

TensorTranspose[array,gen1]===array

TensorTranspose[array,gen2]===array

TensorTranspose[array,gen3]===array

Symmetry Specifications

The function (RefLink[TensorSymmetry, paclet:ref/TensorSymmetry]) returns a complete description of the transposition symmetry of a tensor. It can be given as a named symmetry or as a list of some symmetry generators from which the rest can be constructed by permutation products and powers.

Computation and specification of tensor symmetries.

A symmetric matrix:

TensorSymmetry[{{a,b},{b,c}}]

An antisymmetric rank-3 array:

TensorSymmetry[{{{0,0,0},{0,0,7},{0,-7,0}},{{0,0,-7},{0,0,0},{7,0,0}},{{0,7,0},{-7,0,0},{0,0,0}}}]

The absence of symmetry, or identity symmetry, is represented by an empty list of generators:

TensorSymmetry[{{a,b},{c,d}}]

Representation of the symmetry of a zero tensor:

TensorSymmetry[{{0,0},{0,0}}]

In the general case, (RefLink[TensorSymmetry, paclet:ref/TensorSymmetry]) returns the symmetry of a tensor as a list of generators. Permutations are given in cyclic form:

array={{{{0,a},{-a,b}},{{a,c},{-b,d}}},{{{-a,-b},{-c,-d}},{{b,d},{-d,0}}}};

TensorSymmetry[array]

TensorSymmetry[{{0,a},{-a,0}}⊗{{0,b},{-b,0}}]

Symmetrization of Arrays

It is possible to increase the symmetry of an array by symmetrizing it, using the function (RefLink[Symmetrize, paclet:ref/Symmetrize]). The result is given as a structured array of type (RefLink[SymmetrizedArray, paclet:ref/SymmetrizedArray]). For more information on this type of structure see "Symmetrized Arrays".

Tensor symmetrization and symmetrized arrays.

Take a general array with no symmetry:

Array[(Subscript[a, ##])&,{3,3,3}]

Project into its antisymmetric part, with the result given as a structured array of type (RefLink[SymmetrizedArray, paclet:ref/SymmetrizedArray]), which stores only independent components:

proj=Symmetrize[%,Antisymmetric[{1,2,3}]]

It only contains one independent component:

SymmetrizedArrayRules[proj]

That component is repeated multiple times in the normal form of the array:

Normal[proj]

It is a projection because further antisymmetrization does not change the array:

Symmetrize[proj,Antisymmetric[{1,2,3}]]===proj

Symmetrization in any pair of levels now yields the zero array, with maximal symmetry:

Symmetrize[proj,Symmetric[{1,2}]]//Normal//Simplify

Independent and Dependent Components

When a tensor or array has symmetry, then there is less freedom to specify its components. The symmetries actually specify relations among the components, and only some of them are independent.

Independent and dependent components.

Take an array with symmetry:

array={{{{0,a},{-a,b}},{{a,c},{-b,d}}},{{{-a,-b},{-c,-d}},{{b,d},{-d,0}}}};

dims=Dimensions[array]

sym=TensorSymmetry[array]

The array has only four entries freely specifiable, and you can show that this is actually the maximum number compatible with its dimensions and symmetry:

indeps=SymmetrizedIndependentComponents[dims,sym]

Extract[array,indeps]

There are six independent components for an array of dimensions {3,3,3,3} with the transposition symmetries of a Riemann tensor:

Rsym={{{2,1,3,4},-1},{{3,4,1,2},1}};

SymmetrizedIndependentComponents[{3,3,3,3},Rsym]

Asymptotically, it grows as (d^rank)/S, where S is the order of the symmetry group, 8 for the Riemann symmetry:

Length[SymmetrizedIndependentComponents[{#,#,#,#},Rsym]]&/@Range[20]

%===Table[((d^4)-2(d^3)+3(d^2)-2d)/8,{d,20}]

The dependent components associated to a given independent component can be obtained using orbit computations under the associated permutation group of the symmetry.

Take a generic symmetrized array of rank 3 in dimension 3:

SeedRandom[0];
array=Normal@Symmetrize[RandomInteger[{-10,10},{3,3,3}],Symmetric[{1,2,3}]]

These are the 10 independent components, given as positions:

indeps=SymmetrizedIndependentComponents[{3,3,3},Symmetric[{1,2,3}]]

And these are their respective orbits of dependent components:

(orbits=SymmetrizedDependentComponents[#,Symmetric[{1,2,3}]]&/@indeps)//Column

You can check that indeed all components in each orbit coincide:

Extract[array,#]&/@orbits//Column

More on Symmetry Specifications

The function (RefLink[SymmetrizedIndependentComponents, paclet:ref/SymmetrizedIndependentComponents]) is used to give some more examples of symmetry specifications.

Symmetry given by a single generator, with complex phase:

SymmetrizedIndependentComponents[{3,3,3,3},{Cycles[{{1,2,3,4}}],I}]

Symmetry given by several generators:

SymmetrizedIndependentComponents[{3,3,3,3},{{Cycles[{{1,2}}],1},{Cycles[{{1,2,3,4}}],1}}]

Product of symmetries:

SymmetrizedIndependentComponents[{3,3,3,3},{Antisymmetric[{1,2}],Symmetric[{3,4}]}]

Named symmetries can be mixed with symmetries gives by generators, both using permutation lists or permutation cycles:

SymmetrizedIndependentComponents[{3,3,3,3},{Antisymmetric[{1,2}],{{1,2,4,3},1}}]

For a phased permutation {perm,ϕ} with ϕ a root of unity, in general you need to have (ϕ^n)==1, where n is the permutation order of perm, as given by (RefLink[PermutationOrder, paclet:ref/PermutationOrder])[perm]. Otherwise, the generator can only be a symmetry of the zero tensor, and in such a case that generator is referred to as inconsistent or self-inconsistent. A tensor symmetry may also be compatible only with the zero tensor, even if it is expressed with generators that are self-consistent. That is, the composition of self-consistent generators may give a self-inconsistent generator.

The generator {{2,3,1},-1} is inconsistent because the order of the permutation is 3, but -1 is a root of unity of order 2. The result is the empty list, because the zero tensor does not have independent components:

SymmetrizedIndependentComponents[{3,3,3},{{2,3,1},-1}]

These two generators are consistent, but their combination gives a symmetry only compatible with the zero tensor:

SymmetrizedIndependentComponents[{3,3,3},{{Cycles[{{1,2}}],-1},{Cycles[{{2,3}}],1}}]

Both cases are equivalent to specifying the zero symmetry directly:

SymmetrizedIndependentComponents[{3,3,3},ZeroSymmetric[{1,2,3}]]