Jul 142021
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.