I am trying to do some vector calculus in Mathematica in index notation form because it gives a clear result that can be compared to pen and paper calculations. Since there is no built in Einstein summation convention this makes life rather difficult. I think I'm doing things the right way but if there is a better way please let me know!
I wish to evaluate vector derivatives of the tensor denoted $G$. Using the first of the linked questions below I make the definitions
R /: D[R, R[a_], NonConstants -> {R}] := R[a]/R
R /: D[R[a_], R[b_], NonConstants -> {R}] := KroneckerDelta[a, b]
G = KroneckerDelta[a, b]/R + TensorProduct[R[a], R[b]]/R^3
And evaluate
D[G, R[c], NonConstants -> {R}] // FullSimplify
So far so good, but suppose I wish to evaluate the Laplacian.
D[G, R[c], R[d], NonConstants -> {R}] //. d -> c // TensorExpand
Now we get terms like R[c]^2
that should automatically evaluate to R^2
. This is not a problem, just add the lines
R /: R[a_] R[a_] := R^2
R /: R[a_] KroneckerDelta[a_, b_] := R[b]
And this works. However there are also terms like $\delta_{a,c}\delta_{b,c}$ that I want to automatically contract to $\delta_{a,b}$. These is no way to set a tag for KroneckerDelta
since it is protected. Similarly if I want to take curls using the Levi Civita tensor this is going to get very ugly.
Tl;dr I have defined symbolic derivatives of tensors according to the first linked question since this allows me to get a result that I can visually compare to analytics. However I would also like to be able to automatically sum over all repeated indices. Is there a good way to do this? Thanks in advance!
symbolic summation involving kronecker delta
Implementing Einstein's summation convention for a particular case
EDIT: adding Levi-Civita functionality
I whipped up the ability to use the Levi-Civita tensor symbolically and have it work correctly (as far as I have tested). First its essential that $\delta_{a,a} = d = 3$ instead of 1 then I add total antisymmetry by modifying this question on totally antisymmetric functions.
Unprotect[KroneckerDelta]; KroneckerDelta /:
KroneckerDelta[a_, a_] := 3;
leviC /: MakeBoxes[leviC[a_, b_, c_], fmt_] :=
MakeBoxes[Subscript[\[CurlyEpsilon], a, b, c], fmt]
leviC[a__] := Signature[{a}] (leviC @@ Sort@{a}) /; ! OrderedQ[{a}];
leviC[a__] := 0 /; ! DuplicateFreeQ[{a}];
Finally the Levi-Civita replacement rules are defined by
leviCrules := {leviC[indi_, indj_, indk_] leviC[indl_, indm_,
indn_] :>
KroneckerDelta[indi,
indl] (KroneckerDelta[indj, indm] KroneckerDelta[indk, indn] -
KroneckerDelta[indj, indn] KroneckerDelta[indk, indm]) -
KroneckerDelta[indi,
indm] (KroneckerDelta[indj, indl] KroneckerDelta[indk, indn] -
KroneckerDelta[indj, indn] KroneckerDelta[indk, indl]) +
KroneckerDelta[indi,
indn] (KroneckerDelta[indj, indl] KroneckerDelta[indk, indm] -
KroneckerDelta[indj, indm] KroneckerDelta[indk, indl]),
leviC[indi_indj _, indk_]^2 -> 6,
leviC[a___, b_, c_, d___] A_[Q___, b_, q___] A_[P___, c_, p___] :> 0}
Where the replacement rules here were taken from the code for VEST.
As far as I can tell this gives all the correct behaviour required for symbolic vector calculus! :)
Edit 2: dubious dummy index replacement
I add the rule
A_[Q___, c__, q___] B_[P___, c__, p___] :>
A[Q, dummy, q] B[P, dummy, p]
so that Mathematica can recognize repeated indices.However this is dangerous for the obvious reason that $v_a v_a w_b w_b = v_a w_a v_b w_b$ in this scheme but I have been unable to do rule replacement such that each time the pattern is matched the dummy index is replaced by dummyi+1.