Exit

xAct`xPert`

Authors

© 2005-2018, under the GNU General Public License (GPL)

David Brizuela, david.brizuela@ehu.eus
José M. Martín-García, jose@xact.es
Guillermo A. Mena Marugán, mena@iem.cfmac.csic.es

Intro

xPert` is a package for efficient construction and manipulation of high-order perturbations of the curvature tensors of a Riemannian manifold. Its main application is Perturbation Theory in General Relativity.
xPert` is part of the xAct` framework for Tensor Computer Algebra in Mathematica, and in particular it needs the underlying package xTensor` for abstract tensor manipulations.

Load the package

This loads the package from the default directory, for example $HOME/.Mathematica/Applications/xAct/ for a single-user installation under Linux. xTensor` and xPerm` are automatically loaded.

<<xAct`xPert`

The default options of MakeRule and ContractMetric have been changed:

Options[MakeRule]

Options[ContractMetric]

We also load the timing package and lower its default threshold of 1 second to 0.1 seconds

<<xAct`ShowTime1`

$ShowTimeThreshold=0.1;

We define a function to collect and canonicalize equal-order terms:

org[expr_]:=Collect[ContractMetric[expr],$PerturbationParameter,ToCanonical]

0. Set up

xPert`  has been built on xTensor`  and shares its notation. Then, a session with xPert` begins just like one with xTensor`, defining one or more manifolds and vector bundles and the objects living on them:

Define a 4d manifold M. Note that most of the results will not depend on the chosen dimension.

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

We also define a metric on this manifold, with negative determinant and associated covariant derivative CD. This derivative is extended to act on tensor densities defined using the determinant of the metric g in the basis AIndex:

DefMetric[-1,g[-a,-b],CD,{";","D"},WeightedWithBasis->AIndex]

The absolute value of its determinant in the basis AIndex is obtained as

Determinant[g][]

and it is actually called

InputForm[%]

By default, curvature tensors are output showing the name of the derivative they are associated to:

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

Because we shall work with a single covariant derivative operator, we can choose a simpler output for the geometric tensors

PrintAs[RiemannCD]^="R";
PrintAs[RicciCD]^="R";
PrintAs[RicciScalarCD]^="R";
PrintAs[ChristoffelCD]^="Γ";
PrintAs[EinsteinCD]^="G";

so that now

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

After defining the background manifold in xTensor`, we now define the perturbative structure with the command DefMetricPerturbation of xPert`.

We define the symmetric two-tensor h that will be understood as the perturbation of the metric. As can be seen in the output, the first index of this tensor is a label index (LI), which will encode the perturbative order.

DefMetricPerturbation[g,h,ϵ]

The perturbative parameter ϵ is stored in the global variable

$PerturbationParameter

Finally, we colour in blue the perturbative orders

Unprotect[IndexForm];
IndexForm[LI[x_]]:=ColorString[ToString[x],RGBColor[0,0,1]];
Protect[IndexForm];

IndexForm[LI[n]]

1. Perturbations of the metric and fundamental properties

The main objective of xPert` is giving the n-th perturbation of any object in terms of metric perturbations of order n and lower. Here we introduce the Perturbation head and give examples of use of different perturbative orders. For those readers already familiar with xTensor`, let us point out that the symbol Perturbation is a linear inert-head.

The perturbation of the metric is represented as follows:

Perturbation[ g[-a,-b] ]

Perturbation has actually two argumens in general. The first one is the expression we want to perturb and the second one the perturbative order (with default 1 when it is not specified, as in the previous case). For instance, acting on the metric at fifth perturbative order returns

Perturbation[g[-a,-b],5]

Or on the perturbed tensor itself,

Perturbation[h[LI[3],-a,-b],5]

It also knows how to act on a Kronecker delta

Perturbation[delta[a,-b],3]

Perturbation uses the fundamental properties of a derivative: linearity and Leibnitz rule. When it does not know the answer of the action on a given tensor, for example the inverse of the metric or the Ricci tensor, the head Perturbation is kept (this is where its inert-head character plays a role):

Perturbation[g[-a,-b]+g[c,d]RicciCD[-a,-c]RicciCD[-d,-b]]

We can consider the same case but at a higher perturbative order, for instance at seveteenth order and see that the calculation is almost immediate.

Perturbation[g[-a,-b]+g[c,d]RicciCD[-a,-c]RicciCD[-d,-b],17]

The perturbative order of an expression can be computed with

PerturbationOrder[%]

By definition, Perturbation commutes with partial derivatives,

Perturbation[PD[-a][RicciCD[-c,-d]],5]

and with covariant derivatives acting on scalars,

Perturbation[CD[-a][RicciScalarCD[]],6]

but not with covariant derivatives acting on tensors,

Perturbation[CD[-a][RicciCD[a,-b]],3]

It is essential to have in mind that the ToCanonical or Simplification commands cannot be used as long as there is any Perturbation head in the expression because internal indices of the expression inside Perturbation could be moved improperly. A warning reminds us of the danger:

For example the expression

h[LI[3],-a,-e]CD[-d][Perturbation[RicciCD[a,e]]]

is not properly canonicalized here:

%//ToCanonical

This is not a restriction at all. It just means that the perturbations must be replaced by other tensor expression before canonicalization. How this is done is shown next. In case canonicalization at this stage is really needed the right sequence of commands is

ToCanonical[%%//SeparateMetric[]//ContractMetric,UseMetricOnVBundle->None]

which uses explicit metric factors instead of moving indices up and down.

2. ExpandPerturbation

The command ExpandPerturbation is the most powerful one of this package. As we have seen, the Perturbation operator automatically uses linearity and the Leibnitz rule to expand expressions. But up to now it only knows how to act on the metric with covariant indices. All other cases are handled by ExpandPerturbation, which makes use of exact formulas to expand the perturbations of any geometric object.

The perturbations of the inverse metric are

Perturbation[g[a,b]]

%//ExpandPerturbation

Perturbation[g[a,b],4]

%//ExpandPerturbation

or the perturbations of the Ricci tensor are

Perturbation[RicciCD[-a,-b]]//ExpandPerturbation

Perturbation[RicciCD[-a,-b],2]//ExpandPerturbation

The ExpandPerturbation command has been only predefined on certain tensors, and only when those have indices with their expected characters (for the Ricci tensor, for example, both indices are expected to be covariant; all characters are accepted for the metric). All other cases and derivatives of the tensors are handled through optional internal algorithms.

ExpandPerturbation has two options, which are by default switched on:

Options[ExpandPerturbation]

SeparateMetric moves indices into their character (covariant or contravariant) specified at definition time,  introducing metric factors if required (this is performed using the SeparateMetric command in xTensor`, hence the name of the option). For instance:

Perturbation[RicciCD[a,b]]

%//ExpandPerturbation

The additional metric factors can be absorbed using ContractMetric:

%//ContractMetric

ExpandPerturbation[%%%,SeparateMetric->False]

OverDerivatives allows to jump over Lie or covariant derivatives. The latter gives perturbations of the Christoffel symbols, that are also expanded into derivatives of metric perturbations. For example,

Perturbation [CD[-a][RicciCD[-b,-c]]]

%//ExpandPerturbation

ExpandPerturbation[%%,OverDerivatives->False]

In order to show an example with Lie derivatives, we need a vector-field

DefTensor[v[a],M]

We perturb now at fourth-order the Lie derivative of the metric along a vector field:

Perturbation [LieD[v[a]][g[-a,-b]],4]

Note that the perturbation of a Lie derivative can be written in terms of Lie derivatives only

%//ExpandPerturbation

Again, nothing happens when switching-off the option OverDerivatives

ExpandPerturbation[%%,OverDerivatives->False]

3. Perturbations of curvature tensors

In this section we show how ExpandPerturbation acts on the most important geometric tensors of a Riemannian manifold, at any perturbative order. We shall compare its direct action at a particular order with a recursive computation of that order from lower orders. This is both a consistency check and an example of the efficiency of the direct action.

3.1. Perturbations of the inverse metric

Let us start comparing the seventh-order recursive and direct perturbations of the inverse of our metric tensor field.

Recursively :

Perturbation[g[a,b]]//ExpandPerturbation

%//Perturbation//ExpandPerturbation

%//Perturbation//ExpandPerturbation//org

%//Perturbation//ExpandPerturbation//org

%//Perturbation//ExpandPerturbation//org

%//Perturbation//ExpandPerturbation//org

%//Perturbation//ExpandPerturbation//org

Applying ExpandPerturbation directly,

Perturbation[g[a,b],7]//ExpandPerturbation

Comparison and check:

%-%%//ToCanonical

Another interesting check is proving that the perturbed inverse of the metric is in fact the inverse of the perturbed metric up to the correct order. For that we will use another xPert` command named Perturbed that expands an expression into a power series up to the order provided.

The power series of the perturbed metric up to fifth order (note that we do not use the Series construct of Mathematica)

Perturbed[g[-a,-b],5]

The corresponding expansion for its inverse

Perturbed[g[b,c],5]//ExpandPerturbation

And the check

% %%//org

3.2. Perturbations of the determinant of the metric and the antisymmetric tensor

Now we compute the perturbations of the determinant of the metric up to sixth order. Two comments are in order:
First, note that the result is always proportional to the determinant itself times a combination of contracted metric perturbations. This proportionality scalar depends on the dimension we are considering. In fact, for a given dimension N, there cannot be products of more than N metric perturbations (recall that N=4 in our examples). Timings are highly dependent on the dimensions because the internal algorithms use determinants of NxN matrices.
Second, the concept of determinant is basis-dependent (actually a density) and hence can only be treated properly using xCoba`, the xAct` package for component computations in a given basis. xTensor` implements a fake basis called AIndex, which we will assume throughout this subsection.

Low order perturbations of the determinant:

Perturbation[Detg[]]//ExpandPerturbation//Simplification

Perturbation[Detg[],2]//ExpandPerturbation//Simplification

Perturbation[Detg[],3]//ExpandPerturbation//Simplification

Perturbation[Detg[],4]//ExpandPerturbation//Simplification

Now the perturbative order will exceed the dimension. Still we get just products of up to four metric perturbations. In other dimensions these formulas would be wrong:

Perturbation[Detg[],5]//ExpandPerturbation//Simplification

Perturbation[Detg[],6]//ExpandPerturbation//Simplification

Perturbations of the antisymmetric volume-form tensor are given in terms of the perturbations of the determinant of the metric and have a similar structure.

At first-order

Perturbation[epsilong[-a,-b,-c,-d]]//ExpandPerturbation//Simplification

At third-order (note the head Scalar; see the documentation of xTensor` for a description)

Perturbation[epsilong[-a,-b,-c,-d],3]//ExpandPerturbation//Simplification

Note that now there are five h factors multiplying due to the perturbation of Sqrt[Detg[]], and not only of Detg[]. The formula is still valid only in dimension 4 for the reasons above:

Perturbation[epsilong[-a,-b,-c,-d],5]//ExpandPerturbation//Simplification

3.3. Perturbations of the Christoffel symbols

In order to obtain the perturbation of the Christoffel symbols, we can write them in terms of partial derivatives of the metric and then apply the ExpandPerturbation command that will only act on metrics and inverse metrics. It is faster to do it directly applying ExpandPerturbation, that will calculate the perturbation by making use of non-recursive formulas for the n-th order perturbation of the Christoffel symbols. We shall check and compare the relative efficiency of both methods.

First-order perturbation of the Christoffel in terms of the metric and its inverse

Perturbation[ChristoffelCD[a,-b,-c]//ChristoffelToMetric]

We will frequently convert partial derivatives into covariant derivatives to help canonicalizing:

CovDToChristoffel[%//ExpandPerturbation,PD,CD]//org

Comparison with the direct action of ExpandPerturbation

%-(Perturbation[ChristoffelCD[a,-b,-c]]//ExpandPerturbation)//Simplification

We do the same for the second-order perturbation

Perturbation[ChristoffelCD[a,-b,-c]//ChristoffelToMetric,2]

CovDToChristoffel[%//ExpandPerturbation,PD,CD]//org

%-ExpandPerturbation[Perturbation[ChristoffelCD[a,-b,-c],2]]//ToCanonical

At third order

Perturbation[ChristoffelCD[a,-b,-c]//ChristoffelToMetric,3]

CovDToChristoffel[%//ExpandPerturbation,PD,CD]//org

%-ExpandPerturbation[Perturbation[ChristoffelCD[a,-b,-c],3]]//ToCanonical

And finally at four order

Perturbation[ChristoffelCD[a,-b,-c]//ChristoffelToMetric,4]

CovDToChristoffel[%//ExpandPerturbation,PD,CD]//org

%-ExpandPerturbation[Perturbation[ChristoffelCD[a,-b,-c],4]]//ToCanonical

Note that the first method is much slower: let us compute the seventh-order perturbations:

tmp1=CovDToChristoffel[Perturbation[ChristoffelCD[a,-b,-c]//ChristoffelToMetric,7]//ExpandPerturbation,PD,CD]//org;

tmp2=ExpandPerturbation[Perturbation[ChristoffelCD[a,-b,-c],7]]//org;

tmp1-tmp2//ToCanonical

3.4. Perturbations of the Riemann tensor

As we have done for the Christoffel symbols, we can calculate the perturbations of Riemann in two ways. The first one will start from the expression of Riemann tensor in terms of the metric, its inverse and partial derivatives. The second will apply directly ExpandPerturbation.

At first order going through the metric

Perturbation[RiemannCD[-a,-b,-c,d],1]//RiemannToChristoffel//ChristoffelToMetric

ChangeCovD[%//ExpandPerturbation,PD,CD]//org

Applying directly ExpandPerturbation

Perturbation[RiemannCD[-a,-b,-c,d],1]//ExpandPerturbation

Comparison

%%-%//ToCanonical

That result is usually presented with only four covariant derivatives, but with 10 Riemann terms (which vanish in vacuum):

%%//SortCovDs//ToCanonical

At second order going through the metric

Perturbation[RiemannCD[-a,-b,-c,d],2]//RiemannToChristoffel//ChristoffelToMetric

ChangeCovD[%//ExpandPerturbation,PD,CD]//org

Applying directly ExpandPerturbation

Perturbation[RiemannCD[-a,-b,-c,d],2]//ExpandPerturbation

Comparison

%%-%//ToCanonical

There is a large difference between the timings of both methods.

Here we show that the recursive method takes more of less the same time to compute the third-order perturbation as the direct method takes for the seventh-order one:

ChangeCovD[Perturbation[RiemannCD[-a,-b,-c,d],3]//RiemannToChristoffel//ChristoffelToMetric//ExpandPerturbation,PD,CD]//org;

ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],7]]//org;

3.5. Perturbations of the Ricci tensor

The Ricci tensor is a simple trace of the Riemann tensor and hence behaves very similarly.

First-order perturbation going through the metric

ChangeCovD[Perturbation[RiemannCD[-a,-c,-b,c]//RiemannToChristoffel//ChristoffelToMetric],PD,CD]//ExpandPerturbation//org

Applying directly ExpandPerturbation

Perturbation[RicciCD[-a,-b]]//ExpandPerturbation//org

Comparison

%%-%//ToCanonical

Second-order perturbation going through the metric

ChangeCovD[Perturbation[RiemannCD[-a,-c,-b,c]//RiemannToChristoffel//ChristoffelToMetric,2],PD,CD]//ExpandPerturbation//org

Applying directly ExpandPerturbation

Perturbation[RicciCD[-a,-b],2]//ExpandPerturbation//org

Comparison

%%-%//ToCanonical

Third-order perturbation going through the metric

ChangeCovD[Perturbation[RiemannCD[-a,-c,-b,c]//RiemannToChristoffel//ChristoffelToMetric,3],PD,CD]//ExpandPerturbation//org

Applying directly ExpandPerturbation

Perturbation[RicciCD[-a,-b],3]//ExpandPerturbation//org

Comparison

%%-%//ToCanonical

Let us just compute the fourth-order perturbation making use only of the direct approach. Note that what really takes times is not to construct the perturbation itself but to simplify it.

Perturbation[RicciCD[-a,-b],4]//ExpandPerturbation;

%//org

Some more examples:

Perturbation[RicciCD[-a,-b],8]//ExpandPerturbation;

Perturbation[RicciCD[-a,-b],12]//ExpandPerturbation;

3.6. Perturbations of the Ricci scalar

The Ricci scalar is computed from a double trace of the Riemann tensor.

ricciscalar=g[a,b]RiemannCD[-a,-c,-b,c]//RiemannToChristoffel//ChristoffelToMetric//NoScalar//Simplification

First-order perturbation from the metric

ChangeCovD[Perturbation[ricciscalar]//ExpandPerturbation,PD,CD]//org

Applying directly ExpandPerturbation

Perturbation[RicciScalarCD[]]//ExpandPerturbation//org

Comparison

ChangeCovD[%-%%//RiemannToChristoffel,PD,CD]//Simplification

Second-order perturbation from the metric

ChangeCovD[Perturbation[ricciscalar,2]//ExpandPerturbation,PD,CD]//org

Applying directly ExpandPerturbation

Perturbation[RicciScalarCD[],2]//ExpandPerturbation//org

Comparison

ChangeCovD[%-%%//RiemannToChristoffel,PD,CD]//Simplification

Third-order perturbation iteratively from metric perturbations

ChangeCovD[Perturbation[ricciscalar,3]//ExpandPerturbation,PD,CD]//org

Applying directly ExpandPerturbation

Perturbation[RicciScalarCD[],3]//ExpandPerturbation//org

Comparison

ChangeCovD[%%-%//RiemannToChristoffel,PD,CD]//org

That expression is indeed only zero for a Levi-Civita connection. To show it we change back to partial derivatives and expand the Christoffels into derivatives of the metric:

ChangeCovD[%,CD,PD]//ToCanonical

%//ChristoffelToMetric//ToCanonical

Fourth-order perturbation iteratively from metric perturbations

ChangeCovD[Perturbation[ricciscalar,4]//ExpandPerturbation,PD,CD]//org;

Applying directly ExpandPerturbation

Perturbation[RicciScalarCD[],4]//ExpandPerturbation//org;

Comparison

ChangeCovD[%%-%//ToCanonical//RiemannToChristoffel,PD,CD]//Simplification

Again, this is zero for a Levi-Civita connection (we do not use the metric in the index-canonicalization process to avoid problems with the partial derivatives):

Simplification[ChangeCovD[%,CD,PD],UseMetricOnVBundle->None]

Simplification[%//ChristoffelToMetric,UseMetricOnVBundle->None]

3.7. Perturbations of the Einstein tensor

To help in the recursive computation, we define the Einstein tensor in terms of the Christoffels instead of the metric.

einstein=EinsteinCD[-a,-b]//EinsteinToRicci//RiemannToChristoffel//NoScalar//Simplify

The first-order perturbation from the Christoffel perturbations:

Perturbation[einstein]//ExpandPerturbation//NoScalar

Appliying directly ExpandPerturbation

Perturbation[EinsteinCD[-a,-b]]//ExpandPerturbation

Comparison

ChangeCovD[%%-%//RiemannToChristoffel//NoScalar,PD,CD]//ToCanonical

The second-order perturbation from Christoffel perturbations:

Perturbation[einstein,2]//ExpandPerturbation

Applying directly ExpandPerturbation

Perturbation[EinsteinCD[-a,-b],2]//ExpandPerturbation

Comparison

ChangeCovD[%%-%//RiemannToChristoffel//NoScalar,PD,CD]//ToCanonical

Note that ExpandPerturbation is really fast. The seventh-order perturbation of the Einstein tensor is computed in just a few seconds.

Perturbation[EinsteinCD[-a,-b],7]//ExpandPerturbation;

3.8. Perturbations of the Weyl tensor

The Weyl tensor is given here in terms of Riemann, Ricci and the Ricci scalar. Giving it in terms of the metric would be too slow.

Weyl in terms of Riemann:

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

Perturbation[%]//ExpandPerturbation

The first-order perturbation applying directly ExpandPerturbation is also internally computed along the same lines:

Perturbation[WeylCD[-a,-b,-c,-d],1]//ExpandPerturbation

Comparison:

%-%%//ToCanonical

4. Perturbations of other objects. Densities

Usually we have other, user-defined, geometric objects defined on our manifold. For instance, matter fields. In this section we will see how to construct a tensor that is the perturbation of another one. We will also show that this can be done for densities as well.

Let us define a rank-3 tensor T and a rank-2 symmetric +1-density Π. Note that the characters of the indices at definition will be later privileged in the computation.

DefTensor[T[-a,b,c],M]
DefTensor[Π[b,c],M,Symmetric[{b,c}],WeightOfTensor->AIndex]

We can also define some constant symbol, whose perturbation would be automatically zero

DefConstantSymbol[κ]

We define another two tensors which will represent the perturbations of the previous tensors, and hence must have the same density character. The syntaxis is parallel to that of DefTensor:

DefTensorPerturbation[τ[LI[order],-a,b,c],T[-a,b,c],M]
DefTensorPerturbation[P[LI[order],b,c],Π[b,c],M,Symmetric[{b,c}],WeightOfTensor->AIndex]

Now we have

Perturbation[T[-a,b,c],3]

Perturbation[Π[a,b],2]

Now we can do the perturbation of any expression containing these and the geometric tensors with any index positioning. When the indices are in the natural position, the perturbation will be directly computed

Perturbation[T[-a,b,c]Π[d,e],2]

But when they are in a different position we have to make use of ExpandPerturbation

Perturbation[T[-a,b,-c]Π[-d,e],2]

%//ExpandPerturbation

We can also do more difficult computations at higher order

RicciCD[-a,b]Π[-b,d]+Π[-a,c]RiemannCD[-c,b,-b,d]+Π[-a,b]T[d,-b,c]T[-c,-e,e]

Perturbation[%,3]

%//ExpandPerturbation//ContractMetric//ToCanonical

In the context of xTensor`, we can define scalar functions:

DefScalarFunction[F]

It must have scalar arguments. For example,

F[RicciScalarCD[],T[a,b,c]RicciCD[-a,-b]v[-c]]

The command Perturbation knows how to apply the chain rule when acting on this kind of function at any order. It is essentially implemented through the Mathematica total derivative command Dt.

Perturbation[%,3]

Again we find the head Scalar, to avoid problems with powers of scalars formed by contracted products of tensors.

5. Gauge transformations

Through all this notebook, we have implicitly supposed a family of manifolds M(ϵ) equipped with metric g(ϵ), that depend on a dimensionless parameter ϵ. The member with parameter ϵ=0 will be called the background spacetime. The objective of perturbation theory is to compare perturbed objects, for instance a tensor T(ϵ), with their background counterparts , in this case T(0). The problem is that they are defined in different manifolds. Hence, we have to construct a mapping (the so-called gauge) ϕ(ϵ): M(ϵ) ----> M(0), whose pull-back ϕ*(ϵ) will take tensors defined in the tangent space of M(ϵ) to the tangent space of M(0). Then, the difference between perturbed and background tensors will define its perturbation. For instance,  the full perturbation of the tensor T(0) is given by ϕ*(ϵ)(T(ϵ)) - T(0). This expression will be expanded in a power series of the parameter ϵ. Through this expansion, the different perturbative orders of the tensor T(0) will be defined. But, if we change the gauge ϕ  to a different one ψ, the new perturbation of the tensor will change to ψ*(ϵ)(T(ϵ)) - T(0), which will affect to all the perturbative orders. The theory and formulas for the power expansion of changes of gauge was developed by Bruni et al. in reference Class. Quantum Grav. 14, 2585 (1997).

In the context of xPert`, we have constructed a command named GaugeChange[expr, ξ] that performs the gauge transformation of the expression expr parameterized by the family of vector fields ξ[LI[n],a], where n stands for the perturbative order.

We define the gauge generators. They must be a family of vector fields, one for each perturbative order. This is again taken into account by the label index LI.

DefTensor[ξ[LI[n],a],M]

The background objects do not depend on the perturbative gauge chosen, so they do not change under a gauge transformation.

GaugeChange[g[-a,-b]RicciCD[c,d]+EinsteinCD[-a,c]EinsteinCD[-b,d]RicciScalarCD[],ξ]

The gauge transformation of the first-order metric perturbation is the following well-known formula.

GaugeChange[h[LI[1],-a,-b],ξ]

The first-order gauge transformation of any other object is similar:

GaugeChange[τ[LI[1],-a,b,c],ξ]

%//ToCanonical

At second order this formula is more complicated

GaugeChange[h[LI[2],-a,-b],ξ]

%//ToCanonical

Note that this previous formula is applied when the indices are in the natural position and that the metric, since it is a background object, commutes with the gauge change. This means that the following objects are the same:

g[a,d]g[b,e]GaugeChange[τ[LI[3],-d,-e,c],ξ]

GaugeChange[τ[LI[3],a,b,c],ξ]

ToCanonical[%%-%,UseMetricOnVBundle->None]

We can also do more difficult higher-order calculations. For instance,

GaugeChange[τ[LI[2],a,b,c] h[LI[5],-a,-b],ξ]

6. Background field perturbations

Making use of xPert`, we can also do background field perturbations. This approach is often used in quantum theory. There the perturbed metric is considered to be the background one plus a unique perturbation h. But when computing the inverse of the metric this unique perturbation will coupled to itself.
We can restrict our perturbation scheme to reproduce background field perturbations:

This can be implemented by forcing the vanishing of all perturbations of the metric of order greater than one, with the following rule:

bgfield=h[LI[order_],__]:>0/;order>1;

Then, the perturbed metric would be

Perturbed[g[-a,-b],4]/.bgfield

And its inverse

(Perturbed[g[b,c],4]//ExpandPerturbation)/.bgfield//org

This is consistent because it leads to

% %%//org

We can compute the perturbation of any other geometric object in this context. For example the fourth-order perturbed Riemann will take the following form

(Perturbed[RiemannCD[-a,-b,-c,d],4]//ExpandPerturbation)/.bgfield//org

7. Timings

This section performs a number of experiments to analyze the efficiency of the system. All timings have been performed with a Pentium IV 3GHz Linux box with 2Gbytes of RAM running Mathematica 5.2.

7.1. Timings with perturbations of the Riemann tensor

We compute the perturbations of the Riemann tensor in terms of metric perturbations up to tenth order. We measure the time ExpandPerturbation takes to calculate each order and make a plot of these timings versus the perturbative order. We also consider the the graph of the number of terms versus perturbative order.

Perturbations of the Riemann tensor up to tenth order. Save the results of timing and the perturbative expression itself in pairs (ti, ri).

{t1,r1}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],1]]//ToCanonical];

{t2,r2}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],2]]//ToCanonical];

{t3,r3}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],3]]//ToCanonical];

{t4,r4}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],4]]//ToCanonical];

{t5,r5}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],5]]//ToCanonical];

{t6,r6}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],6]]//ToCanonical];

{t7,r7}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],7]]//ToCanonical];

{t8,r8}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],8]]//ToCanonical];

{t9,r9}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],9]]//ToCanonical];

{t10,r10}=AbsoluteTiming[ExpandPerturbation[Perturbation[RiemannCD[-a,-b,-c,d],10]]//ToCanonical];

The following is the list of the times measured above

times={t1,t2,t3,t4,t5,t6,t7,t8,t9,t10}

We plot then in a logarithmic plot

timesplot=ListLogPlot[times,PlotStyle->Hue[0],Frame->True,Axes->False,Joined->True,PlotMarkers->Automatic]

This is the list of the lengths of each perturbative expression

lengths=Length/@Expand[{r1,r2,r3,r4,r5,r6,r7,r8,r9,r10}]

We also plot then in a logaritmic plot

lengthsplot=ListLogPlot[lengths,PlotStyle->{Hue[0.6],Dashing[{0.01,0.01}]},Frame->True,Axes->False,Joined->True,PlotMarkers->Automatic,PlotStyle->Blue]

7.2. Timings with the Leibnitz rule

We now apply Perturbation on products of different numbers of objects. We then graphically represent the time it takes for the expression to be expanded versus the perturbative order and the number of factors in the product. The n-th order perturbation of the Leibnitz rule is implemented in the context of xPert` through a closed formula. We will see that this is faster than the chain rule, that is implemented essentialy via the Mathematica command Dt.

Driver to average a number of experiments. For timings below a second the computation is repeated a number of times:

average[lists_List]:=Plus@@lists/Length[lists];
threshold=1;
experiment[number_Integer,order_Integer]:=Module[{timing=experiment1[number,order],repeat},
If[timing[[1]]<threshold,
repeat=Max[1,Ceiling[threshold/timing[[1]]]];
average@Table[experiment1[number,order],{repeat}],
timing]
];

Generate products of n>1 arguments:

Table[prod[n]=Times@@Table[Unique["x"],{n}],{n,1,10}];

and measure the time Perturbation takes to act on them, and the number of terms produced:

experiment1[number_,1]:=AbsoluteTiming[Length@Expand@Perturbation[prod[number]]];
experiment1[number_,order_]:=AbsoluteTiming[Length@Expand@Perturbation[prod[number],order]];

Llist[1]=experiment[#,1]&/@Range[2,10]

Llist[2]=experiment[#,2]&/@Range[2,10]

Llist[3]=experiment[#,3]&/@Range[2,10]

Llist[4]=experiment[#,4]&/@Range[2,10]

Llist[5]=experiment[#,5]&/@Range[2,10]

Llist[6]=experiment[#,6]&/@Range[2,10]

Llist[7]=experiment[#,7]&/@Range[2,10]

Llist[8]=experiment[#,8]&/@Range[2,10]

Llist[9]=experiment[#,9]&/@Range[2,10]

Llist[10]=experiment[#,10]&/@Range[2,10]

Ltimingsplot=ListLogPlot[Map[First,Array[Llist,{10}],{2}],Joined->True,PlotMarkers->Automatic]

Ltermsplot=ListLogPlot[Map[Last,Array[Llist,{10}],{2}],Joined->True,PlotMarkers->Automatic]

7.3. Timings with the chain rule

In this section we measure the time it takes to the command Perturbation to act on a scalar function of up to 8 arguments through the chain rule. We analize it up to the fifth perturbative order. In the context of xPert`, we have implemented the nth order perturbation of the chain rule trough the Mathematica command Dt.

Generate functions of n arguments and perturb them:

Table[func[n]=F@@Table[Unique["x"],{n}],{n,1,5}];

experiment1[number_,1]:=AbsoluteTiming[Length@Expand@NoScalar@Perturbation[func[number]]];
experiment1[number_,order_]:=AbsoluteTiming[Length@NoScalar@Expand@Perturbation[func[number],order]];

Flist[1]=experiment1[#,2]&/@Range[10]

The first case is a product of two objects and hence its length must be corrected:

Flist[1]=ReplacePart[Flist[1],1,{1,2}]

Flist[2]=experiment1[#,2]&/@Range[10]

Flist[3]=experiment1[#,3]&/@Range[10]

Flist[4]=experiment1[#,4]&/@Range[7]

Flist[5]=experiment1[#,5]&/@Range[5]

Flist[6]=experiment1[#,6]&/@Range[4]

Flist[7]=experiment1[#,7]&/@Range[4]

Flist[8]=experiment1[#,8]&/@Range[3]

Flist[9]=experiment1[#,9]&/@Range[3]

Flist[10]=experiment1[#,9]&/@Range[3]

MaxMemoryUsed[]

Graphs:

tlist=Transpose[PadRight[Array[Flist,10],{10,10},Null]]/.Null->Nothing;

ListLogPlot[Map[First,tlist,{2}],Joined->True,PlotMarkers->Automatic]

ListLogPlot[Map[Last,tlist,{2}],Joined->True,PlotMarkers->Automatic]

8. Final comments

Note: For further information about xPert`, and to be kept informed about new releases, you may contact the authors at david.brizuela@ehu.eus, jose@xact.es or mena@iem.cfmac.csic.es. Suggestions and comments are welcome and very much appreciated!
This is xPertDoc.nb, the docfile of xPert`, currently in version 1.0.6.	Last update February 28, 2018.