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