xTensor & xCoba
 B: Intermediate concepts

José M. Martín-García
	LUTH & IAP, France

LUTH & IAP, 21-29 April 2009

1. Read xTensor again

<<xAct`xTensor`

$PrePrint=ScreenDollarIndices;

2. The delta tensor

Set up a manifold with symbolic dimension :

DefConstantSymbol[dim,PrintAs->"d"]

dim

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

IndicesOfVBundle[TangentM]

Define a tensor :

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

delta: identity tensor in all vector bundles.

delta is written with down - up indices by default :

delta[-a,b]//Validate

delta[a,-b]//Validate

delta[-a,a]

delta[a,-a]

We can change to a particular value of the dimension at any time :

dim=4;

DimOfManifold[M]

delta[-a,a]

It has no symmetry :

SymmetryGroupOfTensor[delta[-a,b]]

Contraction with delta is automatic :

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

With a metric, delta inherits the properties of the metric :

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

delta[a,-b]//Validate

SymmetryGroupOfTensor[delta[a,-b]]

Actually, now delta is automatically converted into the metric :

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

Note : with spinors the metric will be antisymmetric, and delta as well !!!

3. Metric

We have already defined a metric field on our vector bundle.

Objects associated to the metric :

1) The tensor itself :

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

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

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

2) The volume form

epsilonmetric[a,b,c,d]

SymmetryGroupOfTensor[epsilonmetric]

and the metric determinant :

Detmetric[]

3) Its Levi - Civita connection :

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

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

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

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

4) Tensors associated to the connection (note Wald's index conventions):

ChristoffelCD[a,-b,-c]

SymmetryGroupOfTensor[%]

TorsionCD[a,-b,-c]

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

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

RicciCD[-a,-b]

RicciScalarCD[]

EinsteinCD[-a,-b]

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

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

TFRicciCD[-a,-b]

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

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

5) Tetra :

Tetrametric[a,b,c,d]

Tetrametric[a,b,c,d]/.TetraRule[metric]

Tetrametric†[a,b,c,d]/.TetraRule[metric]

%//ToCanonical

4. Non-compatible derivatives

Sometimes we work with metrics and derivatives which are not compatible with the metric:

DefTensor[X[a,-b],M]

X[b,-c]X[c,-d]

ToCanonical[%]

Now we put a compatible derivative :

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

ToCanonical[%]

And now we put a non-compatible derivative :

X[b,-c]PD[-a][ X[c,-d] ]

ToCanonical[%]

This can be deactivated with

SetOptions[ToCanonical,UseMetricOnVBundle->None]

X[b,-c]PD[-a][ X[c,-d] ]

ToCanonical[%]

Three options :
  - Allow ToCanonical to produce lots of Christoffels (you handle them later).
  - Do not allow it, and do not use ContractMetric.
  - Use "implosion" :

4b. Implosion

(Alfonso's idea; the names are all my fault.)

SetOptions[ToCanonical,UseMetricOnVBundle->All]

X[b,-c]PD[-a][ X[c,-b] ]

%//Implode

%//InputForm

%//ToCanonical

%//Explode

X[b,-c]PD[-a][ X[c,-b] ]

ToCanonical[%,Method->Implode]

Implosion leaves the additional tensors :

$Tensors

5. Several metrics

Suppose that we introduce another metric :

DefMetric[-1,METRIC[-a,-b],cd,SymbolOfCovD->{"|","D"}]

Now the inverse of this metric is :

InvMETRIC[a,b]METRIC[-b,-c]

and not

METRIC[a,b]METRIC[-b,-c]

That is equal to

SeparateMetric[metric][%]

ContractMetric[%]

Beware! This feature has not been tested much.

6. Tensor Rules

By inforcing type declaration we avoid problems like this:

rule=A[B_]->B[B];

A[C]/.rule

However we still have

rule=A[b_]->B[d,-d,b];

A[d]/.rule

Suggestion of Mathematica: use unique variables:

rule=A[b_]:>Module[{d},B[d,-d,b]]

A[d]A[-d]/.rule

B is not a tensor and hence ScreenDollarIndices has no effect. On a defined tensor:

DefTensor[F[a,b],M,Antisymmetric[{1,2}]]

F[d$18,-d$18]

6a. IndexRule

We can avoid building the Module by using (note that there are patterns):

DefTensor[v[a],M]

rule=IndexRule[v[b_],v[a]F[-a,b]]

InputForm[%]

v[a]v[b]/.rule

v[c]v[d]/.rule

Rule is replaced by IndexRule and Set by IndexSet (there are also delayed counterparts).

6b. MakeRule: full control on rules

Typical problem:

rule=F[a_,b_]v[-b_]:>v[a]

{F[c,d]v[-d],F[d,c]v[-d]}/.rule

Solution (note that there are no patterns):

rule=MakeRule[{F[a,b]v[-b],v[a]}]

Options[MakeRule]

{F[c,d]v[-d],F[d,c]v[-d]}/.rule

(cont. 6b)

Options[MakeRule]

We have just seen an example of the use of UseSymmetries->True.
PatternIndices says the indices that must be considered as patterns.
TestIndices->True checks the vbundles of the indices.
MetricOn says the indices in which we allow changes of character.
ContractMetrics->True tries to contract metrics on the RHS.

First[rule]//InputForm

(cont. 6b)

Now we use the metric:

rule=MakeRule[{F[-a,-c],PD[-b][F[b,-a]]v[-c]},MetricOn->All]

{F[a,b],F[a,-b],F[-a,b],F[-a,-b]}/.rule

We can eliminate unnecessary metric factors :

rule=MakeRule[{F[-a,-c],PD[-b][F[b,-a]]v[-c]},MetricOn->All,ContractMetrics->True]

{F[a,b],F[a,-b],F[-a,b],F[-a,-b]}/.rule

(cont. 6b)

Long example:

rule=MakeRule[{F[-a,-b]F[b,c]v[-c],v[-a]},MetricOn->All,ContractMetrics->True]

Length[%]

Another example :

rule=MakeRule[{T[-a,-b,-c]v[c],F[-a,-b]},MetricOn->All]

T[a,b,c]v[-c]/.rule

7. Other types: ConstantSymbol

We have seen the types
	Manifold
	VBundle
	AbstractIndex
	Tensor
	CovD
	Metric
Now we will describe four other types. A ConstantSymbol :

DefConstantSymbol[GNewton,PrintAs->"(Subscript[G, N])"]

PD[-a][GNewton]

CD[-a][GNewton]

D[GNewton,x]

7b. Type Parameter and ParamD

Define a real parameter:

DefParameter[time,PrintAs->"t"]

Now tensors can also depend upon that parameter:

DefTensor[U[a],{M,time}]

DependenciesOf returns both manifold and parameter dependencies:

DependenciesOf[3U[a]U[b]]

ParamD[time][3U[a]U[b]]

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

7c. Type InertHead. Scalar

InertHeads are almost transparent to index manipulations, but carry additional information.

DefInertHead[TFPart]

TFPart/:TFPart[expr_]delta[-a_,b_]:=0/;IsIndexOf[expr,a]&&IsIndexOf[expr,-b];

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

TFPart[T[a,-b]U[c]U[d]]delta[-c,b]

Are these two equivalent ?

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

(cont. 7c)

Two special inert heads:

ERROR

ERROR[3F[-a,-b]]

%U[a]U[b]//ToCanonical

Scalar

(U[a]U[-a])^2

F[b,-b]^2/.IndexRule[F[c_,-c_],U[a]U[-a]]

Scalar[U[a]U[-a]]^2

Scalar[F[b,-b]]^2/.IndexRule[F[c_,-c_],U[a]U[-a]]

NoScalar[%]

PutScalar[%]

7d. Type ScalarFunction

A real function of two real arguments :

DefScalarFunction[SF,2]

$ScalarFunctions

?SF

SF[U[a]U[-a],F[]]

CD[-a][%]

8. Lie derivatives

General notation:

LieD[ U[a] ][ F[-a,-b] ]

Any vector field is valid:

expr=LieD[ 3F[b,a]U[-a]+U[b] ][ F[-a,-b] ]

expr U[a]U[b]//ToCanonical

8b. Lie derivatives to CovD derivatives

expr

LieDToCovD[expr,PD]

LieDToCovD[expr,CD]

%//ToCanonical

8c. Lie brackets

Together with tensors and covds, Bracket is the only other structure with abstract indices:

Bracket[a][U[b],U[b]]

Bracket[a][U[c],T[c]]

BracketToCovD[%,CD]

There is no Jacobi property implemented.

8d. Directions

Two notations for vector contraction:

expr1=U[a]F[-a,-b]

expr2=F[Dir[U[a]],-b]

We can switch between them :

SeparateDir[expr2]

ContractDir[%,U]

Again, Dir can contain any vector field (note the special formatting for larger expressions)

F[a,Dir[ 3U[b]+F[b,a]U[-a]]]

9. Component calculus with xCoba

Load xCoba:

<<xAct/xCoba.m

7a. Type Basis

Define an arbitrary frame. We have not yet specified its properties :

DefBasis[fr,TangentM,{0,1,2,3}]

Bases are represented with colors. Default is Red.

$Bases

7b. Frame vectors and covectors. Basis

Frame vectors :

Basis[{1,-fr},a]

Frame covectors :

Basis[-a,{1,fr}]

Basis is formally equivalent to delta. There is automatic translation:

delta[-a,{0,fr}]

Basis[-a,b]

Identities: duality and completeness :

Basis[-a,{b,fr}]Basis[{-c,-fr},a]

ContractBasis[%]

Basis[-a,{b,fr}]Basis[{-b,-fr},c]

ContractBasis[%]

Note the difference between the identity tensor and the Kronecker delta.

Basis[-a,{1,fr}]Basis[{3,-fr},a]

ContractBasis[%]

{Basis[{3,-fr},{1,fr}],Basis[{3,-fr},{3,fr}]}

7c. The parallel derivative

There is a single connection associated to the frame (its "parallel derivative", which is always flat, but may have torsion). See Bishop and Goldberg.

PDfr[-a][ Basis[{-b,-fr},c] ]

PDfr[-a][ Basis[-b,{c,fr}] ]

Any other derivative on the basis returns the Christoffel tensor from that derivative to the parallel derivative of the basis :

CD[-a][ Basis[-b,{c,fr}] ]

(Ricci rotation coefficients, Christoffels, Cartan calculus all at once!).

The frame is coordinated if and only if the parallel derivative has zero torsion (we call it then a "partial derivative") :

Bracket[a][Basis[{-b,-fr},c],Basis[{-c,-fr},d]]

Notation for components :

InputForm[%]

It is a shortcut of

Dir[Basis[{-c,-fr},a]]

This is the idea of "marked indices" (Schouten 1954).

7d. Type Chart

DefChart[schw,M,{0,1,2,3},{t[],r[],θ[],ϕ[]},ChartColor->Blue]

Coordinate covectors :

PDschw[-a][r[]]

It is a coordinated frame :

Bracket[a][Basis[{1,-schw},c],Basis[{2,-schw},c]]

Christoffels :

CD[-a][Basis[{-b,-schw},c]]

7e. Metric fields

DefConstantSymbol[Mass,PrintAs->"M"]

There are several different ways of doing this type of computations.

Give the metric in abstract form :

metric[-a_Symbol,-b_Symbol]=-(1-2Mass/r[])PD[-a][t[]]PD[-b][t[]]+1/(1-2Mass/r[])PD[-a][r[]]PD[-b][r[]]+r[]^2(PD[-a][θ[]]PD[-b][θ[]]+Sin[θ[]]^2PD[-a][ϕ[]]PD[-b][ϕ[]])

Compute inverse :

InverseMetric[metric[-a,-b],schw][a,b]

metric[a_Symbol,b_Symbol]=Collect[%,_Basis,Simplify]

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

ChristoffelCDPDschw[a_Symbol,-b_Symbol,-c_Symbol]=Collect[%,_Basis,Simplify]

RiemannFromChristoffel[%,schw][-a,-b,-c,d]

RiemannCD[-a_Symbol,-b_Symbol,-c_Symbol,d_Symbol]=Collect[%,_Basis,Simplify]

Ricci vanishes :

RiemannCD[-a,-b,-c,d]delta[-d,b]//ContractBasis

Lowering indices :

RiemannCD[-a,-b,-c,e]metric[-e,-d]//ContractBasis

RiemannCD[-a_Symbol,-b_Symbol,-c_Symbol,-d_Symbol]=Collect[%,_Basis,Simplify]

Check symmetries :

RiemannCD[-a,-b,-c,-d]+RiemannCD[-a,-b,-d,-c]//Expand

A particular component :

ChristoffelCDPDschw[{1,schw},{1,-schw},{1,-schw}]

%//SeparateBasis[]

%//ContractBasis

Remove values for the metric :

metric[-a_Symbol,-b_Symbol]=.
metric[a_Symbol,b_Symbol]=.

7f. Metric fields again

Let us do the same computation in a very different way.

MetricInBasis[metric,-schw,{-(1-2 Mass/r[]),1/(1-2 Mass/r[]),r[]^2,r[]^2 Sin[θ[]]^2}]

Now the values are stored in TensorValues, separating dependent and independent components:

TensorValues[metric]

Column/@%

The foldedrule can be used as any other rule :

metric[{2,-schw},{1,-schw}]

%/.TensorValues[metric]

Let us know construct the metric :

metric[-a,-b]

%//SeparateBasis[schw]

%//TraceBasisDummy

met=%/.TensorValues[metric]

Its inverse :

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

%/.TensorValues[metric]

Inverse[%]//Simplify

%BasisArray[schw,schw][b,c]

imet=Total[Flatten[%]]

Check that they are inverses :

met imet

ContractBasis[%]

Simplify[%]

Let us compute the Christoffel tensor from basic principles now :

zero=CD[-c][met]

Convert all indices into basis - indices :

zero//ToBasis[schw]

and expand into an array of components :

%//ComponentArray

Now canonicalize :

%//ToCanonical

Construct a list of equations :

eqs=Map[#==0&,Union@Flatten[%]]

and solve for all components of the Christoffel :

Simplify@Solve[eqs,Cases[eqs,_ChristoffelCDPDschw,Infinity]]

7g. Frame calculus: Newman-Penrose

Define a new frame:

DefBasis[NP,TangentM,{1,2,3,4},BasisColor->Green]

This is a complex basis and we specify the behaviour of the elements under complex conjugation:

SetDaggerMatrix[NP,{{1,0,0,0},{0,1,0,0},{0,0,0,1},{0,0,1,0}}]

That means that

BasisArray[NP][a]

Dagger/@%

The same metric is now given in terms of this basis as:

MetricInBasis[metric,-NP,{{0,1,0,0},{1,0,0,0},{0,0,0,-1},{0,0,-1,0}}]

Note that the metric coefficients are constants, even though the metric is non-trivial. This cannot happen in coordinate calculus, which stores all nontrivial information in derivatives of the metric.

The values just given are not a definition of a metric. Any Lorentzian metric can be written like that. The only thing we have done is specifying part of the basis with respect to the metric.

Again, let us construct the full metric objects:

metric[-a,-b]//SeparateBasis[NP]

NPmet=TraceBasisDummy[%]/.TensorValues[metric]

NPimet=InverseMetric[NPmet,NP][b,c]

NPmet NPimet//ContractBasis

Let us now compute the change of basis. These are two expressions of the same metric, and hence must coincide:

met-NPmet

Let us expand that expression in the coordinated frame:

%//ToBasis[schw]

ComponentArray[%]

Construct a set of equations for the change of basis:

eqs=Map[#==0&,Union@Flatten[%]]

The system is largely underdetermined. This is because we have six free Lorentz rotations to define the NP basis. Hence we choose six convenient values:

choice={Basis[{0,-schw},{3,NP}]->0,Basis[{0,-schw},{4,NP}]->0,Basis[{1,-schw},{3,NP}]->0,Basis[{1,-schw},{4,NP}]->0,Basis[{2,-schw},{3,NP}]->r[],Basis[{1,-schw},{2,NP}]->1}

eqs/.choice

We solve and simplify:

Solve[%,Cases[%,_Basis,Infinity]][[1]]//FullSimplify//PowerExpand//Simplify

As we had anticipated, the NP frame is complex.

Join[choice,%]

Store those values:

ComponentValue[%]

This is the change-of-basis matrix:

ComponentArray[Basis[-{a,schw},{b,NP}]]/.TensorValues[Basis]

And this is its inverse:

Inverse[%]//FullSimplify

Store as well:

AllComponentValues[Basis[-{a,NP},{b,schw}],%]

Let us check that we can change from one metric to the other:

met

SeparateBasis[NP][%]

TraceBasisDummy[%]

%/.TensorValues[Basis]

%//Simplify

%==NPmet