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

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]

enter image description here

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]

enter image description here

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.


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.


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.