1@c RECOMMEND REVISE TEXT THROUGHOUT TO LOSE NOTION OF TIME RELATIVE TO PRESENT 2@c LOOK FOR "NOW", "OLD", "NEW", "RECENT", "EARLIER", DATES 3 4@c RERUN EXAMPLES WITH ADDT'L WHITESPACE IN INPUT TO AID LEGIBILITY 5 6@menu 7* Introduction to itensor:: 8* Functions and Variables for itensor:: 9@end menu 10 11@c ----------------------------------------------------------------------------- 12@node Introduction to itensor, Functions and Variables for itensor, itensor, itensor 13@section Introduction to itensor 14@c ----------------------------------------------------------------------------- 15 16Maxima implements symbolic tensor manipulation of two distinct types: 17component tensor manipulation (@code{ctensor} package) and indicial tensor 18manipulation (@code{itensor} package). 19 20Nota bene: Please see the note on 'new tensor notation' below. 21 22Component tensor manipulation means that geometrical tensor 23objects are represented as arrays or matrices. Tensor operations such 24as contraction or covariant differentiation are carried out by 25actually summing over repeated (dummy) indices with @code{do} statements. 26That is, one explicitly performs operations on the appropriate tensor 27components stored in an array or matrix. 28 29Indicial tensor manipulation is implemented by representing 30tensors as functions of their covariant, contravariant and derivative 31indices. Tensor operations such as contraction or covariant 32differentiation are performed by manipulating the indices themselves 33rather than the components to which they correspond. 34 35These two approaches to the treatment of differential, algebraic and 36analytic processes in the context of Riemannian geometry have various 37advantages and disadvantages which reveal themselves only through the 38particular nature and difficulty of the user's problem. However, one 39should keep in mind the following characteristics of the two 40implementations: 41 42The representation of tensors and tensor operations explicitly in 43terms of their components makes @code{ctensor} easy to use. Specification of 44the metric and the computation of the induced tensors and invariants 45is straightforward. Although all of Maxima's powerful simplification 46capacity is at hand, a complex metric with intricate functional and 47coordinate dependencies can easily lead to expressions whose size is 48excessive and whose structure is hidden. In addition, many calculations 49involve intermediate expressions which swell causing programs to 50terminate before completion. Through experience, a user can avoid 51many of these difficulties. 52 53Because of the special way in which tensors and tensor operations 54are represented in terms of symbolic operations on their indices, 55expressions which in the component representation would be 56unmanageable can sometimes be greatly simplified by using the special 57routines for symmetrical objects in @code{itensor}. In this way the structure 58of a large expression may be more transparent. On the other hand, because 59of the special indicial representation in @code{itensor}, in some cases the 60user may find difficulty with the specification of the metric, function 61definition, and the evaluation of differentiated "indexed" objects. 62 63The @code{itensor} package can carry out differentiation with respect to an indexed 64variable, which allows one to use the package when dealing with Lagrangian 65and Hamiltonian formalisms. As it is possible to differentiate a field 66Lagrangian with respect to an (indexed) field variable, one can use Maxima 67to derive the corresponding Euler-Lagrange equations in indicial form. These 68equations can be translated into component tensor (@code{ctensor}) programs using 69the @code{ic_convert} function, allowing us to solve the field equations in a 70particular coordinate representation, or to recast the equations of motion 71in Hamiltonian form. See @code{einhil.dem} and @code{bradic.dem} for two comprehensive 72examples. The first, @code{einhil.dem}, uses the Einstein-Hilbert action to derive 73the Einstein field tensor in the homogeneous and isotropic case (Friedmann 74equations) and the spherically symmetric, static case (Schwarzschild 75solution.) The second, @code{bradic.dem}, demonstrates how to compute the Friedmann 76equations from the action of Brans-Dicke gravity theory, and also derives 77the Hamiltonian associated with the theory's scalar field. 78 79@opencatbox 80@category{Tensors} 81@category{Share packages} 82@category{Package itensor} 83@closecatbox 84 85@c ----------------------------------------------------------------------------- 86@subsection New tensor notation 87@c ----------------------------------------------------------------------------- 88 89Earlier versions of the @code{itensor} package in Maxima used a notation that sometimes 90led to incorrect index ordering. Consider the following, for instance: 91 92@example 93(%i2) imetric(g); 94(%o2) done 95(%i3) ishow(g([],[j,k])*g([],[i,l])*a([i,j],[]))$ 96 i l j k 97(%t3) g g a 98 i j 99(%i4) ishow(contract(%))$ 100 k l 101(%t4) a 102@end example 103 104This result is incorrect unless @code{a} happens to be a symmetric tensor. 105The reason why this happens is that although @code{itensor} correctly maintains 106the order within the set of covariant and contravariant indices, once an 107index is raised or lowered, its position relative to the other set of 108indices is lost. 109 110To avoid this problem, a new notation has been developed that remains fully 111compatible with the existing notation and can be used interchangeably. In 112this notation, contravariant indices are inserted in the appropriate 113positions in the covariant index list, but with a minus sign prepended. 114Functions like @mref{contract_Itensor} and @mref{ishow} are now aware of this 115new index notation and can process tensors appropriately. 116 117In this new notation, the previous example yields a correct result: 118 119@example 120(%i5) ishow(g([-j,-k],[])*g([-i,-l],[])*a([i,j],[]))$ 121 i l j k 122(%t5) g a g 123 i j 124(%i6) ishow(contract(%))$ 125 l k 126(%t6) a 127@end example 128 129Presently, the only code that makes use of this notation is the @code{lc2kdt} 130function. Through this notation, it achieves consistent results as it 131applies the metric tensor to resolve Levi-Civita symbols without resorting 132to numeric indices. 133 134Since this code is brand new, it probably contains bugs. While it has been 135tested to make sure that it doesn't break anything using the "old" tensor 136notation, there is a considerable chance that "new" tensors will fail to 137interoperate with certain functions or features. These bugs will be fixed 138as they are encountered... until then, caveat emptor! 139 140@c ----------------------------------------------------------------------------- 141@subsection Indicial tensor manipulation 142@c ----------------------------------------------------------------------------- 143 144The indicial tensor manipulation package may be loaded by 145@code{load("itensor")}. Demos are also available: try @code{demo("tensor")}. 146 147In @code{itensor} a tensor is represented as an "indexed object" . This is a 148function of 3 groups of indices which represent the covariant, 149contravariant and derivative indices. The covariant indices are 150specified by a list as the first argument to the indexed object, and 151the contravariant indices by a list as the second argument. If the 152indexed object lacks either of these groups of indices then the empty 153list @code{[]} is given as the corresponding argument. Thus, @code{g([a,b],[c])} 154represents an indexed object called @code{g} which has two covariant indices 155@code{(a,b)}, one contravariant index (@code{c}) and no derivative indices. 156 157The derivative indices, if they are present, are appended as 158additional arguments to the symbolic function representing the tensor. 159They can be explicitly specified by the user or be created in the 160process of differentiation with respect to some coordinate variable. 161Since ordinary differentiation is commutative, the derivative indices 162are sorted alphanumerically, unless @code{iframe_flag} is set to @code{true}, 163indicating that a frame metric is being used. This canonical ordering makes it 164possible for Maxima to recognize that, for example, @code{t([a],[b],i,j)} is 165the same as @code{t([a],[b],j,i)}. Differentiation of an indexed object with 166respect to some coordinate whose index does not appear as an argument 167to the indexed object would normally yield zero. This is because 168Maxima would not know that the tensor represented by the indexed 169object might depend implicitly on the corresponding coordinate. By 170modifying the existing Maxima function @code{diff} in @code{itensor}, Maxima now 171assumes that all indexed objects depend on any variable of 172differentiation unless otherwise stated. This makes it possible for 173the summation convention to be extended to derivative indices. It 174should be noted that @code{itensor} does not possess the capabilities of 175raising derivative indices, and so they are always treated as 176covariant. 177 178The following functions are available in the tensor package for 179manipulating indexed objects. At present, with respect to the 180simplification routines, it is assumed that indexed objects do not 181by default possess symmetry properties. This can be overridden by 182setting the variable @code{allsym[false]} to @code{true}, which will 183result in treating all indexed objects completely symmetric in their 184lists of covariant indices and symmetric in their lists of 185contravariant indices. 186 187The @code{itensor} package generally treats tensors as opaque objects. Tensorial 188equations are manipulated based on algebraic rules, specifically symmetry 189and contraction rules. In addition, the @code{itensor} package understands 190covariant differentiation, curvature, and torsion. Calculations can be 191performed relative to a metric of moving frame, depending on the setting 192of the @code{iframe_flag} variable. 193 194A sample session below demonstrates how to load the @code{itensor} package, 195specify the name of the metric, and perform some simple calculations. 196 197@example 198(%i1) load("itensor"); 199(%o1) /share/tensor/itensor.lisp 200(%i2) imetric(g); 201(%o2) done 202(%i3) components(g([i,j],[]),p([i,j],[])*e([],[]))$ 203(%i4) ishow(g([k,l],[]))$ 204(%t4) e p 205 k l 206(%i5) ishow(diff(v([i],[]),t))$ 207(%t5) 0 208(%i6) depends(v,t); 209(%o6) [v(t)] 210(%i7) ishow(diff(v([i],[]),t))$ 211 d 212(%t7) -- (v ) 213 dt i 214(%i8) ishow(idiff(v([i],[]),j))$ 215(%t8) v 216 i,j 217(%i9) ishow(extdiff(v([i],[]),j))$ 218(%t9) v - v 219 j,i i,j 220 ----------- 221 2 222(%i10) ishow(liediff(v,w([i],[])))$ 223 %3 %3 224(%t10) v w + v w 225 i,%3 ,i %3 226(%i11) ishow(covdiff(v([i],[]),j))$ 227 %4 228(%t11) v - v ichr2 229 i,j %4 i j 230(%i12) ishow(ev(%,ichr2))$ 231 %4 %5 232(%t12) v - (g v (e p + e p - e p - e p 233 i,j %4 j %5,i ,i j %5 i j,%5 ,%5 i j 234 235 + e p + e p ))/2 236 i %5,j ,j i %5 237(%i13) iframe_flag:true; 238(%o13) true 239(%i14) ishow(covdiff(v([i],[]),j))$ 240 %6 241(%t14) v - v icc2 242 i,j %6 i j 243(%i15) ishow(ev(%,icc2))$ 244 %6 245(%t15) v - v ifc2 246 i,j %6 i j 247(%i16) ishow(radcan(ev(%,ifc2,ifc1)))$ 248 %6 %7 %6 %7 249(%t16) - (ifg v ifb + ifg v ifb - 2 v 250 %6 j %7 i %6 i j %7 i,j 251 252 %6 %7 253 - ifg v ifb )/2 254 %6 %7 i j 255(%i17) ishow(canform(s([i,j],[])-s([j,i])))$ 256(%t17) s - s 257 i j j i 258(%i18) decsym(s,2,0,[sym(all)],[]); 259(%o18) done 260(%i19) ishow(canform(s([i,j],[])-s([j,i])))$ 261(%t19) 0 262(%i20) ishow(canform(a([i,j],[])+a([j,i])))$ 263(%t20) a + a 264 j i i j 265(%i21) decsym(a,2,0,[anti(all)],[]); 266(%o21) done 267(%i22) ishow(canform(a([i,j],[])+a([j,i])))$ 268(%t22) 0 269@end example 270 271@c end concepts itensor 272 273@c ----------------------------------------------------------------------------- 274@node Functions and Variables for itensor, , Introduction to itensor, itensor 275@section Functions and Variables for itensor 276@subsection Managing indexed objects 277@c ----------------------------------------------------------------------------- 278 279@c ----------------------------------------------------------------------------- 280@anchor{dispcon} 281@deffn {Function} dispcon @ 282@fname{dispcon} (@var{tensor_1}, @var{tensor_2}, @dots{}) @ 283@fname{dispcon} (all) 284 285Displays the contraction properties of its arguments as were given to 286@code{defcon}. @code{dispcon (all)} displays all the contraction properties 287which were defined. 288 289@opencatbox 290@category{Display functions} 291@closecatbox 292@end deffn 293 294@c ----------------------------------------------------------------------------- 295@anchor{entertensor} 296@deffn {Function} entertensor (@var{name}) 297 298is a function which, by prompting, allows one to create an indexed 299object called @var{name} with any number of tensorial and derivative 300indices. Either a single index or a list of indices (which may be 301null) is acceptable input (see the example under @mref{covdiff}). 302 303@opencatbox 304@category{Package itensor} 305@closecatbox 306@end deffn 307 308@c ----------------------------------------------------------------------------- 309@anchor{changename} 310@deffn {Function} changename (@var{old}, @var{new}, @var{expr}) 311 312will change the name of all indexed objects called @var{old} to @var{new} 313in @var{expr}. @var{old} may be either a symbol or a list of the form 314@code{[@var{name}, @var{m}, @var{n}]} in which case only those indexed objects called 315@var{name} with @var{m} covariant and @var{n} contravariant indices will be 316renamed to @var{new}. 317 318@opencatbox 319@category{Package itensor} 320@closecatbox 321@end deffn 322 323@c ----------------------------------------------------------------------------- 324@deffn {Function} listoftens 325 326@anchor{listoftens} 327 328Lists all tensors in a tensorial expression, complete with their indices. E.g., 329 330@example 331 332(%i6) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$ 333 k 334(%t6) d e c + a b 335 x y i j u,v 336(%i7) ishow(listoftens(%))$ 337 k 338(%t7) [a , b , c , d] 339 i j u,v x y 340 341@end example 342 343@opencatbox 344@category{Package itensor} 345@closecatbox 346@end deffn 347 348@c ----------------------------------------------------------------------------- 349@anchor{ishow} 350@deffn {Function} ishow (@var{expr}) 351 352displays @var{expr} with the indexed objects in it shown having their 353covariant indices as subscripts and contravariant indices as 354superscripts. The derivative indices are displayed as subscripts, 355separated from the covariant indices by a comma (see the examples 356throughout this document). 357 358@opencatbox 359@category{Package itensor} 360@closecatbox 361@end deffn 362 363@c ----------------------------------------------------------------------------- 364@anchor{indices} 365@deffn {Function} indices (@var{expr}) 366 367Returns a list of two elements. The first is a list of the free 368indices in @var{expr} (those that occur only once). The second is the 369list of the dummy indices in @var{expr} (those that occur exactly twice) 370as the following example demonstrates. 371 372@example 373 374(%i1) load("itensor"); 375(%o1) /share/tensor/itensor.lisp 376(%i2) ishow(a([i,j],[k,l],m,n)*b([k,o],[j,m,p],q,r))$ 377 k l j m p 378(%t2) a b 379 i j,m n k o,q r 380(%i3) indices(%); 381(%o3) [[l, p, i, n, o, q, r], [k, j, m]] 382 383@end example 384 385A tensor product containing the same index more than twice is syntactically 386illegal. @code{indices} attempts to deal with these expressions in a 387reasonable manner; however, when it is called to operate upon such an 388illegal expression, its behavior should be considered undefined. 389 390@opencatbox 391@category{Package itensor} 392@closecatbox 393@end deffn 394 395@c ----------------------------------------------------------------------------- 396@anchor{rename} 397@deffn {Function} rename @ 398@fname{rename} (@var{expr}) @ 399@fname{rename} (@var{expr}, @var{count}) 400 401Returns an expression equivalent to @var{expr} but with the dummy indices 402in each term chosen from the set @code{[%1, %2,...]}, if the optional second 403argument is omitted. Otherwise, the dummy indices are indexed 404beginning at the value of @var{count}. Each dummy index in a product 405will be different. For a sum, @code{rename} will operate upon each term in 406the sum resetting the counter with each term. In this way @code{rename} can 407serve as a tensorial simplifier. In addition, the indices will be 408sorted alphanumerically (if @mref{allsym} is @code{true}) with respect to 409covariant or contravariant indices depending upon the value of @mref{flipflag}. 410If @code{flipflag} is @code{false} then the indices will be renamed according 411to the order of the contravariant indices. If @code{flipflag} is @code{true} 412the renaming will occur according to the order of the covariant 413indices. It often happens that the combined effect of the two renamings will 414reduce an expression more than either one by itself. 415 416@example 417 418(%i1) load("itensor"); 419(%o1) /share/tensor/itensor.lisp 420(%i2) allsym:true; 421(%o2) true 422(%i3) g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%4],[%3])* 423ichr2([%2,%3],[u])*ichr2([%5,%6],[%1])*ichr2([%7,r],[%2])- 424g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%2],[u])* 425ichr2([%3,%5],[%1])*ichr2([%4,%6],[%3])*ichr2([%7,r],[%2]),noeval$ 426(%i4) expr:ishow(%)$ 427@group 428 %4 %5 %6 %7 %3 u %1 %2 429(%t4) g g ichr2 ichr2 ichr2 ichr2 430 %1 %4 %2 %3 %5 %6 %7 r 431 432 %4 %5 %6 %7 u %1 %3 %2 433 - g g ichr2 ichr2 ichr2 ichr2 434 %1 %2 %3 %5 %4 %6 %7 r 435@end group 436(%i5) flipflag:true; 437(%o5) true 438(%i6) ishow(rename(expr))$ 439 %2 %5 %6 %7 %4 u %1 %3 440(%t6) g g ichr2 ichr2 ichr2 ichr2 441 %1 %2 %3 %4 %5 %6 %7 r 442 443 %4 %5 %6 %7 u %1 %3 %2 444 - g g ichr2 ichr2 ichr2 ichr2 445 %1 %2 %3 %4 %5 %6 %7 r 446(%i7) flipflag:false; 447(%o7) false 448(%i8) rename(%th(2)); 449(%o8) 0 450(%i9) ishow(rename(expr))$ 451 %1 %2 %3 %4 %5 %6 %7 u 452(%t9) g g ichr2 ichr2 ichr2 ichr2 453 %1 %6 %2 %3 %4 r %5 %7 454 455 %1 %2 %3 %4 %6 %5 %7 u 456 - g g ichr2 ichr2 ichr2 ichr2 457 %1 %3 %2 %6 %4 r %5 %7 458@end example 459 460@opencatbox 461@category{Package itensor} 462@closecatbox 463@end deffn 464 465@c THIS FUNCTION IS IN THE SHARE PACKAGE itensor.lisp 466@c MOVE THIS DESCRIPTION TO Itensor.texi 467 468@c ----------------------------------------------------------------------------- 469@anchor{show} 470@deffn {Function} show (@var{expr}) 471 472Displays @code{expr} with the indexed objects in it shown 473having covariant indices as subscripts, contravariant indices as 474superscripts. The derivative indices are displayed as subscripts, 475separated from the covariant indices by a comma. 476 477@opencatbox 478@category{Package itensor} 479@category{Display functions} 480@closecatbox 481@end deffn 482 483@c ----------------------------------------------------------------------------- 484@anchor{flipflag} 485@defvr {Option variable} flipflag 486Default value: @code{false} 487 488If @code{false} then the indices will be 489renamed according to the order of the contravariant indices, 490otherwise according to the order of the covariant indices. 491 492If @code{flipflag} is @code{false} then @code{rename} forms a list 493of the contravariant indices as they are encountered from left to right 494(if @code{true} then of the covariant indices). The first dummy 495index in the list is renamed to @code{%1}, the next to @code{%2}, etc. 496Then sorting occurs after the @code{rename}-ing (see the example 497under @code{rename}). 498 499@opencatbox 500@category{Package itensor} 501@closecatbox 502@end defvr 503 504@c ----------------------------------------------------------------------------- 505@anchor{defcon} 506@deffn {Function} defcon @ 507@fname{defcon} (@var{tensor_1}) @ 508@fname{defcon} (@var{tensor_1}, @var{tensor_2}, @var{tensor_3}) 509 510gives @var{tensor_1} the property that the 511contraction of a product of @var{tensor_1} and @var{tensor_2} results in @var{tensor_3} 512with the appropriate indices. If only one argument, @var{tensor_1}, is 513given, then the contraction of the product of @var{tensor_1} with any indexed 514object having the appropriate indices (say @code{my_tensor}) will yield an 515indexed object with that name, i.e. @code{my_tensor}, and with a new set of 516indices reflecting the contractions performed. 517 For example, if @code{imetric:g}, then @code{defcon(g)} will implement the 518raising and lowering of indices through contraction with the metric 519tensor. 520 More than one @code{defcon} can be given for the same indexed object; the 521latest one given which applies in a particular contraction will be 522used. 523@code{contractions} is a list of those indexed objects which have been given 524contraction properties with @code{defcon}. 525 526@opencatbox 527@category{Package itensor} 528@closecatbox 529@end deffn 530 531@c ----------------------------------------------------------------------------- 532@anchor{remcon} 533@deffn {Function} remcon @ 534@fname{remcon} (@var{tensor_1}, ..., @var{tensor_n}) @ 535@fname{remcon} (all) 536 537Removes all the contraction properties 538from the (@var{tensor_1}, ..., @var{tensor_n}). @code{remcon(all)} removes all contraction 539properties from all indexed objects. 540 541@opencatbox 542@category{Package itensor} 543@closecatbox 544@end deffn 545 546@c ----------------------------------------------------------------------------- 547@anchor{contract_Itensor} 548@deffn {Function} contract (@var{expr}) 549 550Carries out the tensorial contractions in @var{expr} which may be any 551combination of sums and products. This function uses the information 552given to the @code{defcon} function. For best results, @code{expr} 553should be fully expanded. @mref{ratexpand} is the fastest way to expand 554products and powers of sums if there are no variables in the denominators 555of the terms. The @mref{gcd} switch should be @code{false} if GCD 556cancellations are unnecessary. 557 558@opencatbox 559@category{Package itensor} 560@closecatbox 561@end deffn 562 563@c ----------------------------------------------------------------------------- 564@anchor{indexed_tensor} 565@deffn {Function} indexed_tensor (@var{tensor}) 566 567Must be executed before assigning components to a @var{tensor} for which 568a built in value already exists as with @code{ichr1}, @code{ichr2}, 569@code{icurvature}. See the example under @mref{icurvature}. 570 571@opencatbox 572@category{Package itensor} 573@closecatbox 574@end deffn 575 576@c ----------------------------------------------------------------------------- 577@anchor{components} 578@deffn {Function} components (@var{tensor}, @var{expr}) 579 580permits one to assign an indicial value to an expression 581@var{expr} giving the values of the components of @var{tensor}. These 582are automatically substituted for the tensor whenever it occurs with 583all of its indices. The tensor must be of the form @code{t([...],[...])} 584where either list may be empty. @var{expr} can be any indexed expression 585involving other objects with the same free indices as @var{tensor}. When 586used to assign values to the metric tensor wherein the components 587contain dummy indices one must be careful to define these indices to 588avoid the generation of multiple dummy indices. Removal of this 589assignment is given to the function @mref{remcomps}. 590 591It is important to keep in mind that @code{components} cares only about 592the valence of a tensor, not about any particular index ordering. Thus 593assigning components to, say, @code{x([i,-j],[])}, @code{x([-j,i],[])}, or 594@code{x([i],[j])} all produce the same result, namely components being 595assigned to a tensor named @code{x} with valence @code{(1,1)}. 596 597Components can be assigned to an indexed expression in four ways, two 598of which involve the use of the @code{components} command: 599 6001) As an indexed expression. For instance: 601 602@example 603(%i2) components(g([],[i,j]),e([],[i])*p([],[j]))$ 604(%i3) ishow(g([],[i,j]))$ 605 i j 606(%t3) e p 607 608@end example 609 6102) As a matrix: 611 612@example 613 614(%i5) lg:-ident(4)$lg[1,1]:1$lg; 615@group 616 [ 1 0 0 0 ] 617 [ ] 618 [ 0 - 1 0 0 ] 619(%o5) [ ] 620 [ 0 0 - 1 0 ] 621 [ ] 622 [ 0 0 0 - 1 ] 623@end group 624(%i6) components(g([i,j],[]),lg); 625(%o6) done 626(%i7) ishow(g([i,j],[]))$ 627(%t7) g 628 i j 629(%i8) g([1,1],[]); 630(%o8) 1 631(%i9) g([4,4],[]); 632(%o9) - 1 633@end example 634 6353) As a function. You can use a Maxima function to specify the 636components of a tensor based on its indices. For instance, the following 637code assigns @mref{kdelta} to @code{h} if @code{h} has the same number 638of covariant and contravariant indices and no derivative indices, and 639@code{g} otherwise: 640 641@example 642 643(%i4) h(l1,l2,[l3]):=if length(l1)=length(l2) and length(l3)=0 644 then kdelta(l1,l2) else apply(g,append([l1,l2], l3))$ 645(%i5) ishow(h([i],[j]))$ 646 j 647(%t5) kdelta 648 i 649(%i6) ishow(h([i,j],[k],l))$ 650 k 651(%t6) g 652 i j,l 653@end example 654 6554) Using Maxima's pattern matching capabilities, specifically the 656@mref{defrule} and @mref{applyb1} commands: 657 658@example 659 660(%i1) load("itensor"); 661(%o1) /share/tensor/itensor.lisp 662(%i2) matchdeclare(l1,listp); 663(%o2) done 664(%i3) defrule(r1,m(l1,[]),(i1:idummy(), 665 g([l1[1],l1[2]],[])*q([i1],[])*e([],[i1])))$ 666 667(%i4) defrule(r2,m([],l1),(i1:idummy(), 668 w([],[l1[1],l1[2]])*e([i1],[])*q([],[i1])))$ 669 670(%i5) ishow(m([i,n],[])*m([],[i,m]))$ 671@group 672 i m 673(%t5) m m 674 i n 675@end group 676(%i6) ishow(rename(applyb1(%,r1,r2)))$ 677 %1 %2 %3 m 678(%t6) e q w q e g 679 %1 %2 %3 n 680@end example 681 682@opencatbox 683@category{Package itensor} 684@closecatbox 685@end deffn 686 687@anchor{remcomps} 688@deffn {Function} remcomps (@var{tensor}) 689 690Unbinds all values from @var{tensor} which were assigned with the 691@mref{components} function. 692 693@opencatbox 694@category{Package itensor} 695@closecatbox 696@end deffn 697 698@c NEED LIST OF ARGUMENTS HERE 699 700@c ----------------------------------------------------------------------------- 701@anchor{showcomps} 702@deffn {Function} showcomps (@var{tensor}) 703 704Shows component assignments of a tensor, as made using the @mref{components} 705command. This function can be particularly useful when a matrix is assigned 706to an indicial tensor using @code{components}, as demonstrated by the 707following example: 708 709@example 710 711(%i1) load(ctensor); 712(%o1) /share/tensor/ctensor.mac 713(%i2) load("itensor"); 714(%o2) /share/tensor/itensor.lisp 715(%i3) lg:matrix([sqrt(r/(r-2*m)),0,0,0],[0,r,0,0], 716 [0,0,sin(theta)*r,0],[0,0,0,sqrt((r-2*m)/r)]); 717 [ r ] 718 [ sqrt(-------) 0 0 0 ] 719 [ r - 2 m ] 720 [ ] 721 [ 0 r 0 0 ] 722(%o3) [ ] 723 [ 0 0 r sin(theta) 0 ] 724 [ ] 725 [ r - 2 m ] 726 [ 0 0 0 sqrt(-------) ] 727 [ r ] 728(%i4) components(g([i,j],[]),lg); 729(%o4) done 730(%i5) showcomps(g([i,j],[])); 731 [ r ] 732 [ sqrt(-------) 0 0 0 ] 733 [ r - 2 m ] 734 [ ] 735 [ 0 r 0 0 ] 736(%t5) g = [ ] 737 i j [ 0 0 r sin(theta) 0 ] 738 [ ] 739 [ r - 2 m ] 740 [ 0 0 0 sqrt(-------) ] 741 [ r ] 742(%o5) false 743 744@end example 745 746The @code{showcomps} command can also display components of a tensor of 747rank higher than 2. 748 749@opencatbox 750@category{Package itensor} 751@closecatbox 752@end deffn 753 754@c ----------------------------------------------------------------------------- 755@anchor{idummy} 756@deffn {Function} idummy () 757 758Increments @mref{icounter} and returns as its value an index of the form 759@code{%n} where n is a positive integer. This guarantees that dummy indices 760which are needed in forming expressions will not conflict with indices 761already in use (see the example under @mref{indices}). 762 763@opencatbox 764@category{Package itensor} 765@closecatbox 766@end deffn 767 768@anchor{idummyx} 769@defvr {Option variable} idummyx 770Default value: @code{%} 771 772Is the prefix for dummy indices (see the example under @mref{indices}). 773 774@opencatbox 775@category{Package itensor} 776@closecatbox 777@end defvr 778 779@c ----------------------------------------------------------------------------- 780@anchor{icounter} 781@defvr {Option variable} icounter 782Default value: @code{1} 783 784Determines the numerical suffix to be used in 785generating the next dummy index in the tensor package. The prefix is 786determined by the option @mref{idummy} (default: @code{%}). 787 788@opencatbox 789@category{Package itensor} 790@closecatbox 791@end defvr 792 793@c ----------------------------------------------------------------------------- 794@anchor{kdelta} 795@deffn {Function} kdelta (@var{L1}, @var{L2}) 796is the generalized Kronecker delta function defined in 797the @code{itensor} package with @var{L1} the list of covariant indices and @var{L2} 798the list of contravariant indices. @code{kdelta([i],[j])} returns the ordinary 799Kronecker delta. The command @code{ev(@var{expr},kdelta)} causes the evaluation of 800an expression containing @code{kdelta([],[])} to the dimension of the 801manifold. 802 803In what amounts to an abuse of this notation, @code{itensor} also allows 804@code{kdelta} to have 2 covariant and no contravariant, or 2 contravariant 805and no covariant indices, in effect providing a co(ntra)variant "unit matrix" 806capability. This is strictly considered a programming aid and not meant to 807imply that @code{kdelta([i,j],[])} is a valid tensorial object. 808 809@opencatbox 810@category{Package itensor} 811@closecatbox 812@end deffn 813 814@c ----------------------------------------------------------------------------- 815@anchor{kdels} 816@deffn {Function} kdels (@var{L1}, @var{L2}) 817 818Symmetrized Kronecker delta, used in some calculations. For instance: 819 820@example 821 822(%i1) load("itensor"); 823(%o1) /share/tensor/itensor.lisp 824(%i2) kdelta([1,2],[2,1]); 825(%o2) - 1 826(%i3) kdels([1,2],[2,1]); 827(%o3) 1 828(%i4) ishow(kdelta([a,b],[c,d]))$ 829 c d d c 830(%t4) kdelta kdelta - kdelta kdelta 831 a b a b 832(%i4) ishow(kdels([a,b],[c,d]))$ 833 c d d c 834(%t4) kdelta kdelta + kdelta kdelta 835 a b a b 836 837@end example 838 839@opencatbox 840@category{Package itensor} 841@closecatbox 842@end deffn 843 844@c ----------------------------------------------------------------------------- 845@anchor{levi_civita} 846@deffn {Function} levi_civita (@var{L}) 847is the permutation (or Levi-Civita) tensor which yields 1 if 848the list @var{L} consists of an even permutation of integers, -1 if it 849consists of an odd permutation, and 0 if some indices in @var{L} are 850repeated. 851 852@opencatbox 853@category{Package itensor} 854@closecatbox 855@end deffn 856 857@c ----------------------------------------------------------------------------- 858@anchor{lc2kdt} 859@deffn {Function} lc2kdt (@var{expr}) 860Simplifies expressions containing the Levi-Civita symbol, converting these 861to Kronecker-delta expressions when possible. The main difference between 862this function and simply evaluating the Levi-Civita symbol is that direct 863evaluation often results in Kronecker expressions containing numerical 864indices. This is often undesirable as it prevents further simplification. 865The @code{lc2kdt} function avoids this problem, yielding expressions that 866are more easily simplified with @mref{rename} or @mref{contract}. 867 868@example 869 870(%i1) load("itensor"); 871(%o1) /share/tensor/itensor.lisp 872(%i2) expr:ishow('levi_civita([],[i,j]) 873 *'levi_civita([k,l],[])*a([j],[k]))$ 874 i j k 875(%t2) levi_civita a levi_civita 876 j k l 877(%i3) ishow(ev(expr,levi_civita))$ 878 i j k 1 2 879(%t3) kdelta a kdelta 880 1 2 j k l 881(%i4) ishow(ev(%,kdelta))$ 882 i j j i k 883(%t4) (kdelta kdelta - kdelta kdelta ) a 884 1 2 1 2 j 885 886 1 2 2 1 887 (kdelta kdelta - kdelta kdelta ) 888 k l k l 889(%i5) ishow(lc2kdt(expr))$ 890 k i j k j i 891(%t5) a kdelta kdelta - a kdelta kdelta 892 j k l j k l 893(%i6) ishow(contract(expand(%)))$ 894 i i 895(%t6) a - a kdelta 896 l l 897@end example 898 899The @code{lc2kdt} function sometimes makes use of the metric tensor. 900If the metric tensor was not defined previously with @mref{imetric}, 901this results in an error. 902 903@example 904 905(%i7) expr:ishow('levi_civita([],[i,j]) 906 *'levi_civita([],[k,l])*a([j,k],[]))$ 907@group 908 i j k l 909(%t7) levi_civita levi_civita a 910 j k 911@end group 912(%i8) ishow(lc2kdt(expr))$ 913Maxima encountered a Lisp error: 914 915 Error in $IMETRIC [or a callee]: 916 $IMETRIC [or a callee] requires less than two arguments. 917 918Automatically continuing. 919To reenable the Lisp debugger set *debugger-hook* to nil. 920(%i9) imetric(g); 921(%o9) done 922(%i10) ishow(lc2kdt(expr))$ 923 %3 i k %4 j l %3 i l %4 j 924(%t10) (g kdelta g kdelta - g kdelta g 925 %3 %4 %3 926 k 927 kdelta ) a 928 %4 j k 929(%i11) ishow(contract(expand(%)))$ 930 l i l i j 931(%t11) a - g a 932 j 933@end example 934 935 936@opencatbox 937@category{Package itensor} 938@closecatbox 939@end deffn 940 941@c HMM, WHICH CATEGORY DOES THIS FALL INTO -- FUNCTION, VARIABLE, OTHER ?? 942 943@c ----------------------------------------------------------------------------- 944@anchor{lc_l} 945@deffn {Function} lc_l 946Simplification rule used for expressions containing the unevaluated Levi-Civita 947symbol (@mref{levi_civita}). Along with @mref{lc_u}, it can be used to simplify 948many expressions more efficiently than the evaluation of @code{levi_civita}. 949For example: 950 951@example 952 953(%i1) load("itensor"); 954(%o1) /share/tensor/itensor.lisp 955(%i2) el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$ 956 i j 957(%t2) a a levi_civita 958 i j k 959(%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$ 960 i j k 961(%t3) levi_civita a a 962 i j 963(%i4) canform(contract(expand(applyb1(el1,lc_l,lc_u)))); 964(%t4) 0 965(%i5) canform(contract(expand(applyb1(el2,lc_l,lc_u)))); 966(%t5) 0 967 968@end example 969 970@opencatbox 971@category{Package itensor} 972@closecatbox 973@end deffn 974 975@c HMM, WHICH CATEGORY DOES THIS FALL INTO -- FUNCTION, VARIABLE, OTHER ?? 976 977@c ----------------------------------------------------------------------------- 978@anchor{lc_u} 979@deffn {Function} lc_u 980 981Simplification rule used for expressions containing the unevaluated Levi-Civita 982symbol (@mref{levi_civita}). Along with @code{lc_u}, it can be used to simplify 983many expressions more efficiently than the evaluation of @code{levi_civita}. 984For details, see @mref{lc_l}. 985 986@opencatbox 987@category{Package itensor} 988@closecatbox 989@end deffn 990 991@c ----------------------------------------------------------------------------- 992@anchor{canten} 993@deffn {Function} canten (@var{expr}) 994Simplifies @var{expr} by renaming (see @mref{rename}) 995and permuting dummy indices. @code{rename} is restricted to sums of tensor 996products in which no derivatives are present. As such it is limited 997and should only be used if @mref{canform} is not capable of carrying out the 998required simplification. 999 1000The @code{canten} function returns a mathematically correct result only 1001if its argument is an expression that is fully symmetric in its indices. 1002For this reason, @code{canten} returns an error if @mref{allsym} is not 1003set to @code{true}. 1004 1005@opencatbox 1006@category{Package itensor} 1007@closecatbox 1008@end deffn 1009 1010@c ----------------------------------------------------------------------------- 1011@anchor{concan} 1012@deffn {Function} concan (@var{expr}) 1013Similar to @mref{canten} but also performs index contraction. 1014 1015@opencatbox 1016@category{Package itensor} 1017@closecatbox 1018@end deffn 1019 1020@c ----------------------------------------------------------------------------- 1021@subsection Tensor symmetries 1022@c ----------------------------------------------------------------------------- 1023 1024@c ----------------------------------------------------------------------------- 1025@anchor{allsym} 1026@defvr {Option variable} allsym 1027Default value: @code{false} 1028 1029If @code{true} then all indexed objects 1030are assumed symmetric in all of their covariant and contravariant 1031indices. If @code{false} then no symmetries of any kind are assumed 1032in these indices. Derivative indices are always taken to be symmetric 1033unless @code{iframe_flag} is set to @code{true}. 1034 1035@opencatbox 1036@category{Package itensor} 1037@closecatbox 1038@end defvr 1039 1040@c ----------------------------------------------------------------------------- 1041@anchor{decsym} 1042@deffn {Function} decsym (@var{tensor}, @var{m}, @var{n}, [@var{cov_1}, @var{cov_2}, ...], [@var{contr_1}, @var{contr_2}, ...]) 1043 1044Declares symmetry properties for @var{tensor} of @var{m} covariant and 1045@var{n} contravariant indices. The @var{cov_i} and @var{contr_i} are 1046pseudofunctions expressing symmetry relations among the covariant and 1047contravariant indices respectively. These are of the form 1048@code{symoper(@var{index_1}, @var{index_2},...)} where @code{symoper} is one of 1049@code{sym}, @code{anti} or @code{cyc} and the @var{index_i} are integers 1050indicating the position of the index in the @var{tensor}. This will 1051declare @var{tensor} to be symmetric, antisymmetric or cyclic respectively 1052in the @var{index_i}. @code{symoper(all)} is also an allowable form which 1053indicates all indices obey the symmetry condition. For example, given an 1054object @code{b} with 5 covariant indices, 1055@code{decsym(b,5,3,[sym(1,2),anti(3,4)],[cyc(all)])} declares @code{b} 1056symmetric in its first and second and antisymmetric in its third and 1057fourth covariant indices, and cyclic in all of its contravariant indices. 1058Either list of symmetry declarations may be null. The function which 1059performs the simplifications is @code{canform} as the example below 1060illustrates. 1061 1062@example 1063 1064(%i1) load("itensor"); 1065(%o1) /share/tensor/itensor.lisp 1066(%i2) expr:contract( expand( a([i1, j1, k1], []) 1067 *kdels([i, j, k], [i1, j1, k1])))$ 1068(%i3) ishow(expr)$ 1069@group 1070(%t3) a + a + a + a + a + a 1071 k j i k i j j k i j i k i k j i j k 1072@end group 1073(%i4) decsym(a,3,0,[sym(all)],[]); 1074(%o4) done 1075(%i5) ishow(canform(expr))$ 1076(%t5) 6 a 1077 i j k 1078(%i6) remsym(a,3,0); 1079(%o6) done 1080(%i7) decsym(a,3,0,[anti(all)],[]); 1081(%o7) done 1082(%i8) ishow(canform(expr))$ 1083(%t8) 0 1084(%i9) remsym(a,3,0); 1085(%o9) done 1086(%i10) decsym(a,3,0,[cyc(all)],[]); 1087(%o10) done 1088(%i11) ishow(canform(expr))$ 1089(%t11) 3 a + 3 a 1090 i k j i j k 1091(%i12) dispsym(a,3,0); 1092(%o12) [[cyc, [[1, 2, 3]], []]] 1093 1094@end example 1095 1096@opencatbox 1097@category{Package itensor} 1098@closecatbox 1099@end deffn 1100 1101@c ----------------------------------------------------------------------------- 1102@anchor{remsym} 1103@deffn {Function} remsym (@var{tensor}, @var{m}, @var{n}) 1104Removes all symmetry properties from @var{tensor} which has @var{m} 1105covariant indices and @var{n} contravariant indices. 1106 1107@opencatbox 1108@category{Package itensor} 1109@closecatbox 1110@end deffn 1111 1112@c ----------------------------------------------------------------------------- 1113@anchor{canform} 1114@deffn {Function} canform @ 1115@fname{canform} (@var{expr}) @ 1116@fname{canform} (@var{expr}, @var{rename}) 1117 1118Simplifies @var{expr} by renaming dummy 1119indices and reordering all indices as dictated by symmetry conditions 1120imposed on them. If @code{allsym} is @code{true} then all indices are assumed 1121symmetric, otherwise symmetry information provided by @code{decsym} 1122declarations will be used. The dummy indices are renamed in the same 1123manner as in the @mref{rename} function. When @code{canform} is applied to a large 1124expression the calculation may take a considerable amount of time. 1125This time can be shortened by calling @code{rename} on the expression first. 1126Also see the example under @mref{decsym}. Note: @code{canform} may not be able to 1127reduce an expression completely to its simplest form although it will 1128always return a mathematically correct result. 1129 1130The optional second parameter @var{rename}, if set to @code{false}, suppresses renaming. 1131 1132@opencatbox 1133@category{Package itensor} 1134@closecatbox 1135@end deffn 1136 1137@c ----------------------------------------------------------------------------- 1138@subsection Indicial tensor calculus 1139@c ----------------------------------------------------------------------------- 1140 1141@c ----------------------------------------------------------------------------- 1142@anchor{itensor_diff} 1143@deffn {Function} diff (@var{expr}, @var{v_1}, [@var{n_1}, [@var{v_2}, @var{n_2}] ...]) 1144 1145is the usual Maxima differentiation function which has been expanded 1146in its abilities for @code{itensor}. It takes the derivative of @var{expr} with 1147respect to @var{v_1} @var{n_1} times, with respect to @var{v_2} @var{n_2} 1148times, etc. For the tensor package, the function has been modified so 1149that the @var{v_i} may be integers from 1 up to the value of the variable 1150@code{dim}. This will cause the differentiation to be carried out with 1151respect to the @var{v_i}th member of the list @code{vect_coords}. If 1152@code{vect_coords} is bound to an atomic variable, then that variable 1153subscripted by @var{v_i} will be used for the variable of 1154differentiation. This permits an array of coordinate names or 1155subscripted names like @code{x[1]}, @code{x[2]}, ... to be used. 1156 1157A further extension adds the ability to @code{diff} to compute derivatives 1158with respect to an indexed variable. In particular, the tensor package knows 1159how to differentiate expressions containing combinations of the metric tensor 1160and its derivatives with respect to the metric tensor and its first and 1161second derivatives. This capability is particularly useful when considering 1162Lagrangian formulations of a gravitational theory, allowing one to derive 1163the Einstein tensor and field equations from the action principle. 1164 1165@opencatbox 1166@category{Package itensor} 1167@closecatbox 1168@end deffn 1169 1170@c ----------------------------------------------------------------------------- 1171@anchor{idiff} 1172@deffn {Function} idiff (@var{expr}, @var{v_1}, [@var{n_1}, [@var{v_2}, @var{n_2}] ...]) 1173Indicial differentiation. Unlike @code{diff}, which differentiates 1174with respect to an independent variable, @code{idiff)} can be used 1175to differentiate with respect to a coordinate. For an indexed object, 1176this amounts to appending the @var{v_i} as derivative indices. 1177Subsequently, derivative indices will be sorted, unless @code{iframe_flag} 1178is set to @code{true}. 1179 1180@code{idiff} can also differentiate the determinant of the metric 1181tensor. Thus, if @code{imetric} has been bound to @code{G} then 1182@code{idiff(determinant(g),k)} will return 1183@code{2 * determinant(g) * ichr2([%i,k],[%i])} where the dummy index @code{%i} 1184is chosen appropriately. 1185 1186@opencatbox 1187@category{Package itensor} 1188@closecatbox 1189@end deffn 1190 1191@c ----------------------------------------------------------------------------- 1192@anchor{liediff} 1193@deffn {Function} liediff (@var{v}, @var{ten}) 1194 1195Computes the Lie-derivative of the tensorial expression @var{ten} with 1196respect to the vector field @var{v}. @var{ten} should be any indexed 1197tensor expression; @var{v} should be the name (without indices) of a vector 1198field. For example: 1199 1200@example 1201 1202(%i1) load("itensor"); 1203(%o1) /share/tensor/itensor.lisp 1204(%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$ 1205 k %2 %2 %2 1206(%t2) b (v a + v a + v a ) 1207 ,l i j,%2 ,j i %2 ,i %2 j 1208 1209 %1 k %1 k %1 k 1210 + (v b - b v + v b ) a 1211 ,%1 l ,l ,%1 ,l ,%1 i j 1212 1213@end example 1214 1215@opencatbox 1216@category{Package itensor} 1217@closecatbox 1218@end deffn 1219 1220@c ----------------------------------------------------------------------------- 1221@anchor{rediff} 1222@deffn {Function} rediff (@var{ten}) 1223 1224Evaluates all occurrences of the @mref{idiff} command in the tensorial 1225expression @var{ten}. 1226 1227@opencatbox 1228@category{Package itensor} 1229@closecatbox 1230@end deffn 1231 1232@c ----------------------------------------------------------------------------- 1233@anchor{undiff} 1234@deffn {Function} undiff (@var{expr}) 1235 1236Returns an expression equivalent to @var{expr} but with all derivatives 1237of indexed objects replaced by the noun form of the @mref{idiff} function. Its 1238arguments would yield that indexed object if the differentiation were 1239carried out. This is useful when it is desired to replace a 1240differentiated indexed object with some function definition resulting 1241in @var{expr} and then carry out the differentiation by saying 1242@code{ev(@var{expr}, idiff)}. 1243 1244@opencatbox 1245@category{Package itensor} 1246@closecatbox 1247@end deffn 1248 1249@c ----------------------------------------------------------------------------- 1250@anchor{evundiff} 1251@deffn {Function} evundiff (@var{expr}) 1252 1253Equivalent to the execution of @mref{undiff}, followed by @mref{ev} and 1254@mref{rediff}. 1255 1256The point of this operation is to easily evalute expressions that cannot 1257be directly evaluated in derivative form. For instance, the following 1258causes an error: 1259 1260@example 1261(%i1) load("itensor"); 1262(%o1) /share/tensor/itensor.lisp 1263(%i2) icurvature([i,j,k],[l],m); 1264Maxima encountered a Lisp error: 1265 1266 Error in $ICURVATURE [or a callee]: 1267 $ICURVATURE [or a callee] requires less than three arguments. 1268 1269Automatically continuing. 1270To reenable the Lisp debugger set *debugger-hook* to nil. 1271@end example 1272 1273However, if @mref{icurvature} is entered in noun form, it can be evaluated 1274using @code{evundiff}: 1275 1276@example 1277(%i3) ishow('icurvature([i,j,k],[l],m))$ 1278 l 1279(%t3) icurvature 1280 i j k,m 1281(%i4) ishow(evundiff(%))$ 1282 l l %1 l %1 1283(%t4) - ichr2 - ichr2 ichr2 - ichr2 ichr2 1284 i k,j m %1 j i k,m %1 j,m i k 1285 1286 l l %1 l %1 1287 + ichr2 + ichr2 ichr2 + ichr2 ichr2 1288 i j,k m %1 k i j,m %1 k,m i j 1289@end example 1290 1291Note: In earlier versions of Maxima, derivative forms of the 1292Christoffel-symbols also could not be evaluated. This has been fixed now, 1293so @code{evundiff} is no longer necessary for expressions like this: 1294 1295@example 1296(%i5) imetric(g); 1297(%o5) done 1298(%i6) ishow(ichr2([i,j],[k],l))$ 1299 k %3 1300 g (g - g + g ) 1301 j %3,i l i j,%3 l i %3,j l 1302(%t6) ----------------------------------------- 1303 2 1304 1305 k %3 1306 g (g - g + g ) 1307 ,l j %3,i i j,%3 i %3,j 1308 + ----------------------------------- 1309 2 1310@end example 1311 1312@opencatbox 1313@category{Package itensor} 1314@closecatbox 1315@end deffn 1316 1317@c ----------------------------------------------------------------------------- 1318@anchor{flush} 1319@deffn {Function} flush (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...) 1320Set to zero, in 1321@var{expr}, all occurrences of the @var{tensor_i} that have no derivative indices. 1322 1323@opencatbox 1324@category{Package itensor} 1325@closecatbox 1326@end deffn 1327 1328@c ----------------------------------------------------------------------------- 1329@anchor{flushd} 1330@deffn {Function} flushd (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...) 1331Set to zero, in 1332@var{expr}, all occurrences of the @var{tensor_i} that have derivative indices. 1333 1334@opencatbox 1335@category{Package itensor} 1336@closecatbox 1337@end deffn 1338 1339@c ----------------------------------------------------------------------------- 1340@anchor{flushnd} 1341@deffn {Function} flushnd (@var{expr}, @var{tensor}, @var{n}) 1342Set to zero, in @var{expr}, all 1343occurrences of the differentiated object @var{tensor} that have @var{n} or more 1344derivative indices as the following example demonstrates. 1345@example 1346 1347(%i1) load("itensor"); 1348(%o1) /share/tensor/itensor.lisp 1349(%i2) ishow(a([i],[J,r],k,r)+a([i],[j,r,s],k,r,s))$ 1350 J r j r s 1351(%t2) a + a 1352 i,k r i,k r s 1353(%i3) ishow(flushnd(%,a,3))$ 1354 J r 1355(%t3) a 1356 i,k r 1357@end example 1358 1359@opencatbox 1360@category{Package itensor} 1361@closecatbox 1362@end deffn 1363 1364@c ----------------------------------------------------------------------------- 1365@anchor{coord} 1366@deffn {Function} coord (@var{tensor_1}, @var{tensor_2}, ...) 1367 1368Gives @var{tensor_i} the coordinate differentiation property that the 1369derivative of contravariant vector whose name is one of the 1370@var{tensor_i} yields a Kronecker delta. For example, if @code{coord(x)} has 1371been done then @code{idiff(x([],[i]),j)} gives @code{kdelta([i],[j])}. 1372@code{coord} is a list of all indexed objects having this property. 1373 1374@opencatbox 1375@category{Package itensor} 1376@closecatbox 1377@end deffn 1378 1379@c ----------------------------------------------------------------------------- 1380@anchor{remcoord} 1381@deffn {Function} remcoord @ 1382@fname{remcoord} (@var{tensor_1}, @var{tensor_2}, ...) @ 1383@fname{remcoord} (all) 1384 1385Removes the coordinate differentiation property from the @code{tensor_i} 1386that was established by the function @code{coord}. @code{remcoord(all)} 1387removes this property from all indexed objects. 1388 1389@opencatbox 1390@category{Package itensor} 1391@closecatbox 1392@end deffn 1393 1394@c ----------------------------------------------------------------------------- 1395@anchor{makebox} 1396@deffn {Function} makebox (@var{expr}) 1397Display @var{expr} in the same manner as @mref{show}; however, 1398any tensor d'Alembertian occurring in @var{expr} will be indicated using the 1399symbol @code{[]}. For example, @code{[]p([m],[n])} represents 1400@code{g([],[i,j])*p([m],[n],i,j)}. 1401 1402@opencatbox 1403@category{Package itensor} 1404@closecatbox 1405@end deffn 1406 1407@c ----------------------------------------------------------------------------- 1408@anchor{conmetderiv} 1409@deffn {Function} conmetderiv (@var{expr}, @var{tensor}) 1410 1411Simplifies expressions containing ordinary derivatives of 1412both covariant and con@-tra@-va@-ri@-ant forms of the metric tensor (the 1413current restriction). For example, @code{conmetderiv} can relate the 1414derivative of the contravariant metric tensor with the Christoffel 1415symbols as seen from the following: 1416 1417@example 1418 1419(%i1) load("itensor"); 1420(%o1) /share/tensor/itensor.lisp 1421(%i2) ishow(g([],[a,b],c))$ 1422 a b 1423(%t2) g 1424 ,c 1425(%i3) ishow(conmetderiv(%,g))$ 1426 %1 b a %1 a b 1427(%t3) - g ichr2 - g ichr2 1428 %1 c %1 c 1429@end example 1430 1431@opencatbox 1432@category{Package itensor} 1433@closecatbox 1434@end deffn 1435 1436@c ----------------------------------------------------------------------------- 1437@anchor{simpmetderiv} 1438@deffn {Function} simpmetderiv @ 1439@fname{simpmetderiv} (@var{expr}) @ 1440@fname{simpmetderiv} (@var{expr}[, @var{stop}]) 1441 1442Simplifies expressions containing products of the derivatives of the 1443metric tensor. Specifically, @code{simpmetderiv} recognizes two identities: 1444 1445@example 1446 1447 ab ab ab a 1448 g g + g g = (g g ) = (kdelta ) = 0 1449 ,d bc bc,d bc ,d c ,d 1450 1451@end example 1452 1453hence 1454 1455@example 1456 1457 ab ab 1458 g g = - g g 1459 ,d bc bc,d 1460@end example 1461 1462and 1463 1464@example 1465 1466 ab ab 1467 g g = g g 1468 ,j ab,i ,i ab,j 1469 1470@end example 1471 1472which follows from the symmetries of the Christoffel symbols. 1473 1474The @code{simpmetderiv} function takes one optional parameter which, when 1475present, causes the function to stop after the first successful 1476substitution in a product expression. The @code{simpmetderiv} function 1477also makes use of the global variable @mref{flipflag} which determines 1478how to apply a ``canonical'' ordering to the product indices. 1479 1480Put together, these capabilities can be used to achieve powerful 1481simplifications that are difficult or impossible to accomplish otherwise. 1482This is demonstrated through the following example that explicitly uses the 1483partial simplification features of @code{simpmetderiv} to obtain a 1484contractible expression: 1485 1486@example 1487 1488(%i1) load("itensor"); 1489(%o1) /share/tensor/itensor.lisp 1490(%i2) imetric(g); 1491(%o2) done 1492(%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([b,c],[],e))$ 1493 a b b c 1494(%t3) g g g g 1495 a b,d b c,e 1496(%i4) ishow(canform(%))$ 1497 1498errexp1 has improper indices 1499 -- an error. Quitting. To debug this try debugmode(true); 1500(%i5) ishow(simpmetderiv(%))$ 1501 a b b c 1502(%t5) g g g g 1503 a b,d b c,e 1504(%i6) flipflag:not flipflag; 1505(%o6) true 1506(%i7) ishow(simpmetderiv(%th(2)))$ 1507 a b b c 1508(%t7) g g g g 1509 ,d ,e a b b c 1510(%i8) flipflag:not flipflag; 1511(%o8) false 1512(%i9) ishow(simpmetderiv(%th(2),stop))$ 1513 a b b c 1514(%t9) - g g g g 1515 ,e a b,d b c 1516(%i10) ishow(contract(%))$ 1517 b c 1518(%t10) - g g 1519 ,e c b,d 1520 1521@end example 1522 1523See also @code{weyl.dem} for an example that uses @mref{simpmetderiv} 1524and @mref{conmetderiv} together to simplify contractions of the Weyl tensor. 1525 1526@opencatbox 1527@category{Package itensor} 1528@closecatbox 1529@end deffn 1530 1531@c -----------------------------------------------------------------------------} 1532@anchor{flush1deriv} 1533@deffn {Function} flush1deriv (@var{expr}, @var{tensor}) 1534 1535Set to zero, in @code{expr}, all occurrences of @code{tensor} that have 1536exactly one derivative index. 1537 1538@opencatbox 1539@category{Package itensor} 1540@closecatbox 1541@end deffn 1542 1543@c ----------------------------------------------------------------------------- 1544@subsection Tensors in curved spaces 1545@c ----------------------------------------------------------------------------- 1546 1547@c ----------------------------------------------------------------------------- 1548@anchor{imetric} 1549@deffn {Function} imetric (@var{g}) 1550@deffnx {System variable} imetric 1551 1552Specifies the metric by assigning the variable @code{imetric:@var{g}} in 1553addition, the con@-trac@-tion properties of the metric @var{g} are set up by 1554executing the commands @code{defcon(@var{g}), defcon(@var{g}, @var{g}, kdelta)}. 1555The variable @code{imetric} (unbound by default), is bound to the metric, assigned by 1556the @code{imetric(@var{g})} command. 1557 1558@opencatbox 1559@category{Package itensor} 1560@closecatbox 1561@end deffn 1562 1563@c ----------------------------------------------------------------------------- 1564@anchor{idim} 1565@deffn {Function} idim (@var{n}) 1566Sets the dimensions of the metric. Also initializes the antisymmetry 1567properties of the Levi-Civita symbols for the given dimension. 1568 1569@opencatbox 1570@category{Package itensor} 1571@closecatbox 1572@end deffn 1573 1574@c ----------------------------------------------------------------------------- 1575@anchor{ichr1} 1576@deffn {Function} ichr1 ([@var{i}, @var{j}, @var{k}]) 1577Yields the Christoffel symbol of the first kind via the 1578definition 1579@example 1580 (g + g - g )/2 . 1581 ik,j jk,i ij,k 1582@end example 1583@noindent 1584To evaluate the Christoffel symbols for a particular metric, the 1585variable @code{imetric} must be assigned a name as in the example under @code{chr2}. 1586 1587@opencatbox 1588@category{Package itensor} 1589@closecatbox 1590@end deffn 1591 1592@c ----------------------------------------------------------------------------- 1593@anchor{ichr2} 1594@deffn {Function} ichr2 ([@var{i}, @var{j}], [@var{k}]) 1595Yields the Christoffel symbol of the second kind 1596defined by the relation 1597@example 1598 ks 1599 ichr2([i,j],[k]) = g (g + g - g )/2 1600 is,j js,i ij,s 1601@end example 1602 1603@opencatbox 1604@category{Package itensor} 1605@closecatbox 1606@end deffn 1607 1608@c ----------------------------------------------------------------------------- 1609@anchor{icurvature} 1610@deffn {Function} icurvature ([@var{i}, @var{j}, @var{k}], [@var{h}]) 1611Yields the Riemann 1612curvature tensor in terms of the Christoffel symbols of the second 1613kind (@code{ichr2}). The following notation is used: 1614@example 1615 h h h %1 h 1616 icurvature = - ichr2 - ichr2 ichr2 + ichr2 1617 i j k i k,j %1 j i k i j,k 1618 h %1 1619 + ichr2 ichr2 1620 %1 k i j 1621@end example 1622 1623@opencatbox 1624@category{Package itensor} 1625@closecatbox 1626@end deffn 1627 1628@c ----------------------------------------------------------------------------- 1629@anchor{covdiff} 1630@deffn {Function} covdiff (@var{expr}, @var{v_1}, @var{v_2}, ...) 1631Yields the covariant derivative of @var{expr} with 1632respect to the variables @var{v_i} in terms of the Christoffel symbols of the 1633second kind (@code{ichr2}). In order to evaluate these, one should use 1634@code{ev(@var{expr},ichr2)}. 1635 1636@example 1637 1638(%i1) load("itensor"); 1639(%o1) /share/tensor/itensor.lisp 1640(%i2) entertensor()$ 1641Enter tensor name: a; 1642Enter a list of the covariant indices: [i,j]; 1643Enter a list of the contravariant indices: [k]; 1644Enter a list of the derivative indices: []; 1645 k 1646(%t2) a 1647 i j 1648(%i3) ishow(covdiff(%,s))$ 1649 k %1 k %1 k 1650(%t3) - a ichr2 - a ichr2 + a 1651 i %1 j s %1 j i s i j,s 1652 1653 k %1 1654 + ichr2 a 1655 %1 s i j 1656(%i4) imetric:g; 1657(%o4) g 1658(%i5) ishow(ev(%th(2),ichr2))$ 1659 %1 %4 k 1660 g a (g - g + g ) 1661 i %1 s %4,j j s,%4 j %4,s 1662(%t5) - ------------------------------------------ 1663 2 1664@group 1665 %1 %3 k 1666 g a (g - g + g ) 1667 %1 j s %3,i i s,%3 i %3,s 1668 - ------------------------------------------ 1669 2 1670 k %2 %1 1671 g a (g - g + g ) 1672 i j s %2,%1 %1 s,%2 %1 %2,s k 1673 + ------------------------------------------- + a 1674 2 i j,s 1675@end group 1676(%i6) 1677@end example 1678 1679@opencatbox 1680@category{Package itensor} 1681@closecatbox 1682@end deffn 1683 1684@c ----------------------------------------------------------------------------- 1685@anchor{lorentz} 1686@deffn {Function} lorentz_gauge (@var{expr}) 1687Imposes the Lorentz condition by substituting 0 for all 1688indexed objects in @var{expr} that have a derivative index identical to a 1689contravariant index. 1690 1691@opencatbox 1692@category{Package itensor} 1693@closecatbox 1694@end deffn 1695 1696@c ----------------------------------------------------------------------------- 1697@anchor{igeodesic_coords} 1698@deffn {Function} igeodesic_coords (@var{expr}, @var{name}) 1699 1700Causes undifferentiated Christoffel symbols and 1701first derivatives of the metric tensor vanish in @var{expr}. The @var{name} 1702in the @mref{igeodesic_coords} function refers to the metric @var{name} 1703(if it appears in @var{expr}) while the connection coefficients must be 1704called with the names @code{ichr1} and/or @code{ichr2}. The following example 1705demonstrates the verification of the cyclic identity satisfied by the Riemann 1706curvature tensor using the @code{igeodesic_coords} function. 1707 1708@example 1709 1710(%i1) load("itensor"); 1711(%o1) /share/tensor/itensor.lisp 1712(%i2) ishow(icurvature([r,s,t],[u]))$ 1713 u u %1 u 1714(%t2) - ichr2 - ichr2 ichr2 + ichr2 1715 r t,s %1 s r t r s,t 1716 1717 u %1 1718 + ichr2 ichr2 1719 %1 t r s 1720(%i3) ishow(igeodesic_coords(%,ichr2))$ 1721 u u 1722(%t3) ichr2 - ichr2 1723 r s,t r t,s 1724(%i4) ishow(igeodesic_coords(icurvature([r,s,t],[u]),ichr2)+ 1725 igeodesic_coords(icurvature([s,t,r],[u]),ichr2)+ 1726 igeodesic_coords(icurvature([t,r,s],[u]),ichr2))$ 1727 u u u u 1728(%t4) - ichr2 + ichr2 + ichr2 - ichr2 1729 t s,r t r,s s t,r s r,t 1730 1731 u u 1732 - ichr2 + ichr2 1733 r t,s r s,t 1734(%i5) canform(%); 1735(%o5) 0 1736 1737@end example 1738 1739@opencatbox 1740@category{Package itensor} 1741@closecatbox 1742@end deffn 1743 1744@c ----------------------------------------------------------------------------- 1745@subsection Moving frames 1746@c ----------------------------------------------------------------------------- 1747 1748Maxima now has the ability to perform calculations using moving frames. 1749These can be orthonormal frames (tetrads, vielbeins) or an arbitrary frame. 1750 1751To use frames, you must first set @code{iframe_flag} to @code{true}. This 1752causes the Christoffel-symbols, @code{ichr1} and @code{ichr2}, to be replaced 1753by the more general frame connection coefficients @code{icc1} and @code{icc2} 1754in calculations. Speficially, the behavior of @mref{covdiff} and 1755@code{icurvature} is changed. 1756 1757The frame is defined by two tensors: the inverse frame field (@mref{ifri}, 1758the dual basis tetrad), 1759and the frame metric @mref{ifg}. The frame metric is the identity matrix for 1760orthonormal frames, or the Lorentz metric for orthonormal frames in Minkowski 1761spacetime. The inverse frame field defines the frame base (unit vectors). 1762Contraction properties are defined for the frame field and the frame metric. 1763 1764When @code{iframe_flag} is true, many @code{itensor} expressions use the frame 1765metric @code{ifg} instead of the metric defined by @code{imetric} for 1766raising and lowerind indices. 1767 1768IMPORTANT: Setting the variable @code{iframe_flag} to @code{true} does NOT 1769undefine the contraction properties of a metric defined by a call to 1770@code{defcon} or @code{imetric}. If a frame field is used, it is best to 1771define the metric by assigning its name to the variable @code{imetric} 1772and NOT invoke the @code{imetric} function. 1773 1774Maxima uses these two tensors to define the frame coefficients (@code{ifc1} 1775and @code{ifc2}) which form part of the connection coefficients (@code{icc1} 1776and @code{icc2}), as the following example demonstrates: 1777 1778@example 1779 1780(%i1) load("itensor"); 1781(%o1) /share/tensor/itensor.lisp 1782(%i2) iframe_flag:true; 1783(%o2) true 1784(%i3) ishow(covdiff(v([],[i]),j))$ 1785 i i %1 1786(%t3) v + icc2 v 1787 ,j %1 j 1788(%i4) ishow(ev(%,icc2))$ 1789 %1 i i 1790(%t4) v ifc2 + v 1791 %1 j ,j 1792(%i5) ishow(ev(%,ifc2))$ 1793 %1 i %2 i 1794(%t5) v ifg ifc1 + v 1795 %1 j %2 ,j 1796(%i6) ishow(ev(%,ifc1))$ 1797@group 1798 %1 i %2 1799 v ifg (ifb - ifb + ifb ) 1800 j %2 %1 %2 %1 j %1 j %2 i 1801(%t6) -------------------------------------------------- + v 1802 2 ,j 1803@end group 1804(%i7) ishow(ifb([a,b,c]))$ 1805 %3 %4 1806(%t7) (ifri - ifri ) ifr ifr 1807 a %3,%4 a %4,%3 b c 1808 1809@end example 1810 1811An alternate method is used to compute the frame bracket (@code{ifb}) if 1812the @code{iframe_bracket_form} flag is set to @code{false}: 1813 1814@example 1815 1816(%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$ 1817 %6 %5 %5 %6 1818(%t8) ifri (ifr ifr - ifr ifr ) 1819 a %5 b c,%6 b,%6 c 1820 1821@end example 1822 1823@c -----------------------------------------------------------------------------} 1824@anchor{iframes} 1825@deffn {Function} iframes () 1826 1827Since in this version of Maxima, contraction identities for @mref{ifr} and 1828@mref{ifri} are always defined, as is the frame bracket (@mref{ifb}), this 1829function does nothing. 1830 1831@opencatbox 1832@category{Package itensor} 1833@closecatbox 1834@end deffn 1835 1836@c ----------------------------------------------------------------------------- 1837@anchor{ifb} 1838@defvr {Variable} ifb 1839 1840The frame bracket. The contribution of the frame metric to the connection 1841coefficients is expressed using the frame bracket: 1842 1843@example 1844 1845 - ifb + ifb + ifb 1846 c a b b c a a b c 1847ifc1 = -------------------------------- 1848 abc 2 1849 1850@end example 1851 1852The frame bracket itself is defined in terms of the frame field and frame 1853metric. Two alternate methods of computation are used depending on the 1854value of @code{frame_bracket_form}. If true (the default) or if the 1855@code{itorsion_flag} is @code{true}: 1856 1857@example 1858 1859 d e f 1860ifb = ifr ifr (ifri - ifri - ifri itr ) 1861 abc b c a d,e a e,d a f d e 1862 1863 1864@end example 1865 1866Otherwise: 1867 1868@example 1869 1870 e d d e 1871ifb = (ifr ifr - ifr ifr ) ifri 1872 abc b c,e b,e c a d 1873 1874@end example 1875 1876@opencatbox 1877@category{Package itensor} 1878@closecatbox 1879@end defvr 1880 1881@c ----------------------------------------------------------------------------- 1882@anchor{icc1} 1883@defvr {Variable} icc1 1884 1885Connection coefficients of the first kind. In @code{itensor}, defined as 1886 1887@example 1888 1889icc1 = ichr1 - ikt1 - inmc1 1890 abc abc abc abc 1891 1892@end example 1893 1894In this expression, if @code{iframe_flag} is true, the Christoffel-symbol 1895@code{ichr1} is replaced with the frame connection coefficient @code{ifc1}. 1896If @code{itorsion_flag} is @code{false}, @mref{ikt1} 1897will be omitted. It is also omitted if a frame base is used, as the 1898torsion is already calculated as part of the frame bracket. 1899Lastly, of @code{inonmet_flag} is @code{false}, 1900@mref{inmc1} will not be present. 1901 1902@opencatbox 1903@category{Package itensor} 1904@closecatbox 1905@end defvr 1906 1907@c ----------------------------------------------------------------------------- 1908@anchor{icc2} 1909@defvr {Variable} icc2 1910 1911Connection coefficients of the second kind. In @code{itensor}, defined as 1912 1913@example 1914 1915 c c c c 1916icc2 = ichr2 - ikt2 - inmc2 1917 ab ab ab ab 1918 1919@end example 1920 1921In this expression, if @code{iframe_flag} is true, the Christoffel-symbol 1922@code{ichr2} is replaced with the frame connection coefficient @code{ifc2}. 1923If @code{itorsion_flag} is @code{false}, @code{ikt2} 1924will be omitted. It is also omitted if a frame base is used, as the 1925torsion is already calculated as part of the frame bracket. 1926Lastly, of @code{inonmet_flag} is @code{false}, 1927@mref{inmc2} will not be present. 1928 1929@opencatbox 1930@category{Package itensor} 1931@closecatbox 1932@end defvr 1933 1934@c ----------------------------------------------------------------------------- 1935@anchor{ifc1} 1936@defvr {Variable} ifc1 1937 1938Frame coefficient of the first kind (also known as Ricci-rotation 1939coefficients.) This tensor represents the contribution 1940of the frame metric to the connection coefficient of the first kind. Defined 1941as: 1942 1943@example 1944 1945 - ifb + ifb + ifb 1946 c a b b c a a b c 1947ifc1 = -------------------------------- 1948 abc 2 1949 1950 1951@end example 1952 1953@opencatbox 1954@category{Package itensor} 1955@closecatbox 1956@end defvr 1957 1958@c ----------------------------------------------------------------------------- 1959@anchor{ifc2} 1960@defvr {Variable} ifc2 1961 1962Frame coefficient of the second kind. This tensor represents the contribution 1963of the frame metric to the connection coefficient of the second kind. Defined 1964as a permutation of the frame bracket (@mref{ifb}) with the appropriate 1965indices raised and lowered as necessary: 1966 1967@example 1968 1969 c cd 1970ifc2 = ifg ifc1 1971 ab abd 1972 1973@end example 1974 1975@opencatbox 1976@category{Package itensor} 1977@closecatbox 1978@end defvr 1979 1980@c ----------------------------------------------------------------------------- 1981@anchor{ifr} 1982@defvr {Variable} ifr 1983 1984The frame field. Contracts with the inverse frame field (@mref{ifri}) to 1985form the frame metric (@mref{ifg}). 1986 1987@opencatbox 1988@category{Package itensor} 1989@closecatbox 1990@end defvr 1991 1992@c ----------------------------------------------------------------------------- 1993@anchor{ifri} 1994@defvr {Variable} ifri 1995 1996The inverse frame field. Specifies the frame base (dual basis vectors). Along 1997with the frame metric, it forms the basis of all calculations based on 1998frames. 1999 2000@opencatbox 2001@category{Package itensor} 2002@closecatbox 2003@end defvr 2004 2005@c ----------------------------------------------------------------------------- 2006@anchor{ifg} 2007@defvr {Variable} ifg 2008 2009The frame metric. Defaults to @mref{kdelta}, but can be changed using 2010@mref{components}. 2011 2012@opencatbox 2013@category{Package itensor} 2014@closecatbox 2015@end defvr 2016 2017@c ----------------------------------------------------------------------------- 2018@anchor{ifgi} 2019@defvr {Variable} ifgi 2020 2021The inverse frame metric. Contracts with the frame metric (@mref{ifg}) 2022to @mref{kdelta}. 2023 2024@opencatbox 2025@category{Package itensor} 2026@closecatbox 2027@end defvr 2028 2029@c ----------------------------------------------------------------------------- 2030@anchor{iframe_bracket_form} 2031@defvr {Option variable} iframe_bracket_form 2032Default value: @code{true} 2033 2034Specifies how the frame bracket (@mref{ifb}) is computed. 2035 2036@opencatbox 2037@category{Package itensor} 2038@closecatbox 2039@end defvr 2040 2041@c ----------------------------------------------------------------------------- 2042@subsection Torsion and nonmetricity 2043@c ----------------------------------------------------------------------------- 2044 2045Maxima can now take into account torsion and nonmetricity. When the flag 2046@code{itorsion_flag} is set to @code{true}, the contribution of torsion 2047is added to the connection coefficients. Similarly, when the flag 2048@code{inonmet_flag} is true, nonmetricity components are included. 2049 2050@c ----------------------------------------------------------------------------- 2051@anchor{inm} 2052@defvr {Variable} inm 2053 2054The nonmetricity vector. Conformal nonmetricity is defined through the 2055covariant derivative of the metric tensor. Normally zero, the metric 2056tensor's covariant derivative will evaluate to the following when 2057@code{inonmet_flag} is set to @code{true}: 2058 2059@example 2060 2061g =- g inm 2062 ij;k ij k 2063 2064@end example 2065 2066@opencatbox 2067@category{Package itensor} 2068@closecatbox 2069@end defvr 2070 2071@c ----------------------------------------------------------------------------- 2072@anchor{inmc1} 2073@defvr {Variable} inmc1 2074 2075Covariant permutation of the nonmetricity vector components. Defined as 2076 2077@example 2078 2079 g inm - inm g - g inm 2080 ab c a bc ac b 2081inmc1 = ------------------------------ 2082 abc 2 2083 2084@end example 2085 2086(Substitute @mref{ifg} in place of @code{g} if a frame metric is used.) 2087 2088@opencatbox 2089@category{Package itensor} 2090@closecatbox 2091@end defvr 2092 2093@c ----------------------------------------------------------------------------- 2094@anchor{inmc2} 2095@defvr {Variable} inmc2 2096 2097Contravariant permutation of the nonmetricity vector components. Used 2098in the connection coefficients if @code{inonmet_flag} is @code{true}. Defined 2099as: 2100 2101@example 2102 2103 c c cd 2104 -inm kdelta - kdelta inm + g inm g 2105 c a b a b d ab 2106inmc2 = ------------------------------------------- 2107 ab 2 2108 2109@end example 2110 2111(Substitute @mref{ifg} in place of @code{g} if a frame metric is used.) 2112 2113@opencatbox 2114@category{Package itensor} 2115@closecatbox 2116@end defvr 2117 2118@c ----------------------------------------------------------------------------- 2119@anchor{ikt1} 2120@defvr {Variable} ikt1 2121 2122Covariant permutation of the torsion tensor (also known as contorsion). 2123Defined as: 2124 2125@example 2126 2127 d d d 2128 -g itr - g itr - itr g 2129 ad cb bd ca ab cd 2130ikt1 = ---------------------------------- 2131 abc 2 2132 2133@end example 2134 2135(Substitute @mref{ifg} in place of @code{g} if a frame metric is used.) 2136 2137@opencatbox 2138@category{Package itensor} 2139@closecatbox 2140@end defvr 2141 2142@c ----------------------------------------------------------------------------- 2143@anchor{ikt2} 2144@defvr {Variable} ikt2 2145 2146Contravariant permutation of the torsion tensor (also known as contorsion). 2147Defined as: 2148 2149@example 2150 2151 c cd 2152ikt2 = g ikt1 2153 ab abd 2154 2155@end example 2156 2157(Substitute @mref{ifg} in place of @code{g} if a frame metric is used.) 2158 2159@opencatbox 2160@category{Package itensor} 2161@closecatbox 2162@end defvr 2163 2164@c ----------------------------------------------------------------------------- 2165@anchor{itr} 2166@defvr {Variable} itr 2167 2168The torsion tensor. For a metric with torsion, repeated covariant 2169differentiation on a scalar function will not commute, as demonstrated 2170by the following example: 2171 2172@example 2173 2174(%i1) load("itensor"); 2175(%o1) /share/tensor/itensor.lisp 2176(%i2) imetric:g; 2177(%o2) g 2178(%i3) covdiff( covdiff( f( [], []), i), j) 2179 - covdiff( covdiff( f( [], []), j), i)$ 2180(%i4) ishow(%)$ 2181 %4 %2 2182(%t4) f ichr2 - f ichr2 2183 ,%4 j i ,%2 i j 2184(%i5) canform(%); 2185(%o5) 0 2186(%i6) itorsion_flag:true; 2187(%o6) true 2188(%i7) covdiff( covdiff( f( [], []), i), j) 2189 - covdiff( covdiff( f( [], []), j), i)$ 2190(%i8) ishow(%)$ 2191 %8 %6 2192(%t8) f icc2 - f icc2 - f + f 2193 ,%8 j i ,%6 i j ,j i ,i j 2194(%i9) ishow(canform(%))$ 2195 %1 %1 2196(%t9) f icc2 - f icc2 2197 ,%1 j i ,%1 i j 2198(%i10) ishow(canform(ev(%,icc2)))$ 2199 %1 %1 2200(%t10) f ikt2 - f ikt2 2201 ,%1 i j ,%1 j i 2202(%i11) ishow(canform(ev(%,ikt2)))$ 2203 %2 %1 %2 %1 2204(%t11) f g ikt1 - f g ikt1 2205 ,%2 i j %1 ,%2 j i %1 2206(%i12) ishow(factor(canform(rename(expand(ev(%,ikt1))))))$ 2207 %3 %2 %1 %1 2208 f g g (itr - itr ) 2209 ,%3 %2 %1 j i i j 2210(%t12) ------------------------------------ 2211 2 2212(%i13) decsym(itr,2,1,[anti(all)],[]); 2213(%o13) done 2214(%i14) defcon(g,g,kdelta); 2215(%o14) done 2216(%i15) subst(g,nounify(g),%th(3))$ 2217(%i16) ishow(canform(contract(%)))$ 2218 %1 2219(%t16) - f itr 2220 ,%1 i j 2221 2222@end example 2223 2224@opencatbox 2225@category{Package itensor} 2226@closecatbox 2227@end defvr 2228 2229@c ----------------------------------------------------------------------------- 2230@subsection Exterior algebra 2231@c ----------------------------------------------------------------------------- 2232 2233The @code{itensor} package can perform operations on totally antisymmetric 2234covariant tensor fields. A totally antisymmetric tensor field of rank 2235(0,L) corresponds with a differential L-form. On these objects, a 2236multiplication operation known as the exterior product, or wedge product, 2237is defined. 2238 2239Unfortunately, not all authors agree on the definition of the wedge 2240product. Some authors prefer a definition that corresponds with the 2241notion of antisymmetrization: in these works, the wedge product of 2242two vector fields, for instance, would be defined as 2243 2244@example 2245 a a - a a 2246 i j j i 2247 a /\ a = ----------- 2248 i j 2 2249@end example 2250 2251More generally, the product of a p-form and a q-form would be defined as 2252 2253@example 2254 1 k1..kp l1..lq 2255A /\ B = ------ D A B 2256 i1..ip j1..jq (p+q)! i1..ip j1..jq k1..kp l1..lq 2257@end example 2258 2259where @code{D} stands for the Kronecker-delta. 2260 2261Other authors, however, prefer a ``geometric'' definition that corresponds 2262with the notion of the volume element: 2263 2264@example 2265a /\ a = a a - a a 2266 i j i j j i 2267@end example 2268 2269and, in the general case 2270 2271@example 2272 1 k1..kp l1..lq 2273A /\ B = ----- D A B 2274 i1..ip j1..jq p! q! i1..ip j1..jq k1..kp l1..lq 2275@end example 2276 2277Since @code{itensor} is a tensor algebra package, the first of these two 2278definitions appears to be the more natural one. Many applications, however, 2279utilize the second definition. To resolve this dilemma, a flag has been 2280implemented that controls the behavior of the wedge product: if 2281@mref{igeowedge_flag} is @code{false} (the default), the first, "tensorial" 2282definition is used, otherwise the second, "geometric" definition will 2283be applied. 2284 2285@anchor{~} 2286@defvr {Operator} ~ 2287@ifinfo 2288@fnindex Wedge product 2289@end ifinfo 2290 2291The wedge product operator is denoted by the tilde @code{~}. This is 2292a binary operator. Its arguments should be expressions involving scalars, 2293covariant tensors of rank one, or covariant tensors of rank @code{l} that 2294have been declared antisymmetric in all covariant indices. 2295 2296The behavior of the wedge product operator is controlled by the 2297@mref{igeowedge_flag} flag, as in the following example: 2298 2299@example 2300(%i1) load("itensor"); 2301(%o1) /share/tensor/itensor.lisp 2302(%i2) ishow(a([i])~b([j]))$ 2303 a b - b a 2304 i j i j 2305(%t2) ------------- 2306 2 2307(%i3) decsym(a,2,0,[anti(all)],[]); 2308(%o3) done 2309(%i4) ishow(a([i,j])~b([k]))$ 2310 a b + b a - a b 2311 i j k i j k i k j 2312(%t4) --------------------------- 2313 3 2314(%i5) igeowedge_flag:true; 2315(%o5) true 2316(%i6) ishow(a([i])~b([j]))$ 2317(%t6) a b - b a 2318 i j i j 2319(%i7) ishow(a([i,j])~b([k]))$ 2320(%t7) a b + b a - a b 2321 i j k i j k i k j 2322@end example 2323 2324@opencatbox 2325@category{Package itensor} 2326@category{Operators} 2327@closecatbox 2328@end defvr 2329 2330@c ----------------------------------------------------------------------------- 2331@anchor{|} 2332@defvr {Operator} | 2333@ifinfo 2334@fnindex Contraction with a vector 2335@end ifinfo 2336 2337The vertical bar @code{|} denotes the "contraction with a vector" binary 2338operation. When a totally antisymmetric covariant tensor is contracted 2339with a contravariant vector, the result is the same regardless which index 2340was used for the contraction. Thus, it is possible to define the 2341contraction operation in an index-free manner. 2342 2343In the @code{itensor} package, contraction with a vector is always carried out 2344with respect to the first index in the literal sorting order. This ensures 2345better simplification of expressions involving the @code{|} operator. For instance: 2346 2347@example 2348(%i1) load("itensor"); 2349(%o1) /share/tensor/itensor.lisp 2350(%i2) decsym(a,2,0,[anti(all)],[]); 2351(%o2) done 2352(%i3) ishow(a([i,j],[])|v)$ 2353 %1 2354(%t3) v a 2355 %1 j 2356(%i4) ishow(a([j,i],[])|v)$ 2357 %1 2358(%t4) - v a 2359 %1 j 2360@end example 2361 2362Note that it is essential that the tensors used with the @code{|} operator be 2363declared totally antisymmetric in their covariant indices. Otherwise, 2364the results will be incorrect. 2365 2366@opencatbox 2367@category{Package itensor} 2368@category{Operators} 2369@closecatbox 2370@end defvr 2371 2372@c ----------------------------------------------------------------------------- 2373@anchor{extdiff} 2374@deffn {Function} extdiff (@var{expr}, @var{i}) 2375 2376Computes the exterior derivative of @var{expr} with respect to the index 2377@var{i}. The exterior derivative is formally defined as the wedge 2378product of the partial derivative operator and a differential form. As 2379such, this operation is also controlled by the setting of @mref{igeowedge_flag}. 2380For instance: 2381 2382@example 2383(%i1) load("itensor"); 2384(%o1) /share/tensor/itensor.lisp 2385(%i2) ishow(extdiff(v([i]),j))$ 2386 v - v 2387 j,i i,j 2388(%t2) ----------- 2389 2 2390(%i3) decsym(a,2,0,[anti(all)],[]); 2391(%o3) done 2392(%i4) ishow(extdiff(a([i,j]),k))$ 2393 a - a + a 2394 j k,i i k,j i j,k 2395(%t4) ------------------------ 2396 3 2397(%i5) igeowedge_flag:true; 2398(%o5) true 2399(%i6) ishow(extdiff(v([i]),j))$ 2400(%t6) v - v 2401 j,i i,j 2402(%i7) ishow(extdiff(a([i,j]),k))$ 2403(%t7) - (a - a + a ) 2404 k j,i k i,j j i,k 2405 2406@end example 2407 2408@opencatbox 2409@category{Package itensor} 2410@closecatbox 2411@end deffn 2412 2413@c ----------------------------------------------------------------------------- 2414@anchor{hodge} 2415@deffn {Function} hodge (@var{expr}) 2416 2417Compute the Hodge-dual of @var{expr}. For instance: 2418 2419@c ===beg=== 2420@c load("itensor"); 2421@c imetric(g); 2422@c idim(4); 2423@c icounter:100; 2424@c decsym(A,3,0,[anti(all)],[])$ 2425@c ishow(A([i,j,k],[]))$ 2426@c ishow(canform(hodge(%)))$ 2427@c ishow(canform(hodge(%)))$ 2428@c lc2kdt(%)$ 2429@c %,kdelta$ 2430@c ishow(canform(contract(expand(%))))$ 2431@c ===end=== 2432@example 2433 2434(%i1) load("itensor"); 2435(%o1) /share/tensor/itensor.lisp 2436(%i2) imetric(g); 2437(%o2) done 2438(%i3) idim(4); 2439(%o3) done 2440(%i4) icounter:100; 2441(%o4) 100 2442(%i5) decsym(A,3,0,[anti(all)],[])$ 2443 2444(%i6) ishow(A([i,j,k],[]))$ 2445(%t6) A 2446 i j k 2447(%i7) ishow(canform(hodge(%)))$ 2448 %1 %2 %3 %4 2449 levi_civita g A 2450 %1 %102 %2 %3 %4 2451(%t7) ----------------------------------------- 2452 6 2453(%i8) ishow(canform(hodge(%)))$ 2454 %1 %2 %3 %8 %4 %5 %6 %7 2455(%t8) levi_civita levi_civita g 2456 %1 %106 2457 g g g A /6 2458 %2 %107 %3 %108 %4 %8 %5 %6 %7 2459(%i9) lc2kdt(%)$ 2460 2461(%i10) %,kdelta$ 2462 2463(%i11) ishow(canform(contract(expand(%))))$ 2464(%t11) - A 2465 %106 %107 %108 2466 2467@end example 2468 2469@opencatbox 2470@category{Package itensor} 2471@closecatbox 2472@end deffn 2473 2474@c ----------------------------------------------------------------------------- 2475@anchor{igeowedge_flag} 2476@defvr {Option variable} igeowedge_flag 2477Default value: @code{false} 2478 2479Controls the behavior of the wedge product and exterior derivative. When 2480set to @code{false} (the default), the notion of differential forms will 2481correspond with that of a totally antisymmetric covariant tensor field. 2482When set to @code{true}, differential forms will agree with the notion 2483of the volume element. 2484 2485@opencatbox 2486@category{Package itensor} 2487@closecatbox 2488@end defvr 2489 2490@c ----------------------------------------------------------------------------- 2491@subsection Exporting TeX expressions 2492@c ----------------------------------------------------------------------------- 2493 2494The @code{itensor} package provides limited support for exporting tensor 2495expressions to TeX. Since @code{itensor} expressions appear as function calls, 2496the regular Maxima @mref{tex} command will not produce the expected 2497output. You can try instead the @mref{tentex} command, which attempts 2498to translate tensor expressions into appropriately indexed TeX objects. 2499 2500@c ----------------------------------------------------------------------------- 2501@anchor{tentex} 2502@deffn {Function} tentex (@var{expr}) 2503 2504To use the @code{tentex} function, you must first load @code{tentex}, 2505as in the following example: 2506 2507@c ===beg=== 2508@c load("itensor"); 2509@c load(tentex); 2510@c idummyx:m; 2511@c ishow(icurvature([j,k,l],[i]))$ 2512@c tentex(%)$ 2513@c ===end=== 2514@example 2515(%i1) load("itensor"); 2516(%o1) /share/tensor/itensor.lisp 2517(%i2) load(tentex); 2518(%o2) /share/tensor/tentex.lisp 2519(%i3) idummyx:m; 2520(%o3) m 2521(%i4) ishow(icurvature([j,k,l],[i]))$ 2522 m1 i m1 i i 2523(%t4) ichr2 ichr2 - ichr2 ichr2 - ichr2 2524 j k m1 l j l m1 k j l,k 2525 2526 i 2527 + ichr2 2528 j k,l 2529(%i5) tentex(%)$ 2530$$\Gamma_@{j\,k@}^@{m_1@}\,\Gamma_@{l\,m_1@}^@{i@}-\Gamma_@{j\,l@}^@{m_1@}\, 2531 \Gamma_@{k\,m_1@}^@{i@}-\Gamma_@{j\,l,k@}^@{i@}+\Gamma_@{j\,k,l@}^@{i@}$$ 2532@end example 2533 2534Note the use of the @code{idummyx} assignment, to avoid the appearance 2535of the percent sign in the TeX expression, which may lead to compile errors. 2536 2537NB: This version of the @code{tentex} function is somewhat experimental. 2538 2539@opencatbox 2540@category{Package itensor} 2541@category{TeX output} 2542@closecatbox 2543@end deffn 2544 2545@c ----------------------------------------------------------------------------- 2546@subsection Interfacing with ctensor 2547@c ----------------------------------------------------------------------------- 2548 2549The @code{itensor} package has the ability to generate Maxima code that can 2550then be executed in the context of the @code{ctensor} package. The function that performs 2551this task is @mref{ic_convert}. 2552 2553@c ----------------------------------------------------------------------------- 2554@anchor{ic_convert} 2555@deffn {Function} ic_convert (@var{eqn}) 2556 2557Converts the @code{itensor} equation @var{eqn} to a @code{ctensor} assignment statement. 2558Implied sums over dummy indices are made explicit while indexed 2559objects are transformed into arrays (the array subscripts are in the 2560order of covariant followed by contravariant indices of the indexed 2561objects). The derivative of an indexed object will be replaced by the 2562noun form of @mref{diff} taken with respect to @mref{ct_coords} subscripted 2563by the derivative index. The Christoffel symbols @mref{ichr1} and @mref{ichr2} 2564will be translated to @code{lcs} and @code{mcs}, respectively and if 2565@code{metricconvert} is @code{true} then all occurrences of the metric 2566with two covariant (contravariant) indices will be renamed to @code{lg} 2567(@code{ug}). In addition, @mref{do} loops will be introduced summing over 2568all free indices so that the 2569transformed assignment statement can be evaluated by just doing 2570@mref{ev}. The following examples demonstrate the features of this 2571function. 2572 2573@c Added some ===beg=== and ==end== pairs around some source code 2574@c 2575@c The tags used here are different. This prevents the Perl parser from 2576@c interpreting this section, since the text-based rendering of the output 2577@c is pretty much unreadable. The origin example is likely been hand-edited 2578@c for readability. 2579@c ===begx=== 2580@c load("itensor"); 2581@c eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j) 2582@c *b([i],[l,k]))$ 2583@c ic_convert(eqn); 2584@c imetric(g); 2585@c metricconvert:true; 2586@c ic_convert(eqn); 2587@c ===endx=== 2588@example 2589(%i1) load("itensor"); 2590(%o1) /share/tensor/itensor.lisp 2591(%i2) eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j) 2592 *b([i],[l,k]))$ 2593 k m l k 2594(%t2) t = f a b g 2595 i j ,j i l m 2596(%i3) ic_convert(eqn); 2597(%o3) for i thru dim do (for j thru dim do ( 2598 for k thru dim do 2599 t : f sum(sum(diff(a , ct_coords ) b 2600 i, j, k m j i, l, k 2601 2602 g , l, 1, dim), m, 1, dim))) 2603 l, m 2604(%i4) imetric(g); 2605(%o4) done 2606(%i5) metricconvert:true; 2607(%o5) true 2608(%i6) ic_convert(eqn); 2609(%o6) for i thru dim do (for j thru dim do ( 2610 for k thru dim do 2611 t : f sum(sum(diff(a , ct_coords ) b 2612 i, j, k m j i, l, k 2613 2614 lg , l, 1, dim), m, 1, dim))) 2615 l, m 2616@end example 2617 2618@opencatbox 2619@category{Package itensor} 2620@category{Package ctensor} 2621@closecatbox 2622@end deffn 2623 2624@c ----------------------------------------------------------------------------- 2625@subsection Reserved words 2626@c ----------------------------------------------------------------------------- 2627 2628The following Maxima words are used by the @code{itensor} package internally and 2629should not be redefined: 2630 2631@c REFORMAT THIS TABLE USING TEXINFO MARKUP 2632@example 2633 Keyword Comments 2634 ------------------------------------------ 2635 indices2() Internal version of indices() 2636 conti Lists contravariant indices 2637 covi Lists covariant indices of a indexed object 2638 deri Lists derivative indices of an indexed object 2639 name Returns the name of an indexed object 2640 concan 2641 irpmon 2642 lc0 2643 _lc2kdt0 2644 _lcprod 2645 _extlc 2646@end example 2647