xAct`SymManipulator`

This is the doc file SymManipulatorDoc.nb of version 0.9.5 of SymManipulator`. Last update on 3 September 2021.

© 2011-2021, under the GNU General Public License (GPL)
     Thomas Bäckdahl
     thomas.backdahl@chalmers.se

SymManipulator` is the xAct` package for computations with symmetrized tensor expressions. By a symmetrized tensor expression we mean a sum of tensors where each term is the original expression with the indices permuted. We require the set of permutations to form a group. We call this group the imposed symmetry group. It is a group of signed permutations. The sign of the permutation gives the sign of the corresponding term.

This loads the package from the default directory, for example $Home/.Mathematica/Applications/xAct/ for a single-user installation under Linux.

MemoryInUse[]

<<xAct`SymManipulator`

To be able to export latex code, we load also load the TexAct package.

<<xAct`TexAct`

Comparing, we see what the packages take in Mathematica 9.0:

MemoryInUse[]

(Out[4]-Out[1])/2^20//N

There are several contexts: xAct`SymManipulator`, xAct`xTensor`, xAct`xPerm` and xAct`xCore` contain the respective reserved words. System` contains Mathematica's reserved words.  The current context Global` will contain your definitions and right now is empty.

$ContextPath

Context[]

?Global`*

All parts of the package, except the spinor tools works for all dimensions. At the moment only abstract indices can be used.

To avoid long messages we turn off all messages about definitions.

$DefInfoQ=False;

Definition of a four dimensional  manifold M4:

DefManifold[M4,4,{a,b,c,d,f,p,q,r,m,l,h,j,n,t,s}]

For most things we don’t need a metric so we do not need to define one now.

We define a tensor without symmetries:

DefTensor[T[-a,-b,-c,-d],M4]

If we want to completely symmetrize T, we can do it using just xTensor:

SymTexpr1=ImposeSymmetry[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2,3,4}]]

This representation is often inconvenient to use so we can impose the symmetry abstractly instead using ImposeSym:

SymTexpr2=ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2,3,4}]]

The label (1234) means that the symmetrization is taken over the slots 1, 2, 3 and 4.

We can manipulate this expression, and only expand it when we need to. We expand it with ExpandSym:

ExpandSym@SymTexpr2

We can check that this is the same as ImposeSymmetry:

Expand[%-SymTexpr1]

The symmetrized expression is treated as a tensor. That is most xTensor tools will work on it. A new tensor is not defined, so all information is carried in the head of the symmetrized object.

Head@SymTexpr2

xTensorQ@%

SymmetryGroupOfTensor@%%

The canonicalizer can therefore work on SymH objects:

SymTexpr2+(SymTexpr2/.{-a->-b,-b->-a})

ToCanonical@%

Other groups can also be imposed. For instance symmetrize over -a,-c and antisymmetrize over -b,-d:

ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],GenSet[Cycles[{1,3}],-Cycles[{2,4}]]]

ExpandSym@%

If the group has more complicaed structure, the label only shows the slots involved.

ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],RiemannSymmetric[{1,2,3,4}]]

ExpandSym@%

TexAct package can produce a nice TeX code output if the symmetrized object is possible to write in a nice way.

ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c],Antisymmetric[{1,2,3}]]

TexPrint@%

ImposeSym[T[a,-b,-c,-d],IndexList[-b,-d],Symmetric[{1,2}]]

TexPrint@%

The internal tensor can also have symmetries.

DefTensor[S[-a,-b,-c,-d],M4, Symmetric[{2,3,4}]]

SymSexpr1=ImposeSym[S[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2}]]

Now the total symmetry is a mixture of the symmetry of S and the imposed symmetry.

SymmetryGroupOfTensor@Head@SymSexpr1

The calculation of this symmetry has special codes for the cases when the imposed symmetry is the symmetric or antisymmetric group on some indices. In all other cases, a more time consuming code is used to compute the mixed symmetry.

If the tensor already has the the imposed symmetry, it is automatically simplified.

ImposeSym[S[-a,-b,-c,-d],IndexList[-c,-d],Symmetric[{1,2}]]

If one antisymmetrizes over a pair of symmetric slots, one will get zero. This idea have been generalized, and this is checked automatically by ImposeSym. This check works for any combination of groups.

ImposeSym[S[-a,-b,-c,-d],IndexList[-c,-d],Antisymmetric[{1,2}]]

ImposeSym[S[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],RiemannSymmetric[{1,2,3,4}]]

Sometimes the expansion of a symmetry gives many more terms than need due to the internal symmetry.

SymSexpr2=ImposeSym[S[-a,-b,-c,-d],IndexList[-a,-b,-c,-d]]

ExpandSym@SymSexpr2

ToCanonical@%

Then one can give the option SmartExpand->True. Instead of computing all elements of the imposed symmetry group, only a transversal is computed. This is a new feature in release 0.8.3 and not very well tested.

ExpandSym[SymSexpr2,SmartExpand->True]

This idea is used in the new commands SmartSymmetrize and SmartAntisymmetrize. They do the same thing as Symmetrize and Antisymmetrize, but number of terms is reduced by taking the internal symmetry into consideration. Observe that this is a new feature in release 0.8.3 and not very well tested.

SmartSymmetrize[S[-a,-b,-c,-d],IndexList[-a,-b,-c,-d]]

Symmetrize[S[-a,-b,-c,-d],IndexList[-a,-b,-c,-d]]

ToCanonical@%

Product of tensors can be handled. In this case, interchange symmetries etc will be considered as usual.

ImposeSym[T[-a,-b,-c,-d]T[-f,-h,-l,-m],IndexList[-d,-m],Symmetric[{1,2}]]

SymmetryGroupOfTensor@Head@%

ImposeSym[S[-a,-b,-c,-d]T[-f,-h,-l,-m],IndexList[-d,-f],Symmetric[{1,2}]]

The order of the tensors is automatically sorted by ImposeSym.

ImposeSym[T[-f,-h,-l,-m]S[-a,-b,-c,-d],IndexList[-d,-f],Symmetric[{1,2}]]

If one would like to sort them alphabetically at any ther time one can use SortTensorsInSym

%/.{T->S,S->T}

SortTensorsInSym@%

If a tensor is inside the SymH object, but the symmetrization is not acting on its indices, one can move it outside the SymH object.

ImposeSym[S[-a,-b,-c,-d]T[-f,-h,-l,-m],IndexList[-a,-b],Symmetric[{1,2}]]

MoveTensorsOutsideSym@%

One can also move tensors inside the SymH object.

MoveTensorsInsideSym@%

Symmetrizations can be nested

ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2,3}]]

ImposeSym[%,IndexList[-a,-b,-c,-d],Symmetric[{3,4}]]

ExpandSym only expands the outermost SymH object

Expand@ExpandSym@%

Expand@ExpandSym@%

Sometimes, when nesting symmeries the inner symmetrization might not be needed because of the outer symmetrization. Then this can be removed by RemoveSuperfluousInnerSym

ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2,3}]]

ImposeSym[%,IndexList[-a,-b,-c,-d],Symmetric[{1,2,3,4}]]

RemoveSuperfluousInnerSym@%

Expand[ExpandSym[%]-ExpandSym@ExpandSym[%%]]

The functions for dealing with nested SymH objects work best when all tensors are innermost. To get that, use MoveTensorsInsideSym before you apply the second ImposeSym.

SymTSexpr1=ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b,-c,-d],Symmetric[{1,2,3}]]S[-f,-h,-l,-m]

ImposeSym[SymTSexpr1,IndexList[-a,-b,-c,-d],Symmetric[{1,2,3,4}]]

RemoveSuperfluousInnerSym@%

MoveTensorsInsideSym@SymTSexpr1

ImposeSym[%,IndexList[-a,-b,-c,-d],Symmetric[{1,2,3,4}]]

RemoveSuperfluousInnerSym@%

MoveTensorsOutsideSym@%

Replacement rules that involve indices will not have any effect on tensors inside the SymH object. The function RuleInSym can be used. This function is not extensively tested so use it with care. In this case it is important to remember that contractions are taken after symmetrization, and are therefore not visible to the the rule used in RuleInSym. Observe that all SymH objects might need to be canonicalized after the use of RuleInSym.

replacementrules1=MakeRule[{S[-a,-b,-c,-d],T[-a,-b,f,h]S[-c,-d,-f,-h]}];

ImposeSym[S[-a,-c,-b,-d],IndexList[-a,-b]]

RuleInSym[%,replacementrules1]

The same thing can be done with FunctionInSym. This is more flexible because any function can be used.

FunctionInSym[%%,(#/.replacementrules1)&]

Definition of a Lorentzian metric on the manifold:

DefMetric[{1,3,0},g[-a,-b],CD]

If you contract indices of a SymH object, this is means that the symmetrization is done first and then the contraction.

expr1a=ImposeSym[T[-a,-b,-c,-d],IndexList[-a,-b],Symmetric[{1,2}]]

expr1b=ContractMetric[expr1a*g[b,c]]

ContractMetric[ExpandSym@expr1a*g[b,c]]

ExpandSym@expr1b

Observe that the symmetrization and trace operations do not commute in general as seen by this example:

DefTensor[V[-a,-b,-c,-d],M4,StrongGenSet[{1,2,3,4},GenSet[-Cycles[{2,3}]]]]

ContractMetric[V[-a,-b,-c,-d]g[b,c]]

ToCanonical@%

expr1a=ToCanonical@Symmetrize[%,{-a,-b}]

Symmetrize[V[-a,-b,-c,-d],{-a,-b}]

ToCanonical@%

expr1b=ToCanonical@ContractMetric[%g[b,c]]

ToCanonical[expr1a-expr1b]

The same example with SymH objects:

ContractMetric[V[-a,-b,-c,-d]g[b,c]]

ToCanonical@%

expr1a=ImposeSym[%,IndexList[-a,-b]]

ImposeSym[V[-a,-b,-c,-d],IndexList[-a,-b]]

expr1b=ToCanonical@ContractMetric[%g[b,c]]

ToCanonical@ExpandSym[expr1a-expr1b]

However, symmetrization and traces do commute if the traces and symmetrizations are taken over disjoint sets of indices.

ContractMetric[V[-a,-b,-c,-d]g[b,d]]

ToCanonical@%

expr1a=ImposeSym[%,IndexList[-a,-c]]

ImposeSym[V[-a,-b,-c,-d],IndexList[-a,-c]]

expr1b=ToCanonical@ContractMetric[%g[b,d]]

expr1b-expr1a

ExpandSym[expr1b-expr1a]

ToCanonical@%

ToCanonical@CanonicalizeGroupInSym[expr1b-expr1a]

Sometimes there is a metric inside the SymH object that later can be contracted. The code for ContractMetricsInsideSym is new in release 0.8.3 and is not well tested.

ImposeSym[V[-a,-b,-c,-d]g[-f,-h],IndexList[-a,-f]]

ContractMetric[g[h,b]%]

ContractMetricsInsideSym@%

ToCanonical[ExpandSym@%-ContractMetric@ExpandSym@%%]

For scalar expressions, tensors can be collected with

expr2=T[-d,a,-c,-f]S[-a,d,f,c]+T[-c,-a,-d,-f]S[f,d,a,c]

FindTensorCoefficients[%,{S[a,b,c,d]}]

This means that the original expression can be written as

Plus@@Times@@@%

The symmetry imposed on T is the one from S. This symmetry is important when one tries to solve tensor equations.

The list of tensors can have contractions, and products of tensors.

T[-d,a,-c,c]S[-a,d,f,-f]+T[-c,-a,-d,-f]S[f,d,a,c]

FindTensorCoefficients[%,{S[a,b,c,d],S[a,b,-d,d]}]

This far only derivatives compatible with the metric are handled. Prefix notation is used.

CD[-a]@T[-b,-c,-d,-f]

The derivative index is the first index of the SymH object. That is, we keep the order of the indices when we use prefix notation.

expr1a=ImposeSym[%,IndexList[-a,-b,-d]]

In many cases the TexAct package can produce the correct TeX code for the expression.

TexPrint@expr1a

The derivative is internally represented by CovarD[CD,T,{-TangentM4}]. The list {-TangentM4} gives VBundle for the derivative index.

InputForm@expr1a

Higher order derivatives also work

CD[-a]@CD[-b]@T[-c,-d,-f,-h]

ImposeSym[%,IndexList[-a,-b,-c,-d]]

TexPrint@%

The IrrDecompose code needs spinors so we begin by loading it.

<<xAct`Spinors`

Pretty printing options for the spinor indices and complex conjugates;

SetOptions[DefAbstractIndex,PrintAs->PrimeDagger];

SetOptions[DefSpinor,PrintDaggerAs->AddBar];

Define the spin structure

DefSpinStructure[g,Spin,{A,B,C,D,F,H,L,M,P,Q,R},ϵ,σ,CDe,{";","▽"},SpinorPrefix->SP,SpinorMark->"S"]

Pretty printing options for the spinor indices and some predefined spinors.

{PrintAs[ϵ†]^="(OverBar[ϵ])",PrintAs[PsiCDe]^="Ψ",PrintAs[PsiCDe†]^="(OverBar[Ψ])",PrintAs[PhiCDe]^="Φ",PrintAs[LambdaCDe]^="Λ"};

Define some spinors

DefSpinor[T1[-A],M4]

DefSpinor[T2[-A,-B],M4]

DefSpinor[T3[-A,-B,-C],M4]

DefSpinor[T4[-A,-B,-C,-D],M4]

DefSpinor[S4[-A,-B,-C,-D],M4,Symmetric[{-A,-B,-C}]]

DefSpinor[Ω4[-A,-B,-C,-D],M4,Symmetric[{-A,-B,-C,-D}],PrintAs->"Ω"]

The basic example is

IrrDecompose[T2[-A,-B]]

For convenience we can also get a rule or an equation  as output.

IrrDecompose[T2[-A,-B],ResultType->"Rule"]

IrrDecT2=IrrDecompose[T2[-A,-B],ResultType->"Equation"]

That the decomposition is correct can be tested by making all possible contractions and symmetrizations

Times[ϵ[A,B],#]&/@IrrDecT2

ToCanonical@ContractMetric@%

ImposeSym[#,IndexList[-A,-B]]&/@IrrDecT2

A slightly more complicated case

IrrDecT3=IrrDecompose[T3[-A,-B,-C],UseSym->False,ResultType->"Equation"]

The IrrDecompose code uses the symmetries of the expression to simplify it

IrrDecT4=IrrDecompose[T4[-A,-B,-C,-D],UseSym->False,ResultType->"Equation"]

IrrDecS4=IrrDecompose[S4[-A,-B,-C,-D],UseSym->False,ResultType->"Equation"]

One can also simplify it afterwards

ToCanonicalSym@RemoveSuperfluousSym[IrrDecT4/.T4->S4]

IrrDecS4[[2]]-%[[2]]

The decomposition can be simplified further. We see that the left hand side of IrrDecS4 is symmetric in {-A,-B,-C}, but this is not obvoius on the right hand side.

IrrDecS4

IrrDecS4[[1]]==ToCanonical@ImposeSymmetry[IrrDecS4[[2]],IndexList[-A,-B,-C],Symmetric[{1,2,3}]]

If we use the option UseSym, the function will automatically finds this symmetry and imposes it

IrrDecS4b=IrrDecompose[S4[-A,-B,-C,-D],UseSym->True,ResultType->"Equation",TimeVerbose->True]

Larger cases can be handled

IrrDecompose[Ω4[-A,-B,-C,L]Ω4[-D,-F,-H,-L],ResultType->"Equation",TimeVerbose->True]

For even larger cases we can save some time by using the option IrrDecImposeNewMethod->True.

IrrDecompose[Ω4[-A,-B,-C,-D]Ω4[-F,-H,-L,-M],ResultType->"Equation",TimeVerbose->True,IrrDecImposeNewMethod->True]

When dealing with more advanced cases it can happen that the different irreducible pieces can be dependent of each other. In this section we see how one can eliminate dependent parts.

We begin with a tensor with Riemann symmetries, but not the first Bianchi identity.

DefTensor[RT[-a,-b,-c,-d],M4,RiemannSymmetric[{1,2,3,4}],PrintAs->"R"]

Next, we define a spinor version of the tensor.

DefSpinorOfTensor[RS[-A,-A†,-B,-B†,-C,-C†,-D,-D†],RT[-a,-b,-c,-d],σ,PrintAs->"R"]

We can decompose it with IrrDecompose.

irrdec1=IrrDecompose[GiveIndicesToTensor@RS,ResultType->"Equation"]

The irreducible parts can be found with FindSpinorsInIrrDec.

irrdecparts1=FindSpinorsInIrrDec[irrdec1[[2]],{ϵ,ϵ†}]

Unfortunately the valence (2,2) parts are actually dependent. We can see this by separating the metric and applying the irreducible decomposition.

irrdecparts1[[3;;5]]

(#==ToCanonical@ImposeSym@ToCanonical@ContractMetric[SeparateMetric[]@RemoveSym@#/.MakeCompareRule[Evaluate[List@@irrdec1]]])&/@%

First@Solve@%/.Rule->Equal

Hence, we can eliminate two of them.
All this can be done automatically with IndepIrrDecompose.

irrdec2=IndepIrrDecompose[GiveIndicesToTensor@RS,ResultType->"Equation",Verbose->True]

Observe that the algorithm is not analysed for completeness, so we can not yet guarantee that all dependencies have been found. However, irreducible pieces with different valence can not be dependent.

We can also name the irreducible parts.

irrdecparts2=FindSpinorsInIrrDec[irrdec2[[2]],{ϵ,ϵ†}]

irrdecdefs=DefIrreducibleSpinors[irrdecparts2,"RS","R", Spin]

irrdec2b=irrdec2/.Flatten[EqToCompareRule/@Reverse/@irrdecdefs]

This part needs both the spinor package and the TexAct package.

Any covariant spinor derivative acting on a symmetric spinor can be split into at most 4 different irreducible parts. We call these irreducible parts of the derivative fundamental spinor operators. The fundamental spinor operators corresponding to a spinor covariant derivative is defined by the function DefFundSpinOperators. This also defines a set of tools to handle them. All names that are defined will end with the name of the covariant derivative. This way it is possible to handle fundamental spinor operators for several covariant derivatives at the same time.

?DefFundSpinOperators

To see what is defined, we can check the name global name space.

oldnames=Names["Global`*"];

DefFundSpinOperators[CDe,HideCovDSymbolReference->True]

Select[Names["Global`*"],FreeQ[oldnames,#]&]

First we define a symmetric spinor:

DefSpinor[U[-A,-B,-C,A†,B†],M4,CompatibleSymmetric[IndexList[-A,-B,-C,A†,B†]]]

The fundamental operators are defined as follows:

DivCDe[U][-A,-B,A†]==ExpandFundSpinOp[DivCDe[U][-A,-B,A†]]

CurlCDe[U][-A,-B,-C,-D,A†]==ExpandFundSpinOp[CurlCDe[U][-A,-B,-C,-D,A†]]

CurlDgCDe[U][-A,-B,A†,B†,C†]==ExpandFundSpinOp[CurlDgCDe[U][-A,-B,A†,B†,C†]]

TwistCDe[U][-A,-B,-C,-D,A†,B†,C†]==ExpandFundSpinOp[TwistCDe[U][-A,-B,-C,-D,A†,B†,C†]]

The numbers after the operator tells how many unprimed and primed indices the spinor has that it acts on.
These numbers can be swithed off by setting the ShowValenceInfo option.

SetOptions[DefFundSpinOperators,ShowValenceInfo->False]

{DivCDe[U][-A,-B,A†],CurlCDe[U][-A,-B,-C,-D,A†],CurlDgCDe[U][-A,-B,A†,B†,C†],TwistCDe[U][-A,-B,-C,-D,A†,B†,C†]}

SetOptions[DefFundSpinOperators,ShowValenceInfo->True]

There is a special function for the irreducible decomposition of a derivative of a symmetric spinor.

?IrrDecomposeCovD

IrrDecomposeCovD[CDe[-A,A†]@U[-B,-C,B†,C†]]

IrrDecomposeCovD[U,CDe,ResultType->"Equation"]

IrrDecomposeCovD[U,CDe,ResultType->"Equation",ExpandSym->True]

The function ToFundOp will try to replace all CDe derivatives of an expression with the fundamental operators.

CDe[-D,-D†][PhiCDe[-A,-B,-A†,-B†]U[A,B,-C,A†,B†]]

ToFundSpinOp[%,CDe]

During this process irreducible decomposition rules are added to $IrrDecRulesCDe.

$IrrDecRulesCDe

The commutator relations for the fundamental operators produces curvature terms cosisting of symmetrizations and BoxCDe. This can be turmed into curvature spinors by ExpandBoxCDe.
In this example we use the function GiveIndicesToTensor so we don’t have to write all indices manually.

?GiveIndicesToTensor

GiveIndicesToTensor[DivCDe@CurlCDe@U]

%==(%/.CommuteFundSpinOp[DivCDe,CurlCDe])

ExpandBox@%

GiveIndicesToTensor[TwistCDe@CurlDgCDe@U,{Spin†}]

%==(%/.CommuteFundSpinOp[TwistCDe,CurlDgCDe])

GiveIndicesToTensor[CurlCDe@CurlDgCDe@U,{Spin†}]

%==(%/.CommuteFundSpinOp[CurlCDe,CurlDgCDe,CurlDgCDe,CurlCDe])

GiveIndicesToTensor[DivCDe@TwistCDe@U,{Spin†}]

%==(%/.CommuteFundSpinOp[DivCDe,TwistCDe,CurlCDe,CurlDgCDe])

To commute operators which are not outermost, we can use FunctionInFundSpinOp. Often there will be derivatives of products in an intermediate step. These will be expanded with the standard Leibniz rule. After that, the function ToFundSpinOp to converts all derivatives to fundamental spinor operators.

?FunctionInFundSpinOp

GiveIndicesToTensor[CurlDgCDe@DivCDe@CurlCDe@U]

%==ToCanonicalSym@FunctionInFundSpinOp[%,ExpandBox[#/.CommuteFundSpinOp[DivCDe,CurlCDe]]&]

The expressions can be exported as latex code.

TexPrintAlignedEquations@%

The commands \sDiv, \sCurl, \sCurlDagger and \sTwist are defined as:

$TexInitLatexExtraCode

One can analyse valence numbers and check if some spinor is symmetric with the following commands

DefSpinor[SPA[-A,-B,-C,A†,B†,-a,-b,-c],M4,CompatibleSymmetric[IndexList[-A,-B,-C,A†,B†,-a,-b]]]

SymmetryGroupOfTensor@SPA

ValenceNumbersOfSpinor[SPA,Spin]

ExtractUnprimedAndPrimed[Spin]@List[-A,-B,-C,A†,B†,-a,-b]

NumOfUnprimedVBundles[Spin]@SlotsOfTensor[SPA]

NumOfPrimedVBundles[Spin]@SlotsOfTensor[SPA]

NumOfUnprimedSlots[Spin][SPA]

NumOfPrimedSlots[Spin][SPA]

SymmetricSpinorOfValenceQ[3,2,Spin][SPA]

SymmetricSpinorOfArbitraryValenceQ[Spin][SPA]

SymmetricSpinorOfArbitraryValenceQ[Spin]@TwistCDe[SPA]

UndefFundSpinOperators[CDe]

MaxMemoryUsed[]

TimeUsed[]

Note: For further information about SymManipulator`, and to be kept informed about new releases, you may contact the author electronically at thomas.backdahl@chalmers.se. This is SymManipulatorDoc.nb, the docfile of SymManipulator`, currently in version 0.9.5.

?xAct`SymManipulator`*