Introduction to xAct

a collection of Mathematica packages for efficient tensor computer algebra.

Teake Nutma

Max-Planck-Institute for Gravitation Physics

(Albert Einstein Institute)

teake.nutma@aei.mpg.de

25th of October, 2012.

Introduction

xAct is a very powerful tensor algebra package for Mathematica. 
It is developed and maintained by José M. Martín-García and collaborators. You can get it for free at http://www.xact.es/ .
Amongst others, it can do the following:

Abstract index manipulation & tensor computations:

(Subscript[▽, a])(Subscript[▽, b])({{T, ({{a, b,  ,  ,  }, { ,  , c, d, e}})}})==(Subscript[▽, b])(Subscript[▽, a])({{T, ({{a, b,  ,  ,  }, { ,  , c, d, e}})}})+({{R[▽], ({{ ,  ,  ,  }, {e, f, a, b}})}}) ({{T, ({{a, b,  ,  , f}, { ,  , c, d,  }})}})+({{R[▽], ({{ ,  ,  ,  }, {d, f, a, b}})}}) ({{T, ({{a, b,  , f,  }, { ,  , c,  , e}})}})+({{R[▽], ({{ ,  ,  ,  }, {c, f, a, b}})}}) ({{T, ({{a, b, f,  ,  }, { ,  ,  , d, e}})}})

Component computations:

({{g, ({{ ,  }, {a, b}})}})==(({{-1-((r^2)/(L^2)), 0, 0}, {0, (1/(1+((r^2)/(L^2)))), 0}, {0, 0, (r^2)}})),    R[▽]==-(6/(L^2))

Perturbations (up to any order!):

△[R[▽]]==-({{h, ({{1, a, b}, { ,  ,  }})}}) ({{R[▽], ({{ ,  }, {a, b}})}})+(Subscript[▽, b])(Subscript[▽, a])({{h, ({{1, a, b}, { ,  ,  }})}})-(Subscript[▽, b])(▽^b)({{h, ({{1, a,  }, { ,  , a}})}})

Invariants of Riemann tensors:

({{R[▽], ({{a, b}, { ,  }})}}) ({{R[▽], ({{ , c, d, e}, {a,  ,  ,  }})}}) ({{R[▽], ({{ ,  ,  ,  }, {b, d, c, e}})}})==(1/2) ({{R[▽], ({{a, b}, { ,  }})}}) ({{R[▽], ({{ , c, d, e}, {a,  ,  ,  }})}}) ({{R[▽], ({{ ,  ,  ,  }, {b, c, d, e}})}})

Spherical harmonics (SU(2) only)

Spinors (4D only)

Export to LaTeX!

But it can’t do everything (yet):

No multiterm symmetries (i.e. Young diagram symmetries)

No SUSY

No group- or Lie-algebra-valued tensors

And you’ll have to beef up on your Mathematica skills if you want to get the most out of it:

f[x] vs x // f vs f@x

x_ vs x__ vs x___

-> vs  :>

UpValues vs DownValues

etc ...

Getting started

Before we start: Mathematica essentials

While you don’t need to be a Mathematica jedi to use xAct, there are some things that make life easier, and some things that are absolutely indispensable. Here we briefly touch some of them.
A good introduction to more advanced Mathematica concepts is “Mathematica programming: an advanced introduction” by Leonid Shifrin. It’s available for free at http://www.mathprogramming-intro.org/

Information (?)

If you forgot what a command actually does, you can use the command Information to get information on that function. The short-hand notation for Information is “?”. So here’s information on Information:

?Information

And here’s the information on Sin:

?Sin

Guessing command names

I often forget the exact name of a command, right when I need it. That’s when the command “Names” comes in handy:

?Names

So when I want to see which Mathematica commands start with “Map”, this gives the answer:

Names["Map*"]

Another way of seeing what all the command names are, is to use the Information command with a wildcard (*):

?Map*

Postfix and prefix notation

The normal way to enter functions is

f[x]

We’ll frequently use the postfix (//) notation and prefix (@) notation, which are equivalent.

x//f

f@x

They both have the advantage of being easier to read if you want to chain a lot of functions:

f@f@f@f@x

x//f//f//f//f

FullForm / InputForm

Mathematica allows users to enter formulas with short-hand notation, even though it stores it internally in a more complex form. You can view the complete form which Mathematica uses to store the expression with FullForm.

?FullForm

Here’s one example:

a+b
%//FullForm

I can also enter the full form, even though it prints as before:

Plus[a,b]

There’s also the InputForm, which returns the easiest way to enter an expression:

Times[a,b]
%//InputForm

The distinction between FullForm and StandardForm is important because xAct has no short-hand notations for entering tensors, but it does format tensors when printing expressions.

Rules, patterns, and replacements

Say we have some expression

expr = Exp[f[x]] (2 + 1/f[y])

and we want to change f[x] into a specific function. For this, a Rule comes in handy:

?Rule

rule = f->Sin

We can use ReplaceAll ( “/.”) to replace all occurences of f with Sin:

expr/.rule

But what if we wanted to replace f[x] with x^2? Let’s see what happens:

expr/.f[x]->x^2

Notice that it didn’t replace f[y], because f[x] doesn’t match f[y]. But we wanted to replace all occurences of f with squares; and for this we need use a blank pattern.

?Blank

We can use MatchQ to test how patterns work. Here’s what we tried to do before, with the f[x]->x^2 statement:

MatchQ[f[x],f[x]]
MatchQ[f[y],f[x]]

But if we now use a blank, we can match both f[x] and f[y]:

MatchQ[f[x],f[x_]]
MatchQ[f[y],f[x_]]

So using the rule f[x_] -> x^2 does the job:

expr/.f[x_]->x^2

One pitfall here is that the variables on the RHS of the rule might have a value:

z=2
expr/.f[z_]->z

In these cases (and others) it’s better to use RuleDelayed (“ :>” ) instead of a rule:

?RuleDelayed

z=2
expr/.f[z_]:>z

Map

Say we have a list,

list = {a,b,c}

and we want to apply a function to every member of that list. This doesn’t work:

f[list]

We wanted to get {f[a],f[b],f[c]}. The procedural way of programming this is to use a “For” loop, but in Mathematica we can use Map :

?Map

Map[f,list]
f/@list

The first steps

I assume you’ve already installed xAct. If you haven’t, go get it now from http://www.xact.es/. It’s free!
The first step is to load the xTensor package with the Get (“<<”) command:

?Get

<<xAct`xTensor`

Before we actually begin, there are a few things worth mentioning:

xAct is actually a collection of packages, all located in the “xAct” directory, and xTensor is the package that handles tensor algebra. That’s why you need to type <<xAct`xTensor`, and not <<xAct`.

xTensor loads the package xPerm, which handles index permutations.

The packages are mature, but they’re not garantueed to be bug-free. If you feel unsafe about their output, don’t be shy to double-check the calculations by hand!

Okay, we’re ready to do some tensor calculations! But how do we get started? What are the commands in xAct? You’ll notice there is no build-in help system like Mathematica’s help browser. But there is quite some documentation available, which came along with your xAct installation (it’s in the directory xAct/Documentation). For instance, here’s the documentation file for xTensor:

NotebookOpen[$xActDirectory<>"/Documentation/English/xTensorDoc.nb"]

If you do get stuck at some, it’s always possible to ask for help at the xAct mailing list at http://groups.google.com/group/xAct

Defining stuff

A quick look in the xTensor documentation tells us that we first need to define a manifold. We can do this with the DefManifold command:

?DefManifold

That doesn’t seem too hard. Let’s name our manifold M, let it be 4 dimensional, and let it have the indices {a,b,c,d,e,f}:

DefManifold[M,4,{a,b,c,d,e,f}]

You’ll notice that besides defining a manifold, this also defined a vector bundle “TangentM” where our tensors will live in. In fact, xAct is build around the notion of “defining” geometric quantities and tensors, and has quite some commands to do so. We can get a list of them with the Information command:

?xAct`xTensor`Def*

The two most important ones (next to DefManifold) are DefMetric, which defines the metric, and DefTensor, which defines a tensor. Let’s first define a metric on our manifold M.

?DefMetric

We don’t need to specify the manifold, because xAct determines that from the indices of the metric. But we do need to specify a symbol for the associated covariant derivative. We’ll name it CD. Oh, and our metric is Lorentzian (hence the -1).

DefMetric[-1,g[-a,-b],CD]

This did a whole lot of things. It first defined a metric, and then a number of curvature tensors (the Christoffel tensors, Riemann, Ricci’s, the Weyl tensor, etc).

Tensors

For instance, we now have a Riemann tensor. It has the same structure as every tensor in xAct, namely the name of the tensor followed by its indices. Because we named our covariant derivative CD, this Riemann tensor is called RiemannCD (it’s the Riemann tensor of the covariant derivative CD). We can input it as follows:

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

Note that it prints much nicer than how it’s put in: xAct formats the indices properly and shortens the name of the tensor to something readable. But underneath it still has the same structure:

%//InputForm

The minus signs in front of the indices indicate that they’re (covariant) lower indices. If we want to put in (contravariant) upper indices, we just forgo the minus sign:

RiemannCD[a,b,c,d]

We can define other tensors with the DefTensor command:

?DefTensor

The simplest type of tensor is a scalar. As they don’t have indices, we can define them with the command

DefTensor[scalar[],M]

It’s very important to not forget the bracket [], even though scalars don’t have indices! Thus

scalar[]

is a valid xAct expression, even though it doesn’t print its indices.

More complicated tensors can be defined by just specifying their index structure. We can also specify if it’s (anti)symmetric as follows:

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

F[-a,-b]

xAct does not automatically enforce the symmetries of the tensor. For instance, this should be zero:

F[-b,-a]+F[-a,-b]

And it is zero, if we use the command “ToCanonical”.

ToCanonical

Arguably one of the most important commands in xAct is ToCanonical.

?ToCanonical

ToCanonical ‘canonicalizes’ expressions, which roughly means ‘sorting the indices and introduce minus signs where necessary’:

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

This introduced a minus sign, because the tensor F is antisymmetric.

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

This didn’t do anything, because the expression was already canonical (it’s indices were already sorted).

The symmetrization of F does reduce to zero if we use ToCanonical:

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

ToCanonical also works on  more general expressions and symmetries. Here is its action on a permutation of the Riemann tensor:

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

ToCanonical interchanged a and b, which introduced a minus sign, and swapped the first pair of indices with the last pair (which happens to be a symmetry of the Riemann tensor).

ContractMetric

We can contract indices with the metric:

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

This is not automatically contracted. We have to use the function ContractMetric if we want to do so:

?ContractMetric

g[a,c]RiemannCD[-a,-b,-c,-d]
%//ContractMetric

This is automatically converted to the Ricci tensor:

%//InputForm

Contracting again gives, as expected, the Ricci scalar:

g[b,d]%//ContractMetric

%//InputForm

Contracting a pair of antisymmetric indices results in zero, but only after using ToCanonical:

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

Covariant derivatives

We defined a covariant derivative CD along with the metric g. Covariant derivatives are entered as

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

Again, this prints much nicer than its input form.

ToCanonical doesn’t touch multiple covariant derivatives.

CD[-c]@CD[-a]@CD[-b]@F[-d,-e]
%//ToCanonical

We’ll have to use the command SortCovDs instead:

?SortCovDs

CD[-c]@CD[-a]@CD[-b]@F[-d,-e]
%//SortCovDs

Note that the covariant derivatives are sorted in what is seemingly a reverse alphabetical order.

You’ve probably also noticed the ugly indices with dollar signs in them. These are automatically generated dummy indices. Although they’re perfectly harmless, they do hinder readability of the expression somewhat. That’s why there’s a handy function ScreenDollarIndices.

ScreenDollarIndices & $PrePrint

Dollar indices are indices of a tangent bundle that are generated on-the-fly in calculations when more indices are necessary than that are around. They can be suppressed with the function ScreenDollarIndices:

?ScreenDollarIndices

Here it is in action:

CD[-c]@CD[-a]@CD[-b]@F[-d,-e]
%//SortCovDs
%//ScreenDollarIndices

Much better!

But of course we don’t want to type “ScreenDollarIndices” after every calculation. That would be stupid. That’s why xAct parses every result through the function associated to the $PrePrint variable:

?$PrePrint

So if we set $PrePrint to ScreenDollarIndices, we’re all set.

$PrePrint=ScreenDollarIndices;

Let’s see if it works:

CD[-c]@CD[-a]@CD[-b]@F[-d,-e]
%//SortCovDs