# Covariant Derivative

I'm trying to create a function which receives as inputs a coordinate system $$x^\mu$$, metric tensor $$g_{\mu\nu}$$, a general tensor $$T$$ of rank $$n$$, and a list $$I$$ of length $$n$$ that looks like this:

$$I=(c_1,c_2,\dots,c_n)\quad\quad \forall i\in[1,n]_{\mathbb N}: c_i\in\{\mathrm{u},\mathrm{d}\}$$

which describes the location of the indices of the tensor ($$\mathrm{u}$$ for up, $$\mathrm{d}$$ for down). For example - if $$T=T^{\mu\ \ \sigma}_{\ \ \nu\rho}$$, then $$I=(\mathrm{u},\mathrm{d},\mathrm{d},\mathrm{u})$$ and $$n=4$$.

The output of the function should be the covariant derivative of the tensor in the given coordinate system, defined as the following:

$$\nabla_iv^j=\partial_iv^j+\Gamma^j_{\ ik}v^k \\\nabla_iv_j=\partial_iv_j-\Gamma^k_{\ ij}v_k$$

where $$\partial_i\equiv{\partial}/{\partial x_i}$$, and $$\Gamma^i_{\ ij}$$ are the Christoffel symbols. The main difficulty here for me is differentiating between the up and down indices. Also, it's not very clear how the ""matrix"" multiplication should be made.

• I did create a function which computes the Christoffel symbols given a metric $$g$$ and returns them as a tensor of degree 3 (essentially, it returns a matrix of column vectors), but I don't calculating them in a different way which will make the implementation of the covariant derivative function easier.

• I did search for such implementations, but I didn't find any implementations which differ between contravectors and covectors (up and down indices).

Thanks!

• Have you seen Compute covariant derivative in Mathematica? Commented May 3, 2022 at 17:57
• @MarcoB Yes I have, I'm looking for a example which works with higher dimensions. Commented May 3, 2022 at 18:59
• @AmitZach have a look at my answer here. The computation of the Christoffel is for one index up and two down. I think that the logic is clear, but please, feel free to ask any questions
– bmf
Commented May 3, 2022 at 20:59

I do not really understand the problem implementing the definition \begin{align} {(\nabla_{e_c} T)^{a_1 \ldots a_r}}_{b_1 \ldots b_s} = {} &\frac{\partial}{\partial x^c}{T^{a_1 \ldots a_r}}_{b_1 \ldots b_s} \\ &+ \,{\Gamma ^{a_1}}_{dc} {T^{d a_2 \ldots a_r}}_{b_1 \ldots b_s} + \cdots + {\Gamma^{a_r}}_{dc} {T^{a_1 \ldots a_{r-1}d}}_{b_1 \ldots b_s} \\ &-\,{\Gamma^d}_{b_1 c} {T^{a_1 \ldots a_r}}_{d b_2 \ldots b_s} - \cdots - {\Gamma^d}_{b_s c} {T^{a_1 \ldots a_r}}_{b_1 \ldots b_{s-1} d}. \end{align} (taken from wikipedia) in Mathematica

coD[T_,struct_List,q_,\[CapitalGamma]ijk_,c_,ab_List]:=Module[{dim,rank,k,m},
dim=Length[q];
rank=Length[ab];

D[T[[##]]&@@ab,q[[c]]]+Sum[
If[struct[[k]]==="u",
+Sum[\[CapitalGamma]ijk[[ab[[k]],m,c]]T[[##]]&@@ReplacePart[ab,k->m],{m,1,dim}],
-Sum[\[CapitalGamma]ijk[[m,ab[[k]],c]]T[[##]]&@@ReplacePart[ab,k->m],{m,1,dim}]
]
,{k,1,rank}]
]


should do the trick. I have not checked this extensively but at least for one covariant derivative of a mixed second rank tensor (energy momentum conservation TOV eq.) it works

dim=4;
q={t,r,\[Theta],\[Phi]};
gdd=DiagonalMatrix[{-Exp[\[Nu][r]],Exp[\[Lambda][r]],r^2,Sin[\[Theta]]^2 r^2}];
guu=Inverse[gdd];
\[CapitalGamma]ddd=Table[1/2 (D[gdd[[c,a]],q[[b]]]+D[gdd[[c,b]],q[[a]]]-D[gdd[[a,b]],q[[c]]]),{c,1,dim},{a,1,dim},{b,1,dim}];
\[CapitalGamma]udd=Table[Sum[guu[[c,m]]\[CapitalGamma]ddd[[m,a,b]],{m,1,dim}],{c,1,dim},{a,1,dim},{b,1,dim}];

Tdu=DiagonalMatrix[{-\[Rho][r],P[r],P[r],P[r]}];
Sum[coD[Tdu,{"d","u"},q,\[CapitalGamma]udd,m,{2,m}],{m,1,4}]//Simplify


Some tips for writing code concerning Ricci/tensor calculus like this: do not use matrix/vector multiplication but rather write out the sums explicitly to avoid any confusion about placement of indices. Writing a wrapper for tensor-type objects which holds the elements as well as the index structure might also be a good idea to keep the information about the index location and data in one place. E.g.:

ClearAll[tensor,struct]
tensor/:Part[tensor[mat_,struct_List],ab__]:=mat[[ab]]
struct[tensor[mat_,struct_List]]:=struct
MakeBoxes[tensor[mat_,struc_List],StandardForm]:=ToBoxes@StandardForm@mat

gdd=tensor[DiagonalMatrix[{-Exp[\[Nu][r]],Exp[\[Lambda][r]],r^2,Sin[\[Theta]]^2 r^2}],{"d","d"}]
struct[%]


this would make passing around the index locations for a given object easier and less error prone but is of course not necessary.