The other day, someone asked a question: Can the itensor package in Maxima calculate the Laplace-Beltrami operator applied to a scalar field in the presence of torsion?

Well, it can. But I was very happy to get this question because it allowed me to uncover some long-standing, subtle bugs in the package that prevented some essential simplifications and in some cases, even produced nonsensical results.

With these fixes, Maxima now produces a beautiful result, as evidenced by this nice newly created demo, which I am about to add to the package:

(%i1)if get('itensor,'version) = false then load(itensor)(%i2) "First, we set up the basic properties of the system" (%i3)imetric(g)(%i4) "Demo is faster in 3D but works for other values of dim, too" (%i5)dim:3(%i6) "We declare symmetries of the metric and other symbols" (%i7)decsym(g,2,0,[sym(all)],[])(%i8)decsym(g,0,2,[],[sym(all)])(%i9)components(g([a],[b]),kdelta([a],[b]))(%i10)decsym(levi_civita,0,dim,[],[anti(all)])(%i11)decsym(itr,2,1,[anti(all)],[])(%i12) "It is useful to set icounter to avoid indexing conflicts" (%i13)icounter:100(%i14) "We choose the appropriate convention for exterior algebra" (%i15)igeowedge_flag:true(%i16) "Now let us calculate the Laplacian of a scalar field and simplify" (%i17)canform(hodge(extdiff(hodge(extdiff(f([],[]))))))(%i18)contract(expand(lc2kdt(%)))(%i19)ev(%,kdelta)(%i20)D1:ishow(canform(%)) %1 %2 %3 %4 %1 %2 %1 %2 (%t20) (- f g g g ) + f g + f g ,%4 ,%3 %1 %2 ,%2 ,%1 ,%1 %2(%i21) "We can re-express the result using Christoffel symbols, too" (%i22)ishow(canform(conmetderiv(D1,g))) %1 %4 %2 %5 %3 %1 %2 %3 (%t22) 2 f g g ichr2 g - f g ichr2 ,%5 %1 %2 %3 %4 ,%3 %1 %2 %1 %3 %2 %1 %2 - f g ichr2 + f g ,%3 %1 %2 ,%1 %2(%i23) "Nice. Now let us repeat the same calculation with torsion" (%i24)itorsion_flag:true(%i25)canform(hodge(extdiff(hodge(extdiff(f([],[]))))))(%i26) "Additional simplifications are now needed" (%i27)contract(expand(lc2kdt(%th(2))))(%i28)ev(%,kdelta)(%i29)canform(%)(%i30)ev(%,ichr2)(%i31)ev(%,ikt2)(%i32)ev(%,ikt1)(%i33)ev(%,g) (%i34) ev(%,ichr1)(%i35)contract(rename(expand(canform(%))))(%i36)flipflag:not flipflag(%i37)D2:ishow(canform(%th(2))) %1 %2 %3 %4 %1 %2 %3 %1 %2 (%t37) (- f g g g ) + f g itr + f g ,%1 ,%2 %3 %4 ,%1 %2 %3 ,%1 ,%2 %1 %2 + f g ,%1 %2(%i38) "Another clean result; can also be expressed using Christoffel symbols" (%i39)ishow(canform(conmetderiv(D2,g))) %1 %2 %3 %4 %5 %1 %2 %3 (%t39) 2 f g g ichr2 g + f g itr ,%1 %2 %3 %4 %5 ,%1 %2 %3 %1 %2 %3 %2 %3 %1 %1 %2 - f g ichr2 - f g ichr2 + f g ,%1 %2 %3 ,%1 %2 %3 ,%1 %2(%i40) "Finally, we see that the two results differ only by torsion" (%i41)ishow(canform(D2-D1)) %1 %2 %3 (%t41) f g itr ,%1 %2 %3(%i42) "Last but not least, d^2 is not nilpotent in the presence of torsion" (%i43)extdiff(extdiff(f([],[])))(%i44)ev(%,icc2,ikt2,ikt1)(%i45)canform(%)(%i46)ev(%,g)(%i47)ishow(contract(%)) %3 (%t47) f itr ,%3 %275 %277(%i48) "Reminder: when dim = 2n, the Laplacian is -1 times these results."

The learning curve is steep and there are many pitfalls, but itensor remains an immensely powerful package.