4.1. Basics

In any calculation it is essential to bring all tensors and products of tensors down to a canonical form, in order to be compared. This is done by the function ToCanonical, probably the most important ingredient of xTensor`, and certainly the most complicated function.
Do not confuse the canonicalization proces, by which an expression is brought to a canonical form (not necessarily simple) from the simplification process, by which an expression is rewritten as an equivalent, but simpler form. The former is uniquely defined once the canonical form of every sintactycally correct expression is decided. The latter is largely subjective, and generally more difficult to work with. Fortunately Mathematica has a very good algorithm for simplification (Simplify). This is one of the main reasons to avoid introducing TensorTimes or TensorPlus, which would force us to build a new TensorSimplify, and another strong reason to use abstract index notation. In xTensor` we have defined a command Simplification, which simply applies ToCanonical first, and then Simplify.
The hardest part of the process (the canonicalization of indices) is performed by the companion package xPerm`. The canonicalization code is duplicated in that package: there is first a pure Mathematica version of the code, and then there is an external C-executable, which is much faster, but requires a MathLink connection, which does not work for some operating systems. Which code is used is controlled with several switches, as we will see later on.

ToCanonical                Canonicalization of indices of an expression
Simplification            Apply ToCanonical and then Simplify

Simplification functions

Canonical form of the totally antisymmetric tensor U: sort indices in alphabetical order:

In[222]:=

ToCanonical[ U[-a, -d, -b] ]

Out[222]=

-U_abd^   

In[223]:=

U[-a, -b, -c] + U[-c, -b, -a]//ToCanonical

Out[223]=

0

Dummy indices are replaced so that the total number of different dummies is minimal:

In[224]:=

T[a, b] v[-b] + T[a, c] v[-c]//ToCanonical

Out[224]=

2 T_  ^ab v_b^

The process of canonicalization is far from trivial (see next section). We can monitor it using Verbose options.

Verbose                Gives a real-time report of the tensorial canonicalization process
TimeVerbose            Gives timings of several canonicalization steps
xPermVerbose        Gives a real-time report of the permutation canonicalization process

Verbosing options of ToCanonical.

These three cells show the output of the three Verbose options of ToCanonical in a simple case. The output of xPermVerbose can be extremely large even for small expressions. We do not use the external executable because there is not verbose information from it:

In[225]:=

SetOptions[CanonicalPerm, MathLink→False]

Out[225]=

{MathLink→False, TimeVerbose→False, xPermVerbose→False, OrderedBase→True}

In[226]:=

ToCanonical[U[b, c, a] v[-b], TimeVerbose→True]

Free algorithm applied in 0.004 secs.

Dummy algorithm applied in 0.004 secs.

Out[226]=

-U_   ^acb v_b^

In[227]:=

ToCanonical[U[b, c, a] v[-b], Verbose→True]

***********************************************************

ToCanonicalOne:: Actual configuration:  {-b, b, c, a}

ToCanonicalOne:: Standard configuration:  {a, c, b, -b}

ToCanonicalOne:: Repeated indices:  {}

ToCanonicalOne:: Repeated indices:  {}

ToCanonicalOne:: Permutation to be canonicalized: Images[{4, 3, 2, 1}]

ToCanonicalOne:: dummysets_tmp:  {DummySet[TangentS2, {}, 0], DummySet[TangentM3, {b}, 0], DummySet[TangentM5, {}, 0], DummySet[InnerC, {}, 0], DummySet[InnerC†, {}, 0]}

ToCanonicalOne:: dummysets:  {DummySet[TangentS2, {}, 0], DummySet[TangentM3, {{3, 4}}, 0], DummySet[TangentM5, {}, 0], DummySet[InnerC, {}, 0], DummySet[InnerC†, {}, 0]}

ToCanonicalOne:: Free indices:  {1, 2}

ToCanonicalOne:: Canonical permutation:  -Images[{4, 1, 2, 3}]

ToCanonical:: newindices:  {-1, {-b, a, c, b}}

ToCanonical:: needmetrics: False

ToCanonical:: cQ: False

ToCanonical:: result:  -U_   ^acb v_b^

Out[227]=

-U_   ^acb v_b^

In[228]:=

ToCanonical[U[b, c, a] v[-b], xPermVerbose→True]

Free indices at slots:  {4, 3}

RIGHT-COSET-REPRESENTATIVE ALGORITHM for Images[{4, 3, 2, 1}]

which corresponds to the index list: Perm[{4, 3, 2, 1}]

base:  {1, 2, 3, 4}

****** Analysing element i=1 of base: slot 1 ******

Symmetry orbit Delta of slots:  {1}

Free slots:  {4, 3}

Free slots that can go to that slot:  {}

****** Analysing element i=2 of base: slot 2 ******

Symmetry orbit Delta of slots:  {2, 3, 4}

Free slots:  {4, 3}

Free slots that can go to that slot:  {3, 4}

At those slots we respectively find indices Deltap:  {2, 1}

The least index is 1, found at position pk: 2 of Deltap

That index is found in tensor at slot pp: 4

We can move slot 4 to slot 2 using permutation om: Images[{1, 4, 2, 3}]  in S

New indices list: Perm[{4, 1, 3, 2}]

Computing stabilizer in S of slot 2

newbase before change:  {1, 2, 3, 4}

newbase after change:  {1, 3, 4}

****** Analysing element i=3 of base: slot 3 ******

Symmetry orbit Delta of slots:  {3, 4}

Free slots:  {2, 4}

Free slots that can go to that slot:  {4}

At those slots we respectively find indices Deltap:  {2}

The least index is 2, found at position pk: 1 of Deltap

That index is found in tensor at slot pp: 4

We can move slot 4 to slot 3 using permutation om:  -Images[{1, 2, 4, 3}]  in S

New indices list:  -Perm[{4, 1, 2, 3}]

Computing stabilizer in S of slot 3

newbase before change:  {1, 3, 4}

newbase after change:  {1, 4}

Canonical Permutation after RightCosetRepresentative:  -Images[{4, 1, 2, 3}]

DOUBLE-COSET-REPRESENTATIVE ALGORITHM for  -Images[{4, 1, 2, 3}]

index-dummysets:  {DummySet[TangentS2, {}, 0], DummySet[TangentM3, {{3, 4}}, 0], DummySet[TangentM5, {}, 0], DummySet[InnerC, {}, 0], DummySet[InnerC†, {}, 0]}

dummyindices:  {3, 4}

dummyslots:  {4, 1}

Extended  {1, 4}  to  {1, 4}

Initial SGSS: StrongGenSet[{1, 4}, GenSet[]]

base for sorting:  {3, 4}

Initial SGSD: StrongGenSet[{3}, GenSet[]]

******************* Loop i= 1 *********************

Analyzing slot 1 of tensor

nuS: Schreier[{1}, {2}, {3}, {4}, {0, 0, 0, 0}, {0, 0, 0, 0}]  with first element 1

Under S, slot 1 can go to slots Deltab:  {1}

Orbits of indices under D: DeltaD:  {{1}, {2}, {3}, {4}}

With L= {}  we get sgd:  -Images[{4, 1, 2, 3}]

which maps slots in Deltab to indices list:  {4}

whose points belong to orbits  {4}

Therefore at slot 1 we can have indices IMAGES:  {4}

The least of them is p[[1]]: 4

Moved pairs  {DummySet[TangentS2, {}, 0], DummySet[TangentM3, {{4, 3}}, 0], DummySet[TangentM5, {}, 0], DummySet[InnerC, {}, 0], DummySet[InnerC†, {}, 0]}

New SGS of D: StrongGenSet[{4}, GenSet[]]

with Schreier vector nuD: Schreier[{1}, {2}, {3}, {4}, {0, 0, 0, 0}, {0, 0, 0, 0}]

In particular, the orbit of index 4 is Deltap:  {4}

Now looking for all permutations sgd that move index 4 to slot 1

Loop with l=1

L=  {}

TAB[L] = {s, d} =  {Images[{1, 2, 3, 4}], Images[{1, 2, 3, 4}]}

Calculating NEXT. We need the intersection of sets of slots  {1}  and  {1}

Intermediate slots NEXT=  {1}

From slot 1 to intermediate slot 1 use s1=Images[{1, 2, 3, 4}]

d1= Images[{1, 2, 3, 4}]

L1=  {1}

This gives us the new index configuration:  -Perm[{4, 1, 2, 3}]

New ALPHA:  {{1}}

Checking consistency in set  {-Images[{2, 3, 4, 1}]}

Removing permutations from SGS of S that move slot 1

New SGS of S: StrongGenSet[{4}, GenSet[]]

Removing permutations from SGS of D that move index 4

New SGS of D: StrongGenSet[{}, GenSet[]]

******************* Loop i= 2 *********************

Analyzing slot 4 of tensor

nuS: Schreier[{1}, {2}, {3}, {4}, {0, 0, 0, 0}, {0, 0, 0, 0}]  with first element 4

Under S, slot 4 can go to slots Deltab:  {4}

Orbits of indices under D: DeltaD:  {{1}, {2}, {3}, {4}}

With L= {1}  we get sgd:  -Images[{4, 1, 2, 3}]

which maps slots in Deltab to indices list:  {3}

whose points belong to orbits  {3}

Therefore at slot 4 we can have indices IMAGES:  {3}

The least of them is p[[2]]: 3

Moved pairs  {DummySet[TangentS2, {}, 0], DummySet[TangentM3, {}, 0], DummySet[TangentM5, {}, 0], DummySet[InnerC, {}, 0], DummySet[InnerC†, {}, 0]}

New SGS of D: StrongGenSet[{}, GenSet[]]

with Schreier vector nuD: Schreier[{1}, {2}, {3}, {4}, {0, 0, 0, 0}, {0, 0, 0, 0}]

In particular, the orbit of index 3 is Deltap:  {3}

Now looking for all permutations sgd that move index 3 to slot 4

Loop with l=1

L=  {1}

TAB[L] = {s, d} =  {Images[{1, 2, 3, 4}], Images[{1, 2, 3, 4}]}

Calculating NEXT. We need the intersection of sets of slots  {4}  and  {4}

Intermediate slots NEXT=  {4}

From slot 4 to intermediate slot 4 use s1=Images[{1, 2, 3, 4}]

d1= Images[{1, 2, 3, 4}]

L1=  {1, 4}

This gives us the new index configuration:  -Perm[{4, 1, 2, 3}]

New ALPHA:  {{1, 4}}

Checking consistency in set  {-Images[{2, 3, 4, 1}]}

Removing permutations from SGS of S that move slot 4

New SGS of S: StrongGenSet[{}, GenSet[]]

Removing permutations from SGS of D that move index 3

New SGS of D: StrongGenSet[{}, GenSet[]]

Out[228]=

-U_   ^acb v_b^

The canonicalization of expressions involving a large number of indices is a slow process, mainly when most of those indices are dummies. In those cases the Mathematica code for xPerm`, which is interpreted, becomes too slow. A C executable called xperm is used to compute the hardest part of the calculations; xTensor` communicates with it using a MathLink connection. Currently this executable exists for Linux and Mac for any version of Mathematica, and for MS Windows starting Mathematica 6.0.

MathLink            Option of CanonicalPerm to use the external C executable xperm

MathLink connection.

We define an antisymmetric tensor Anti:

In[229]:=

DefTensor[Anti[a, b], M3, Antisymmetric[{a, b}], PrintAs->"A"]

** DefTensor: Defining tensor Anti[a, b] .

Now we fake that there is a metric on TangentM3. We shall later explain how to define a metric properly.

In[230]:=

MetricsOfVBundle[TangentM3]^={metricg} ;

SymmetryGroupOfTensor[metricg]^=Symmetric[{1, 2}] ;

Powers of an odd number of antisymmetric tensors are 0. These are timings with the interpreted Mathematica code:

In[232]:=

AbsoluteTiming[ToCanonical[Anti[a, -a], TimeVerbose→True]]

Free algorithm applied in 0. secs.

Dummy algorithm applied in 0.004 secs.

Out[232]=

{0.005253 Second, 0}

In[233]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -a], TimeVerbose→True]]

Free algorithm applied in 0. secs.

Dummy algorithm applied in 0.024002 secs.

Out[233]=

{0.027611 Second, -A_ab^   A_  ^ab}

In[234]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, -a], TimeVerbose→True]]

Free algorithm applied in 0.004 secs.

Dummy algorithm applied in 0.044003 secs.

Out[234]=

{0.052529 Second, 0}

In[235]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -a], TimeVerbose→True]]

Free algorithm applied in 0. secs.

Dummy algorithm applied in 0.112007 secs.

Out[235]=

{0.120125 Second, A_a ^( c) A_  ^ab A_b ^( d) A_cd^  }

In[236]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, -a], TimeVerbose→True]]

Free algorithm applied in 0.004001 secs.

Dummy algorithm applied in 0.184011 secs.

Out[236]=

{0.192207 Second, 0}

In[237]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -a], TimeVerbose→True]]

Free algorithm applied in 0. secs.

Dummy algorithm applied in 0.352022 secs.

Out[237]=

{0.364298 Second, -A_a ^( c) A_  ^ab A_b ^( d) A_c ^( e) A_d ^( f) A_ef^  }

In[238]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -g] Anti[g, -a], TimeVerbose→True]]

Free algorithm applied in 0. secs.

Dummy algorithm applied in 0.516032 secs.

Out[238]=

{0.534410 Second, 0}

In order to be able to connect to the external executable, the following global variable must return True. If you get False, contact JMM to see what is the problem, and whether it can be solved.

In[239]:=

$xpermQ

Out[239]=

True

These are the corresponding timings with the C executable:

In[240]:=

SetOptions[CanonicalPerm, MathLink→True]

Out[240]=

{MathLink→True, TimeVerbose→False, xPermVerbose→False, OrderedBase→True}

In[241]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, -a]]]

Out[241]=

{0.012787 Second, 0}

In[242]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -a]]]

Out[242]=

{0.011747 Second, -A_a ^( c) A_  ^ab A_b ^( d) A_c ^( e) A_d ^( f) A_ef^  }

In[243]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -g] Anti[g, -a]]]

Out[243]=

{0.015843 Second, 0}

In[244]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -g] Anti[g, h] Anti[-h, -a]]]

Out[244]=

{0.016446 Second, A_a ^( c) A_  ^ab A_b ^( d) A_c ^( e) A_d ^( f) A_e ^( g) A_f ^( h) A_gh^  }

In[245]:=

AbsoluteTiming[ToCanonical[Anti[a, b] Anti[-b, -c] Anti[c, d] Anti[-d, -e] Anti[e, f] Anti[-f, -g] Anti[g, h] Anti[-h, -h1] Anti[h1, -a]]]

Out[245]=

{0.018259 Second, 0}


Created by Mathematica  (May 16, 2008) Valid XHTML 1.1!