@c Language=Russian
@c Encoding=CP1251
@c File=Itensor.texi
@c OriginalRevision=1.44    
@c TranslatedBy: (c) 2005-12 Valery Pipin <pip@iszf.irk.ru>

@menu
* Введение в пакет itensor::
* Функции и переменные пакета itensor::
@end menu

@node Введение в пакет itensor, Функции и переменные пакета itensor, Пакет itensor, Пакет itensor
@section Введение в пакет itensor

В Maxima реализованы два различных типа операций над тензорами:
операции над компонентами -- пакет @code{ctensor} и операции с индексами -- пакет
@code{itensor}.

ВАЖНОЕ ЗАМЕЧАНИЕ: Пожалуйста, ниже, обратите внимание на нововведения в системе индексных
обозначений для тензоров.

При операциях с компонентами тензорный объект рассматривается, как многомерный массив
или матрица.  Операции свертки и ковариантного дифференцирования над такими объектами
фактически сводятся к дифференцированию элементов матрицы и суммированию по повторяющимся индексам
при помощи команды @code{do}.  Полученный результат операций над компонентами тензора
хранится в форме массива или матрицы.

При операциях с индексами, тензор рассматривается как функция своих индексов (ковариантных,
контравариантных и индексов производной).  В этом случае результат тензорных операций,
например, таких как свертка или ковариантное дифференцирование, достигается только
с помощью соответствующих манипуляций с индексами, а не с
компонентами, которым они соответствуют.

Оба подхода к рассмотрению дифференциальных, алгебраических и аналитических проблем в
контексте Римановой геометрии имеют и преимущества,  и недостатки,
которые выявляются при рассмотрении конкретных задач.  Необходимо иметь ввиду
следующие специфические свойства каждого из методов:

i) Представление тензоров в явном виде через их компоненты делает
@code{ctensor} алгоритмически простым в использовании. Вычисления метрики,
производных тензоров и инвариантов реализуются непосредственно по определению.
Однако, несмотря на вычислительную мощь Maxima, в случае достаточно
сложной метрики, внутренние функциональные связи и координатные зависимости
компонент метрики легко могут привести к чрезвычайно громоздким выражениям,
со скрытой структурой.

ii) В силу специфики способа, при котором тензора и операции над ними
рассматриваются в терминах символьных операций над их индексами, выражения,
вычисления которых в компонентном представлении выглядели бы громоздко, могут быть
иногда сильно упрощены при помощи использования симметрий тензоров и
специальных функций пакета @code{itensor}, использующих симметрии.  В тоже
время, индексное представление тензоров в этом пакете создает
определенные трудности при определении метрики, функций
и вычислении дифференцируемых объектов.

@opencatbox
@category{Тензоры} @category{Пакеты библиотеки share} @category{Пакет itensor}
@closecatbox

@subsection Новые соглашения для обозначения тензорных индексов

До настоящего времени, в пакете  @code{itensor} были приняты обозначения,
которые не сохраняли порядок индексов при операциях свертки, например:

@example
(%i2) imetric(g);
(%o2)                                done
(%i3) ishow(g([],[j,k])*g([],[i,l])*a([i,j],[]))$
                                 i l  j k
(%t3)                           g    g    a
                                           i j
(%i4) ishow(contract(%))$
                                      k l
(%t4)                                a
@end example

Этот результат не верен за исключением случая когда тензор @code{a}
симметричен.  Порядок следования индекса теряется при свертке, несмотря на
то, что @code{itensor} сохраняет порядок индексов внутри
каждого набора ковариантных и контравариантных индексов (в соответствии
со свойствами симметрии).

Для того, чтобы избежать данной проблемы была предложена новая система
обозначений, которая совместима с существующей. В данном случае
контравариантные индексы могут быть вставлены в нужную позицию в наборе
ковариантных, но со знаком минус. Функции типа  @code{contract()} и
@code{ishow()} были модифицированы таким образом, чтобы понимать
новые обозначения.

В данных обозначениях вычисление предыдущего примера дает:

@example
(%i5) ishow(g([-j,-k],[])*g([-i,-l],[])*a([i,j],[]))$
                                 i l       j k
(%t5)                           g    a    g
                                      i j
(%i6) ishow(contract(%))$
                                      l k
(%t6)                                a
@end example

В настоящий момент, единственной функцией, где  новые обозначения
играют существенную роль является @code{lc2kdt}. Благодаря этому
удается получить корректный результат для тензорного произведения
символов Леви-Чивита, применяя метрический тензор не прибегая
к пересортировке численных индексов обобщенных символов Кронекера.

Поскольку данные нововведения сделаны относительно недавно, можно
ожидать присутствие ошибок.  Код был достаточно тщательно
протестирован, чтобы убедиться, что ничего не нарушается
при использовании старых обозначений. В тоже время при работе
в новых обозначения шанс получения ошибки довольно значителен.
Для исправления замеченных ошибок обращайтесь к разработчикам.


@subsection Манипулирование тензорными индексами

Пакет манипулирования тензорными индексами загружается в Maxima командой
@code{load(itensor)}. Доступен ряд демонстрационных программ,
которые загружаются командой @code{demo(tensor)}.

В этом пакете тензор рассматривается, как функция индексов и их списков.
Список ковариантных индексов -- это первый аргумент индексного
объекта. Далее идет список контравариантных индексов и индексы
производной. Списки могут быть пустыми -- @code{[]}. Это говорит об отсутствии
ковариантный или контравариантных индексов тензора. Таким образом, @code{g([a,b],[c])}
представляет тензор @code{g}, который имеет 2 ковариантных индекса
@code{(a,b)}, один контравариантный -- (@code{c}) и не имеет индексов производной.

Если есть индексы производной, то они добавляются в качестве
дополнительных аргументов после списка контравариантных индексов.
Они могут быть либо определены пользователем в явном виде,  либо
получены в процессе дифференцирования тензора.
Поскольку обычная производная -- это коммутативная операция, то индексы
производной по умолчанию сортируются в алфавитном порядке если флаг
@code{iframe_flag} не равен @code{true}, указывая на то, что
используется тетрадная метрика. Такой принцип сортировки делает возможным
для  Maxima распознать что, например, @code{t([a],[b],i,j)} есть тоже
самое что и @code{t([a],[b],j,i)}.  Дифференцирование индексных
объектов в отношении координат, индексы которых не являются аргументом
этого объекта, в обычной ситуации давало бы ноль, потому, что
по-умолчанию Maxima не знает, что тензор, представляемый в виде функции
по индексам, может неявно зависеть от соответствующей
координаты.  Модификация существующей функции @code{diff} в
пакете @code{itensor} приводит к тому, что любой индексный объект зависит от
любой переменной дифференцирования пока не объявлено обратное. Это
делает возможным распространить известное правило суммирования по немым
индексам на индексы производных. Необходимо отметить, что @code{itensor} не
заложена возможность для подъема индексов производных и поэтому они
всегда рассматриваются как ковариантные.

В настоящий момент, все функции направленные на упрощение тензорных
выражений предполагают, что по умолчанию тензор не обладает
какими-либо свойствами симметрии. Это условие может быть переопределено путем
замены значения флага @code{allsym:false} на @code{true}. В этом
случае функции манипулирования индексами будут рассматривать все
индексные объекты, как полностью симметричные по спискам ковариантных
и контравариантных индексов.

Пакет @code{itensor} рассматривает тензора, как функциональные объекты. При
манипулировании тензорными уравнениями используются алгебраические правила,
свойства симметрии и свертки. Кроме того, в @code{itensor} определены операции
ковариантного дифференцирования, а также кривизна и
кручение. Вычисления могут проводится также и с учетом метрики
подвижных базисов (тетрады) если значение переменной
@code{iframe_flag} равно @code{true}.

В примере ниже показано как загрузить пакет @code{itensor}, задать имя
метрики и выполнить простые вычисления.

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) imetric(g);
(%o2)                                done
(%i3) components(g([i,j],[]),p([i,j],[])*e([],[]))$
(%i4) ishow(g([k,l],[]))$
(%t4)                               e p
                                       k l
(%i5) ishow(diff(v([i],[]),t))$
(%t5)                                  0
(%i6) depends(v,t);
(%o6)                               [v(t)]
(%i7) ishow(diff(v([i],[]),t))$
                                    d
(%t7)                               -- (v )
                                    dt   i
(%i8) ishow(idiff(v([i],[]),j))$
(%t8)                                v
                                      i,j
(%i9) ishow(extdiff(v([i],[]),j))$
(%t9)                             v    - v
                                   j,i    i,j
                                  -----------
                                       2
(%i10) ishow(liediff(v,w([i],[])))$
                               %3          %3
(%t10)                        v   w     + v   w
                                   i,%3    ,i  %3
(%i11) ishow(covdiff(v([i],[]),j))$
                                              %4
(%t11)                        v    - v   ichr2
                               i,j    %4      i j
(%i12) ishow(ev(%,ichr2))$
               %4 %5
(%t12) v    - g      v   (e p       + e   p     - e p       - e    p
        i,j           %4     j %5,i    ,i  j %5      i j,%5    ,%5  i j

                                         + e p       + e   p    )/2
                                              i %5,j    ,j  i %5
(%i13) iframe_flag:true;
(%o13)                               true
(%i14) ishow(covdiff(v([i],[]),j))$
                                             %6
(%t14)                        v    - v   icc2
                               i,j    %6     i j
(%i15) ishow(ev(%,icc2))$
                                             %6
(%t15)                        v    - v   ifc2
                               i,j    %6     i j
(%i16) ishow(radcan(ev(%,ifc2,ifc1)))$
             %6 %8                    %6 %8
(%t16) - (ifg      v   ifb       + ifg      v   ifb       - 2 v
                    %6    j %8 i             %6    i j %8      i,j

                                             %6 %8
                                        - ifg      v   ifb      )/2
                                                    %6    %8 i j
(%i17) ishow(canform(s([i,j],[])-s([j,i])))$
(%t17)                            s    - s
                                   i j    j i
(%i18) decsym(s,2,0,[sym(all)],[]);
(%o18)                               done
(%i19) ishow(canform(s([i,j],[])-s([j,i])))$
(%t19)                                 0
(%i20) ishow(canform(a([i,j],[])+a([j,i])))$
(%t20)                            a    + a
                                   j i    i j
(%i21) decsym(a,2,0,[anti(all)],[]);
(%o21)                               done
(%i22) ishow(canform(a([i,j],[])+a([j,i])))$
(%t22)                                 0
@end example


@node Функции и переменные пакета itensor,  , Введение в пакет itensor, Пакет itensor

@section Функции и переменные пакета @code{itensor}
@subsection Манипулирование индексными объектами

@deffn {Функция} entertensor (@var{name})

это интерактивная функция, которая позволяет создать индексный объект с
именем @var{name}, содержащий заданные пользователем списки
ковариантных и контравариантных индексов и индексы производных.
Отдельный индекс или список индексов (возможно пустой) считаются
допустимым вводом (см. пример в секции @code{covdiff}).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} changename (@var{old}, @var{new}, @var{expr})

заменяет имя тензора со старого @var{old} на новое @var{new}
в выражении @var{expr}. @var{old} может быть как простым символом,
так и списком в форме @code{[@var{name}, @var{m}, @var{n}]}.
В последнем случае переименовываются только индексные объекты
с именем @var{name} с @var{m} ковариантным и @var{n}
контравариантным индексами.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} listoftens (@var{expr})

в качестве результата возвращает список всех тензоров выражения
@var{expr}. Например,

@example

(%i6) ishow(a([i,j],[k])*b([u],[],v)+c([x,y],[])*d([],[])*e)$
                                         k
(%t6)                        d e c    + a    b
                                  x y    i j  u,v
(%i7) ishow(listoftens(%))$
                               k
(%t7)                        [a   , b   , c   , d]
                               i j   u,v   x y

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} ishow (@var{expr})

печатает выражение @var{expr}, содержащее индексные объекты,
в виде, где ковариантные индексы изображены в нижней позиции,
а контравариантные в верхней.  Индексы производной изображаются после
ковариантных индексов и отделены запятой (примеры вывода данной
функции можно найти практически в любой части этого документа).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} indices (@var{expr})

Возвращает список из двух элементов.  Первый -- список свободных
индексов, не участвующих в свертке, в  @var{expr}. Второй --
список немых индексов, участвующих в свертках.  Например,

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(a([i,j],[k,l],m,n)*b([k,o],[j,m,p],q,r))$
                                k l      j m p
(%t2)                          a        b
                                i j,m n  k o,q r
(%i3) indices(%);
(%o3)                 [[l, p, i, n, o, q, r], [k, j, m]]

@end example

Тензорное произведение в котором один и тот же немой индекс
встречается более чем два раза является синтаксически
неправильным. При работе с ним Maxima выдаст ошибку.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} rename (@var{expr})
@deffnx {Функция} rename (@var{expr}, @var{count})

Возвращает выражение эквивалентное исходному @var{expr}, но в
котором все немые индексы переименованы и пронумерованы. Имена берутся из списка
@code{[%1, %2, ...]}. В качестве опции можно задать номер @var{count}
с которого начинается список пронумерованных индексов. По умолчанию
немые индексы нумеруются от текущей величины @var{count}. Все немые
индексы в произведении встречаются ровно 2 раза. В случае ошибки
пользователя, когда в исходном выражении одно и тоже имя немого индекса
встречается более двух раз, Maxima выдаст ошибку и остановит вычисления.
Для суммы тензорных произведений, @code{rename} применяется к каждому
члену суммы при этом счетчик @var{count} каждый раз обнуляется при переходе к следующему
слагаемому.  В этом случае функция @code{rename} может служить
для упрощения тензорных выражений.  Кроме того, если @code{allsym} равно
@code{true}, то индексы сортируются в алфавитном порядке.
Если значение @code{flipflag} равно @code{false}, то переименование
и сортировка осуществляется относительно порядка контравариантных индексов.
В случае если значение @code{flipflag} равно  @code{true} переименование и сортировка
производится относительно порядка ковариантных индексов. Часто
бывает, что комбинированный эффект двух применений  @code{rename} с
переменой значения флага  @code{flipflag} позволяет существенно
упростить исходное выражение. Например,

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) allsym:true;
(%o2)                                true
(%i3) g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%4],[%3])*
ichr2([%2,%3],[u])*ichr2([%5,%6],[%1])*ichr2([%7,r],[%2])-
g([],[%4,%5])*g([],[%6,%7])*ichr2([%1,%2],[u])*
ichr2([%3,%5],[%1])*ichr2([%4,%6],[%3])*ichr2([%7,r],[%2]),noeval$
(%i4) expr:ishow(%)$

       %4 %5  %6 %7      %3         u          %1         %2
(%t4) g      g      ichr2      ichr2      ichr2      ichr2
                         %1 %4      %2 %3      %5 %6      %7 r

        %4 %5  %6 %7      u          %1         %3         %2
     - g      g      ichr2      ichr2      ichr2      ichr2
                          %1 %2      %3 %5      %4 %6      %7 r
(%i5) flipflag:true;
(%o5)                                true
(%i6) ishow(rename(expr))$
       %2 %5  %6 %7      %4         u          %1         %3
(%t6) g      g      ichr2      ichr2      ichr2      ichr2
                         %1 %2      %3 %4      %5 %6      %7 r

        %4 %5  %6 %7      u          %1         %3         %2
     - g      g      ichr2      ichr2      ichr2      ichr2
                          %1 %2      %3 %4      %5 %6      %7 r
(%i7) flipflag:false;
(%o7)                                false
(%i8) rename(%th(2));
(%o8)                                  0
(%i9) ishow(rename(expr))$
       %1 %2  %3 %4      %5         %6         %7        u
(%t9) g      g      ichr2      ichr2      ichr2     ichr2
                         %1 %6      %2 %3      %4 r      %5 %7

        %1 %2  %3 %4      %6         %5         %7        u
     - g      g      ichr2      ichr2      ichr2     ichr2
                          %1 %3      %2 %6      %4 r      %5 %7
@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@defvr {Управляющая переменная} flipflag
Значение по умолчанию: @code{false}

Если значение @code{flipflag} равно @code{false}, то сортировка и переименование индексов
осуществляется  относительно порядка контравариантных индексов, в
противном случае  -- относительно порядка ковариантных индексов.
Значение флага  @code{flipflag} влияет на результат применения функции
@code{rename()} следующим образом: если  @code{flipflag} равно
@code{false} то @code{rename} формирует список немых индексов по списку контравариантных
индексов, по мере поступления, слева направо (если значение флага равно
@code{true}, тогда используется список ковариантных индексов). Первый
немой индекс в списке переименовывается в  @code{%1}, следующий в
@code{%2} и т.д.). Затем индексы сортируются (см. пример в  @code{rename()}).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@deffn {Функция} defcon (@var{tensor_1})
@deffnx {Функция} defcon (@var{tensor_1}, @var{tensor_2}, @var{tensor_3})
задает свойства тензорной свертки тензора @var{tensor_1} с @var{tensor_3} так, что в
результате получается @var{tensor_3} с соответствующими индексами.
Если задан единственный аргумент, @var{tensor_1}, тогда свертка любого
другого тензора (скажем @code{my_tensor}) с  @var{tensor_1} дает тот
же тензор (@code{my_tensor}), но с новым набором индексов в
соответствии с операцией свертки.  В этом случае, @var{tensor_1}
может быть использован для подъема или опускания индексов.

Например, пусть @code{imetric:g}, тогда путем @code{defcon(g)} можно
реализовать подъем и опускание индексов тензора, сворачивая его с метрическим тензором.

Для одного и того же индексного объекта может быть задано более одного
правила свертки.  В этом случае, для одинаковых объектов
используется правило свертки заданное последним.
@code{contractions}  содержит список индексных объектов с заданными,
посредством @code{defcon}, правилами  свертки.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} remcon (@var{tensor_1} , ..., @var{tensor_n})
удаляет все правила свертки для объектов @var{tensor_i}.
@code{remcon(all)} удаляет все правила свертки для всех
индексных объектов.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} contract (@var{expr})

Выполняет свертку тензорного выражения @var{expr}, которое само по себе может быть
произвольной комбинацией сумм и произведений тензоров. Правила свертки должны
быть предварительно заданы с помощью @code{defcon}.
Для наилучших результатов, в выражении @var{expr}, необходимо раскрыть
все скобки. Если коэффициенты при тензорах в @var{expr}
не содержат дробей, то  наиболее эффективный и быстрый способ
раскрытия скобок в @var{expr} состоит в применении функции
@code{ratexpand}. При этом, флаг @code{gcd} можно положить равным
@code{false}, чтобы программа не пыталась искать сокращение
множителей, используя GCD алгоритмы.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} indexed_tensor (@var{tensor})

Данная операция необходима всяких раз, когда пользователь собирается
присвоить новые индексные выражения компонентам тензора
@var{tensor}, для которого в системе уже предусмотрено свое
индексное представление.  Примером могут служить символы Кристоффеля 1-го и 2-го рода
@code{ichr1}, @code{ichr2}, выраженные через компоненты метрики, или
тензор кривизны Римана @code{icurvature}. См. пример в
пункте @code{icurvature}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} components (@var{tensor}, @var{expr})

Данная функция присваивает тензору @var{tensor} индексное выражение
@var{expr}. Это приводит к тому, что при последующих вычислениях
индексные выражения @var{tensor} автоматически заменяются на
соответствующие @var{expr}. @var{tensor} должен иметь вид @code{t([...],[...])},
где каждый из списков может быть пустым. @var{expr} может быть любым
индексным выражением имеющим тот же набор свободных индексов (не
участвующих в свертке), что и @var{tensor}. Если @var{expr} содержит
свертки, то необходимо быть внимательным в выборе значений немых
индексов, чтобы избежать повторных немых индексов. В
этом случае можно рекомендовать другой способ присваивания
компонент, заключающийся в использовании конструкций @code{defrule}
(см. пример ниже).  Функция @code{remcomps} очищает использованное
ранее определение компонент тензора.

Важно понимать, что для @code{components} важна только валентность
тензора а не порядок индексов.  Присваивание значения
@code{x([i,-j],[])}, @code{x([-j,i],[])} или @code{x([i],[j])}
приводит к одному результату -- значение присваивается
тензору с именем @code{x} и валентностью @code{(1,1)}.


Любому индексному выражению можно присвоить любое другое индексное
представление и компоненты 4-мя различными способами, 2 способа
включают использование, рассмотренной выше функции  @code{components}:

1) Присваивание одного индексного выражения другому:

@example

(%i2) components(g([],[i,j]),e([],[i])*p([],[j]))$
(%i3) ishow(g([],[i,j]))$
                                      i  j
(%t3)                                e  p

@end example

2) В виде матрицы компонент:

@example

(%i6) components(g([i,j],[]),lg);
(%o6)                                done
(%i7) ishow(g([i,j],[]))$
(%t7)                                g
                                      i j
(%i8) g([3,3],[]);
(%o8)                                  1
(%i9) g([4,4],[]);
(%o9)                                 - 1

@end example

3) Путем определения функции. В примере ниже, тензор
@code{h} равен  @code{kdelta} если  @code{h} имеет одинаковое
количество ковариантных и контравариантных индексов, а индексы
производной отсутствуют. В любом другом случае, тензор @code{h}
равен тензору @code{g}:

@example

(%i4) h(l1,l2,[l3]):=if length(l1)=length(l2) and length(l3)=0
  then kdelta(l1,l2) else apply(g,append([l1,l2], l3))$
(%i5) ishow(h([i],[j]))$
                                          j
(%t5)                               kdelta
                                          i
(%i6) ishow(h([i,j],[k],l))$
                                     k
(%t6)                               g
                                     i j,l

@end example

4) Последний пример связан с использованием конструкций
типа @code{defrule}.

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) matchdeclare(l1,listp);
(%o2)                                done
(%i3) defrule(r1,m(l1,[]),(i1:idummy(),
      g([l1[1],l1[2]],[])*q([i1],[])*e([],[i1])))$

(%i4) defrule(r2,m([],l1),(i1:idummy(),
      w([],[l1[1],l1[2]])*e([i1],[])*q([],[i1])))$

(%i5) ishow(m([i,n],[])*m([],[i,m]))$
                                    i m
(%t5)                              m    m
                                         i n
(%i6) ishow(rename(applyb1(%,r1,r2)))$
                           %1  %2  %3 m
(%t6)                     e   q   w     q   e   g
                                         %1  %2  %3 n


@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} remcomps (@var{tensor})

Удаляет из системы значения компонент тензора
@code{tensor}, присвоенных при помощи функции @code{components}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@c NEED LIST OF ARGUMENTS HERE
@deffn {Функция} showcomps (@var{tensor})

Печатает значение компонент тензора, которые были присвоены с
помощью @code{components}.
Данная функция особенно полезна в случае, когда компоненты
тензора были заданы с помощью матрицы, как в данном примере:

@example

(%i1) load(ctensor);
(%o1)       /share/tensor/ctensor.mac
(%i2) load(itensor);
(%o2)      /share/tensor/itensor.lisp
(%i3) lg:matrix([sqrt(r/(r-2*m)),0,0,0],[0,r,0,0],
                [0,0,sin(theta)*r,0],[0,0,0,sqrt((r-2*m)/r)]);
               [         r                                     ]
               [ sqrt(-------)  0       0              0       ]
               [      r - 2 m                                  ]
               [                                               ]
               [       0        r       0              0       ]
(%o3)          [                                               ]
               [       0        0  r sin(theta)        0       ]
               [                                               ]
               [                                      r - 2 m  ]
               [       0        0       0        sqrt(-------) ]
               [                                         r     ]
(%i4) components(g([i,j],[]),lg);
(%o4)                                done
(%i5) showcomps(g([i,j],[]));
                  [         r                                     ]
                  [ sqrt(-------)  0       0              0       ]
                  [      r - 2 m                                  ]
                  [                                               ]
                  [       0        r       0              0       ]
(%t5)      g    = [                                               ]
            i j   [       0        0  r sin(theta)        0       ]
                  [                                               ]
                  [                                      r - 2 m  ]
                  [       0        0       0        sqrt(-------) ]
                  [                                         r     ]
(%o5)                                false

@end example

Функция @code{showcomps} может также печатать компоненты тензоров
ранга выше чем 2.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} idummy ()

Увеличивает значение счетчика @code{icounter} немых индексов на 1 и возвращает
значение индекса в форме @code{%n}, где n это положительное целое число.
Применение @code{idummy} гарантирует, что немые индексы, встречающиеся в
текущем выражении? не будут конфликтовать с уже использованными
(см. пример в секции @code{indices}).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@defvr {Управляющая переменная} idummyx
Значение по умолчанию: @code{%}

Данная переменная задает приставку (префикс) для генерируемых немых индексов
(см. пример в секции @code{indices}).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr

@defvr {Управляющая переменная} icounter
Значение по умолчанию: @code{1}

Определяет численный суффикс для генерируемого
немого индекса. Приставка (префикс) определяется
переменной @code{idummyx}

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr

@deffn {Функция} kdelta (@var{l1}, @var{l2})
Обобщенный символ Кронекера, где  @var{l1} и @var{l2} -- списки ковариантных и
контравариантных индексов соответственно. @code{kdelta([i],[j])} возвращает обычный
дельта-символ Кронекера. Команда @code{ev(@var{expr},kdelta)} вычисляет @var{expr}, заменяя
все конструкции вида @code{kdelta([],[])} (след @code{kdelta}) на размерность многообразия.

@code{itensor} также позволяет использование в @code{kdelta()} c  двумя ковариантными или
двумя контравариантными индексами. Эта дает возможность задать единичную ко(нтра)-вариантную
матрицу. Данная конструкция предусмотрена только для целей программирования. Следует помнить,
что в @code{itensor}  @code{kdelta([i,j],[])} не является разрешенным тензорным объектом.
Будьте готовы,что при операциях с @code{kdelta([i,j],[])} Maxima может
пожаловаться на неправильный индексный объект и отказаться от дальнейших вычислений.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} kdels (@var{l1}, @var{l2})

Симметризованная версия обобщенного дельта-символа Кронекера. Введена для удобства вычислений.
Свертка выражения с этим тензором приводит к его симметризации. Примеры:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) kdelta([1,2],[2,1]);
(%o2)                                 - 1
(%i3) kdels([1,2],[2,1]);
(%o3)                                  1
(%i4) ishow(kdelta([a,b],[c,d]))$
                             c       d         d       c
(%t4)                  kdelta  kdelta  - kdelta  kdelta
                             a       b         a       b
(%i4) ishow(kdels([a,b],[c,d]))$
                             c       d         d       c
(%t4)                  kdelta  kdelta  + kdelta  kdelta
                             a       b         a       b

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} levi_civita (@var{l})
Перестановочный тензор Леви-Чивита, который дает 1 если список @var{l}
является четной перестановкой целых чисел, -1 для нечетной
перестановки, и 0 когда встречаются повторяющиеся индексы.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} lc2kdt (@var{expr})
Приводит к упрощению выражений содержащих символы Леви-Чивита (произведения этих символов
заменяются на соответствующие дельта-символы Кронекера). Основная разница между действием
данной функции и непосредственным вычислением перестановочного тензора состоит в том,
что прямое вычисление тензора Леви-Чивита часто приводит к выражениям
содержащим дельта-символы с  целочисленными значения индексов, что затрудняет
дальнейшие операции. Применение функции @code{lc2kdt} позволяет избежать этих проблем.

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) expr:ishow('levi_civita([],[i,j])
                 *'levi_civita([k,l],[])*a([j],[k]))$
                                  i j  k
(%t2)                  levi_civita    a  levi_civita
                                       j            k l
(%i3) ishow(ev(expr,levi_civita))$
                                  i j  k       1 2
(%t3)                       kdelta    a  kdelta
                                  1 2  j       k l
(%i4) ishow(ev(%,kdelta))$
             i       j         j       i   k
(%t4) (kdelta  kdelta  - kdelta  kdelta ) a
             1       2         1       2   j

                               1       2         2       1
                        (kdelta  kdelta  - kdelta  kdelta )
                               k       l         k       l
(%i5) ishow(lc2kdt(expr))$
                     k       i       j    k       j       i
(%t5)               a  kdelta  kdelta  - a  kdelta  kdelta
                     j       k       l    j       k       l
(%i6) ishow(contract(expand(%)))$
                                 i           i
(%t6)                           a  - a kdelta
                                 l           l

@end example

Для использования @code{lc2kdt()} необходимо задать метрический тензор
(для случая когда, встречаются произведения перестановочных тензоров одинакового
ранга и типа).  Если метрика не была задана заранее (с помощью
@code{imetric}), то можно столкнуться с ошибкой.

@example

(%i7) expr:ishow('levi_civita([],[i,j])
                 *'levi_civita([],[k,l])*a([j,k],[]))$
                                 i j            k l
(%t7)                 levi_civita    levi_civita    a
                                                     j k
(%i8) ishow(lc2kdt(expr))$
Maxima encountered a Lisp error:

 Error in $IMETRIC [or a callee]:
 $IMETRIC [or a callee] requires less than two arguments.

Automatically continuing.
To reenable the Lisp debugger set *debugger-hook* to nil.
(%i9) imetric(g);
(%o9)                                done
(%i10) ishow(lc2kdt(expr))$
         %3 i       k   %4 j       l     %3 i       l   %4 j
(%t10) (g     kdelta   g     kdelta   - g     kdelta   g    
                    %3             %4               %3
              k
        kdelta  ) a
              %4   j k
(%i11) ishow(contract(expand(%)))$
                                  l i      l i
(%t11)                           a    - a g

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} lc_l

Правило упрощения выражений содержащих индексные символы Леви-Чивита
(@code{levi_civita}). Данное правило преобразования использует свойства антисимметрии
перестановочного тензора. Например:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2)  el1:ishow('levi_civita([i,j,k],[])*a([],[i])*a([],[j]))$
                             i  j
(%t2)                       a  a  levi_civita
                                             i j k
(%i3) el2:ishow('levi_civita([],[i,j,k])*a([i])*a([j]))$
                                       i j k
(%t3)                       levi_civita      a  a
                                              i  j
(%i4) ishow(canform(contract(expand(applyb1(el1,lc_l,lc_u)))))$
(%t4)                                  0
(%i5) ishow(canform(contract(expand(applyb1(el2,lc_l,lc_u)))))$
(%t5)                                  0

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} lc_u

Правило упрощения выражений содержащих индексные символы Леви-Чивита
(@code{levi_civita}), аналогично @code{lc_l}, данное правило преобразования
использует свойства антисимметрии перестановочного тензора
(см. пример в секции  @code{lc_l}).

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} canten (@var{expr})
Функция предназначена для упрощения тензорных выражений путем переименования
и перестановки немых индексов. Область применения @code{canten} ограничена. Данная функция
применима только для сумм тензорных произведений в которых отсутствуют индексы производной
и не встречаются символы Леви-Чивита. Ввиду этих ограничений, следует избегать
ее использования. Вместо нее рекомендуется применять  @code{canform}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} concan (@var{expr})

Аналогична @code{canten} но дополнительно производит
свертку индексов.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@subsection Симметрии тензоров

@defvr {Управляющая переменная} allsym
Значение по умолчанию: @code{false}

Если данной переменной присвоить  @code{true}, тогда все индексные
объекты будут считаться симметричными
по всем ковариантным и контравариантным индексам. Если @code{allsym} равно
@code{false}, все тензора не имеют никаких свойств симметрии априори,
пока симметрии не будут объявлены. Индексы производной предполагаются симметричными,
до тех пор пока не объявлено, что @code{iframe_flag} равен @code{true}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@deffn {Функция} decsym (@var{tensor}, @var{m}, @var{n}, [@var{cov_1}, @var{cov_2}, ...], [@var{contr_1}, @var{contr_2}, ...])

Объявляет свойства симметрии тензора @var{tensor} по @var{m} ковариантному и
@var{n} контравариантным индексам, где @var{cov_i} и @var{contr_i} --
псевдофункции, выражающие соотношения перестановочных симметрий по ковариантным и
контравариантным индексам соответственно. Данные псевдофункции
записываются в форме @code{symoper(@var{index_1}, @var{index_2}, ...)}, где
переменная @code{symoper} принимает  одно из следующих: @code{sym},
@code{anti} или @code{cyc}, которые означают соответственно, симметрию,
антисимметрию или цикличность индексов. Переменная
@var{index_i} принимает целочисленные значения и указывает на позицию
индекса в  @var{tensor}, для которого объявляются свойства симметрии.
Определения вида @code{symoper(all)} также дозволены, означая, что все
индексы удовлетворяют выбранному свойству симметрии.
Например, рассмотрим тензорный объект @code{b} с 5-ю ковариантными
индексами. Команда
 @code{decsym(b,5,3,[sym(1,2),anti(3,4)],[cyc(all)])} объявляет @code{b}
симметричным по первому и второму индексу, антисимметричным по 3 и 4
ковариантным индексам и циклическим по всем контравариантным индексам.
Список декларирующий симметрии может быть пустым. Функция @code{canform}
использует декларированные свойства симметрии для упрощения тензорных
выражений. Примеры даны ниже.

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) expr:contract( expand( a([i1, j1, k1], [])
           *kdels([i, j, k], [i1, j1, k1])))$
(%i3) ishow(expr)$
(%t3)         a      + a      + a      + a      + a      + a
               k j i    k i j    j k i    j i k    i k j    i j k
(%i4) decsym(a,3,0,[sym(all)],[]);
(%o4)                                done
(%i5) ishow(canform(expr))$
(%t5)                              6 a
                                      i j k
(%i6) remsym(a,3,0);
(%o6)                                done
(%i7) decsym(a,3,0,[anti(all)],[]);
(%o7)                                done
(%i8) ishow(canform(expr))$
(%t8)                                  0
(%i9) remsym(a,3,0);
(%o9)                                done
(%i10) decsym(a,3,0,[cyc(all)],[]);
(%o10)                               done
(%i11) ishow(canform(expr))$
(%t11)                        3 a      + 3 a
                                 i k j      i j k
(%i12) dispsym(a,3,0);
(%o12)                     [[cyc, [[1, 2, 3]], []]]

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} remsym (@var{tensor}, @var{m}, @var{n})

Удаляет все свойства симметрии тензора @var{tensor}, имеющего @var{m}
ковариантных и @var{n} контравариантных индексов.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} canform (@var{expr})
@deffnx {Функция} canform (@var{expr}, @var{rename})
Упрощает выражение @var{expr}, используя
переименование немых индексов и сортировку всех индексов с учетом
объявленных свойств симметрии. Если @code{allsym} равен @code{true},
тогда все индексные выражения подразумеваются симметричными по всем
индексам. В противном случае используется свойства , объявленные при помощи @code{decsym}.
Немые индексы переименовываются таким же образом, как и при
использовании @code{rename}.
Следует иметь ввиду, что упрощение громоздких выражений может потребовать
значительного количества вычислительного времени и ресурсов
памяти. Иногда затраты на вычисления можно уменьшить если сначала
переименовать индексы при помощи @code{rename}.
См. примеры в пункте @code{decsym}. Заметим, что @code{canform} не
всегда приводит выражение к простейшей форме.
В тоже время @code{canform} всегда возвращает математически
корректный результат.

Если значение второго необязательного параметра @var{rename} равно @code{false}, 
то переименование не производится.


@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@subsection Операции над индексами тензоров


@deffn {Функция} diff (@var{expr}, @var{v_1}, [@var{n_1}, [@var{v_2}, @var{n_2}] ...])
Стандартная функция дифференцирования Maxima, которая в пакете @code{itensor} имеет
дополнительные свойства. Данная конструкция означает взятие
производной выражения @var{expr} по переменной @var{v_1}, @var{n_1}
раз, по @var{v_2}, @var{n_2}раз и т.д.
В применении к тензорным объектам, функция дифференцирования
модифицирована таким образом, что @code{v_i} может иметь целочисленные
значения от 1 до @code{dim}. В этом случае дифференцирование выполняется
по отношению к @code{v_i}-ому элементу списка @code{vect_coords}. Если
@code{vect_coords} является атомом, тогда переменная
индексированная именем @code{v_i} будет использована как переменная для
дифференцирования. Это допускает использование массива имен координат или индексированных
имен типа @code{x[1]}, @code{x[2]}, в качестве переменных
дифференцирования.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} idiff (@var{expr}, @var{v_1}, [@var{n_1}, [@var{v_2}, @var{n_2}] ...])
Индексное дифференцирование. В отличие от функции @code{diff}, которая
дифференцирует в отношении некоторой независимой переменной, @code{idiff} может
быть использован при дифференцировании по координате. Для индексного
объекта, такое дифференцирование добавляет @code{v_i} к индексам
производной (он добавляется последовательно к ковариантным индексам
после запятой). В дальнейшем индексы производной могут сортироваться
если переменная @code{iframe_flag} не равна @code{true}.

@code{idiff} можно использовать при дифференцировании детерминанта
метрического тензора. Таким образом, если метрика @code{imetric}
обозначена через @code{g}, тогда @code{idiff(determinant(g),k)} возвращает
@code{2*determinant(g)*ichr2([%i,k],[%i])}, где немой индекс @code{%i}
пробегает соответствующие значения.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} liediff (@var{v}, @var{tensor})

Вычисляет производную Ли от тензорного выражения @var{tensor} в отношении
векторного поля @var{v}. @var{tensor} может быть произвольным тензорным
объектом, а @var{v} -- имя векторного поля (без индексов). Например:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(liediff(v,a([i,j],[])*b([],[k],l)))$
       k    %2            %2          %2
(%t2) b   (v   a       + v   a     + v   a    )
       ,l       i j,%2    ,j  i %2    ,i  %2 j

                          %1  k        %1  k      %1  k
                      + (v   b      - b   v    + v   b   ) a
                              ,%1 l    ,l  ,%1    ,l  ,%1   i j

@end example


@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn



@deffn {Функция} rediff (@var{ten})

Вычисляет все команды @code{idiff} в выражении @var{ten}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} undiff (@var{expr})

Возвращает выражение эквивалентное @var{expr}, но в котором все
производные индексных объектов заменяются на  не вычисляемую форму
функции @code{idiff} с такими аргументами, чтобы при дифференцировании
получился бы соответствующий индексный объект. Это бывает полезно, когда
желательно провести некоторые замены в продифференцированных индексных
объектах. После этого дифференцирование выполняется при помощи
@code{ev(@var{expr}, idiff)}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} evundiff

Эквивалентно применению @code{undiff}, затем @code{ev} и
@code{rediff}.

При помощи этой функции можно легко вычислять выражения,
дифференциальную форму которых иначе
невозможно вычислить. Например, следующее выражение приводит к ошибке:

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) icurvature([i,j,k],[l],m);
Maxima encountered a Lisp error:

 Error in $ICURVATURE [or a callee]: 
 $ICURVATURE [or a callee] requires less than three arguments.

Automatically continuing.
To reenable the Lisp debugger set *debugger-hook* to nil.
@end example

Однако, если сначала ввести @code{icurvature} в не вычисляемой форме, а
затем применить @code{evundiff}, то получим желаемый результат:

@example
(%i3) ishow('icurvature([i,j,k],[l],m))$
                                         l
(%t3)                          icurvature
                                         i j k,m
(%i4) ishow(evundiff(%))$
             l              l         %1           l           %1
(%t4) - ichr2        - ichr2     ichr2      - ichr2       ichr2
             i k,j m        %1 j      i k,m        %1 j,m      i k

             l              l         %1           l           %1
      + ichr2        + ichr2     ichr2      + ichr2       ichr2
             i j,k m        %1 k      i j,m        %1 k,m      i j
@end example

ЗАМЕЧАНИЕ: В ранних версиях Maxima, операции производных в определениях
символов Кристоффеля всегда должны были вводится в не вычисляемой
форме. Сейчас это исправлено и надобность в процедуре @code{evundiff}
в этом случае отпала. Например:

@example
(%i5) imetric(g);
(%o5)                                done
(%i6) ishow(ichr2([i,j],[k],l))$
       k %3
      g     (g         - g         + g        )
              j %3,i l    i j,%3 l    i %3,j l
(%t6) -----------------------------------------
                          2

                         k %3
                        g     (g       - g       + g      )
                         ,l     j %3,i    i j,%3    i %3,j
                      + -----------------------------------
                                         2
@end example


@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} flush (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...)
Обнуляет в @var{expr} все объекты  @var{tensor_i}, не имеющие индексов
производной.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} flushd (@var{expr}, @var{tensor_1}, @var{tensor_2}, ...)
Обнуляет в @var{expr} все объекты  @var{tensor_i}, имеющие индексы
производной.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} flushnd (@var{expr}, @var{tensor}, @var{n})
Обнуляет в @var{expr} все объекты  @var{tensor}, имеющие @var{n} и больше индексов
производной. Например,

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(a([i],[J,r],k,r)+a([i],[j,r,s],k,r,s))$
                                J r      j r s
(%t2)                          a      + a
                                i,k r    i,k r s
(%i3) ishow(flushnd(%,a,3))$
                                     J r
(%t3)                               a
                                     i,k r
@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} coord (@var{tensor_1}, @var{tensor_2}, ...)

Дает тензорам @var{tensor_i} свойства координатного дифференцирования,
такие что производная контравариантного вектора, имя которого  совпадает
с одним из @var{tensor_i}, дает дельта-символ Кронекера. Например, если
@code{coord(x)}, тогда  вычисление @code{idiff(x([],[i]),j)} дает @code{kdelta([i],[j])}.
@code{coord} это список всех индексных объектов имеющих это свойство.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} remcoord (@var{tensor_1}, @var{tensor_2}, ...)

Удаляет свойства координатного дифференцирования для объектов @var{tensor_i}.
@code{remcoord(all)} удаляет свойства координатного дифференцирования
для всех индексных объектов.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} makebox (@var{expr})
Служит для цели аналогичной @code{ishow}. В дополнение,
все  даламбертианы, встречающиеся в @var{expr} отображаются символом @code{[]}.
Например, @code{[]p([m],[n])} представляет сокращение для
@code{g([],[i,j])*p([m],[n],i,j)}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} conmetderiv (@var{expr}, @var{tensor})
Используется для упрощения выражений, содержащих
частные производные ковариантных и контравариантных форм метрического
тензора.
Например, при помощи @code{conmetderiv} можно связать частные
производные  метрического тензора с символами Кристоффеля:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(g([],[a,b],c))$
                                      a b
(%t2)                                g
                                      ,c
(%i3) ishow(conmetderiv(%,g))$
                         %1 b      a       %1 a      b
(%t3)                 - g     ichr2     - g     ichr2
                                   %1 c              %1 c

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} simpmetderiv (@var{expr})
@deffnx {Функция} simpmetderiv (@var{expr} [, @var{stop}])

Упрощает выражения, содержащие произведения производных метрического
тензора.  В частности @code{simpmetderiv} использует два тождества:

@example

   ab        ab           ab                 a
  g   g   + g   g     = (g   g  )   = (kdelta )   = 0
   ,d  bc        bc,d         bc ,d          c ,d

@end example

откуда

@example

   ab          ab
  g   g   = - g   g
   ,d  bc          bc,d
@end example

и

@example

  ab          ab
 g   g     = g   g
  ,j  ab,i    ,i  ab,j

@end example

которое следует из симметрии символов Кристоффеля.

Функция @code{simpmetderiv} имеет один необязательный аргумент,
который, если присутствует, вызывает прекращение работы функции
сразу после первой успешной подстановки.
Функция @code{simpmetderiv} использует глобальную опцию
@var{flipflag}, которая определяет каким образом следует выбирать
"канонический" порядок индексов произведения.

В целом, данные возможности позволяют осуществлять упрощения,
которые невозможно реализовать другими способами,
что демонстрируется в следующем примере:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) imetric(g);
(%o2)                                done
(%i3) ishow(g([],[a,b])*g([],[b,c])*g([a,b],[],d)*g([b,c],[],e))$
                             a b  b c
(%t3)                       g    g    g      g
                                       a b,d  b c,e
(%i4) ishow(canform(%))$

errexp1 has improper indices
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i5) ishow(simpmetderiv(%))$
                             a b  b c
(%t5)                       g    g    g      g
                                       a b,d  b c,e
(%i6) flipflag:not flipflag;
(%o6)                                true
(%i7) ishow(simpmetderiv(%th(2)))$
                               a b  b c
(%t7)                         g    g    g    g
                               ,d   ,e   a b  b c
(%i8) flipflag:not flipflag;
(%o8)                                false
(%i9) ishow(simpmetderiv(%th(2),stop))$
                               a b  b c
(%t9)                       - g    g    g      g
                                    ,e   a b,d  b c
(%i10) ishow(contract(%))$
                                    b c
(%t10)                           - g    g
                                    ,e   c b,d

@end example

См. также @code{weyl.dem}, для примера совместного применения @code{simpmetderiv}
и @code{conmetderiv} для упрощения тензора Вейля.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} flush1deriv (@var{expr}, @var{tensor})

Обнуляет все производные первого порядка от @var{tensor} в @var{expr}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@subsection Тензоры в искривленном пространстве


@deffn {Функция} imetric (@var{g})
@deffnx {Системная переменная} imetric

Определяет имя метрического тензора, присваивая соответствующее значение
переменной @code{imetric}, @code{imetric:@var{g}}. В дополнение к этому программа
устанавливает соответствующие свойства свертки для данной метрики:
@code{defcon(@var{g})}, @code{defcon(@var{g},@var{g},kdelta)}.
По умолчанию переменная @code{imetric} не имеет значения.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} ichr1 ([@var{i}, @var{j}, @var{k}])
Дает значение символа Кристоффеля первого рода, которое по определению равно:

@example
       (g      + g      - g     )/2 .
         ik,j     jk,i     ij,k
@end example
@noindent
Перед тем как использовать явные выражения для символов Кристоффеля
необходимо определить имя метрического тензора, присвоив соответствующее
значение переменной @code{imetric}, см. пример ниже в разделе @code{covdiff}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@deffn {Функция} ichr2 ([@var{i}, @var{j}],[@var{k}])
Дает значение символа Кристоффеля 2-го рода, которые по определению равны:

@example
                       ks
   ichr2([i,j],[k]) = g    (g      + g      - g     )/2
                             is,j     js,i     ij,s
@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} icurvature ([@var{i}, @var{j}, @var{k}], [@var{h}])
Дает выражение для тензора кривизны Римана через символы Кристоффеля
2-го рода (@code{ichr2}).  Используется следующее определение:
@example
            h             h            h         %1         h
  icurvature     = - ichr2      - ichr2     ichr2    + ichr2
            i j k         i k,j        %1 j      i k        i j,k
                            h          %1
                     + ichr2      ichr2
                            %1 k       i j
@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} covdiff (@var{expr}, @var{v_1}, @var{v_2}, ...)
Вычисляет ковариантную производную от @var{expr} по переменным
@var{v_i} используя символы Кристоффеля
2-го рода (@code{ichr2}).  Для получения явных выражений ковариантной
производной через компоненты метрики необходимо использовать
@code{ev(@var{expr},ichr2)}, определив предварительно метрический тензор.

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) entertensor()$
Enter tensor name: a;
Enter a list of the covariant indices: [i,j];
Enter a list of the contravariant indices: [k];
Enter a list of the derivative indices: [];
                                      k
(%t2)                                a
                                      i j
(%i3) ishow(covdiff(%,s))$
             k         %1     k         %1     k
(%t3)     - a     ichr2    - a     ichr2    + a
             i %1      j s    %1 j      i s    i j,s

             k     %1
      + ichr2     a
             %1 s  i j
(%i4) imetric:g;

(%o4)                                  g
(%i5) ishow(ev(%t3,ichr2))$

         %1 %4  k
        g      a     (g       - g       + g      )
                i %1   s %4,j    j s,%4    j %4,s
(%t5) - ------------------------------------------
                            2
    %1 %3  k
   g      a     (g       - g       + g      )
           %1 j   s %3,i    i s,%3    i %3,s
 - ------------------------------------------
                       2
    k %2  %1
   g     a    (g        - g        + g       )
          i j   s %2,%1    %1 s,%2    %1 %2,s     k
 + ------------------------------------------- + a
                        2                         i j,s

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} lorentz_gauge (@var{expr})
Налагает условие Лоренцевой калибровки на все индексные объекты в @var{expr},
приравнивая к нулю те, в которых индекс производной совпадает с
одним из контравариантных индексов.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} igeodesic_coords (@var{expr}, @var{name})

Позволяет пользователю обнулить не дифференцированные символы
Кристоффеля и первые производные метрического тензора в @var{expr} (подразумевая
"нормальные" координаты). Переменная @var{name} в
функции @code{igeodesic_coords} может относится, или к имени метрики (если таковая
присутствует в явном виде в @var{expr}), или к имени связности
в качестве которых используются фиксированные имена @code{ichr1} и (или)
@code{ichr2}. В следующем примере, при помощи
@code{igeodesic_coords}), проверяется свойство цикличности
тензора Римана.

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(icurvature([r,s,t],[u]))$
             u            u         %1         u     
(%t2) - ichr2      - ichr2     ichr2    + ichr2      
             r t,s        %1 s      r t        r s,t 

                                              u         %1
                                       + ichr2     ichr2
                                              %1 t      r s
(%i3) ishow(igeodesic_coords(%,ichr2))$
                                 u            u
(%t3)                       ichr2      - ichr2
                                 r s,t        r t,s
(%i4) ishow(igeodesic_coords(icurvature([r,s,t],[u]),ichr2)+
            igeodesic_coords(icurvature([s,t,r],[u]),ichr2)+
            igeodesic_coords(icurvature([t,r,s],[u]),ichr2))$
             u            u            u            u
(%t4) - ichr2      + ichr2      + ichr2      - ichr2
             t s,r        t r,s        s t,r        s r,t

                                             u            u
                                      - ichr2      + ichr2
                                             r t,s        r s,t
(%i5) canform(%);
(%o5)                                  0

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn

@subsection Вычисления в подвижном базисе

В Maxima существует возможность проводить вычисления с использованием
подвижных базисов в качестве которых можно выбирать, либо
ортонормированный  базис типа тетрады либо произвольный базис.

Для использования подвижного базиса переменной @code{iframe_flag}
необходимо присвоить значение @code{true}. В этом случае символы
Кристоффеля  @code{ichr1} и @code{ichr2} заменяются более общими
коэффициентами связности @code{icc1} и @code{icc2} соответственно.
Выражения для  @code{covdiff} и @code{icurvature} также заменяются более
общими.

Базис определяется двумя тензорами: полем дуального базиса (@code{ifri}),
и метрическим тензором @code{ifg}. Для ортонормированного базиса
метрический тензор совпадает с единичной матрицей или Лоренцевой
метрикой для пространства-времени Минковского. Дуальный базис
определяется базисом векторов (единичных). Явный вид дуального базиса и
его метрики не обязателен. По умолчанию все
вычисления проводятся в общем виде без использования явных выражений для
@code{ifri} и @code{ifg}.

При @code{iframe_flag} равном @code{true}, во многих случаях для
опускания и подъема индексов вместо стандартной метрики @code{imetric}
используется метрика тетрады @code{ifg}.

ВАЖНО: Присвоение @code{iframe_flag} значения @code{true} не отменяет
свойства свертки обычной метрики, определенные ранее командами
@code{defcon} или @code{imetric}. Если используется тетрадный
формализм, то определение стандартной метрики лучше всего ввести с
помощью присвоения соответствующего имени переменной
@code{imetric}. Команду @code{imetric} лучше НЕ использовать.

Maxima использует  поле дуального базиса (@code{ifri})
и метрический тензор @code{ifg} для определения структурных коэффициентов базиса (@code{ifc1}
и @code{ifc2}), которые в дальнейшем используются для вычисления
коэффициентов связности (@code{icc1}
и @code{icc2}), как показано в следующем примере:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) iframe_flag:true;
(%o2)                                true
(%i3) ishow(covdiff(v([],[i]),j))$
                               i        i     %1
(%t3)                         v   + icc2     v
                               ,j       %1 j
(%i4) ishow(ev(%,icc2))$
                        %1      i           i        i
(%t4)                  v   (ifc2     + ichr2    ) + v
                                %1 j        %1 j     ,j
(%i5) ishow(ev(%,ifc2))$
            %1    i %2
           v   ifg     (ifb        - ifb        + ifb       )
                           j %2 %1      %2 %1 j      %1 j %2     i
(%t5)      -------------------------------------------------- + v
                                   2                             ,j
(%i6) ishow(ifb([a,b,c]))$
                       %5    %4
(%t6)               ifr   ifr   (ifri        - ifri       )
                       a     b       c %4,%5       c %5,%4

@end example

Когда переменной @code{iframe_bracket_form} присвоено
@code{false}, то  используется альтернативный метод для вычисления
коммутатора тетрады (@code{ifb}).

@example

(%i8) block([iframe_bracket_form:false],ishow(ifb([a,b,c])))$
                       %7    %6        %6      %7
(%t8)              (ifr   ifr     - ifr     ifr  ) ifri
                       a     b,%7      a,%7    b       c %6

@end example


@deffn {Функция} iframes ()

Поскольку в данной версии Maxima свойства свертки для @code{ifr} и
@code{ifri}, а также (@code{ifb}) определены всегда, то
данная функция не выполняет никаких действий.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@defvr {Переменная} ifb

Скобка тетрады (коммутатор). Вклад метрического тензора тетрады в
коэффициенты связности выражается через коммутатор тетрады.

@example

          - ifb      + ifb      + ifb
               c a b      b c a      a b c
ifc1    = --------------------------------
    abc                  2

@end example

Сам по себе коммутатор вычисляется через компоненты тетрады и
метрический тензор тетрады. В зависимости от значения
@code{frame_bracket_form} вычисление скобки тетрады дает разный
результат. При @code{frame_bracket_form} равном @code{true}
получим:

@example

          d      e                                      f
ifb =  ifr    ifr   (ifri      - ifri      - ifri    itr   )
   abc    b      c       a d,e       a e,d       a f    d e


@end example

А при @code{itorsion_flag} равном @code{true}:

@example
             e      d        d      e
ifb    = (ifr    ifr    - ifr    ifr   ) ifri
   abc       b      c,e      b,e    c        a d

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} icc1

Коэффициенты связности первого рода. В @code{itensor}, определяется как:

@example

icc1    = ichr1    - ikt1    - inmc1
    abc        abc       abc        abc

@end example

В этом выражении, если @code{iframe_flag} равно @code{true}, символы Кристоффеля
@code{ichr1} заменяются коэффициентами связности тетрады @code{ifc1}.
Если @code{itorsion_flag} равно @code{false}, то @code{ikt1}
опускается. @code{ikt1} опускается и в случае если используется базис
тетрады, так как кручение уже вычислено, как часть скобки тетрады.
Наконец, если @code{inonmet_flag} равен @code{false}, то
@code{inmc1}, также опускается при вычислениях.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} icc2

Коэффициенты связности второго рода. В @code{itensor}, определяются как,

@example

    c         c        c         c
icc2   = ichr2   - ikt2   - inmc2
    ab        ab       ab        ab

@end example

В этом выражении, если @code{iframe_flag} равно @code{true}, символы Кристоффеля
@code{ichr2} заменяются коэффициентами связности тетрады @code{ifc2}.
Если @code{itorsion_flag} равно @code{false}, то @code{ikt2}
опускается. @code{ikt2} опускается и в случае, если используется базис
тетрады, так как кручение уже вычислено, как часть скобки тетрады.
Наконец, если @code{inonmet_flag} равен @code{false}, то
@code{inmc2}, также опускается при вычислениях.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifc1

Структурные коэффициенты 1-го рода, известные, также, как коэффициенты
вращения Риччи. Этот тензор выражает  вклад метрики тетрады в
коэффициенты связности 1-го рода.  Определяется как:

@example

          - ifb      + ifb      + ifb
               c a b      b c a      a b c
ifc1    = --------------------------------
    abc                   2


@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifc2

Структурные коэффициенты 2-го рода. Получаются сверткой структурных
коэффициентов 1-го рода и метрики тетрады:

@example

    c       cd
ifc2   = ifg   ifc1
    ab             abd

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifr

Базис тетрады. Произведение с дуальным базисом (@code{ifri}) дает
метрику тетрады.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifri

Дуальный базис тетрады. Определяется набором векторов.
Вместе с тензором тетрадной метрики @code{ifg} образует основу тетрадного
формализма реализованного в @code{itensor}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifg

Тензор тетрадной метрики. По умолчанию равен @code{kdelta}. Пользователь может
определить свой, используя @code{components}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ifgi

Обратная тетрадная метрика. Свертка с @code{ifg} дает  @code{kdelta}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Управляющая переменная} iframe_bracket_form
Значение по умолчанию: @code{true}

Определяет метод вычисления скобки тетрады @code{ifb}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr

@subsection Кручение и неметричность

Maxima умеет учитывать кручение и неметричность. Вклад кручения в
коэффициенты связности вычисляется, если @code{itorsion_flag} равен
@code{true}. Аналогично, компоненты  неметричности будут учтены, если
@code{inonmet_flag} равен @code{true}.


@defvr {Переменная} inm

Вектор неметричности.  Конформная неметричность определяется через
ковариантную производную метрического тензора, которая в обычном случае
равна нулю. Если @code{inonmet_flag} равен @code{true}, то вычисление
ковариантной производной метрики дает:

@example

g     =- g  inm
 ij;k     ij   k

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} inmc1

Ковариантная перестановка компонент вектора неметричности. Определяется путем:

@example

           g   inm  - inm  g   - g   inm
            ab    c      a  bc    ac    b
inmc1    = ------------------------------
     abc                 2

@end example

В тетрадном формализме вместо @code{g} используется @code{ifg}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} inmc2

Контравариантная перестановка компонент вектора
неметричности. Применяется когда @code{inonmet_flag} равен @code{true}.
Определяется путем:


@example

                      c         c         cd
          -inm  kdelta  - kdelta  inm  + g   inm  g
     c        a       b         a    b          d  ab
inmc2   = -------------------------------------------
     ab                        2

@end example

В тетрадном формализме вместо @code{g} используется @code{ifg}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ikt1

Ковариантная перестановка тензора кручения.
Вычисляется посредством:

@example

                  d           d       d
          -g   itr  - g    itr   - itr   g
            ad    cb    bd    ca      ab  cd
ikt1    = ----------------------------------
    abc                   2

@end example

В тетрадном формализме вместо @code{g} используется @code{ifg}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} ikt2

Контравариантная перестановка тензора кручения.
Вычисляется посредством:

@example

    c     cd
ikt2   = g   ikt1
    ab           abd

@end example

В тетрадном формализме вместо @code{g} используется @code{ifg}.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@defvr {Переменная} itr

Тензор кручения. Для метрики с кручением индексы ковариантной
производной не коммутируют. Пример:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) imetric:g;
(%o2)                                  g
(%i3) covdiff( covdiff( f( [], []), i), j)
                      - covdiff( covdiff( f( [], []), j), i)$
(%i4) ishow(%)$
                                   %4              %2
(%t4)                    f    ichr2    - f    ichr2
                          ,%4      j i    ,%2      i j
(%i5) canform(%);
(%o5)                                  0
(%i6) itorsion_flag:true;
(%o6)                                true
(%i7) covdiff( covdiff( f( [], []), i), j)
                      - covdiff( covdiff( f( [], []), j), i)$
(%i8) ishow(%)$
                           %8             %6
(%t8)             f    icc2    - f    icc2    - f     + f
                   ,%8     j i    ,%6     i j    ,j i    ,i j
(%i9) ishow(canform(%))$
                                   %1             %1
(%t9)                     f    icc2    - f    icc2
                           ,%1     j i    ,%1     i j
(%i10) ishow(canform(ev(%,icc2)))$
                                   %1             %1
(%t10)                    f    ikt2    - f    ikt2
                           ,%1     i j    ,%1     j i
(%i11) ishow(canform(ev(%,ikt2)))$
                      %2 %1                    %2 %1
(%t11)          f    g      ikt1       - f    g      ikt1
                 ,%2            i j %1    ,%2            j i %1
(%i12) ishow(factor(canform(rename(expand(ev(%,ikt1))))))$
                           %3 %2            %1       %1
                     f    g      g      (itr    - itr   )
                      ,%3         %2 %1     j i      i j
(%t12)               ------------------------------------
                                      2
(%i13) decsym(itr,2,1,[anti(all)],[]);
(%o13)                               done
(%i14) defcon(g,g,kdelta);
(%o14)                               done
(%i15) subst(g,nounify(g),%th(3))$
(%i16) ishow(canform(contract(%)))$
                                           %1
(%t16)                           - f    itr
                                    ,%1    i j

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr

@subsection Внешняя алгебра

В @code{itensor} реализованы возможности для операций с полностью
антисимметричными ковариантными тензорными объектами (внешние формы).
Полностью антисимметричное тензорное поле ранга
(0,L) соответствует внешней (дифференциальной) L-форме. Грассманова
алгебра L-форм включает операции внешнего (косого) произведения.

Операция внешнего произведения не имеет общепринятого определения.
Некоторые авторы определяют внешнее произведение способом, который
соответствует операции антисимметризации. Например,

@example
            a a  - a a
             i j    j i
 a  /\ a  = -----------
  i     j        2
@end example

В более общем случае, внешнее произведение p-формы и q-формы можно
определить путем:

@example
                       1     k1..kp l1..lq
A       /\ B       = ------ D              A       B
 i1..ip     j1..jq   (p+q)!  i1..ip j1..jq  k1..kp  l1..lq
@end example

где @code{D} обозначает дельта-символ Кронекера.

Другие авторы предпочитают  "геометрическое" определение,
соответствующее понятию элемента объема:

@example
a  /\ a  = a a  - a a
 i     j    i j    j i
@end example

В более общем случае имеем:

@example
                       1    k1..kp l1..lq
A       /\ B       = ----- D              A       B
 i1..ip     j1..jq   p! q!  i1..ip j1..jq  k1..kp  l1..lq
@end example

С алгебраической точки зрения первое определение выглядит
более естественным для @code{itensor}. С другой стороны, во многих приложения
более принято следовать "геометрическому" определению. У пользователя
есть выбор -- какое из двух определений использовать.  При
@code{igeowedge_flag} равном @code{false} (по умолчанию), используется
антисимметризация.  В противном случае применяется "геометрическое" определение.


@defvr {Оператор} ~
@ifinfo
@fnindex Внешнее произведение
@end ifinfo

Обозначает операцию внешнего произведения. Это бинарная операция.
В качестве аргументов можно использовать выражения, включающие
скаляры, ковариантные тензоры 1-го ранга или антисимметричные
ковариантные тензоры ранга  @code{l} (предварительно объявленные, как
антисимметричные по всем ковариантным индексам).

Результат внешнего произведения контролируется флагом
@code{igeowedge_flag}. Например:

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(a([i])~b([j]))$
                                 a  b  - b  a
                                  i  j    i  j
(%t2)                            -------------
                                       2
(%i3) decsym(a,2,0,[anti(all)],[]);
(%o3)                                done
(%i4) ishow(a([i,j])~b([k]))$
                          a    b  + b  a    - a    b
                           i j  k    i  j k    i k  j
(%t4)                     ---------------------------
                                       3
(%i5) igeowedge_flag:true;
(%o5)                                true
(%i6) ishow(a([i])~b([j]))$
(%t6)                            a  b  - b  a
                                  i  j    i  j
(%i7) ishow(a([i,j])~b([k]))$
(%t7)                     a    b  + b  a    - a    b
                           i j  k    i  j k    i k  j
@end example

@opencatbox
@category{Пакет itensor} @category{Операторы}
@closecatbox
@end defvr


@defvr {Оператор} |
@ifinfo
@fnindex Свертка с вектором
@end ifinfo

Бинарная операция, обозначающая "внутреннее" произведение -- свертку с
контравариантным вектором. При этой операции
результат не зависит от векторных индексов, участвующих в
свертке. Поэтому вектор можно задать только именем.

В пакете @code{itensor}, "внутренняя" свертка с вектором всегда выполняется по
первому (в отношении алфавитного порядка) индексу. Это позволяет
проводить  более эффективные упрощения выражений, включающих
"внутренние" свертки. Например:

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) decsym(a,2,0,[anti(all)],[]);
(%o2)                                done
(%i3) ishow(a([i,j],[])|v)$
                                    %1
(%t3)                              v   a
                                        %1 j
(%i4) ishow(a([j,i],[])|v)$
                                     %1
(%t4)                             - v   a
                                         %1 j
@end example

Заметим, что "внутренняя" свертка определена только для  полностью
антисимметричных объектов. В противном случае результат вычисления будет неправильным.

@opencatbox
@category{Пакет itensor} @category{Операторы}
@closecatbox
@end defvr

@deffn {Функция} extdiff (@var{expr}, @var{ind})

Внешнее дифференцирование @var{expr} по индексу @var{ind}.
В @code{itensor} оператор внешней производной определен как внешнее
произведение оператора производной и формы. Таким образом, результат
вычисления, также зависит от значения флага @code{igeowedge_flag}.
Например:

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) ishow(extdiff(v([i]),j))$
                                  v    - v
                                   j,i    i,j
(%t2)                             -----------
                                       2
(%i3) decsym(a,2,0,[anti(all)],[]);
(%o3)                                done
(%i4) ishow(extdiff(a([i,j]),k))$
                           a      - a      + a
                            j k,i    i k,j    i j,k
(%t4)                      ------------------------
                                      3
(%i5) igeowedge_flag:true;
(%o5)                                true
(%i6) ishow(extdiff(v([i]),j))$
(%t6)                             v    - v
                                   j,i    i,j
(%i7) ishow(extdiff(a([i,j]),k))$
(%t7)                      a      - a      + a
                            j k,i    i k,j    i j,k
@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@deffn {Функция} hodge (@var{expr})

Вычисляет форму дуальную @var{expr}. Например:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) imetric(g);
(%o2)                            done
(%i3) idim(4);
(%o3)                            done
(%i4) icounter:100;
(%o4)                             100
(%i5) decsym(A,3,0,[anti(all)],[])$

(%i6) ishow(A([i,j,k],[]))$
(%t6)                           A
                                 i j k
(%i7) ishow(canform(hodge(%)))$
                          %1 %2 %3 %4
               levi_civita            g        A
                                       %1 %102  %2 %3 %4
(%t7)          -----------------------------------------
                                   6
(%i8) ishow(canform(hodge(%)))$
                 %1 %2 %3 %8            %4 %5 %6 %7
(%t8) levi_civita            levi_civita            g       
                                                     %1 %106
                             g        g        g      A         /6
                              %2 %107  %3 %108  %4 %8  %5 %6 %7
(%i9) lc2kdt(%)$

(%i10) %,kdelta$

(%i11) ishow(canform(contract(expand(%))))$
(%t11)                     - A
                              %106 %107 %108

@end example

@opencatbox
@category{Пакет itensor}
@closecatbox
@end deffn


@defvr {Переменная} igeowedge_flag
Значение по умолчанию: @code{false}

Контролирует результат вычисления внешнего произведения или внешней
производной. При @code{igeowedge_flag} равном @code{false} (по
умолчанию), понятие  внешней (дифференциальной) формы соответствует
полностью антисимметричному ковариантному тензорному полю.
В противном случае внешняя форма будет согласована с понятием элемента объема.

@opencatbox
@category{Пакет itensor}
@closecatbox
@end defvr


@subsection Экспорт в TeX

В @code{itensor} имеется некоторая поддержка экспорта тензорных выражений в
формат TeX. Поскольку на базовом уровне Maxima тензорные выражения
представлены как вызов некоторых функций, то вызов команды,
@code{tex()} не даст желаемого результата. Для экспорта тензорных
выражений в TeX можно использовать команду @code{tentex}.

@deffn {Функция} tentex (@var{expr})

Команда экспорта тензорных
выражений в TeX. Перед использованием необходимо загрузить необходимый
подпакет, @code{load(tentex)}. Например:

@example

(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) load(tentex);
(%o2)       /share/tensor/tentex.lisp
(%i3) idummyx:m;
(%o3)                                  m
(%i4) ishow(icurvature([j,k,l],[i]))$
            m1       i           m1       i           i
(%t4)  ichr2    ichr2     - ichr2    ichr2     - ichr2
            j k      m1 l        j l      m1 k        j l,k

                                                      i
                                               + ichr2
                                                      j k,l
(%i5) tentex(%)$
$$\Gamma_@{j\,k@}^@{m_1@}\,\Gamma_@{l\,m_1@}^@{i@}-\Gamma_@{j\,l@}^@{m_1@}\,
 \Gamma_@{k\,m_1@}^@{i@}-\Gamma_@{j\,l,k@}^@{i@}+\Gamma_@{j\,k,l@}^@{i@}$$

@end example

Заметим, что данном примере @code{idummyx} равен @code{m}, для того
чтобы избежать символов % в TeX-овских выражениях.

ЗАМЕЧАНИЕ: Текущая версия @code{tentex} является экспериментальной.

@opencatbox
@category{Пакет itensor} @category{Вывод в формате TeX}
@closecatbox
@end deffn

@subsection Взаимодействие с пакетом @code{ctensor}

В пакет @code{itensor} заложены возможности для генерации кода Maxima
 для компонент тензорных выражений для последующего использования в
 @code{ctensor}. Эта задача выполняется вызовом команды @code{ic_convert()}.


@deffn {Функция} ic_convert (@var{eqn})

Конвертирует тензорное выражение @var{eqn} из формата @code{itensor} в
компоненты для использования в @code{ctensor}. При этом суммирование по немым
индексам выполняется в явном виде, используя соответствующие замены
индексных объектов в массивы; индексы производной заменяются
не вычисляемую форму @code{diff}; символы Кристоффеля @code{ichr1} и @code{ichr2}
заменяются на @code{lcs} и @code{mcs}, соответственно и если флаг
@code{metricconvert} равен @code{true}, тогда ковариантные
(контравариантные) выражения для метрического тензора везде
заменяется на  @code{lg} (или @code{ug}). Кроме того, для суммирования по
всем немым индексам вводится @code{do}. Полученное выражение можно
вычислить  (загрузив предварительно пакет @code{ctensor}), используя
@code{ev}.  Пример:

@example
(%i1) load(itensor);
(%o1)      /share/tensor/itensor.lisp
(%i2) eqn:ishow(t([i,j],[k])=f([],[])*g([l,m],[])*a([],[m],j)
      *b([i],[l,k]))$
                             k        m   l k
(%t2)                       t    = f a   b    g
                             i j      ,j  i    l m
(%i3) ic_convert(eqn);
(%o3) for i thru dim do (for j thru dim do (
       for k thru dim do
        t        : f sum(sum(diff(a , ct_coords ) b
         i, j, k                   m           j   i, l, k

 g    , l, 1, dim), m, 1, dim)))
  l, m
(%i4) imetric(g);
(%o4)                                done
(%i5) metricconvert:true;
(%o5)                                true
(%i6) ic_convert(eqn);
(%o6) for i thru dim do (for j thru dim do (
       for k thru dim do
        t        : f sum(sum(diff(a , ct_coords ) b
         i, j, k                   m           j   i, l, k

 lg    , l, 1, dim), m, 1, dim)))
   l, m
@end example

@opencatbox
@category{Пакет itensor} @category{Пакет ctensor}
@closecatbox
@end deffn

@subsection Зарезервированные имена переменных

Следующие имена переменных зарезервированы для использования
в пакете @code{itensor}. Следует избегать их переопределения.

@example

  Имя        Комментарий
  ------------------------------------------
  indices2() Внутренняя версия indices()
  conti      Список контравариантных индексов
  covi       Список ковариантных индексов
  deri       Список индексов производной
  name       Возвращает имя индексного объекта
  concan
  irpmon
  lc0
  _lc2kdt0
  _lcprod
  _extlc

@end example

@subsection Замечания разработчика

Я (Viktor Toth) добавил поддержку тетрадного формализма,
кручения и неметричности в @code{itensor}
в ноябре, 2004.  Эти возможности были реконструированы на основе описаний
данных в руководстве коммерческой версии Macsyma, а также с
использованием результатов исполнения демонстрационных файлов Macsyma.

Данная функциональность должна рассматриваться как
экспериментальная. Следует учесть, что доступная документация  Macsyma содержала
несколько очевидных ошибок, например, неправильные комбинации
индексов. Кроме того, результаты демонстрационных расчетов
показали, что функциональность  тетрадного формализма  в Macsyma
далеко не полна. Моей цель состоит не в том, чтобы механически воспроизвести все
возможности Macsyma, включая ошибки, а в том, чтобы в итоге получить
математически корректную поддержку данных видов вычислений в @code{itensor}.
Выполнение этой задачи займет некоторое время.

