# Define Matrix Function in a For loop

Let $$g\in\mathcal R^{3\times 3}$$ be a given known rank 2 tensor function, $$gInv$$ its inverse, and $$dg\in\mathcal R^{3\times 3\times 3}$$ its gradiant:

g[x_,y_,z_] = {{g11[x,y,z],g12[x,y,z],g13[x,y,z]},
{g21[x,y,z],g22[x,y,z],g23[x,y,z]},
{g31[x,y,z],g32[x,y,z],g33[x,y,z]}};
dg[x_,y_,z_] = Grad[g[x, y, z], {x, y, z}];


I want to define a rank 3 tensor function componentwise by looping over each entry. Ideally like this:

G[x_, y_, z_][[k, i, j]] = 0;
For[i = 1, i <= 3, i++, For[j = 1, j <= 3, j++, For[k = 1, k <= 3, k++, For[d = 1, d <= 3, d++,
G[x_, y_, z_][[k, i, j]] +=  0.5 gInv[x, y, z][[k, d]]
(dg[x, y, z][[i, d, j]] + dg[x, y, z][[d, j, i]] - dg[x, y, z][[i, j, d]]);
]]]]


or maybe like this if the += is not suitable for a function definition:

For[i = 1, i <= 3, i++, For[j = 1, j <= 3, j++, For[k = 1, k <= 3, k++,
G[x_, y_, z_][[k, i, j]] =
0.5 gInv[x, y, z][[k, 1]](dg[x, y, z][[i, 1, j]] + dg[x, y, z][[1, j, i]] - dg[x, y, z][[i, j, 1]])
+0.5 gInv[x, y, z][[k, 2]](dg[x, y, z][[i, 2, j]] + dg[x, y, z][[2, j, i]] - dg[x, y, z][[i, j, 2]])
+0.5 gInv[x, y, z][[k, 3]](dg[x, y, z][[i, 3, j]] + dg[x, y, z][[3, j, i]] - dg[x, y, z][[i, j, 3]]);
]]]


However this notation does not work and unrolling all 4 For loops will most centainly introduce typos.

I am rather new to mathematica. Maybe there is a completely different solution which is much better. Feel free correct my approach or advice me something completely different. I might learn something.

Physics Background:

G are the Christoffel symbols from general relativity/differential geometry, and g the spatial 3-metric of a spatial hypersurface.

• You might be better off doing something like g[1,2][x_, y_, z_] and G[k_,i_,j_][x_,y_,z_] = ... (note that the first set of brackets are not [[double]]). Commented Aug 12, 2021 at 10:21
• There are numerous questions about Christoffel Symbols on this site. Do any meet your needs? Commented Aug 12, 2021 at 14:34
• TensorProduct-TensorContract combo. Commented Aug 13, 2021 at 8:35
• And I suggest using a specific $g$ as an example. Commented Aug 13, 2021 at 12:26

## 1 Answer

With the help of ebanb's comment I managed to solve my issue. Here is the solution for anybody who has a similar problem. By reversing the brakets and basicly defining one function for each tensor entry it it possible to loop over them the way I want to,

For[i = 1, i <= 3, i++, For[j = 1, j <= 3, j++, For[k = 1, k <= 3, k++,
G[k, i, j][x_, y_, z_] =
0.5 gInv[k, 1][x, y, z](dg[i, 1, j][x, y, z] + dg[1, j, i][x, y, z] - dg[i, j, 1][x, y, z])
+0.5 gInv[k, 2][x, y, z](dg[i, 2, j][x, y, z] + dg[2, j, i][x, y, z] - dg[i, j, 2][x, y, z])
+0.5 gInv[k, 3][x, y, z](dg[i, 3, j][x, y, z] + dg[3, j, i][x, y, z] - dg[i, j, 3][x, y, z]);
]]]


This way also gInv and dg need to be defined in that manner. Finally I still need to be able to do Matrix operations on some of these tensors (e.g. inverting the 3x3 metric). For this I just create a Matrix and give it the corresponding entries,

g[x_,y_,z_] =
{{g[1,1][x,y,z],g[1,2][x,y,z],g[1,3][x,y,z]},
{g[2,1][x,y,z],g[2,2][x,y,z],g[2,3][x,y,z]},
{g[3,1][x,y,z],g[3,2][x,y,z],g[3,3][x,y,z]}};
gInv[x_,y_,z_] = Inverse[g[x,y,z]];


and then reextract them if needed for the loop.

For[i = 1, i <= 3, i++, For[j = 1, j <= 3, j++,
gInv'[i, j][x_, y_, z_] = gInv[x, y, z][[i, j]];
]]

• nice! but note that you'd have an easier time using Do here with nested indices! check out Do[Print["i = ", i, ", j = ", j, ", k = ", k], {i, 3}, {j, 3}, {k, 3}] to see how it loops over all values—then substitute your i,j,k-dependent assignment for Print[...]. Commented Aug 13, 2021 at 0:22
• however, i do wonder why you perform all assignments individually—why not simply evaluate one statement, G[k_, i_, j_][x_, y_, z_] := 0.5 gInv[k, 1][x, y, z](dg[i, 1, j][x, y, z] + dg[1, j, i][x, y, z] - dg[i, j, 1][x, y, z]) +0.5 gInv[k, 2][x, y, z](dg[i, 2, j][x, y, z] + dg[2, j, i][x, y, z] - dg[i, j, 2][x, y, z]) +0.5 gInv[k, 3][x, y, z](dg[i, 3, j][x, y, z] + dg[3, j, i][x, y, z] - dg[i, j, 3][x, y, z]), which allows generic i,j,k? Commented Aug 13, 2021 at 0:25
• I didn't think of i,j,k as variables which then can be assigned later. For me in my mind there are already fixed, so it made more sense to me to do it this way. Thanks for the hint, ill keep it in mind for the next time!
– Tom
Commented Aug 13, 2021 at 11:04