1
/* Copyright (C) 2003 Valerij Pipin <pip@iszf.irk.ru>
3
* This program is free software; you can redistribute it and/or
4
* modify it under the terms of the GNU General Public License as
5
* published by the Free Software Foundation; either version 2 of
6
* the License, or (at your option) any later version.
8
* This program is distributed in the hope that it will be
9
* useful, but WITHOUT ANY WARRANTY; without even the implied
10
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the GNU General Public License for more details.
14
* Its purpose is to extend the maxima's itensor ability to manage the
15
exterior forms. We introduce the "&" operator for the exterior product,
16
the "|_" for the inner product of a form with a vector and "@L" for the
17
Lie derivative of the form.
19
load("tensor/itensor")$
21
declare("&",additive);
23
"&"(ANY,BODY):=block(local(I),
24
L1:first(indices(ANY)),
25
L2:first(indices(BODY)),
26
if L1=[] then return(ANY*BODY)
27
else if L2=[] then return(ANY*BODY)
28
else ( L11 : MAKELIST(DUMMY(), I,1, LENGTH(L1)),
29
L22 : MAKELIST(DUMMY(), I,1, LENGTH(L2)),
30
L1S:MAP("=",L1,L11), L2S:MAP("=",L2,L22),
31
LK1:append(L1,L2),LK2:append(L11,L22),
32
ANY:sublis(L1S,ANY), BODY:sublis(L2S,BODY),
33
evf:(if evenp(length(LK1)) then 1 else -1),
35
expand(evf*KDELTA(LK1,LK2)*ANY*BODY/(length(LK1)-1)!)))));
38
declare("@",additive);
39
"@"(forma,ind):=block(L1:first(indices(forma)),
40
if L1=[] then return(diff(forma,ind))
41
else ( L11 : MAKELIST(DUMMY(), I,1, LENGTH(L1)),
44
indd:dummy(),LK2:append(L11,[indd]),
45
forma:sublis(L1S,forma),
46
evf:(if evenp(length(LK1)) then 1 else -1),
47
contract(canform(ratexpand(
48
evf*kdelta(LK1,LK2)*diff(forma,indd)/(length(LK1)-1)!)))));
50
/* VTT: To ensure consistent application of the "first" index in |_ */
51
PERMUTATOR(L):=BLOCK([RESULT:1,TEMP],
52
FOR I THRU LENGTH(L)-1 DO IF ORDERLESSP(L[I+1],L[I]) THEN
53
(TEMP:L[I+1],L[I+1]:L[I],L[I]:TEMP,I:0,RESULT:-RESULT),
58
declare("|_",additive);
59
/* VTT: ADDITIVE doesn't always do the trick so we break up sums manually */
60
"|_"(forma,vec):=BLOCK(LOCAL(ind,perm),
61
IF NOT(ATOM(forma)) AND (OP(forma)="+" OR OP(forma)="=") THEN
62
APPLY(OP(forma),[PART(forma,1)|_vec,REST(forma)|_vec])
63
ELSE (perm:PERMUTATOR(first(indices(forma))),
65
ELSE perm[1]*(CONTRACT(CANFORM(EXPAND(forma*vec([],[FIRST(perm[2])])))))));
69
declare("@L",additive);
71
"@L"(forma,L1):=block(local(temp1,temp2,ind1),
72
vec:first(L1),ind1:second(L1),
73
if ind1=0 then (ind1:dummy(),V([],[ind1])*diff(forma,ind1))
75
/* VTT: some black magic needed because MAXIMA doesn't handle ADDITIVE as expected */
76
temp1:rename(forma@ind1),
77
temp1:ev(temp1|_vec,noeval),
80
temp2:ev(temp2|_vec,noeval),
81
temp2:ev(temp2,eval)@ind1,