Here is some code I wrote a while back:
ClearAll["Global`*"]
SetAttributes[Rs, Constant]
$Assumptions = Rs > 0;
Coordinates = {t, r, \[Theta], \[Phi]};
dim = Length[Coordinates];
MetricTensorLL = {{(1 - Rs/r), 0, 0, 0}, {0, -(1 - Rs/r)^-1, 0,
0}, {0, 0, -r^2, 0}, {0, 0, 0, -r^2 Sin[\[Theta]]^2}};
MetricTensorUU := MetricTensorUU = Simplify[Inverse[MetricTensorLL]];
ChristoffelSymbolsULL :=
ChristoffelSymbolsULL =
Simplify@
Array[1/2 Sum[
MetricTensorUU[[#1, \[Lambda]]] (D[
MetricTensorLL[[#3, \[Lambda]]], Coordinates[[#2]]] +
D[MetricTensorLL[[\[Lambda], #2]], Coordinates[[#3]]] -
D[MetricTensorLL[[#2, #3]],
Coordinates[[\[Lambda]]]]), {\[Lambda], dim}] &, {dim,
dim, dim}];
ChristoffelSymbolsLLL :=
ChristoffelSymbolsLLL =
Simplify@
Array[1/2 (D[MetricTensorLL[[#1, #2]], Coordinates[[#3]]] +
D[MetricTensorLL[[#1, #3]], Coordinates[[#2]]] -
D[MetricTensorLL[[#2, #3]], Coordinates[[#1]]]) &, {dim, dim,
dim}];
RiemannCurvatureTensorULLL :=
RiemannCurvatureTensorULLL =
Simplify@
Array[D[ChristoffelSymbolsULL[[#1, #2, #4]], Coordinates[[#3]]] -
D[ChristoffelSymbolsULL[[#1, #2, #3]], Coordinates[[#4]]] +
Sum[ChristoffelSymbolsULL[[#1, #3, \[Epsilon]]] \
ChristoffelSymbolsULL[[\[Epsilon], #2, #4]], {\[Epsilon], dim}] -
Sum[ChristoffelSymbolsULL[[#1, #4, \[Epsilon]]] \
ChristoffelSymbolsULL[[\[Epsilon], #2, #3]], {\[Epsilon],
dim}] &, {dim, dim, dim, dim}];
RiemannCurvatureTensorLLLL :=
RiemannCurvatureTensorLLLL =
Simplify@
Array[Sum[
MetricTensorLL[[#1, \[Tau]]] \
RiemannCurvatureTensorULLL[[\[Tau], #2, #3, #4]], {\[Tau],
dim}] &, {dim, dim, dim, dim}];
RiemannCurvatureTensorUUUU :=
RiemannCurvatureTensorUUUU =
Simplify@
Array[Sum[
MetricTensorUU[[#2, \[Alpha]]] MetricTensorUU[[#3, \[Beta]]] \
MetricTensorUU[[#4, \[Gamma]]] RiemannCurvatureTensorULLL[[#1, \
\[Alpha], \[Beta], \[Gamma]]], {\[Alpha], dim}, {\[Beta],
dim}, {\[Gamma], dim}] &, {dim, dim, dim, dim}];
RiemannCurvatureTensorLL :=
RiemannCurvatureTensorLL =
Simplify@
Array[Sum[
RiemannCurvatureTensorULLL[[\[Lambda], #1, \[Lambda], #2]], {\
\[Lambda], dim}] &, {dim, dim}];
RiemannCurvatureTensorUL :=
RiemannCurvatureTensorUL =
Simplify@
Array[Sum[
MetricTensorUU[[#1, \[Lambda]]] RiemannCurvatureTensorLL[[\
\[Lambda], #2]], {\[Lambda], dim}] &, {dim, dim}];
ScalarCurvature := ScalarCurvature = Tr[RiemannCurvatureTensorUL];
KretschmannScalar :=
KretschmannScalar =
Simplify@
Sum[RiemannCurvatureTensorLLLL[[\[Alpha], \[Beta], \[Gamma], \
\[Delta]]] RiemannCurvatureTensorUUUU[[\[Alpha], \[Beta], \[Gamma], \
\[Delta]]], {\[Alpha], dim}, {\[Beta], dim}, {\[Gamma],
dim}, {\[Delta], dim}];
WeylCurvatureTensorLLLL :=
WeylCurvatureTensorLLLL =
Simplify@
Array[If[dim > 3,
RiemannCurvatureTensorLLLL[[#1, #2, #3, #4]] -
1/(
dim - 2) (MetricTensorLL[[#1, #3]] \
RiemannCurvatureTensorLL[[#4, #2]] +
MetricTensorLL[[#2, #4]] RiemannCurvatureTensorLL[[#3, \
#1]] - MetricTensorLL[[#1, #4]] RiemannCurvatureTensorLL[[#3, #2]] - MetricTensorLL[[#2, #3]] RiemannCurvatureTensorLL[[#4, \
#1]]) + ScalarCurvature/((dim - 1) (dim - 2)) (MetricTensorLL[[#1, #3]] MetricTensorLL[[#4, #2]] -
MetricTensorLL[[#1, #4]] MetricTensorLL[[#3, #2]]),
0] &, {dim, dim, dim, dim}];
EinsteinTensor :=
EinsteinTensor =
Simplify[
RiemannCurvatureTensorLL - 1/2 MetricTensorLL ScalarCurvature];
ConformallyFlatSpaceQ :=
ConformallyFlatSpaceQ =
Simplify[Equal[Sequence @@ Flatten@WeylCurvatureTensorLLLL, 0]];
MaximallySymmetricSpaceQ :=
MaximallySymmetricSpaceQ =
Simplify[
And @@ Flatten@
Map[# == 0 &,
RiemannCurvatureTensorLLLL -
Array[ScalarCurvature/(
dim (dim -
1)) (MetricTensorLL[[#1, #3]] MetricTensorLL[[#2, #4]] -
MetricTensorLL[[#1, #4]] MetricTensorLL[[#2, #3]]) &, \
{dim, dim, dim, dim}], {4}]];
It is hopefully self-explanatory.
In this particular example I am using the Schwarzschild metric. The first line declares Rs
, the Schwarzschild radius, to be a constant. We then define the coordinates of the manifold, in this case, $t,r,\theta,\phi$. After that, we input the components of the metric tensor, with its indices lowered (as indicated by the LL
tag, meaning "lower-lower").
The rest of tensors are calculated by MMA. For example, ChristoffelSymbolsULL
are the components of the Christoffel symbols, with one upper and two lower indices. Similarly, ChristoffelSymbolsLLL
are the components of the Christoffel symbols with all indices lowered.
The code also computes the Riemann tensor, the Weyl tensor, and several scalars (Ricci and Kretschmann). Finally, there is a check for whether the manifold is conformally flat and/or maximally symmetric.
To compute covariant derivatives, you can use the known value of the Christoffel symbols, or the expression
Sum[1/Sqrt[Det[MetricTensorLL]] D[Sqrt[Det[MetricTensorLL]] MetricTensorUU[[\[Mu] + 1, \[Nu] + 1]] D[f @@ Coordinates, Coordinates[[\[Nu] + 1]]], Coordinates[[\[Mu] + 1]]], {\[Mu], 0, dim - 1}, {\[Nu], 0, dim - 1}]
where f
is an arbitrary scalar function. For higher rank tensor fields, you'll have to make some small modifications to the code.