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
7 * Introduction to itensor::
8 * Functions and Variables for itensor::
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
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:}
81 @category{Share packages}
82 @category{Package itensor}
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:
95 (%i3) ishow(g([],[j,k])*g([],[i,l])*a([i,j],[]))$
99 (%i4) ishow(contract(%))$
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
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:
120 (%i5) ishow(g([-j,-k],[])*g([-i,-l],[])*a([i,j],[]))$
124 (%i6) ishow(contract(%))$
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
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
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.
198 (%i1) load("itensor");
199 (%o1) /share/tensor/itensor.lisp
202 (%i3) components(g([i,j],[]),p([i,j],[])*e([],[]))$
203 (%i4) ishow(g([k,l],[]))$
206 (%i5) ishow(diff(v([i],[]),t))$
210 (%i7) ishow(diff(v([i],[]),t))$
214 (%i8) ishow(idiff(v([i],[]),j))$
217 (%i9) ishow(extdiff(v([i],[]),j))$
222 (%i10) ishow(liediff(v,w([i],[])))$
226 (%i11) ishow(covdiff(v([i],[]),j))$
230 (%i12) ishow(ev(%,ichr2))$
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
237 (%i13) iframe_flag:true;
239 (%i14) ishow(covdiff(v([i],[]),j))$
243 (%i15) ishow(ev(%,icc2))$
247 (%i16) ishow(radcan(ev(%,ifc2,ifc1)))$
249 (%t16) - (ifg v ifb + ifg v ifb - 2 v
250 %6 j %7 i %6 i j %7 i,j
255 (%i17) ishow(canform(s([i,j],[])-s([j,i])))$
258 (%i18) decsym(s,2,0,[sym(all)],[]);
260 (%i19) ishow(canform(s([i,j],[])-s([j,i])))$
262 (%i20) ishow(canform(a([i,j],[])+a([j,i])))$
265 (%i21) decsym(a,2,0,[anti(all)],[]);
267 (%i22) ishow(canform(a([i,j],[])+a([j,i])))$
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 -----------------------------------------------------------------------------
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
289 @opencatbox{Categories:}
290 @category{Display functions}
294 @c -----------------------------------------------------------------------------
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}
308 @c -----------------------------------------------------------------------------
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}
323 @c -----------------------------------------------------------------------------
324 @deffn {Function} listoftens
328 Lists all tensors in a tensorial expression, complete with their indices. E.g.,
332 (%i6) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$
336 (%i7) ishow(listoftens(%))$
338 (%t7) [a , b , c , d]
343 @opencatbox{Categories:}
344 @category{Package itensor}
348 @c -----------------------------------------------------------------------------
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}
363 @c -----------------------------------------------------------------------------
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.
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))$
381 (%o3) [[l, p, i, n, o, q, r], [k, j, m]]
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}
395 @c -----------------------------------------------------------------------------
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.
418 (%i1) load("itensor");
419 (%o1) /share/tensor/itensor.lisp
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$
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
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;
448 (%i8) rename(%th(2));
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
460 @opencatbox{Categories:}
461 @category{Package itensor}
465 @c -----------------------------------------------------------------------------
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}
486 @c -----------------------------------------------------------------------------
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
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
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}
513 @c -----------------------------------------------------------------------------
515 @deffn {Function} remcon @
516 @fname{remcon} (@var{tensor_1}, ..., @var{tensor_n}) @
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}
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}
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}
558 @c -----------------------------------------------------------------------------
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:
585 (%i2) components(g([],[i,j]),e([],[i])*p([],[j]))$
586 (%i3) ishow(g([],[i,j]))$
596 (%i5) lg:-ident(4)$lg[1,1]:1$lg;
606 (%i6) components(g([i,j],[]),lg);
608 (%i7) ishow(g([i,j],[]))$
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
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]))$
631 (%i6) ishow(h([i,j],[k],l))$
637 4) Using Maxima's pattern matching capabilities, specifically the
638 @mref{defrule} and @mref{applyb1} commands:
642 (%i1) load("itensor");
643 (%o1) /share/tensor/itensor.lisp
644 (%i2) matchdeclare(l1,listp);
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]))$
658 (%i6) ishow(rename(applyb1(%,r1,r2)))$
664 @opencatbox{Categories:}
665 @category{Package itensor}
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}
680 @c NEED LIST OF ARGUMENTS HERE
682 @c -----------------------------------------------------------------------------
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
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)]);
700 [ sqrt(-------) 0 0 0 ]
705 [ 0 0 r sin(theta) 0 ]
708 [ 0 0 0 sqrt(-------) ]
710 (%i4) components(g([i,j],[]),lg);
712 (%i5) showcomps(g([i,j],[]));
714 [ sqrt(-------) 0 0 0 ]
719 i j [ 0 0 r sin(theta) 0 ]
722 [ 0 0 0 sqrt(-------) ]
728 The @code{showcomps} command can also display components of a tensor of
731 @opencatbox{Categories:}
732 @category{Package itensor}
736 @c -----------------------------------------------------------------------------
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}
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}
761 @c -----------------------------------------------------------------------------
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}
775 @c -----------------------------------------------------------------------------
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
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}
796 @c -----------------------------------------------------------------------------
798 @deffn {Function} kdels (@var{L1}, @var{L2})
800 Symmetrized Kronecker delta, used in some calculations. For instance:
804 (%i1) load("itensor");
805 (%o1) /share/tensor/itensor.lisp
806 (%i2) kdelta([1,2],[2,1]);
808 (%i3) kdels([1,2],[2,1]);
810 (%i4) ishow(kdelta([a,b],[c,d]))$
812 (%t4) kdelta kdelta - kdelta kdelta
814 (%i4) ishow(kdels([a,b],[c,d]))$
816 (%t4) kdelta kdelta + kdelta kdelta
821 @opencatbox{Categories:}
822 @category{Package itensor}
826 @c -----------------------------------------------------------------------------
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
834 @opencatbox{Categories:}
835 @category{Package itensor}
839 @c -----------------------------------------------------------------------------
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}.
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]))$
857 (%t2) levi_civita a levi_civita
859 (%i3) ishow(ev(expr,levi_civita))$
861 (%t3) kdelta a kdelta
863 (%i4) ishow(ev(%,kdelta))$
865 (%t4) (kdelta kdelta - kdelta kdelta ) a
869 (kdelta kdelta - kdelta kdelta )
871 (%i5) ishow(lc2kdt(expr))$
873 (%t5) a kdelta kdelta - a kdelta kdelta
875 (%i6) ishow(contract(expand(%)))$
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.
887 (%i7) expr:ishow('levi_civita([],[i,j])
888 *'levi_civita([],[k,l])*a([j,k],[]))$
891 (%t7) levi_civita levi_civita a
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.
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
911 (%i11) ishow(contract(expand(%)))$
918 @opencatbox{Categories:}
919 @category{Package itensor}
923 @c HMM, WHICH CATEGORY DOES THIS FALL INTO -- FUNCTION, VARIABLE, OTHER ??
925 @c -----------------------------------------------------------------------------
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}.
935 (%i1) load("itensor");
936 (%o1) /share/tensor/itensor.lisp
937 (%i2) el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$
939 (%t2) a a levi_civita
941 (%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$
943 (%t3) levi_civita a a
945 (%i4) canform(contract(expand(applyb1(el1,lc_l,lc_u))));
947 (%i5) canform(contract(expand(applyb1(el2,lc_l,lc_u))));
952 @opencatbox{Categories:}
953 @category{Package itensor}
957 @c HMM, WHICH CATEGORY DOES THIS FALL INTO -- FUNCTION, VARIABLE, OTHER ??
959 @c -----------------------------------------------------------------------------
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}
973 @c -----------------------------------------------------------------------------
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
987 @opencatbox{Categories:}
988 @category{Package itensor}
992 @c -----------------------------------------------------------------------------
994 @deffn {Function} concan (@var{expr})
995 Similar to @mref{canten} but also performs index contraction.
997 @opencatbox{Categories:}
998 @category{Package itensor}
1002 @c -----------------------------------------------------------------------------
1003 @subsection Tensor symmetries
1004 @c -----------------------------------------------------------------------------
1006 @c -----------------------------------------------------------------------------
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}
1022 @c -----------------------------------------------------------------------------
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
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])))$
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
1055 (%i4) decsym(a,3,0,[sym(all)],[]);
1057 (%i5) ishow(canform(expr))$
1060 (%i6) remsym(a,3,0);
1062 (%i7) decsym(a,3,0,[anti(all)],[]);
1064 (%i8) ishow(canform(expr))$
1066 (%i9) remsym(a,3,0);
1068 (%i10) decsym(a,3,0,[cyc(all)],[]);
1070 (%i11) ishow(canform(expr))$
1073 (%i12) dispsym(a,3,0);
1074 (%o12) [[cyc, [[1, 2, 3]], []]]
1078 @opencatbox{Categories:}
1079 @category{Package itensor}
1083 @c -----------------------------------------------------------------------------
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}
1094 @c -----------------------------------------------------------------------------
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}
1101 @opencatbox{Categories:}
1102 @category{Package itensor}
1106 @c -----------------------------------------------------------------------------
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}
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}
1164 @c -----------------------------------------------------------------------------
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}
1185 @c -----------------------------------------------------------------------------
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
1196 (%i1) load("itensor");
1197 (%o1) /share/tensor/itensor.lisp
1198 (%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$
1200 (%t2) b (v a + v a + v a )
1201 ,l i j,%2 ,j i %2 ,i %2 j
1204 + (v b - b v + v b ) a
1205 ,%1 l ,l ,%1 ,l ,%1 i j
1209 @opencatbox{Categories:}
1210 @category{Package itensor}
1214 @c -----------------------------------------------------------------------------
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}
1226 @c -----------------------------------------------------------------------------
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}
1243 @c -----------------------------------------------------------------------------
1245 @deffn {Function} evundiff (@var{expr})
1247 Equivalent to the execution of @mref{undiff}, followed by @mref{ev} and
1250 The point of this operation is to easily evaluate expressions that cannot
1251 be directly evaluated in derivative form. For instance, the following
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.
1267 However, if @mref{icurvature} is entered in noun form, it can be evaluated
1268 using @code{evundiff}:
1271 (%i3) ishow('icurvature([i,j,k],[l],m))$
1275 (%i4) ishow(evundiff(%))$
1277 (%t4) - ichr2 - ichr2 ichr2 - ichr2 ichr2
1278 i k,j m %1 j i k,m %1 j,m i k
1281 + ichr2 + ichr2 ichr2 + ichr2 ichr2
1282 i j,k m %1 k i j,m %1 k,m i j
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:
1292 (%i6) ishow(ichr2([i,j],[k],l))$
1295 j %3,i l i j,%3 l i %3,j l
1296 (%t6) -----------------------------------------
1301 ,l j %3,i i j,%3 i %3,j
1302 + -----------------------------------
1306 @opencatbox{Categories:}
1307 @category{Package itensor}
1311 @c -----------------------------------------------------------------------------
1313 @deffn {Function} flush (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...)
1315 @var{expr}, all occurrences of the @var{tensor_i} that have no derivative indices.
1317 @opencatbox{Categories:}
1318 @category{Package itensor}
1322 @c -----------------------------------------------------------------------------
1324 @deffn {Function} flushd (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...)
1326 @var{expr}, all occurrences of the @var{tensor_i} that have derivative indices.
1328 @opencatbox{Categories:}
1329 @category{Package itensor}
1333 @c -----------------------------------------------------------------------------
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.
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))$
1347 (%i3) ishow(flushnd(%,a,3))$
1353 @opencatbox{Categories:}
1354 @category{Package itensor}
1358 @c -----------------------------------------------------------------------------
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}
1373 @c -----------------------------------------------------------------------------
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}
1388 @c -----------------------------------------------------------------------------
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}
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:
1413 (%i1) load("itensor");
1414 (%o1) /share/tensor/itensor.lisp
1415 (%i2) ishow(g([],[a,b],c))$
1419 (%i3) ishow(conmetderiv(%,g))$
1421 (%t3) - g ichr2 - g ichr2
1425 @opencatbox{Categories:}
1426 @category{Package itensor}
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:
1442 g g + g g = (g g ) = (kdelta ) = 0
1443 ,d bc bc,d bc ,d c ,d
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:
1482 (%i1) load("itensor");
1483 (%o1) /share/tensor/itensor.lisp
1486 (%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([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(%))$
1498 (%i6) flipflag:not flipflag;
1500 (%i7) ishow(simpmetderiv(%th(2)))$
1504 (%i8) flipflag:not flipflag;
1506 (%i9) ishow(simpmetderiv(%th(2),stop))$
1510 (%i10) ishow(contract(%))$
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}
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}
1537 @c -----------------------------------------------------------------------------
1538 @subsection Tensors in curved spaces
1539 @c -----------------------------------------------------------------------------
1541 @c -----------------------------------------------------------------------------
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}
1557 @c -----------------------------------------------------------------------------
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}
1568 @c -----------------------------------------------------------------------------
1570 @deffn {Function} ichr1 ([@var{i}, @var{j}, @var{k}])
1571 Yields the Christoffel symbol of the first kind via the
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}
1586 @c -----------------------------------------------------------------------------
1588 @deffn {Function} ichr2 ([@var{i}, @var{j}], [@var{k}])
1589 Yields the Christoffel symbol of the second kind
1590 defined by the relation
1593 ichr2([i,j],[k]) = g (g + g - g )/2
1597 @opencatbox{Categories:}
1598 @category{Package itensor}
1602 @c -----------------------------------------------------------------------------
1604 @deffn {Function} icurvature ([@var{i}, @var{j}, @var{k}], [@var{h}])
1606 curvature tensor in terms of the Christoffel symbols of the second
1607 kind (@code{ichr2}). The following notation is used:
1610 icurvature = - ichr2 - ichr2 ichr2 + ichr2
1611 i j k i k,j %1 j i k i j,k
1617 @opencatbox{Categories:}
1618 @category{Package itensor}
1622 @c -----------------------------------------------------------------------------
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)}.
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: [];
1642 (%i3) ishow(covdiff(%,s))$
1644 (%t3) - a ichr2 - a ichr2 + a
1645 i %1 j s %1 j i s i j,s
1652 (%i5) ishow(ev(%th(2),ichr2))$
1655 i %1 s %4,j j s,%4 j %4,s
1656 (%t5) - ------------------------------------------
1661 %1 j s %3,i i s,%3 i %3,s
1662 - ------------------------------------------
1666 i j s %2,%1 %1 s,%2 %1 %2,s k
1667 + ------------------------------------------- + a
1673 @opencatbox{Categories:}
1674 @category{Package itensor}
1678 @c -----------------------------------------------------------------------------
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}
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.
1704 (%i1) load("itensor");
1705 (%o1) /share/tensor/itensor.lisp
1706 (%i2) ishow(icurvature([r,s,t],[u]))$
1708 (%t2) - ichr2 - ichr2 ichr2 + ichr2
1709 r t,s %1 s r t r s,t
1714 (%i3) ishow(igeodesic_coords(%,ichr2))$
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))$
1722 (%t4) - ichr2 + ichr2 + ichr2 - ichr2
1723 t s,r t r,s s t,r s r,t
1733 @opencatbox{Categories:}
1734 @category{Package itensor}
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:
1774 (%i1) load("itensor");
1775 (%o1) /share/tensor/itensor.lisp
1776 (%i2) iframe_flag:true;
1778 (%i3) ishow(covdiff(v([],[i]),j))$
1782 (%i4) ishow(ev(%,icc2))$
1786 (%i5) ishow(ev(%,ifc2))$
1788 (%t5) v ifg ifc1 + v
1790 (%i6) ishow(ev(%,ifc1))$
1793 v ifg (ifb - ifb + ifb )
1794 j %2 %1 %2 %1 j %1 j %2 i
1795 (%t6) -------------------------------------------------- + v
1798 (%i7) ishow(ifb([a,b,c]))$
1800 (%t7) (ifri - ifri ) ifr ifr
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}:
1810 (%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$
1812 (%t8) ifri (ifr ifr - ifr ifr )
1817 @c -----------------------------------------------------------------------------}
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}
1830 @c -----------------------------------------------------------------------------
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:
1841 ifc1 = --------------------------------
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}:
1854 ifb = ifr ifr (ifri - ifri - ifri itr )
1855 abc b c a d,e a e,d a f d e
1865 ifb = (ifr ifr - ifr ifr ) ifri
1870 @opencatbox{Categories:}
1871 @category{Package itensor}
1875 @c -----------------------------------------------------------------------------
1877 @defvr {Variable} icc1
1879 Connection coefficients of the first kind. In @code{itensor}, defined as
1883 icc1 = ichr1 - ikt1 - inmc1
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}
1901 @c -----------------------------------------------------------------------------
1903 @defvr {Variable} icc2
1905 Connection coefficients of the second kind. In @code{itensor}, defined as
1910 icc2 = ichr2 - ikt2 - inmc2
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}
1928 @c -----------------------------------------------------------------------------
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
1941 ifc1 = --------------------------------
1947 @opencatbox{Categories:}
1948 @category{Package itensor}
1952 @c -----------------------------------------------------------------------------
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:
1969 @opencatbox{Categories:}
1970 @category{Package itensor}
1974 @c -----------------------------------------------------------------------------
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}
1986 @c -----------------------------------------------------------------------------
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
1994 @opencatbox{Categories:}
1995 @category{Package itensor}
1999 @c -----------------------------------------------------------------------------
2001 @defvr {Variable} ifg
2003 The frame metric. Defaults to @mref{kdelta}, but can be changed using
2006 @opencatbox{Categories:}
2007 @category{Package itensor}
2011 @c -----------------------------------------------------------------------------
2013 @defvr {Variable} ifgi
2015 The inverse frame metric. Contracts with the frame metric (@mref{ifg})
2018 @opencatbox{Categories:}
2019 @category{Package itensor}
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}
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 -----------------------------------------------------------------------------
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}:
2060 @opencatbox{Categories:}
2061 @category{Package itensor}
2065 @c -----------------------------------------------------------------------------
2067 @defvr {Variable} inmc1
2069 Covariant permutation of the nonmetricity vector components. Defined as
2073 g inm - inm g - g inm
2075 inmc1 = ------------------------------
2080 (Substitute @mref{ifg} in place of @code{g} if a frame metric is used.)
2082 @opencatbox{Categories:}
2083 @category{Package itensor}
2087 @c -----------------------------------------------------------------------------
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
2098 -inm kdelta - kdelta inm + g inm g
2100 inmc2 = -------------------------------------------
2105 (Substitute @mref{ifg} in place of @code{g} if a frame metric is used.)
2107 @opencatbox{Categories:}
2108 @category{Package itensor}
2112 @c -----------------------------------------------------------------------------
2114 @defvr {Variable} ikt1
2116 Covariant permutation of the torsion tensor (also known as contorsion).
2122 -g itr - g itr - itr g
2124 ikt1 = ----------------------------------
2129 (Substitute @mref{ifg} in place of @code{g} if a frame metric is used.)
2131 @opencatbox{Categories:}
2132 @category{Package itensor}
2136 @c -----------------------------------------------------------------------------
2138 @defvr {Variable} ikt2
2140 Contravariant permutation of the torsion tensor (also known as contorsion).
2151 (Substitute @mref{ifg} in place of @code{g} if a frame metric is used.)
2153 @opencatbox{Categories:}
2154 @category{Package itensor}
2158 @c -----------------------------------------------------------------------------
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:
2168 (%i1) load("itensor");
2169 (%o1) /share/tensor/itensor.lisp
2172 (%i3) covdiff( covdiff( f( [], []), i), j)
2173 - covdiff( covdiff( f( [], []), j), i)$
2176 (%t4) f ichr2 - f ichr2
2180 (%i6) itorsion_flag:true;
2182 (%i7) covdiff( covdiff( f( [], []), i), j)
2183 - covdiff( covdiff( f( [], []), j), i)$
2186 (%t8) f icc2 - f icc2 - f + f
2187 ,%8 j i ,%6 i j ,j i ,i j
2188 (%i9) ishow(canform(%))$
2190 (%t9) f icc2 - f icc2
2192 (%i10) ishow(canform(ev(%,icc2)))$
2194 (%t10) f ikt2 - f ikt2
2196 (%i11) ishow(canform(ev(%,ikt2)))$
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))))))$
2204 (%t12) ------------------------------------
2206 (%i13) decsym(itr,2,1,[anti(all)],[]);
2208 (%i14) defcon(g,g,kdelta);
2210 (%i15) subst(g,nounify(g),%th(3))$
2211 (%i16) ishow(canform(contract(%)))$
2218 @opencatbox{Categories:}
2219 @category{Package itensor}
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,
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
2241 a /\ a = -----------
2245 More generally, the product of a p-form and a q-form would be defined as
2249 A /\ B = ------ D A B
2250 i1..ip j1..jq (p+q)! i1..ip j1..jq k1..kp l1..lq
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:
2263 and, in the general case
2267 A /\ B = ----- D A B
2268 i1..ip j1..jq p! q! i1..ip j1..jq k1..kp l1..lq
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
2280 @fnindex Wedge product
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:
2292 (%i1) load("itensor");
2293 (%o1) /share/tensor/itensor.lisp
2294 (%i2) ishow(a([i])~b([j]))$
2299 (%i3) decsym(a,2,0,[anti(all)],[]);
2301 (%i4) ishow(a([i,j])~b([k]))$
2304 (%t4) ---------------------------
2306 (%i5) igeowedge_flag:true;
2308 (%i6) ishow(a([i])~b([j]))$
2311 (%i7) ishow(a([i,j])~b([k]))$
2312 (%t7) a b + b a - a b
2316 @opencatbox{Categories:}
2317 @category{Package itensor}
2318 @category{Operators}
2322 @c -----------------------------------------------------------------------------
2324 @fnindex Contraction with a vector
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:
2338 (%i1) load("itensor");
2339 (%o1) /share/tensor/itensor.lisp
2340 (%i2) decsym(a,2,0,[anti(all)],[]);
2342 (%i3) ishow(a([i,j],[])|v)$
2346 (%i4) ishow(a([j,i],[])|v)$
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}
2362 @c -----------------------------------------------------------------------------
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}.
2373 (%i1) load("itensor");
2374 (%o1) /share/tensor/itensor.lisp
2375 (%i2) ishow(extdiff(v([i]),j))$
2380 (%i3) decsym(a,2,0,[anti(all)],[]);
2382 (%i4) ishow(extdiff(a([i,j]),k))$
2385 (%t4) ------------------------
2387 (%i5) igeowedge_flag:true;
2389 (%i6) ishow(extdiff(v([i]),j))$
2392 (%i7) ishow(extdiff(a([i,j]),k))$
2393 (%t7) - (a - a + a )
2398 @opencatbox{Categories:}
2399 @category{Package itensor}
2403 @c -----------------------------------------------------------------------------
2405 @deffn {Function} hodge (@var{expr})
2407 Compute the Hodge-dual of @var{expr}. For instance:
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(%)))$
2420 @c ishow(canform(contract(expand(%))))$
2424 (%i1) load("itensor");
2425 (%o1) /share/tensor/itensor.lisp
2432 (%i5) decsym(A,3,0,[anti(all)],[])$
2434 (%i6) ishow(A([i,j,k],[]))$
2437 (%i7) ishow(canform(hodge(%)))$
2441 (%t7) -----------------------------------------
2443 (%i8) ishow(canform(hodge(%)))$
2444 %1 %2 %3 %8 %4 %5 %6 %7
2445 (%t8) levi_civita levi_civita g
2448 %2 %107 %3 %108 %4 %8 %5 %6 %7
2453 (%i11) ishow(canform(contract(expand(%))))$
2459 @opencatbox{Categories:}
2460 @category{Package itensor}
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}
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 -----------------------------------------------------------------------------
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:
2501 @c ishow(icurvature([j,k,l],[i]))$
2505 (%i1) load("itensor");
2506 (%o1) /share/tensor/itensor.lisp
2507 (%i2) load("tentex");
2508 (%o2) /share/tensor/tentex.lisp
2511 (%i4) ishow(icurvature([j,k,l],[i]))$
2513 (%t4) ichr2 ichr2 - ichr2 ichr2 - ichr2
2514 j k m1 l j l m1 k j l,k
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@}$$
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}
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 -----------------------------------------------------------------------------
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
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
2571 @c eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j)
2575 @c metricconvert:true;
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)
2586 (%i3) ic_convert(eqn);
2587 (%o3) for i thru dim do (for j thru dim do (
2589 t : f sum(sum(diff(a , ct_coords ) b
2592 g , l, 1, dim), m, 1, dim)))
2596 (%i5) metricconvert:true;
2598 (%i6) ic_convert(eqn);
2599 (%o6) for i thru dim do (for j thru dim do (
2601 t : f sum(sum(diff(a , ct_coords ) b
2604 lg , l, 1, dim), m, 1, dim)))
2608 @opencatbox{Categories:}
2609 @category{Package itensor}
2610 @category{Package ctensor}
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
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