# How to calculate scalar curvature, Ricci tensor and Christoffel symbols in Mathematica?

I am seeking a convenient and effective way to calculate such geometric quantities. I've used packages like TensoriaCalc, but they don't work at all time. Sometimes, I run into the following error:

Symbol Tensor is Protected.
Symbol TensorType is Protected.
Symbol TensorName is Protected.

Here is the code I'm using:

Clear [i, j, φ, τ, σ]
q["case"] = Metric[ SubMinus[i], SubMinus[j],
E^(2 φ[σ]) (\[DifferentialD]τ^2 + \[DifferentialD] σ^2),
CoordinateSystem -> {τ, σ}, TensorName -> "T", StartIndex -> 1 ]


I think the above is correct, since I merely modified the example from the package manual. It gives me the correct answer sometimes (if I only use one notebook).

Also, I ran the codes from the chapter "General Relativity" in the book "Mathmatica for theoretical physics" by Gerd Baumann, but none of them work

• Also Hartle has mathematica notebooks on his website that can do everything from the Christofell symbols to the Einstein tensor. web.physics.ucsb.edu/~gravitybook Jul 31, 2012 at 21:32

I stumbled upon this question via Google. Thanks for using my TensoriaCalc package!

My response is probably too late, but I believe the problem you cited

Symbol Tensor is Protected.
Symbol TensorType is Protected.
Symbol TensorName is Protected.

is because you loaded TensoriaCalc more than once in the same kernel session.

When writing the package, I had to Protect all the symbols used in the package, such as Tensor, Metric, etc. This means their definitions cannot be altered by an external user, as otherwise, it will create inconsistencies. This is why loading TensoriaCalc more than once gives an error, because you are essentially trying to define these symbols yet again.

Hope this helps.

## General remarks

In General Relativity we work in a 4-dimentional Lorentzian manifold i.e. there is a metric tensor $g$ of signature $(+,-,-,-)$ or $(-,+,+,+)$. Theses signatures are mathematically equivalent and we choose the latter because of certain quite formal aspects even though there are some physically relevant reasons for choosing the former one. In a neighbourhood of any point we choose a local chart $xx = (x^{1},x^{2},x^{3},x^{4})$ where the metric tensor is represented by real functions $g_{\alpha\beta}(x^{\mu})$ i.e. $g = g_{\alpha\beta}(x^{\mu}) dx^{\alpha}\otimes dx^{\beta}$ (We enumerate indices by $1,2,3,4$ unlike traditionally $0,1,2,3$ for representing tensors in Mathematica by Tables and accessing their entries by Part e.g. [[1,1]]). Now assuming the Einstein notation we need the following objects :

• inverse metric $g^{\mu \nu}$ : (i.e. $g^{\mu \nu} g_{\nu\alpha} = \delta^{\mu}_{\alpha} )\quad$ ( InverseMetric[g][[μ, ν]] )
• Christoffel symbols (of the second kind) $\Gamma^{\mu}_{\phantom{\mu}\nu\sigma}=\frac{1}{2}g^{\mu\alpha}\left\{\frac{\partial g_{\alpha\nu}}{\partial x^{\sigma}}+\frac{\partial g_{\alpha\sigma}}{\partial x^{\nu}}-\frac{\partial g_{\nu\sigma}}{\partial x^{\alpha}}\right\}\quad$ (ChristoffelSymbol[g, xx][[μ, ν, σ]] )
• Riemann tensor $R^{\mu}_{\phantom{\mu}\nu\lambda\sigma}=\partial_{\lambda}\Gamma^{\mu}_{\phantom{\mu}\nu\sigma}-\partial_{\sigma} \Gamma^{\mu}_{\phantom{\mu}\nu\lambda}+\Gamma^{\mu}_{\phantom{\mu}\rho\lambda}\Gamma^{\rho}_{\phantom{\mu}\nu\sigma}-\Gamma^{\mu}_{\phantom{\mu}\rho\sigma}\Gamma^{\rho}_{\phantom{\mu}\nu\lambda}\quad$

( RiemannTensor[g, xx][[μ, ν, λ, σ]] )

• Ricci tensor $R_{\mu\nu}=R^{\lambda}_{\phantom{\lambda}\mu\lambda\nu}\quad$ ( RicciTensor[g, xx][[μ, ν]] )

• Ricci scalar $R = R^{\mu}_{\phantom{\lambda}\mu}\quad$ (RicciScalar[g, xx])

## A straightforward implementation

It will be convenient to define geometrical objects in the following order (this may become a frame for developing a package):

InverseMetric[ g_] := Simplify[ Inverse[g] ]
ChristoffelSymbol[g_, xx_] :=
Block[{n, ig, res},
n = 4; ig = InverseMetric[ g];
res = Table[(1/2)*Sum[ ig[[i,s]]*(-D[ g[[j,k]], xx[[s]]] +
D[ g[[j,s]], xx[[k]]]
+ D[ g[[s,k]], xx[[j]]]),
{s, 1, n}],
{i, 1, n}, {j, 1, n}, {k, 1, n}];
Simplify[ res]
]
RiemannTensor[g_, xx_] :=
Block[{n, Chr, res},
n   = 4; Chr = ChristoffelSymbol[ g, xx];
res = Table[  D[ Chr[[i,k,m]], xx[[l]]]
- D[ Chr[[i,k,l]], xx[[m]]]
+ Sum[ Chr[[i,s,l]]*Chr[[s,k,m]], {s, 1, n}]
- Sum[ Chr[[i,s,m]]*Chr[[s,k,l]], {s, 1, n}],
{i, 1, n}, {k, 1, n}, {l, 1, n}, {m, 1, n}];
Simplify[ res]
]
RicciTensor[g_, xx_] :=
Block[{Rie, res, n},
n = 4; Rie = RiemannTensor[ g, xx];
res = Table[ Sum[ Rie[[ s,i,s,j]],
{s, 1, n}], {i, 1, n}, {j, 1, n}];
Simplify[ res]
]
RicciScalar[g_, xx_] :=
Block[{Ricc,ig, res, n},
n = 4; Ricc = RicciTensor[ g, xx]; ig = InverseMetric[ g];
res = Sum[ ig[[s,i]] Ricc[[s,i]], {s, 1, n}, {i, 1, n}];
Simplify[res]
]


Following this way one could define another interesting geometrical objects e.g. the Weyl tensor $C_{\mu\nu\lambda\sigma}=R_{\mu\nu\lambda\sigma}-\left(g_{\mu[\lambda}R_{\nu]\sigma}-g_{\nu[\lambda}R_{\sigma]\mu}\right)+\frac{1}{3}R g_{\mu[\lambda}g_{\nu]\sigma}$

## Schwarzschild-like ansatz for a static spherically symmetric spacetime

In order to start with a concrete example let's define coordinates and a metric tensor of 4-dimensional static spherically symmetric Lorentzian spacetime :

xx = {t, x, θ, ϕ};

g  = { {-E^(2 ν[x]), 0         ,   0,            0},
{          0, E^(2 λ[x]),   0,            0},
{          0,          0, x^2,            0},
{          0,          0,   0, x^2 Sin[θ]^2}};


Now let's compute RicciScalar :

RicciScalar[g, xx]


If you want to solve Einstein equations of a vacuum spacetime (e.g. the Schwarzschild spacetime) you should solve equations : RicciTensor[g, xx] == 0.

 RicciTensor[g, xx]


Now you have to choose two independent equations, e.g.

eqs={ λ'[x] ( 2 + x ν'[x]) -x ( ν'[x]^2+ ν''[x]), -1 + E^(2 λ[x]) + x ( λ'[x] - ν'[x])};


and solve this system of ordinary differential equations :

eqs[[1]] == 0;
eqs[[2]] == 0;


with appropriate boundary conditions. In case of the Schwarzschild solution that should be g -> g0 at infinity, where g0 is the Minkowski metric.

## de-Sitter spacetime

Let's find e.g. scalar curvature of de-Sitter spacetime (a is a constant):

Clear[g]
g = {{-(1 - x^2/a^2),               0,   0,            0},
{             0, 1/(1 - x^2/a^2),   0,            0},
{             0,               0, x^2,            0},
{             0,               0,   0, x^2 Sin[θ]^2}};
RicciScalar[g, xx]

 12/a^2


Thus we have shown that de-Sitter spacetime has a constant scalar curvature.

• Thank everybody above for your patience and help. I have some seminars those days, I will come back soon and give the feedback. Jul 31, 2012 at 18:15
• Wouldn't it be better to use n=Length[g] instead of n=4? This helps generalize the package to more dimensions. Feb 15, 2014 at 21:09
• @cartonn This is a part of my larger package I wrote some time ago. In fact I needed only n = 4 case because of another functions therein, which were defined properly assuming that there were 4 dimensions. A generalization shouldn't be difficult but it would need a bit more than changing only n = 4 to n = Length[g]. Feb 15, 2014 at 23:49

This one might be a starter to calculate the tensors.

partialDer[T_, vars_] := D[T, #] & /@ vars // Simplify

christoffelSymbols[metric_, coord_] :=

Module[{dg = partialDer[metric, coord],
inverse = Simplify[Inverse[metric]]},
inverse.(Transpose[dg, {2, 1, 3}] + Transpose[dg, {3, 2, 1}] - dg)/
2 // Simplify]

curvTensor[christ_, var_] :=

Module[{temp1, temp2, i, h, j, k, s, n},
n = Length[var];
temp1[i_, h_, j_, k_] := D[christ[[i, h, j]], var[[k]]];
temp2[i_, h_, j_, k_] :=
temp1[i, h, k, j] - temp1[i, h, j, k] +
Sum[christ[[s, h, k]] christ[[i, s, j]] -
christ[[s, h, j]] christ[[i, s, k]], {s, n}];
Simplify[Table[temp2[i, h, j, k], {i, n}, {h, n}, {j, n}, {k, n}]]
]

ricciTensor[curv_] :=
Module[{k, j, n},
n = Length[curv[[1, 1]]];
Table[Sum[curv[[k, i, k, j]], {k, n}], {i, n}, {j, n}] //
ExpandAll // Simplify
]


This is the usage of the functions used:

partialDer::usage = "partialDer[T,vars] builts the list of the \
partial derivatives \!$$\*SubscriptBox[\(\[PartialD]$$, $$i$$]\)T of \
tensor T w.r.t. the variables of list \"vars\".  The first index of \
the produced list will be the derivative index."

christoffelSymbols::usage = "christoffelSymbols[metric, vars] gives \
the Christoffel-Symbols christ\[LeftDoubleBracket]i,j,k\
\[RightDoubleBracket] with variables of list vars and the metric \
Tensor metric. The first indes will be the \"upper\" index."

curvTensor::usage = "curvTensor[christ,vars] takes the Christoffel \
symbols \"christ\" with variables vars and calcules the Rieman \
curvature tensor. The first index will be the \
\"upper\\[CloseCurlyDoubleQuote] index."

ricciTensor::usage = "ricciTensor[curv] takes the Riemann curvarture \
tensor \"curv\" and calculates the Ricci tensor"


Example

First we need to give a metric Tensor gM and the variables list vars we will use, then we calculate the Christoffel symbols, the Riemann Curvature tensor and the Ricci tensor:

vars = {u, v}; gM = {{1, 0}, {0, Sin[u]^2}};
christ = christoffelSymbols[gM, vars]
curv = curvTensor[christ, vars]
ricciTensor[curv]


Output:

{{{0, 0}, {0, -Cos[u] Sin[u]}}, {{0, Cot[u]}, {Cot[u], 0}}}

{{{{0, 0}, {0, 0}}, {{0, Sin[u]^2}, {-Sin[u]^2, 0}}}, {{{0, -1}, {1, 0}}, {{0, 0}, {0, 0}}}}

{{1, 0}, {0, Sin[u]^2}}

This works for 3 and 4 dimensional Tensors as well. I only wanted to keep the example small.

Since Version 9, functions to do this have been built into Mathematica but not documented. They live in the SymbolicTensors package which underlies CoordinateChartData, CoordinateTransform, and related functions. You could add the context to \$ContextPath to save needing to type it everywhere, though I won't do that in the example below.

They easiest way to get there is to define a "patch". This can be done in various ways, but for a diagonal metric tensor the easiest way is scale factors. Here I'll use Minkowski in spherical coordinates as my example:

vars = {t, r, th, p};
patch = SymbolicTensorsScaleFactorGeometryPatch[{-1, 1, r, r Sin[th]}, vars];


There is also an OrthonormalFrameGeometryPatch which takes a matrix in the first argument, interpreted as the matrix which takes 1-forms to an orthonormal frame, and a RiemannianGeometryPatch which takes a metric as a Tensor object in the first argument.

Once you have a patch, you can query available properties:

patch["Properties"]
(*{"CotangentBasis", "InverseMetric", "InverseMetricTensor", "LeviCivitaConnection",
"Metric", "MetricTensor", "OrthonormalBasis", "RicciScalar", "RicciTensor",
"RiemannTensor", "ScaleFactors", "TangentBasis", "VolumeFactor"}*)


Simiarly to CoordinateChartData, you can extract the property with a variable list which is the evaluation point:

patch["RicciTensor", vars] // Simplify
(*SymbolicTensorsTensor[{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{SymbolicTensorsCotangentBasis[{t,r,th,p}],SymbolicTensorsCotangentBasis[{t,r,th,p}]}
]*)


Note that what you call the Christoffel symbols of the first kind is what we call the "LeviCivitaConnection".

For the basic tensorial properties, we have corresponding functions, but you need to take care with the arguments. RiemmanTensor and RicciTensor take a connection followed by variables, since they make sense for non-metric tensors. LeviCivitaConnection, RicciScalar, and EinsteinTensors take a a metric. In all cases it should be a proper Tensor object as returned above.

I'm not sure why "EinsteinTensor" isn't an available property of a patch. Probably just an oversight. If I get enough requests here, I'll add it.

• These look too nice to be kept undocumented. Hopefully some day... anyway, since "EinsteinTensor" isn't available yet, what could be done in the meantime to get it? Aug 16, 2017 at 0:28
• Plus and Times understand Tensor addition and scalar multiplication, so you can just form it in the obvious way from "RicciTensor", "RicciScalar", and "MetricTensors". Aug 16, 2017 at 2:28

There are a few packages in Mathsource already available they are

http://library.wolfram.com/infocenter/MathSource/8329/

and

http://library.wolfram.com/infocenter/MathSource/4781/

for the basics both programs do the same thing but the first one has more functionality.

A very good tutorial may be found here:

http://www.physics.ucsb.edu/~gravitybook/math/curvature.nb