xTensor types: continuation

We start a fresh session of xTensor:

<<xAct`xTensor`

$PrePrint=ScreenDollarIndices;

The delta tensor

<<xAct`xTensor`

Set up a manifold with symbolic dimension :

DefConstantSymbol[dim,PrintAs->"d"]

DefManifold[M,dim,IndexRange[a,q]]

IndicesOfVBundle[TangentM]

By default we always have a tensor defined in any vector bundle: The Kronecker’s delta tensor.The symbol for this tensor is delta and it is written with down - up indices by convention:

?delta

The Kronecker delta can be defined for the tangent bundle of any manifold and for any vector bundle. For that reason, xTensor uses the same symbol for the Kronecker delta in any vector bundle.  In the following output All means “any vector bundle”:

SlotsOfTensor@delta

delta[-a,b]//Validate

delta with up-down configuration is not valid unless we have a metric:

delta[a,-b]//Validate

We check the elementary properties of delta:

delta[-a,a]

DefTensor[T[a,-b,-c],M,Antisymmetric[{2,3}]]

T[a,-b,-c]delta[-f,c]

Hold[delta[-a,b]]T[c,-b,-d]Hold[delta[-c,i]]

%//ReleaseHold

Note also that tensors are defined with a specific index configuration. Changing this configuration without the presence of a metric results in invalid expressions:

SlotsOfTensor@T

T[-a,-b,-c]//Validate

T[-a,-b,-c]

%//ToCanonical

There are two generalizations of the Kronecker delta: the Gdelta (generalized Kronecker delta) and the Sdelta (symmetrized Kronecker delta).  Actually Sdelta contains Gdelta as a particular case:

?Gdelta

?Sdelta

Examples:

Gdelta[-c,-d,a,b]

Gdelta[-c,-d,a,b]//ExpandGdelta

Gdelta[-c,-d,-f,a,b,e]//ExpandGdelta

Sdelta[Symmetric[{a,b}]][-c,-d,a,b]

%//ExpandSdelta

Sdelta[GenSet@Cycles[{1,2}]][-c,-d,a,b]

%//InputForm

Unprotect@Sdelta;
PrintAs[Sdelta[StrongGenSet[{1},GenSet[Cycles[{1,2}]]]]]^="(δ^S)";
Protect@Sdelta;

%//ExpandSdelta

Sdelta[RiemannSymmetric[{1,2,3,4}]][-e,-f,-g,-h,a,b,c,d]

%//ExpandSdelta

Tensors with the corresponding symmetries are invariant under Sdelta:

DefTensor[R[-a,-b,-c,-d],M,RiemannSymmetric[{-a,-b,-c,-d}]]

IndicesOfVBundle@TangentM

S:=Sdelta[RiemannSymmetric[{1,2,3,4}]];

S[-e,-f,-g,-h,a,b,c,d]R[-a,-b,-c,-d]

%//ExpandSdelta

Sdelta[RiemannSymmetric[{1,2,3,4}]][-e,-f,-g,-h,a,b,c,d]R[-a,-b,-c,-d]

%//ExpandSdelta

ToCanonical@%

Sdelta[Antisymmetric[{1,2,3,4}]][-e,-f,-g,-h,a,b,c,d]

%//ExpandSdelta

Gdelta

Gdelta[-a,-b,b,c]

Gdelta[-a,-b,b,c]

Type metric

A metric in the tangent bundle of a differentiable manifold is introduced with the command DefMetric. In addition to the metric itself a number of other additional objects are defined:

?DefMetric

DefMetric[-1,metric[-a,-b],CD,PrintAs->"g"]

$Metrics

Additional objects defined:

ServantsOf@metric

ServantsOf@CD

Now delta with up-down configuration is valid:

delta[a,-b]//Validate

Whenever there is a metric, delta can be regarded as the metric with one index raised and therefore it is regarded as a symmetric tensor:

delta[a,-b]==SeparateMetric[metric][delta[a,-b],a]

SymmetryGroupOfTensor[delta[a,-b]]

Note that this is a property which is specific of an index configuration. If we do not put indices then delta has no symmetries:

SymmetryGroupOfTensor@delta

Actually, delta with both indices downstairs or both indices upstairs is automatically converted into the metric :

{delta[-a,-b],delta[a,b]}

Properties of the metric

We have already defined a metric field on our (tangent) vector bundle. The presence of a metric enables us to raise and lower indices in tensorial expressions:

{metric[-a,-b],metric[a,b]}

The product of the metric and its inverse yields the delta tensor in the known way:

{HoldForm[metric[b,c]metric[-a,-c]]==metric[b,c]metric[-a,-c]}

metric[a,b]metric[-b,-c]

The definition of the metric introduces automatically a number of new objects (Servants). Let us have a look to each o them:

ServantsOf@metric

The volume form: epsilonmetric: to properly work with the volume form we need to choose a manifold dimension and fix the number of slots of the volume form:

dim=4;

SlotsOfTensor@epsilonmetric^={-TangentM,-TangentM,-TangentM,-TangentM};

The volume form is totally antisymmetric as expected:

SymmetryGroupOfTensor[epsilonmetric[-a,-b,-c,-d]]

SymmetryGroupOfTensor[epsilonmetric]

Basic algebraic properties of the volume form. Remember that these formulae depend on the sign of the metric determinant, chosen at definition time:

epsilonmetric[-a,-b,-c,-g]epsilonmetric[e,f,h,p]

epsilonmetric[-a,-b,-c,-g]epsilonmetric[e,f,h,g]

epsilonmetric[-a,-b,-h,-g]epsilonmetric[e,f,h,g]

epsilonmetric[-a,-f,-h,-g]epsilonmetric[e,f,h,g]

epsilonmetric[-e,-f,-h,-g]epsilonmetric[e,f,h,g]

epsilonmetric[-a,-b,-c,-g]epsilonmetric[e,f,h,p]==-ExpandGdelta@Gdelta[-a,-b,-c,-g,e,f,h,p]

dim=.

The metric determinant Detmetric[]:

Detmetric[]

SignDetOfMetric@metric

The Levi - Civita connection. The compatibility with the metric and the volume element is automatic:

CD[-a][metric[-b,-c]]

CD[-a][metric[b,c]]

CD[-a][epsilonmetric[a,b,c,d]]

We can construct the Levi-Civita covariant derivative of any tensor or tensorial expression:

CD[-a][ 7T[a,-b,-c]T[b,-d,-e] ]

Tensors associated to the Levi-Civitta connection:

ServantsOf@CD

We check next that the properties of all these tensors are the expected ones:

ChristoffelCD[a,-b,-c]

SymmetryGroupOfTensor[%]

Levi-Civita covariant derivative was defined without torsion, so the Riemann tensor has the expected symmetries:

TorsionCD[a,-b,-c]

RiemannCD[-a,-b,-c,d]

RiemannCD[a,-b,-c,-d]-RiemannCD[-d,-c,-b,a]//ToCanonical

Einstein tensor and its basic properties:

EinsteinCD[-a,-b]

%//EinsteinToRicci

CD[-a][EinsteinCD[a,b]]

Weyl tensor:

WeylCD[-a,-b,-c,d]

%//WeylToRiemann

TFRicciCD[-a,-b]

%//TFRicciToRicci

Trace free properties of the Weyl tensor and trace-free part of Ricci and trace properties of the Ricci tensor:

{WeylCD[a,-b,-a,-d],TFRicciCD[-a,a]}

{RiemannCD[-a,-c,c,-b],RicciCD[a,-a]}

Standard metric contraction is carried out with ContractMetric:

metric[a,c]R[-a,-b,-c,-d]

ContractMetric@%

Working with multiple metrics

Let us introduce a second metric:

DefMetric[-1,metrictilde[-a,-b],cd,{"|","(OverTilde[∇])"},PrintAs->"(OverTilde[g])"]

This second metric is frozen. This means that it cannot be used to raise and lower indices. Leaving aside some exceptions, indices are always raised and lowered with the first metric in the list of metrics of a tangent bundle:

MetricsOfVBundle@TangentM

$Metrics

Now a new tensor to represent the inverse of the new metric is required:

Invmetrictilde[a,b]

Invmetrictilde[a,b]metrictilde[-b,-c]

metrictilde[a,b]===Invmetrictilde[a,b]

Use SeparateMetric with no arguments to express any tensor in terms of its natural index configuration. This is achieved by inserting the appropriate unfrozen metrics:

SeparateMetric[]@metrictilde[a,b]

SeparateMetric[]@Invmetrictilde[a,b]

Objects automatically defined along with metrictilde:

ServantsOf@metrictilde

ServantsOf@cd

Note that the Riemann tensor with all its indices downstairs with respect to the second metric has to be defined separately:

RiemannDowncd[-a,-b,-c,-d]

By definition this is:

metrictilde[-d,-f]Riemanncd[-a,-b,-c,f]

It has, however, the expected symmetry properties:

SymmetryGroupOfTensor@RiemannDowncd

In this set-up, the Weyl tensor with respect to the frozen metric is defined with respect to Riemann with all its indices downstairs:

SlotsOfTensor@Weylcd

Weylcd[-a,-b,-c,-d]//WeylToRiemann

Any tensor has a natural index configuration which is specified at definition time. Use SlotsOfTensor to find what that configuration is:

SlotsOfTensor@R

Any change of the natural index configuration is understood as done with respect to the first metric:

R[a,b,-c,-d]

SeparateMetric[]@%

Attempting metric contraction with respect to any other metric results in error:

metrictilde[a,p]metrictilde[b,q]R[-p,-q,-c,-d]

Catch@ContractMetric[%,metrictilde]

WARNING! in the following the input and output are not equal (probably the output should be an error) :

SeparateMetric[metrictilde]@R[a,b,-c,-d]

Summary

Symmetrized Kronecker deltas of arbitrary rank are fully supported by xTensor.  These are implemented with Gdelta and Sdelta.

Support of an arbitrary number of metrics and their compatible connections. However, it is only possible to raise and lower indices with respect to the first defined metric. The remaining metrics are called frozen and cannot be used to raise or lower indices.

Use DefMetric to define a new metric. Use ContractMetric to raise and lower indices with an unfrozen metric.  Use SeparateMetric to express any tensor in terms of its natural index configuration by inserting appropriate unfrozen metrics.

Exercises

Exercise 1

Given a n-dimensional manifold define an antisymmetric (symplectic) metric on it.

Answer

We start a new session of xTensor:

Exit

<<xAct`xTensor`

$PrePrint=ScreenDollarIndices;

DefConstantSymbol[n]

DefManifold[M,n,Complement[IndexRange[a,r],{n}]]

It is currently not possible to use DefMetric to define an antisymmetric metric but we can bypass DefMetric and define the metric by hand. First define an antisymmetric tensor which will represent the metric:

DefTensor[ϵ[-a,-b],M,Antisymmetric[{-a,-b}]]

Now we create the metric tensor:

MetricQ[ϵ]^=True;
xUpAppendTo[MetricsOfVBundle[TangentM],ϵ];
VBundleOfMetric[ϵ]^=TangentM;
$Metrics=Join[$Metrics,{ϵ}];
InducedFrom[ϵ]^=Null;

Metric contraction. Pay attention to the conventions which are hardwired into the system:

DefTensor[T[a],M]

T[a]ϵ[-a,-b]

%//ContractMetric

ϵ[a,b]T[-b]

%//ContractMetric

Relation between the metric and delta:

ϵ[a_Symbol,-b_Symbol]:=delta[a,-b];
ϵ[-a_Symbol,b_Symbol]:=delta[-a,b];

Now metric contraction and index raising & lowering are commutative:

T[a]ϵ[-a,-b]

%/.-b->b

%%//ContractMetric

T[a]ϵ[-a,-b]

%//ContractMetric

%%/.-b->b

ϵ[a,b]T[-b]

%/.a->-a

%%//ContractMetric

ϵ[a,b]T[-b]

%//ContractMetric

%%/.a->-a

Further computations:

ϵ[a,-b]

SeparateMetric[][%,a]

%//ToCanonical

ContractMetric@%

ϵ[b,a]ϵ[-b,-c]

ContractMetric@%

%//ToCanonical

We see that delta tensor must be now regarded as an antisymmetric tensor. This is already taken care of:

SymmetryGroupOfTensor[delta[a,-b]]

Scalar product of a vector by itself is zero when the metric is antisymmetric. ToCanonical knows that:

T[a]T[-a]

%//ToCanonical

Exercise 2

Given a N-dimensional vector bundle over an n-dimensional manifold, define a symmetric or antisymmetric metric on it.

Answer

We start a new session of xTensor:

Exit

<<xAct`xTensor`

$PrePrint=ScreenDollarIndices;

Define manifold dimension:

DefConstantSymbol[n]

Define vector bundle dimension:

DefConstantSymbol[Nd,PrintAs->"N"]

DefManifold[M,n,Complement[IndexRange[a,r],{n}]]

DefVBundle[IN,M,Nd,{A,B,F,G,H,J,L}]

It is currently not possible to use DefMetric to define an antisymmetric metric but we can bypass DefMetric and define the metric by hand. First define a symmetric tensor which will represent the metric:

DefTensor[Gmetric[-A,-B],M,Symmetric[{-A,-B}],PrintAs->"G"]

Now we create the metric tensor:

MetricQ[Gmetric]^=True;
xUpAppendTo[MetricsOfVBundle[IN],Gmetric];
VBundleOfMetric[Gmetric]^=IN;
$Metrics=Join[$Metrics,{Gmetric}];
InducedFrom[Gmetric]^=Null;

Relation between the metric tensor and the Kronecker delta:

Gmetric[A_Symbol,-B_Symbol]:=delta[A,-B];
Gmetric[-A_Symbol,B_Symbol]:=delta[-A,B];

Metric contraction:

DefTensor[T[A],M]

T[A]Gmetric[-A,-B]

%//ContractMetric

Gmetric[A,B]T[-B]

%//ContractMetric

Now metric contraction and index raising & lowering are consistent:

T[A]Gmetric[-A,-B]

%/.-B->B

%%//ContractMetric

Gmetric[A,B]T[-B]

%/.A->-A

%%//ContractMetric

Gmetric[A,-B]

SeparateMetric[][%,A]

%//ToCanonical

ContractMetric@%

delta[-A,-B]

Gmetric[B,A]Gmetric[-B,-F]

ContractMetric@%

%//ToCanonical

Delta  tensor must be now regarded as a symmetric tensor:

SymmetryGroupOfTensor[delta[A,-B]]

Exercise 3

Define a symmetric tensor with an arbitrary number of indices (tensor of arbitrary rank) on the tangent bundle of a n-dimensional manifold.

Answer

Again there is no DefTensor support for this operation. We need to do bypass DefTensor:

Exit

<<xAct`xTensor`

$PrePrint=ScreenDollarIndices;

DefConstantSymbol[n]

DefManifold[M,n,Complement[IndexRange[a,r],{n}]]

We need to bypass DefTensor. A possibility is the following:

xTensorQ[Y]^=True;
Dagger[Y]^=Y;
DependenciesOfTensor[Y]^={M};
HostsOf[Y]^={M,TangentM};
PrintAs[Y]^="Y";
SlotsOfTensor[Y]^={AnyIndices@TangentM};
SymmetryGroupOfTensor[Y[inds__]]^:=With[{length=Length@{inds}},
With[{base=Range@length},
SchreierSims[base,GenSet@Symmetric[base],length]
]
];
TensorID[Y]^={};

SymmetryGroupOfTensor@Y[f,b,c,p,q,r]

The tensor is totally symmetric regardless of the index character (contravariant, covariant) of each index

Y[f,-b,c]-Y[-b,f,c]//Validate

%//ToCanonical

Y[-f,-b,-c,-h,-p,-q]-Y[-f,-b,-h,-c,-p,-q]

%//Validate

%//ToCanonical

Y[-f,-b,-c,-h,-q,-p]-Y[-f,-b,-h,-c,-p,-q]

%//ToCanonical

Canonicalization in the presence of an unfrozen metric

Start a fresh session of xTensor and define a metric:

Exit

<<xAct`xTensor`

DefManifold[M4,4,IndexRange[a,q]]

DefMetric[-1,metric[-a,-b],CD,PrintAs->"g"]

Consider the following tensorial expression:

expr=CD[h]@RiemannCD[-a,-b,-c,-d]CD[-h]@RiemannCD[c,d,-e,-f]RiemannCD[f,e,-p,-q]

Let us have a more detailed look at the canonicalization process:

ToCanonical[%,Verbose->True]

Any tensorial monomial has its own symmetry group which is constructed from the mono-term symmetry group of the product factors. Use SymmetryOf to find the symmetry group of any tensor monomial:

SymmetryOf@expr

generatingset=First@Cases[%,_StrongGenSet]

The complete symmetry group can become rather large, even for small tensor monomials:

monomialgroup=Dimino@generatingset

%//Length

Sort all the indices of our tensor monominal with respect to a default configuration. This defines a permutation from the actual to the standard configuration. In the standard configuration free indices come first and dummy indices come next:

actualconfiguration={f, e, -p, -q, -a, -b, -c, -d, h, c, d, -e, -f, -h};

standardconfiguration={-a, -b, -p, -q, c, -c, d, -d, e, -e, f, -f, h, -h};

perm=Images[{5,6,3,4,10,7,11,8,2,12,1,13,9,14}];

In addition we need to bear in mind that our tensor monomial has an extra symmetry group arising from the dummy indices. This is due to the fact that raising and lowering dummy indices simultaneously results in an equivalent expression. The notation for the generating set of this group is different from the notation of the generating set of the mono-term symmetries  because the symmetry group of dummy indices is special. This is due to the fact that we are not permuting indices, we are changing the up-down character of indices and permuting pairs of dummy indices.

dummysymmetry=DummySet[TangentM4,{{5,6},{7,8},{9,10},{11,12},{13,14}},1];

SGSOfDummySet[dummysymmetry]

Dimino@%

%//Length

With all this information we are ready to find the canonical permutation which shall give us the final index configuration of our tensor expression. This is achieved through the use of CanonicalPerm:

?CanonicalPerm

CanonicalPerm[InversePerm@perm,14,generatingset,{1,2,3,4},{dummysymmetry}]

The canonical permutation is defined with respect to the standard configuration. We check that the canonical permutation gives us the canonicalized expression with the new index configuration:

ToCanonical@expr

standardconfiguration

Summary

The canonicalization involves an algorithm which finds a canonical index configuration for each tensor monomial of a tensorial polynomial.

The canonical index configuration is found by means of an algorithm of permutation group theory (the double coset representative).

To learn more see:
José M. Martín-García, xPerm: fast index canonicalization for tensor computer algebra, Computer Physics Communications 179 (2008) 597-603.
https://doi.org/10.1016/j.cpc.2008.05.009

Exercises

Exercise 1

Define an antisymmetric tensor (Subscript[F, ab]).

Construct scalars of the form:

(Subscript[(F^(Subscript[b, 1])), (Subscript[b, 2])])(Subscript[(F^(Subscript[b, 2])), (Subscript[b, 3])])⋯ (Subscript[(F^(Subscript[b, n-1])), (Subscript[b, n])])(Subscript[(F^(Subscript[b, n])), (Subscript[b, 1])])

Show that these scalars vanish when you give odd values to n.

(Harder) Construct a function which does the computation for arbitrary n.

Answer

Exit

<<xAct`xTensor`

<<xAct`ShowTime1`

DefManifold[M4,4,IndexRange[a,m]]

DefMetric[-1,metric[-a,-b],CD,PrintAs->"g"]

Define the antisymmetric tensor first:

DefTensor[F[-a,-b],M4,Antisymmetric[{-a,-b}]]

Hide away dollar - indices :

$PrePrint=ScreenDollarIndices;

Examples for n=2 and n=3:

F[a,b]F[-b,-a]//ToCanonical

F[a,b]F[-b,-c]F[c,-a]//ToCanonical

We might need additional abstract indices to construct the expressions for higher values of n. For that reason we use GetIndicesOfVBundle:

indices=GetIndicesOfVBundle[TangentM4,11]

{indices,-indices}

Transpose[%]

Flatten[%]

RotateLeft[%]

Partition[%,2]

Apply[F,%,{1}]

Apply[Times,%]

ToCanonical[%]//Timing

Generalization for a product of n-factors:

FProduct[n_]:=Module[{indices,counter},
indices=GetIndicesOfVBundle[TangentM4,n];
counter={indices,-indices};
counter=Transpose[counter];
counter=Flatten[counter];
counter=RotateLeft[counter];
counter=Partition[counter,2];
counter=Apply[F,counter,{1}];
Apply[Times,counter]]

FProduct[79]

ToCanonical@%//AbsoluteTiming