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