~ubuntu-branches/debian/squeeze/maxima/squeeze

« back to all changes in this revision

Viewing changes to share/tensor/itensor.lisp

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2006-10-18 14:52:42 UTC
  • mto: (1.1.5 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20061018145242-vzyrm5hmxr8kiosf
ImportĀ upstreamĀ versionĀ 5.10.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
;;; -*- Mode:LISP; Package:MACSYMA -*-
2
 
;; (based on itensor.116 ,117)
3
 
(in-package "MAXIMA")
 
2
;;      ** (c) Copyright 1981 Massachusetts Institute of Technology **
 
3
;; 
 
4
;; This program is free software; you can redistribute it and/or
 
5
;; modify it under the terms of the GNU General Public License as
 
6
;; published by the Free Software Foundation; either version 2 of
 
7
;; the License, or (at your option) any later version.
 
8
;;
 
9
;; This program is distributed in the hope that it will be
 
10
;; useful, but WITHOUT ANY WARRANTY; without even the implied
 
11
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
12
;; PURPOSE.  See the GNU General Public License for more details.
 
13
;;
 
14
;; Comments:
 
15
;;
 
16
;; The Itensor package was downcased, cleaned up, and moving frames
 
17
;; functionality was added by Viktor Toth (http://www.vttoth.com/).
 
18
;;
 
19
;; As of November, 2004, the naming conventions in this package now
 
20
;; correspond with the naming conventions in commercial MACSYMA.
 
21
;;
 
22
 
 
23
(in-package :maxima)
4
24
 
5
25
(macsyma-module itensor) ;; added 9/24/82 at UCB
6
 
;       ** (c) Copyright 1981 Massachusetts Institute of Technology **
7
 
 
8
 
;    Various functions in Itensr have been parceled out to separate files. A
 
26
 
 
27
(cond (($get '$itensor '$version) (merror "ITENSOR already loaded"))
 
28
      (t ($put '$itensor '$v20041126 '$version))
 
29
)
 
30
 
 
31
;    Various functions in Itensor have been parceled out to separate files. A
9
32
;    function in one of these files will only be loaded in (automatically) if
10
 
;    explicitly used in the Macsyma. (It is necessary to have first loaded in
11
 
;    ITENSR FASL for this autoloading to take place.) The current status of
 
33
;    explicitly used in the Maxima. (It is necessary to have first loaded in
 
34
;    ITENSOR FASL for this autoloading to take place.) The current status of
12
35
;    these separate files are:
13
36
 
14
37
;    Filename          Macsyma Functions
15
38
;    --------          -----------------
16
39
;    CANTEN FASL       CANTEN, CONCAN, IRPMON
17
 
;    GENER FASL        GENERATE, MAKEBOX, AVERAGE, CONMETDERIV, FLUSH1DERIV,
18
 
;                      GEODESIC
 
40
;    GENER FASL        IC_CONVERT, MAKEBOX, AVERAGE, CONMETDERIV, FLUSH1DERIV,
 
41
;                      IGEODESIC_COORDS
19
42
;    SYMTRY FASL       CANFORM, DECSYM, DISPSYM, REMSYM
20
43
 
21
44
#+maclisp(progn
22
 
(putprop '$GENERATE '((dsk tensor) gener fasl) 'autoload)
23
 
(putprop '$DECSYM '((dsk tensor) symtry fasl) 'autoload)
24
 
(putprop '$CANFORM '((dsk tensor) symtry fasl) 'autoload)
25
 
(putprop '$CANTEN '((dsk tensor) canten fasl) 'autoload)
26
 
(putprop '$MAKEBOX '((dsk tensor) gener fasl) 'autoload)
27
 
(putprop '$GEODESIC '((dsk tensor) gener fasl) 'autoload)
28
 
(putprop '$CONMETDERIV '((dsk tensor) gener fasl) 'autoload))
 
45
(putprop '$ic_convert '((dsk tensor) gener fasl) 'autoload)
 
46
(putprop '$decsym '((dsk tensor) symtry fasl) 'autoload)
 
47
(putprop '$canform '((dsk tensor) symtry fasl) 'autoload)
 
48
(putprop '$canten '((dsk tensor) canten fasl) 'autoload)
 
49
(putprop '$makebox '((dsk tensor) gener fasl) 'autoload)
 
50
(putprop '$igeodesic_coords '((dsk tensor) gener fasl) 'autoload)
 
51
(putprop '$conmetderiv '((dsk tensor) gener fasl) 'autoload))
29
52
#+Franz (progn
30
 
(putprop '$GENERATE (concat vaxima-main-dir '|//tensor//gener|) 'autoload)
31
 
(putprop '$DECSYM (concat vaxima-main-dir  '|//tensor//symtry| )'autoload)
32
 
(putprop '$CANFORM (concat vaxima-main-dir  '|//tensor//symtry| )'autoload)
33
 
(putprop '$CANTEN (concat vaxima-main-dir  '|//tensor//canten| )'autoload)
34
 
(putprop '$MAKEBOX (concat vaxima-main-dir  '|//tensor//gener| )'autoload)
35
 
(putprop '$GEODESIC  (concat vaxima-main-dir '|//tensor//gener| )'autoload)
36
 
(putprop '$CONMETDERIV  (concat vaxima-main-dir '|//tensor//gener| )'autoload))
 
53
(putprop '$ic_convert (concat vaxima-main-dir '|//tensor//gener|) 'autoload)
 
54
(putprop '$decsym (concat vaxima-main-dir  '|//tensor//symtry| )'autoload)
 
55
(putprop '$canform (concat vaxima-main-dir  '|//tensor//symtry| )'autoload)
 
56
(putprop '$canten (concat vaxima-main-dir  '|//tensor//canten| )'autoload)
 
57
(putprop '$makebox (concat vaxima-main-dir  '|//tensor//gener| )'autoload)
 
58
(putprop '$igeodesic_coords (concat vaxima-main-dir '|//tensor//gener| )'autoload)
 
59
(putprop '$conmetderiv (concat vaxima-main-dir '|//tensor//gener| )'autoload))
37
60
 
38
61
#+cl
39
62
(progn
40
 
(autof '$GENERATE '|gener|)
41
 
(autof '$DECSYM '|symtry|)
42
 
(autof '$CANFORM '|symtry|)
43
 
(autof '$CANTEN '|canten|)
44
 
(autof '$MAKEBOX '|gener|)
45
 
(autof '$GEODESIC '|gener|)
46
 
(autof '$CONMETDERIV '|gener|)
47
 
(autof '$NAME '|canten|)
48
 
(autof '$CONTI '|canten|)
49
 
(autof '$COVI '|canten|)
50
 
(autof '$DERI '|canten|)
 
63
(autof '$ic_convert '|gener|)
 
64
(autof '$decsym '|symtry|)
 
65
(autof '$canform '|symtry|)
 
66
(autof '$canten '|canten|)
 
67
(autof '$makebox '|gener|)
 
68
(autof '$igeodesic_coords '|gener|)
 
69
(autof '$conmetderiv '|gener|)
 
70
(autof '$name '|canten|)
51
71
)
 
72
 
52
73
#+cl
53
74
(eval-when (eval compile)
54
 
           (defmacro fixp (x) `(typep ,x 'fixnum)))
55
 
 
56
 
 
57
 
 
58
 
#+maclisp ($UUO)                                ;Restore calls to SDIFF so it can be redefined  
59
 
 
60
 
(DECLARE-TOP (SPECIAL SMLIST $DUMMYX $COORDINATES $METRIC $COUNTER $DIM
61
 
                  $CONTRACTIONS $COORD $ALLSYM $METRICCONVERT)
62
 
         (*LEXPR $RENAME $DIFF $COORD $REMCOORD $LORENTZ))
63
 
 
64
 
(SETQ $DUMMYX '$%                    ;Prefix for dummy indices
65
 
      $COUNTER 0.                    ;Dummy variable numeric indexs
66
 
      SMLIST '(MLIST SIMP)           ;Simplified MLIST header
67
 
      $COORDINATES NIL               ;Used when differentiating w.r.t. a number
68
 
      $COORD '((MLIST SIMP))         ;Objects treated liked coordinates in DIFF
69
 
      $ALLSYM T                      ;If T then all indexed objects symmetric
70
 
      $METRICCONVERT T)              ;Flag used by $GENERATE
71
 
 
72
 
;(DEFUN IFNOT MACRO (CLAUSE) (CONS 'OR (CDR CLAUSE)))
73
 
(DEFmacro IFNOT  (&rest CLAUSE) `(or ,@ clause))
74
 
 
75
 
;(DEFUN M+OR*OR^P MACRO (CL)
76
 
(defmacro M+OR*OR^P (&whole cl &rest ign) ign
77
 
       (SUBST (CADR CL)
78
 
              'X
79
 
              '(MEMQ (CAAR X) '(MTIMES MPLUS MEXPT))))
80
 
 
81
 
(DEFMFUN $DUMMY nil                              ;Sets arguments to dummy indices
82
 
       (progn (setq $COUNTER (1+ $COUNTER))
83
 
              (concat $DUMMYX $COUNTER)))
84
 
 
85
 
(DEFPROP $KDELTA ((/  . / )) CONTRACTIONS)
 
75
  (defmacro fixp (x) `(typep ,x 'fixnum))
 
76
)
 
77
 
 
78
#+maclisp ($UUO)                   ;Restore calls to SDIFF so it can be redefined       
 
79
 
 
80
(declare-top
 
81
  (special smlist $idummyx $vect_coords $imetric $icounter $dim
 
82
           $contractions $coord $allsym $metricconvert $iframe_flag
 
83
           $itorsion_flag $inonmet_flag)
 
84
  (*lexpr $rename $diff $idiff $coord $remcoord $lorentz_gauge)
 
85
)
 
86
 
 
87
(setq $idummyx '$%                   ;Prefix for dummy indices
 
88
      $icounter 0.                   ;Dummy variable numeric index
 
89
      smlist '(mlist simp)           ;Simplified mlist header
 
90
      $vect_coords nil               ;Used when differentiating w.r.t. a number
 
91
      $coord '((mlist simp))         ;Objects treated liked coordinates in diff
 
92
      $allsym nil                    ;If T then all indexed objects symmetric
 
93
      $metricconvert t               ;Flag used by $ic_convert
 
94
      $iframe_flag nil
 
95
      $itorsion_flag nil
 
96
)
 
97
 
 
98
;(defun ifnot macro (clause) (cons 'or (cdr clause)))
 
99
(defmacro ifnot  (&rest clause) `(or ,@ clause))
 
100
 
 
101
;(defun m+or*or^p macro (cl)
 
102
(defmacro m+or*or^p (&whole cl &rest ign) ign
 
103
       (subst (cadr cl)
 
104
              'x
 
105
              '(memq (caar x) '(mtimes mplus mexpt))))
 
106
 
 
107
(defmfun $idummy nil                              ;Sets arguments to dummy indices
 
108
       (progn (setq $icounter (1+ $icounter))
 
109
              (concat $idummyx $icounter)))
 
110
 
 
111
(defprop $kdelta ((/  . / )) contractions)
 
112
 
 
113
(defun isprod (x) (or (equal x '(mtimes)) (equal x '(mtimes simp))
 
114
                      (equal x '(mtimes simp ratsimp)))
 
115
)
 
116
 
 
117
;; Remove occurrences of ratsimp from elements of x
 
118
(defun derat (x)
 
119
  (cond
 
120
    ((null x) nil)
 
121
    ((atom x) x)
 
122
    ((eq (car x) 'ratsimp) (derat (cdr x)))
 
123
    (t (cons (derat (car x)) (derat (cdr x))))
 
124
  )
 
125
)
 
126
 
 
127
(defun plusi(l)
 
128
  (cond
 
129
    ((null l) l)
 
130
    ((and (numberp (car l)) (< (car l) 0)) (plusi (cdr l)))
 
131
    ((atom (car l))  (cons (car l) (plusi (cdr l))))
 
132
    ((and (isprod (caar l)) (eq (cadar l) -1)) (plusi (cdr l)))
 
133
    (t (cons (car l) (plusi (cdr l))))
 
134
  )
 
135
)
 
136
 
 
137
(defun minusi(l)
 
138
  (cond
 
139
    ((null l) l)
 
140
    ((and (numberp (car l)) (< (car l) 0)) (cons (neg (car l)) (plusi (cdr l))))
 
141
    ((atom (car l))  (minusi (cdr l)))
 
142
    (
 
143
      (and (isprod (caar l)) (eq (cadar l) -1)) 
 
144
      (cons (caddar l) (minusi (cdr l)))
 
145
    )
 
146
    (t (minusi (cdr l)))
 
147
  )
 
148
)
 
149
 
 
150
 
 
151
(defun covi (rp) (plusi (cdadr rp)))
 
152
(defun conti (rp) (append (minusi (cdadr rp)) (cdaddr rp)))
 
153
(defun deri (rp) (cdddr rp))
 
154
(defun name (rp) (caar rp))
 
155
(defmfun $covi (rp) (cond ((rpobj rp) (cons smlist (covi rp)))
 
156
                          (t (merror "Not an RPOBJ"))
 
157
                    )
 
158
)
 
159
(defmfun $conti (rp) (cond ((rpobj rp) (cons smlist (conti rp)))
 
160
                                       (t (merror "Not an RPOBJ"))
 
161
                     )
 
162
)
 
163
(defmfun $deri (rp) (cond ((rpobj rp) (cons smlist (deri rp)))
 
164
                                      (t (merror "Not an RPOBJ"))
 
165
                    )
 
166
)
 
167
(defmfun $name (rp) (cond ((rpobj rp) (caar rp)) (t (merror "Not an RPOBJ"))))
86
168
 
87
169
;KDELTA has special contraction property because it contracts with any indexed
88
170
;object.
89
171
 
90
 
(meval '(($DECLARE) %KDELTA $CONSTANT))                        ;So derivative will be zero
 
172
(meval '(($declare) %kdelta $constant))          ;So derivative will be zero
 
173
(meval '(($declare) $kdelta $constant))          ;So derivative will be zero
 
174
(meval '(($declare) %levi_civita $constant))
 
175
(meval '(($declare) $levi_civita $constant))
91
176
 
92
 
(SETQ $DIM 4. $CONTRACTIONS '((MLIST SIMP))) 
 
177
(setq $dim 4. $contractions '((mlist simp))) 
93
178
 
94
 
(DEFMFUN $DEFCON N            ;Defines contractions: A contracts with B to form C
95
 
       ((LAMBDA (A)
96
 
         (ADD2LNC A $CONTRACTIONS)
97
 
         (PUTPROP
98
 
          A
99
 
          (CONS (COND ((= N 1.) '(/  . / ))
100
 
                      ((= N 3.) (CONS (ARG 2.) (ARG 3.)))
101
 
                      (T (merror "DEFCON takes 1 or 3 arguments")))
102
 
                (ZL-GET A 'CONTRACTIONS))
103
 
          'CONTRACTIONS)
104
 
         '$DONE)
105
 
        (ARG 1.))) 
 
179
(defmfun $defcon n            ;Defines contractions: A contracts with B to form C
 
180
       ((lambda (a)
 
181
         (add2lnc a $contractions)
 
182
         (putprop
 
183
          a
 
184
          (cons (cond ((= n 1.) '(/  . / ))
 
185
                      ((= n 3.) (cons (arg 2.) (arg 3.)))
 
186
                      (t (merror "DEFCON takes 1 or 3 arguments")))
 
187
                (zl-get a 'contractions))
 
188
          'contractions)
 
189
         '$done)
 
190
        (arg 1.))) 
106
191
 
107
 
(DEFMSPEC $DISPCON (A) (SETQ A (CDR A))
 
192
(defmspec $dispcon (a) (setq a (cdr a))
108
193
  ;;Displays contraction definitions
109
 
       ((LAMBDA (TMP) 
110
 
         (AND (EQ (CAR A) '$ALL) (SETQ A (CDR $CONTRACTIONS)))
111
 
         (CONS
112
 
          SMLIST
113
 
          (MAPCAR 
114
 
           #'(LAMBDA (E) 
115
 
             (COND ((SETQ TMP (ZL-GET E 'CONTRACTIONS))
116
 
                    (CONS SMLIST
117
 
                          (MAPCAR #'(LAMBDA (Z) 
118
 
                                           (COND ((EQ (CAR Z)
 
194
       ((lambda (tmp) 
 
195
         (and (eq (car a) '$all) (setq a (cdr $contractions)))
 
196
         (cons
 
197
          smlist
 
198
          (mapcar 
 
199
           #'(lambda (e) 
 
200
             (cond ((setq tmp (zl-get e 'contractions))
 
201
                    (cons smlist
 
202
                          (mapcar #'(lambda (z) 
 
203
                                           (cond ((eq (car z)
119
204
                                                      '/ )
120
 
                                                  (LIST SMLIST E))
121
 
                                                 (T (LIST SMLIST
122
 
                                                          E
123
 
                                                          (CAR Z)
124
 
                                                          (CDR Z)))))
125
 
                                  TMP)))
126
 
                   (T '((MLIST SIMP)))))
127
 
           A)))
128
 
        NIL)) 
 
205
                                                  (list smlist e))
 
206
                                                 (t (list smlist
 
207
                                                          e
 
208
                                                          (car z)
 
209
                                                          (cdr z)))))
 
210
                                  tmp)))
 
211
                   (t '((mlist simp)))))
 
212
           a)))
 
213
        nil)) 
129
214
 
130
 
(DEFMSPEC $REMCON (A) (SETQ A (CDR A))
 
215
(defmspec $remcon (a) (setq a (cdr a))
131
216
  ;;Removes contraction definitions
132
 
       (AND (EQ (CAR A) '$ALL) (SETQ A (CDR $CONTRACTIONS)))
133
 
       (CONS SMLIST (MAPC (FUNCTION (LAMBDA (E) (ZL-REMPROP E 'CONTRACTIONS)
134
 
                                            (DELQ E $CONTRACTIONS)))
135
 
                          A)))
 
217
       (and (eq (car a) '$all) (setq a (cdr $contractions)))
 
218
       (cons smlist (mapc (function (lambda (e) (zl-remprop e 'contractions)
 
219
                                            (delq e $contractions)))
 
220
                          a)))
136
221
 
137
 
(DEFUN GETCON (E)
 
222
(defun getcon (e)
138
223
  ;; Helper to obtain contractions on both the noun and verb form of E
139
 
        (COND ((AND (SYMBOLP E) (EQ (GETCHAR E 1) '%))  (ZL-GET ($VERBIFY E) 'CONTRACTIONS))
140
 
                (T (ZL-GET E 'CONTRACTIONS))
 
224
        (cond ((and (symbolp e) (eq (getchar e 1) '%))  (zl-get ($verbify e) 'contractions))
 
225
                (t (zl-get e 'contractions))
141
226
        )
142
227
)
143
228
 
144
 
(DEFUN RPOBJ (E)                  ;"True" if an indexed object and not a matrix
145
 
       (COND ((AND (NOT (ATOM E)) (EQ (CAAR E) 'MQAPPLY)) (RPOBJ (CDR E)))
146
 
             (T 
147
 
       (AND (NOT (ATOM E))
148
 
            (NOT (EQ (CAAR E) '$MATRIX))
149
 
            ($LISTP (CADR E))
150
 
            (COND ((CDDR E) ($LISTP (CADDR E)))
151
 
                  (T (NCONC E '(((MLIST SIMP))))))))))
 
229
(defun rpobj (e)                  ;"True" if an indexed object and not a matrix
 
230
       (cond ((and (not (atom e)) (eq (caar e) 'mqapply)) (rpobj (cdr e)))
 
231
             (t 
 
232
       (and (not (atom e))
 
233
            (not (eq (caar e) '$matrix))
 
234
            ($listp (cadr e))
 
235
            (cond ((cddr e) ($listp (caddr e)))
 
236
                  (t (nconc e '(((mlist simp))))  t  ))))))
152
237
                                          ;Transforms F([...]) into F([...],[])
153
238
 
154
239
;RPOBJ is the predicate for indexed objects. In the case of no contravariant
156
241
 
157
242
(deff $tenpr #'rpobj)
158
243
 
159
 
(DEFMFUN $METRIC (V) (SETQ $METRIC V) ($DEFCON V) ($DEFCON V V '$KDELTA))
160
 
 
161
 
(DEFUN MYSUBST0 (NEW OLD)                  ;To reuse subparts of old expression
162
 
       (COND ((ALIKE1 NEW OLD) OLD) (T NEW))) 
163
 
 
164
 
(DEFUN COV (A B)                            ;COV gives covariant form of metric
165
 
       (COND ((BOUNDP '$METRIC)
166
 
              (MEVAL (LIST (NCONS $METRIC)
167
 
                           (LIST SMLIST A B)
168
 
                           '((MLIST SIMP)))))
169
 
             (T (merror "Name of metric must be specified"))))
170
 
 
171
 
(DEFUN CONTR (A B)                      ;CONTR gives contraviant form of metric
172
 
       (COND ((BOUNDP '$METRIC)
173
 
              (MEVAL (LIST (NCONS $METRIC)
174
 
                           '((MLIST SIMP))
175
 
                           (LIST SMLIST A B))))
176
 
             (T (merror "Name of metric must be specified"))))
177
 
 
178
 
(DEFUN DIFFCOV (A B D)
179
 
        (COND ((BOUNDP '$METRIC)
180
 
                (MEVAL (LIST (NCONS $METRIC)
181
 
                           (LIST SMLIST A B)
182
 
                           '((MLIST SIMP))
183
 
                                D
 
244
(defmfun $imetric (v) (setq $imetric v) ($defcon v) ($defcon v v '$kdelta))
 
245
 
 
246
(defun mysubst0 (new old)                  ;To reuse subparts of old expression
 
247
       (cond ((alike1 new old) old) (t new))) 
 
248
 
 
249
(defun cov (a b)                            ;COV gives covariant form of metric
 
250
       (cond ((boundp '$imetric)
 
251
              (meval (list (ncons $imetric)
 
252
                           (list smlist a b)
 
253
                           '((mlist simp)))))
 
254
             (t (merror "Name of metric must be specified"))))
 
255
 
 
256
(defun contr (a b)                      ;contr gives contraviant form of metric
 
257
       (cond ((boundp '$imetric)
 
258
              (meval (list (ncons $imetric)
 
259
                           '((mlist simp))
 
260
                           (list smlist a b))))
 
261
             (t (merror "Name of metric must be specified"))))
 
262
 
 
263
(defun diffcov (a b d)
 
264
        (cond ((boundp '$imetric)
 
265
                (meval (list (ncons $imetric)
 
266
                           (list smlist a b)
 
267
                           '((mlist simp))
 
268
                                d
184
269
                        )
185
270
 
186
271
                ))
187
 
                (T (merror "Name of metric must be specified"))))
188
 
 
189
 
;(DEFMFUN $CHR1 (L1)                             ;Christoffel symbol of first kind
190
 
;       (PROG (A B C)
191
 
;            (SETQ A (CADDDR L1) B (CADR L1) C (CADDR L1))
192
 
;            (RETURN (LIST '(MTIMES)
193
 
;                          '((RAT SIMP) 1. 2.)
194
 
;                          (LIST '(MPLUS)
195
 
;                                (SDIFF (COV B A) C)
196
 
;                                (SDIFF (COV C A) B)
197
 
;                                (LIST '(MTIMES)
198
 
;                                      -1.
199
 
;                                      (SDIFF (COV B C) A)))))))
200
 
(DEFMFUN $CHR1 NARGS
201
 
        (PROG (A B C)
202
 
                (COND 
203
 
;                       ((> NARGS 2) (RETURN (MEVAL (CONS '$COVDIFF (CONS ($CHR1 (ARG 1) (ARG 2)) (CDDR (LISTIFY NARGS)))))))
204
 
                        ((> NARGS 2) (RETURN (MEVAL (CONS '$DIFF (CONS ($CHR1 (ARG 1) (ARG 2)) (APPLY #'APPEND (MAPCAR #'(LAMBDA (E) (LIST E 1)) (CDDR (LISTIFY NARGS)))))))))
205
 
                        ((> NARGS 1) (AND (EQ 1 (LENGTH (ARG 2))) (RETURN ($CHR1 (ARG 1))))
206
 
                                        (merror "CHR1 cannot have contravariant indices"))
207
 
;;                              (COND
208
 
;;                                      ((NULL (ARG 2)) (merror "CHR1 has no contravariant indices"))
209
 
;;                                      (T (RETURN ($CHR1 (ARG 1))))
210
 
;;                              )
211
 
;;                      )
212
 
                        (T
213
 
                                (SETQ A (CADDDR (ARG 1)) B (CADR (ARG 1)) C (CADDR (ARG 1)))
214
 
                                (RETURN (LIST '(MTIMES)
215
 
                                        '((RAT SIMP) 1. 2.)
216
 
                                        (LIST '(MPLUS)
217
 
;;                                              (SDIFF (COV B A) C)
218
 
;;                                              (SDIFF (COV C A) B)
219
 
                                                (DIFFCOV B A C)
220
 
                                                (DIFFCOV C A B)
221
 
                                                (LIST '(MTIMES) -1.
222
 
;;                                                      (SDIFF (COV B C) A))))))
223
 
                                                        (DIFFCOV B C A))))))
224
 
                )
225
 
        )
226
 
)
227
 
 
228
 
;(DEFMFUN $CHR2 (L1 L2)                         ;Christoffel symbol of second kind
229
 
;       (PROG (A B C D) 
230
 
;            (SETQ A (CADR L1) B (CADDR L1) C (CADR L2))
231
 
;            (return (do ((flag) (l (append (cdr l1) (cdr l2))))
232
 
;                        (flag (LIST '(MTIMES)
233
 
;                                    (CONTR C D)
234
 
;                                    ($CHR1 (LIST SMLIST A B D))))
235
 
;                        (setq d ($dummy))
236
 
;                        (and (not (memq d l)) (setq flag t))))))
237
 
(DEFMFUN $CHR2 NARGS
238
 
        (PROG (A B C D) 
239
 
                (COND
240
 
                        ((> NARGS 2) (RETURN (MEVAL (CONS '$DIFF (CONS ($CHR2 (ARG 1) (ARG 2)) (APPLY #'APPEND (MAPCAR #'(LAMBDA (E) (LIST E 1)) (CDDR (LISTIFY NARGS)))))))))
241
 
                        (T
242
 
                                (SETQ A (CADR (ARG 1)) B (CADDR (ARG 1)) C (CADR (ARG 2)))
243
 
                                (return (do ((flag) (l (append (cdr (ARG 1)) (cdr (ARG 2)))))
244
 
                                        (flag (LIST '(MTIMES)
245
 
                                                (CONTR C D)
246
 
                                                ($CHR1 (LIST SMLIST A B D))))
247
 
                                (setq d ($dummy))
248
 
                                (and (not (memq d l)) (setq flag t))))))
249
 
        )
250
 
)
251
 
 
252
 
(DEFMFUN $curvature (L1 L2) 
253
 
       (PROG (I J K H R) 
254
 
             (setq r ($dummy))
255
 
             (SETQ I (CADR L1) K (CADDR L1) H (CADDDR L1) J (CADR L2))
256
 
             (RETURN (LIST '(MPLUS)
257
 
                           (SDIFF (LIST '($CHR2 SIMP)
258
 
                                        (LIST SMLIST I K)
259
 
                                        L2)
260
 
                                  H)
261
 
                           (LIST '(MTIMES)
262
 
                                 -1.
263
 
                                 (SDIFF (LIST '($CHR2 SIMP)
264
 
                                              (LIST SMLIST I H)
265
 
                                              (LIST SMLIST J))
266
 
                                        K))
267
 
                           (LIST '(MTIMES)
268
 
                                 (LIST '($CHR2 SIMP)
269
 
                                       (LIST SMLIST I K)
270
 
                                       (LIST SMLIST R))
271
 
                                 (LIST '($CHR2 SIMP)
272
 
                                       (LIST SMLIST R H)
273
 
                                       L2))
274
 
                           (LIST '(MTIMES)
275
 
                                 -1.
276
 
                                 (LIST '($CHR2 SIMP)
277
 
                                       (LIST SMLIST I H)
278
 
                                       (LIST SMLIST R))
279
 
                                 (LIST '($CHR2 SIMP)
280
 
                                       (LIST SMLIST R K)
281
 
                                       L2)))))) 
282
 
 
283
 
(DEFUN COVSUBST (X Y RP)       ;Substitutes X for Y in the covariant part of RP
284
 
       (CONS (CAR RP) (CONS (SUBST X Y (CADR RP)) (CDDR RP)))) 
285
 
 
286
 
(DEFUN CONSUBST (X Y RP)   ;Substitutes X for Y in the contravariant part of RP
287
 
       (CONS (CAR RP)
288
 
             (CONS (CADR RP)
289
 
                   (CONS (SUBST X Y (CADDR RP)) (CDDDR RP))))) 
290
 
 
291
 
(DEFUN DERSUBST (X Y RP)   ;Substitutes X for Y in the derivative indices of RP
292
 
       (NCONC (LIST (CAR RP) (CADR RP) (CADDR RP))
293
 
              (SUBST X Y (CDDDR RP)))) 
294
 
 
295
 
(DECLARE-TOP (SPECIAL X TEMP D)) 
296
 
 
297
 
(DEFMFUN $COVDIFF NARGS
298
 
       (PROG (X E TEMP D I)
299
 
             (AND (< NARGS 2) (merror "COVDIFF must have at least 2 args"))
300
 
             (SETQ I 2 E (ARG 1))
301
 
       AGAIN (SETQ X (ARG I) E (COVDIFF E) I (1+ I))
302
 
             (AND (> I NARGS) (RETURN E))
303
 
             (GO AGAIN)))
304
 
 
305
 
(DEFUN COVDIFF (E) 
306
 
       (setq d ($dummy)) 
307
 
       (COND
308
 
        ((OR (ATOM E) (EQ (CAAR E) 'RAT)) (SDIFF E X))
309
 
        ((RPOBJ E)
310
 
         (SETQ TEMP (MAPCAR #'(LAMBDA (V) (LIST '(MTIMES)
311
 
                                               (LIST '($CHR2 SIMP)
312
 
                                                     (LIST SMLIST D X)
313
 
                                                     (LIST SMLIST V))
314
 
                                               (CONSUBST D V E)))
315
 
                            (CDADDR E)))  
316
 
         (SIMPLUS
317
 
          (CONS
318
 
           '(MPLUS)
319
 
           (CONS
320
 
            (SDIFF E X)
321
 
            (COND
322
 
             ((OR (CDADR E) (CDDDR E))
323
 
              (CONS
324
 
               (LIST
325
 
                '(MTIMES)
326
 
                -1.
327
 
                (CONS '(MPLUS)
328
 
                      (NCONC (MAPCAR #'(LAMBDA (V) 
329
 
                                              (LIST '(MTIMES)
330
 
                                                    (LIST '($CHR2 SIMP)
331
 
                                                          (LIST SMLIST
332
 
                                                                V
333
 
                                                                X)
334
 
                                                          (LIST SMLIST
335
 
                                                                D))
336
 
                                                    (COVSUBST D V E)))
337
 
                                     (CDADR E))
338
 
                             (MAPCAR #'(LAMBDA (V) 
339
 
                                              (LIST '(MTIMES)
340
 
                                                    (LIST '($CHR2 SIMP)
341
 
                                                          (LIST SMLIST
342
 
                                                                V
343
 
                                                                X)
344
 
                                                          (LIST SMLIST
345
 
                                                                D))
346
 
                                                    (DERSUBST D V E)))
347
 
                                     (CDDDR E)))))
348
 
               TEMP))
349
 
             (T TEMP))))
350
 
          1.
351
 
          T))
352
 
        ((EQ (CAAR E) 'MTIMES) (SIMPLUS (COVDIFFTIMES (CDR E) X) 1 T))
353
 
        ((EQ (CAAR E) 'MPLUS)
354
 
         (SIMPLIFYA (CONS '(MPLUS)
355
 
                          (MAPCAR 'COVDIFF (CDR E)))
356
 
                    NIL))
357
 
        ((EQ (CAAR E) 'MEXPT)
358
 
         (SIMPTIMES (LIST '(MTIMES)
359
 
                          (CADDR E)
360
 
                          (LIST '(MEXPT)
361
 
                                (CADR E)
362
 
                                (LIST '(MPLUS) -1. (CADDR E)))
363
 
                          ($COVDIFF (CADR E) X))
364
 
                    1.
365
 
                    NIL))
366
 
        ((EQ (CAAR E) 'MEQUAL)
367
 
         (LIST (CAR E) (COVDIFF (CADR E)) (COVDIFF (CADDR E))))
368
 
        (T 
369
 
           (MERROR "Not acceptable to COVDIFF: ~M"
370
 
                   (ISHOW E)))))
371
 
 
372
 
(DEFUN COVDIFFTIMES (L X) 
373
 
       (PROG (SP LEFT OUT) 
374
 
             (SETQ OUT (NCONS '(MPLUS)))
375
 
        LOOP (SETQ SP (CAR L) L (CDR L))
376
 
             (NCONC OUT
377
 
                    (LIST (SIMPTIMES (CONS '(MTIMES)
378
 
                                           (CONS ($COVDIFF SP X)
379
 
                                                 (APPEND LEFT L)))
380
 
                                     1.
381
 
                                     T)))
382
 
             (COND ((NULL L) (RETURN OUT)))
383
 
             (SETQ LEFT (NCONC LEFT (NCONS SP)))
384
 
             (GO LOOP))) 
385
 
 
386
 
(DECLARE-TOP (UNSPECIAL R TEMP D)) 
387
 
 
388
 
(DEFMFUN $LORENTZ n
389
 
       (cond ((equal n 0) (merror "LORENTZ requires at least one argument"))
 
272
                (t (merror "Name of metric must be specified"))))
 
273
 
 
274
(defmfun $ichr1 nargs                   ; Christoffel-symbol of the first kind
 
275
  (prog (a b c)
 
276
    (cond 
 
277
      (
 
278
        (> nargs 2) ; Derivative indices present; use idiff() to resolve
 
279
        (return
 
280
          (meval
 
281
            (cons
 
282
              '$idiff
 
283
              (cons
 
284
                ($ichr1 (arg 1) (arg 2))
 
285
                (apply
 
286
                  #'append
 
287
                  (mapcar #'(lambda (e) (list e 1)) (cddr (listify nargs)))
 
288
                )
 
289
              )
 
290
            )
 
291
          )
 
292
        )
 
293
      )
 
294
      (
 
295
        (> nargs 1)
 
296
        (and (eq 1 (length (arg 2))) (return ($ichr1 (arg 1))))
 
297
        (merror "ichr1 cannot have contravariant indices")
 
298
      )
 
299
      (t            ; G_abc = 1/2*(g_ba,c+g_ca,b-g_bc,a)
 
300
        (setq a (cadddr (arg 1)) b (cadr (arg 1)) c (caddr (arg 1)))
 
301
        (return
 
302
          (list
 
303
            '(mtimes)
 
304
            '((rat simp) 1. 2.)
 
305
            (list
 
306
              '(mplus)
 
307
              (diffcov b a c)
 
308
              (diffcov c a b)
 
309
              (list '(mtimes) -1. (diffcov b c a))
 
310
            )
 
311
          )
 
312
        )
 
313
      )
 
314
    )
 
315
  )
 
316
)
 
317
 
 
318
(defmfun $ichr2 nargs                   ; Christoffel-symbol of the second kind
 
319
  (prog (a b c d) 
 
320
    (cond
 
321
      (
 
322
        (> nargs 2) ; Derivative indices present; use idiff() to resolve
 
323
        (return
 
324
          (meval
 
325
            (cons
 
326
              '$idiff
 
327
              (cons
 
328
                ($ichr2 (arg 1) (arg 2))
 
329
                (apply
 
330
                  #'append
 
331
                  (mapcar #'(lambda (e) (list e 1)) (cddr (listify nargs)))
 
332
                )
 
333
              )
 
334
            )
 
335
          )
 
336
        )
 
337
      )
 
338
      (t            ; G_ab^c=g^cd*G_abd
 
339
        (setq a (cadr (arg 1)) b (caddr (arg 1)) c (cadr (arg 2)))
 
340
        (return
 
341
          (do
 
342
            ((flag) (l (append (cdr (arg 1)) (cdr (arg 2)))))
 
343
            (flag
 
344
              (list '(mtimes) (contr c d) ($ichr1 (list smlist a b d)))
 
345
            )
 
346
            (setq d ($idummy))
 
347
            (and (not (memq d l)) (setq flag t))
 
348
          )
 
349
        )
 
350
      )
 
351
    )
 
352
  )
 
353
)
 
354
 
 
355
(defmfun $icurvature (l1 l2) 
 
356
  (prog (i j k h r) 
 
357
    (setq r ($idummy) i (cadr l1) k (caddr l1) h (cadddr l1) j (cadr l2))
 
358
    (return
 
359
      (list
 
360
        '(mplus)
 
361
        (idiff (list (diffop) (list smlist i k) l2) h)
 
362
        (list
 
363
          '(mtimes) -1.
 
364
          (idiff (list (diffop) (list smlist i h) (list smlist j)) k)
 
365
        )
 
366
        (list
 
367
          '(mtimes)
 
368
          (list (diffop) (list smlist i k) (list smlist r))
 
369
          (list (diffop) (list smlist r h) l2)
 
370
        )
 
371
        (list
 
372
          '(mtimes)
 
373
          -1.
 
374
          (list (diffop) (list smlist i h) (list smlist r))
 
375
          (list (diffop) (list smlist r k) l2)
 
376
        )
 
377
        (cond
 
378
          (
 
379
            $iframe_flag
 
380
            (list
 
381
              '(mtimes) -1.
 
382
              (list '($ifb) (list smlist k h) (list smlist r))
 
383
              (list '($icc2) (list smlist r i) (list smlist j))
 
384
            )
 
385
          )
 
386
          (t 0.)
 
387
        )
 
388
      )
 
389
    )
 
390
  )
 
391
 
392
 
 
393
(defun covsubst (x y rp)       ;Substitutes X for Y in the covariant part of RP
 
394
       (cons (car rp) (cons (subst x y (cadr rp)) (cddr rp)))) 
 
395
 
 
396
(defun consubst (x y rp)   ;Substitutes X for Y in the contravariant part of RP
 
397
       (cons (car rp)
 
398
             (cons (cadr rp)
 
399
                   (cons (subst x y (caddr rp)) (cdddr rp))))) 
 
400
 
 
401
(defun dersubst (x y rp)   ;Substitutes X for Y in the derivative indices of RP
 
402
       (nconc (list (car rp) (cadr rp) (caddr rp))
 
403
              (subst x y (cdddr rp)))) 
 
404
 
 
405
;; COVARIANT DIFFERENTIATION
 
406
;; As of November, 2004, COVDIFF now takes into account the value of
 
407
;; iframe_flag. If true, COVDIFF uses the coefficients icc2 in place
 
408
;; of the Christoffel-symbols ichr2.
 
409
 
 
410
(defun diffop ()                ; ichr2 or icc2 depending on iframe_flag
 
411
  (cond
 
412
    (
 
413
      (or $iframe_flag $itorsion_flag $inonmet_flag)
 
414
      '($icc2 simp)
 
415
    ) 
 
416
    (t '($ichr2 simp))
 
417
  )
 
418
)
 
419
 
 
420
(declare-top (special x temp d)) 
 
421
 
 
422
(defmfun $covdiff nargs
 
423
  (prog
 
424
    (x e temp d i)
 
425
    (and (< nargs 2) (merror "COVDIFF must have at least 2 args"))
 
426
    (setq i 2 e (arg 1))
 
427
    again (setq x (arg i) e (covdiff e) i (1+ i))
 
428
    (and (> i nargs) (return e))
 
429
    (go again)
 
430
  )
 
431
)
 
432
 
 
433
(defun covdiff (e)                      ; The covariant derivative...
 
434
  (setq d ($idummy))
 
435
  (cond
 
436
    (               ; is the partial derivative for scalars (*** torsion?)
 
437
      (or (atom e) (eq (caar e) 'rat))
 
438
      (idiff e x)
 
439
    )
 
440
    (
 
441
      (rpobj e)
 
442
      (setq temp
 
443
        (mapcar 
 
444
          #'(lambda (v)
 
445
            (list '(mtimes)
 
446
              (list (diffop) (list smlist d x) (list smlist v))
 
447
              (consubst d v e)
 
448
            )
 
449
          )
 
450
          (cdaddr e)
 
451
        )
 
452
      )
 
453
      (simplus
 
454
        (cons
 
455
          '(mplus)
 
456
          (cons
 
457
            (idiff e x)
 
458
              (cond
 
459
                (
 
460
                  (or (cdadr e) (cdddr e))
 
461
                  (cons (list '(mtimes) -1.  (cons '(mplus)
 
462
                    (nconc
 
463
                      (mapcar 
 
464
                        #'(lambda (v) 
 
465
                          (list '(mtimes)
 
466
                              (list
 
467
                                (diffop)
 
468
                                (list smlist v x)
 
469
                                (list smlist d)
 
470
                              )
 
471
                              (covsubst d v e)
 
472
                            )
 
473
                          )
 
474
                          (cdadr e)
 
475
                        )
 
476
                        (mapcar 
 
477
                          #'(lambda (v) 
 
478
                            (list
 
479
                              '(mtimes)
 
480
                              (list 
 
481
                                (diffop)
 
482
                                (list smlist v x)
 
483
                                (list smlist d)
 
484
                              )
 
485
                              (dersubst d v e)
 
486
                            )
 
487
                          )
 
488
                          (cdddr e)
 
489
                        )
 
490
                      )
 
491
                    )
 
492
                  )
 
493
                  temp
 
494
                )
 
495
              )
 
496
              (t temp)
 
497
            )
 
498
          )
 
499
        )
 
500
        1. t
 
501
      )
 
502
    )
 
503
    (
 
504
      (eq (caar e) 'mtimes)     ; (a*b)'
 
505
      (simplus
 
506
        (covdifftimes (cdr e) x)
 
507
        1 t
 
508
      )
 
509
    )
 
510
    (
 
511
      (eq (caar e) 'mplus)      ; (a+b)'=a'+b'
 
512
      (simplifya
 
513
        (cons
 
514
          '(mplus)
 
515
          (mapcar 'covdiff (cdr e))
 
516
        )
 
517
        nil
 
518
      )
 
519
    )
 
520
    (
 
521
      (eq (caar e) 'mexpt)      ; (a^b)'=b*a^(b-1)*a'
 
522
      (simptimes
 
523
        (list
 
524
          '(mtimes)
 
525
          (caddr e)
 
526
          (list
 
527
            '(mexpt)
 
528
            (cadr e)
 
529
            (list '(mplus) -1. (caddr e))
 
530
          )
 
531
          ($covdiff (cadr e) x)
 
532
        )
 
533
        1. nil
 
534
      )
 
535
    )
 
536
    (
 
537
      (eq (caar e) 'mequal)
 
538
      (list (car e) (covdiff (cadr e)) (covdiff (caddr e)))
 
539
    )
 
540
    (t (merror "Not acceptable to COVDIFF: ~M" (ishow e)))
 
541
  )
 
542
)
 
543
 
 
544
(defun covdifftimes (l x) 
 
545
  (prog (sp left out) 
 
546
    (setq out (ncons '(mplus)))
 
547
    loop (setq sp (car l) l (cdr l))
 
548
    (nconc out
 
549
      (list
 
550
        (simptimes
 
551
          (cons '(mtimes) (cons ($covdiff sp x) (append left l)))
 
552
          1. t
 
553
        )
 
554
      )
 
555
    )
 
556
    (cond ((null l) (return out)))
 
557
    (setq left (nconc left (ncons sp)))
 
558
    (go loop)
 
559
  )
 
560
 
561
 
 
562
(declare-top (unspecial r temp d)) 
 
563
 
 
564
(defun vecdiff (v i j d) ;Add frame bracket contribution when iframe_flag:true
 
565
  (cond
 
566
    (
 
567
      $iframe_flag
 
568
      (cons
 
569
        '(mplus simp)
 
570
        (list
 
571
          (list (list v) '((mlist)) (list '(mlist) i) j)
 
572
          (list
 
573
            '(mtimes simp)
 
574
            (list (list v) '((mlist)) (list '(mlist) d))
 
575
            (list
 
576
              '(mtimes simp)
 
577
              -1.
 
578
              (list '(%ifb) (list '(mlist) d j) (list '(mlist) i))
 
579
            )
 
580
          )
 
581
        )
 
582
      )
 
583
    )
 
584
    (t
 
585
      (list (list v) '((mlist)) (list '(mlist) i) j)
 
586
    )
 
587
  )
 
588
)
 
589
 
 
590
(defun liediff (v e n)
 
591
  (cond
 
592
    ((not (symbolp v)) (merror "~M is not a symbol" v))
 
593
    (
 
594
      (or (atom e) (eq (caar e) 'rat)) ; Scalar field
 
595
                                       ; v([],[%1])*idiff(e,%1)
 
596
      (let
 
597
        ((dummy (implode (nconc (exploden $idummyx) (exploden n)))))
 
598
        (list
 
599
          '(mtimes) (list (list v) '((mlist)) (list '(mlist) dummy))
 
600
          ($idiff e dummy)
 
601
        )
 
602
      )
 
603
    )
 
604
    (
 
605
      (rpobj e)                        ; Tensor field
 
606
 
 
607
;     Dummy implementation for logic tests
 
608
;     (list '(%liediff) v e)
 
609
 
 
610
;     Shall the dummy index be in ICOUNTER sequence? Probably yes.
 
611
;     (let ((dummy (implode (nconc (exploden $idummyx) (exploden n)))))
 
612
      (let
 
613
        (
 
614
          (dummy ($idummy))
 
615
          (dummy2
 
616
            (cond
 
617
              ($iframe_flag ($idummy))
 
618
              (t nil)
 
619
            )
 
620
          )
 
621
        )
 
622
        (
 
623
          append
 
624
          (list
 
625
            '(mplus) 0
 
626
            (list
 
627
              '(mtimes)                ; e([...],[...],%1)*v([],[%1])
 
628
              (list (list v) '((mlist)) (list '(mlist) dummy))
 
629
              ($idiff e dummy)
 
630
            )
 
631
          )
 
632
          (maplist
 
633
            #'(lambda (s)              ; e([..%1..],[...])*v([],[%1],k)
 
634
              (list
 
635
                '(mtimes)
 
636
                (cond ((atom (car s)) 1) (t -1))
 
637
                (append
 
638
                  (list
 
639
                    (car e)
 
640
                    (cons
 
641
                      '(mlist)
 
642
                      (append
 
643
                        (subseq (cdadr e) 0 (- (length (cdadr e)) (length s)))
 
644
                        (cons
 
645
                          (cond ((atom (car s)) dummy)
 
646
                                (t (list '(mtimes simp) -1 dummy))
 
647
                          )
 
648
                          (cdr s)
 
649
                        )
 
650
                      )
 
651
                    )
 
652
                    (caddr e)
 
653
                  )
 
654
                  (cdddr e)
 
655
                )
 
656
                (vecdiff
 
657
                  v
 
658
                  (cond ((atom (car s))  dummy) (t (caddr (car s))))
 
659
                  (cond ((atom (car s)) (car s)) (t dummy))
 
660
                  dummy2
 
661
                )
 
662
              )
 
663
            )
 
664
            (cdadr e)
 
665
          )
 
666
          (maplist
 
667
            #'(lambda (s)              ; +e([...],[...],..%1..)*v([],[%1],k)
 
668
              (list
 
669
                '(mtimes)
 
670
                (append
 
671
                  (list (car e) (cadr e) (caddr e))
 
672
                  (subseq (cdddr e) 0 (- (length (cdddr e)) (length s)))
 
673
                  (cons dummy (cdr s))
 
674
                )
 
675
                (vecdiff v dummy (car s) dummy2)
 
676
              )
 
677
            )
 
678
            (cdddr e)
 
679
          )
 
680
          (maplist
 
681
            #'(lambda (s)             ; -e([...],[..%1..])*v([],[k],%1)
 
682
              (list
 
683
                '(mtimes) -1
 
684
                (append
 
685
                  (list (car e) (cadr e)
 
686
                    (cons
 
687
                      '(mlist)
 
688
                      (append
 
689
                        (subseq (cdaddr e) 0 (- (length (cdaddr e)) (length s)))
 
690
                        (cons dummy (cdr s))
 
691
                      )
 
692
                    )
 
693
                  )
 
694
                  (cdddr e)
 
695
                )
 
696
                (vecdiff v (car s) dummy dummy2)
 
697
              )
 
698
            )
 
699
            (cdaddr e)
 
700
          )
 
701
        )
 
702
      )
 
703
    )
 
704
    (
 
705
      (eq (caar e) 'mtimes)           ; Leibnitz rule
 
706
                                      ; Lv(cadr e)*(cddr e)+(cadr e)*Lv(cddr e)
 
707
      (list
 
708
        '(mplus)
 
709
        (cons '(mtimes) (cons (liediff v (cadr e) n) (cddr e)))
 
710
        (cons
 
711
          '(mtimes)
 
712
          (list
 
713
            (cadr e)
 
714
            (liediff
 
715
              v
 
716
              (cond ((cdddr e) (cons '(mtimes) (cddr e))) (t (caddr e)))
 
717
              n
 
718
            )
 
719
          )
 
720
        )
 
721
      )
 
722
    )
 
723
    (
 
724
      (eq (caar e) 'mplus)            ; Linearity
 
725
;     We prefer mapcar to iteration, but the recursive code also works
 
726
;     (list
 
727
;       '(mplus)
 
728
;       (liediff v (cadr e) n)
 
729
;       (liediff v (cond ((cdddr e) (cons '(mplus) (cddr e))) (t (caddr e))) n)
 
730
;     )
 
731
      (cons '(mplus) (mapcar #'(lambda (u) (liediff v u n)) (cdr e)))
 
732
    )
 
733
    (t (merror "~M is not a tensorial expression liediff can handle" e))
 
734
  )
 
735
)
 
736
 
 
737
(defmfun $liediff (v e) (liediff v e 1))
 
738
 
 
739
(defmfun $rediff (x) (meval '(($ev) x $idiff)))
 
740
 
 
741
;;(defmfun $evundiff (x) ($rediff ($undiff x)))
 
742
(defmfun $evundiff (x) (meval (list '($ev) ($undiff x) '$nouns)))
 
743
 
 
744
(defmfun $undiff (x) 
 
745
  (cond
 
746
    ((atom x) x)
 
747
    (
 
748
      (rpobj x)
 
749
      (cond
 
750
        (
 
751
          (cdddr x)
 
752
          (nconc
 
753
            (list '(%idiff) (list (car x) (cadr x) (caddr x)))
 
754
            (putinones (cdddr x))
 
755
          )
 
756
        )
 
757
        (t x)
 
758
      )
 
759
    )
 
760
    (t
 
761
      (mysubst0
 
762
        (simplifya (cons (ncons (caar x)) (mapcar '$undiff (cdr x))) t)
 
763
        x
 
764
      )
 
765
    )
 
766
  )
 
767
)
 
768
 
 
769
(defun putinones (e) 
 
770
  (cond
 
771
    ((cdr e) (cons (car e) (cons 1. (putinones (cdr e)))))
 
772
    (t (list (car e) 1.))
 
773
  )
 
774
 
775
 
 
776
 
 
777
 
 
778
(defmfun $lorentz_gauge n
 
779
       (cond ((equal n 0) (merror "LORENTZ_GAUGE requires at least one argument"))
390
780
             ((equal n 1) (lorentz (arg 1) nil))
391
781
             (t (lorentz (arg 1)
392
782
                         ((lambda (l) (cond ((sloop for v in  l
393
783
                                                     always (symbolp v)) l)
394
784
                                            (t (merror
395
 
"Invalid tensor name(s) in argument to LORENTZ"))))
 
785
"Invalid tensor name(s) in argument to LORENTZ_GAUGE"))))
396
786
                          (listify (f- 1 n)))))))
397
787
 
398
788
;Lorentz contraction of E: indexed objects with a derivative index matching a
399
789
;contravariant index become 0. If L is NIL then do this for all indexed objects
400
790
;otherwise do this only for those indexed objects whose names are members of L.
401
791
 
402
 
(defun LORENTZ (e l)
 
792
(defun lorentz (e l)
403
793
       (cond ((atom e) e)
404
794
             ((rpobj e)
405
795
              (cond ((and (or (null l) (memq (caar e) l))
413
803
                                (cdr e)))
414
804
                  t) e))))
415
805
 
416
 
(DEFUN LESS (X Y)                                         ;Alphanumeric compare
417
 
       (COND ((NUMBERP X)
418
 
              (COND ((NUMBERP Y) (< X Y))
419
 
                    (T (ALPHALESSP (ASCII X) Y))))
420
 
             (T (COND ((NUMBERP Y) (ALPHALESSP X (ASCII Y)))
421
 
                      (T (ALPHALESSP X Y)))))) 
422
 
 
423
 
(DECLARE-TOP (SPECIAL CHRISTOFFELS))
424
 
 
425
 
(SETQ CHRISTOFFELS '($CHR2 $CHR1 %CHR2 %CHR1))
426
 
 
427
 
(DEFMFUN $CONTRACT (E)                                 ;Main contraction function
428
 
       (COND ((ATOM E) E)
429
 
             ((RPOBJ E) (CONTRACT5 E))
430
 
             ((EQ (CAAR E) 'MTIMES)
431
 
              (MYSUBST0 (SIMPLIFYA (CONS '(MTIMES) (CONTRACT4 E))
432
 
                                   T)
433
 
                        E))
434
 
             ((EQ (CAAR E) 'MPLUS)
435
 
              (MYSUBST0 (SIMPLUS (CONS '(MPLUS)
436
 
                                       (MAPCAR '$CONTRACT
437
 
                                               (CDR E)))
438
 
                                 1.
439
 
                                 T)
440
 
                        E))
441
 
             (T (MYSUBST0 (SIMPLIFYA (CONS (CAR E) (MAPCAR '$CONTRACT (CDR E)))
442
 
                                     NIL) E))))
443
 
 
444
 
(DEFUN CONTRACT5 (E) 
445
 
       ((LAMBDA (K) (COND ((AND (NOT (MEMQ (CAAR E) CHRISTOFFELS)) K)
446
 
                           (NCONC (LIST (CAR E)
447
 
                                        (CONS SMLIST (CAR K))
448
 
                                        (CONS SMLIST (CDR K)))
449
 
                                  (CDDDR E)))
450
 
                          (T E)))
451
 
        (CONTRACT2 (CDADR E) (CDADDR E)))) 
452
 
 
453
 
;L1 and L2 are lists. This function removes all like members from L1 and L2 and
454
 
;returns their cons or returns NIL if there aren't any like members.
455
 
 
456
 
(DEFUN CONTRACT2 (L1 L2)             
457
 
       ((LAMBDA (I) (AND I (CONS (SETDIFF L1 I) (SETDIFF L2 I))))
458
 
        (INTERSECT L1 L2))) 
459
 
 
460
 
(DEFUN SETDIFF (S1 S2)                             ;Set difference of S1 and S2
461
 
       (DO ((J S1 (CDR J)) (A))
462
 
           ((NULL J) A)
463
 
           (OR (AND (NOT (NUMBERP (CAR J))) (MEMQ (CAR J) S2)) (SETQ A (CONS (CAR J) A)))))
464
 
 
465
 
(DEFUN CONTRACT3 (IT LST)      ;Tries to contract IT with some element of LST.
466
 
       (PROG (FRST R REST)     ;If none occurs then return NIL otherwise return
 
806
(defun less (x y)                                         ;alphanumeric compare
 
807
       (cond ((numberp x)
 
808
              (cond ((numberp y) (< x y))
 
809
                    (t (alphalessp (ascii x) y))))
 
810
             (t (cond ((numberp y) (alphalessp x (ascii y)))
 
811
                      (t (alphalessp x y)))))) 
 
812
 
 
813
;; Christoffels contains all Christoffel-like symbols: i.e., symbols
 
814
;; that make sense only with certain index patterns. These symbols are
 
815
;; excluded from contractions, because those would produce illegal
 
816
;; index combinations (e.g., ichr1([a,b],[c])). However, special rules
 
817
;; exist to convert a covariant symbol into a mixed symbol and vice
 
818
;; versa; for instance, g^ad*ichr1_bcd will contract to ichr2_bc^a.
 
819
(declare-top (special christoffels christoffels1 christoffels2))
 
820
 
 
821
(setq christoffels1 '($ichr1 %ichr1 $icc1 %icc1 $ifc1 %ifc1
 
822
                      $inmc1 %inmc1 $ikt1 %ikt1))
 
823
(setq christoffels2 '($ichr2 %ichr2 $icc2 %icc2 $ifc2 %ifc2
 
824
                      $inmc2 %inmc2 $ikt2 %ikt2))
 
825
(setq christoffels (append christoffels1 christoffels2 '(%ifb $ifb)))
 
826
 
 
827
;; Main contraction function
 
828
(defmfun $contract (e)
 
829
  (cond
 
830
    ((atom e) e)
 
831
    ((rpobj e) (contract5 e))
 
832
    (
 
833
      (eq (caar e) 'mtimes)
 
834
      (mysubst0 (simplifya (cons '(mtimes) (contract4a e)) nil) e)
 
835
    )
 
836
    (
 
837
      (eq (caar e) 'mplus)
 
838
      (mysubst0 (simplus (cons '(mplus) (mapcar '$contract (cdr e))) 1. t) e)
 
839
    )
 
840
    (t
 
841
      (mysubst0 (simplifya (cons (car e) (mapcar '$contract (cdr e))) nil) e)
 
842
    )
 
843
  )
 
844
)
 
845
 
 
846
(defun contract4a (e)
 
847
  (prog (l1 l2)
 
848
    (setq l1 nil l2 nil)
 
849
    (dolist (o (cdr e))
 
850
      (cond
 
851
        ((or (atom o) (atom (car o))) (setq l1 (cons o l1)))
 
852
        (
 
853
          (and (eq (caar o) 'mexpt) (eq (caddr o) -1))
 
854
          (setq l2 (cons (cadr o) l2))
 
855
        )
 
856
        (t (setq l1 (cons o l1)))
 
857
      )
 
858
    )
 
859
    (cond (l1 (setq l1 (contract4 (cons '(mtimes) l1)))))
 
860
    (cond (l2 (setq l1 (cons (list '(mexpt)
 
861
                                   (cons '(mtimes)
 
862
                                          (contract4 (cons '(mtimes) l2))
 
863
                                   )
 
864
                                   '-1
 
865
                             )
 
866
                             l1
 
867
                       ))))
 
868
    (return l1)
 
869
  )
 
870
)
 
871
 
 
872
;; Contract a single tensor with itself
 
873
(defun contract5 (e)
 
874
  (prog
 
875
    (       ; See if e contracts with itself, find contraction symbol
 
876
      (c (or (and (rpobj e) (getcon (caar e))) (return e)))
 
877
      (
 
878
        symbol
 
879
        (do
 
880
          (
 
881
            (c (getcon (caar e)) (cdr c))
 
882
          )
 
883
          ((or (eq (caar c) (caar e)) (null c)) (cond (c (cdar c)) (t nil)) )
 
884
        )
 
885
      )
 
886
    )
 
887
    (return
 
888
      (cond
 
889
        ((or (null symbol) (memq (caar e) christoffels)) e)
 
890
        (
 
891
          t
 
892
          (prog (cov con f sgn)
 
893
            (setq sgn (cond ((rpobj ($canform e)) 1) (t -1))
 
894
                  cov (contractinside (derat (cadr e)))
 
895
                  con (derat (caddr e))
 
896
                  f (not (equal cov (derat (cadr e))))
 
897
            )
 
898
            ; Calling contract2 here won't do the trick as it messes up the
 
899
            ; order of indices. So we remove indices that appear both in cov
 
900
            ; and in con the hard way, with a do loop.
 
901
            (do
 
902
              ((i cov (cdr i)))
 
903
              ((null i))
 
904
              (cond
 
905
                ((not (atom (car i))))
 
906
                (
 
907
                  (member (car i) con)
 
908
                  (setq f t con (delete (car i) con) cov (delete (car i) cov))
 
909
                )
 
910
              )
 
911
            )
 
912
            (setq c
 
913
              (nconc
 
914
                (list (cond (f (list symbol)) (t (car e))) cov con)
 
915
                (cdddr e)
 
916
              )
 
917
            )
 
918
            (return (cond ((and f (eq sgn -1)) (list '(mtimes) sgn c)) (t c)))
 
919
          )
 
920
        )
 
921
      )
 
922
    )
 
923
  )
 
924
)
 
925
 
 
926
(defun head (x) (cond ((atom x) nil) (t (cons (car x) nil))))
 
927
 
 
928
(defun firstintersect (l1 l2) (head (intersect l1 l2)))
 
929
 
 
930
;; Remove like members. Return (cons l1 l2) or nil if no like members found.
 
931
(defun contract2 (l1 l2)
 
932
  (
 
933
    (lambda (i) (and i (cons (setdiff l1 i) (setdiff l2 i))))
 
934
    (firstintersect l1 l2)
 
935
  )
 
936
)
 
937
 
 
938
;; Return a list with those members of s1 that are not in s2
 
939
(defun setdiff (s1 s2)
 
940
  (do
 
941
    ((j s1 (cdr j)) (a))
 
942
    ((null j) (reverse a))
 
943
    (or
 
944
      (and (not (numberp (car j))) (memq (car j) s2))
 
945
      (setq a (cons (car j) a))
 
946
    )
 
947
  )
 
948
)
 
949
 
 
950
(defun contract3 (it lst)      ;Tries to contract IT with some element of LST.
 
951
       (prog (frst r rest)     ;If none occurs then return NIL otherwise return
467
952
                               ;a list whose first member is the result of
468
953
                               ;contraction and whose cdr is a top-level copy
469
954
                               ;of LST with the element which contracted
470
955
                               ;removed.
471
 
        LOOP (SETQ FRST (CAR LST) LST (CDR LST))
472
 
;;           (AND (EQ (CAAR FRST) '%KDELTA) (GO SKIP))
473
 
             (AND (SETQ R (CONTRACT1 IT FRST))
474
 
                  (RETURN (CONS R (NCONC (NREVERSE REST) LST))))
 
956
        loop (setq frst (car lst) lst (cdr lst))
 
957
;;           (and (eq (caar frst) '%kdelta) (go skip))
 
958
             (and (setq r (contract1 it frst))
 
959
                  (return (cons r (nconc (nreverse rest) lst))))
475
960
                               ;Try contraction in reverse order since the
476
961
                               ;operation is commutative.
477
 
;;      SKIP (AND (ZL-GET (CAAR FRST) 'CONTRACTIONS)
478
 
        SKIP (AND (GETCON (CAAR FRST))
479
 
                  (SETQ R (CONTRACT1 FRST IT))
480
 
                  (RETURN (CONS R (NCONC (NREVERSE REST) LST))))
481
 
             (AND (NULL LST) (RETURN NIL))
482
 
             (SETQ REST (CONS FRST REST))
483
 
             (GO LOOP))) 
 
962
;;      skip (and (zl-get (caar frst) 'contractions)
 
963
        skip (and (getcon (caar frst))
 
964
                  (setq r (contract1 frst it))
 
965
                  (return (cons r (nconc (nreverse rest) lst))))
 
966
             (and (null lst) (return nil))
 
967
             (setq rest (cons frst rest))
 
968
             (go loop))) 
484
969
 
485
 
(DEFUN CONTRACT4 (L)                                        ;Contracts products
486
 
       (PROG (L1 L2 L3 F CL SF) 
487
 
             (SETQ CL (CDR L)) ;Following loop sets up 3 lists from the factors
 
970
(defun contract4 (l)                                        ;contracts products
 
971
       (prog (l1 l2 l3 f cl sf)
 
972
             (setq cl (cdr l)) ;Following loop sets up 3 lists from the factors
488
973
                               ;on L: L1 - atoms or the contraction of non
489
974
                               ;indexed objects (the contraction is to handle
490
975
                               ;sub-expressions in case E is not fully expanded
491
976
                               ;as in A*B*(C*D+E*F). ), L2 - indexed objects in
492
977
                               ;L with contraction property, L3 - indexed
493
978
                               ;objects in L without contraction property
494
 
        AGAIN(SETQ F (CAR CL) CL (CDR CL))
495
 
             (COND ((ATOM F) (SETQ L1 (CONS F L1)))
496
 
                   ((RPOBJ F)
497
 
                    (SETQ F (CONTRACT5 F))
498
 
;;                  (COND ((ZL-GET (CAAR F) 'CONTRACTIONS)
499
 
                    (COND ((GETCON (CAAR F))
500
 
                           (SETQ L2 (CONS F L2)))
501
 
                          (T (SETQ L3 (CONS F L3)))))
502
 
                   (T (SETQ L1 (CONS ($CONTRACT F) L1))))
503
 
             (AND CL (GO AGAIN))
504
 
             (AND (NULL L2) (RETURN (NCONC L1 L3)))
505
 
             (AND (NULL (CDR L2)) (SETQ CL L2) (GO LOOP2+1))
 
979
        again(setq f (car cl) cl (cdr cl))
 
980
             (cond ((atom f) (setq l1 (cons f l1)))
 
981
                   ((rpobj f)
 
982
;;*** contract5 may return a negative result
 
983
                    (setq f (contract5 f))
 
984
(cond (
 
985
 (and (or (eq (car f) '(mtimes)) (eq (car f) '(mtimes simp))) (eq (cadr f) -1))
 
986
 (setq l1 (cons -1 l1) f (caddr f)) ))
 
987
                    (cond ((getcon (caar f))
 
988
                           (setq l2 (cons f l2)))
 
989
                          (t (setq l3 (cons f l3)))))
 
990
                   (t (setq l1 (cons ($contract f) l1))))
 
991
             (and cl (go again))
 
992
             (and (null l2) (return (nconc l1 l3)))
 
993
             (and (null (cdr l2)) (setq cl l2) (go loop2+1))
506
994
                               ;If L2 is empty then no more contractions are
507
995
                               ;needed. If L2 has only 1 member then just
508
996
                               ;contract it with L3 otherwise contract the
515
1003
                               ;by CONTRACT3). If it doesn't then add it to CL.
516
1004
                               ;If it does then take result of contraction and
517
1005
                               ;add to L1, L2, or L3 as above.
518
 
        LOOP1(SETQ F (CAR L2) L2 (CDR L2))
519
 
             (COND ((NULL (SETQ SF (CONTRACT3 F L2)))
520
 
                    (SETQ CL (CONS F CL)))
521
 
                   (T (SETQ L2 (CDR SF) SF (CAR SF))
522
 
                      (COND ((ATOM SF) (SETQ L1 (CONS SF L1)))
523
 
                            ((RPOBJ SF)
524
 
;;                           (COND ((ZL-GET (CAAR SF)
525
 
;;                                       'CONTRACTIONS)
526
 
                             (COND ((GETCON (CAAR SF))
527
 
                                    (SETQ L2 (CONS SF L2)))
528
 
                                   (T (SETQ L3 (CONS SF L3)))))
529
 
                            (T (SETQ L1 (CONS SF L1))))))
 
1006
        loop1(setq f (car l2) l2 (cdr l2))
 
1007
             (cond ((null (setq sf (contract3 f l2)))
 
1008
                    (setq cl (cons f cl)))
 
1009
                   (t
 
1010
;;*** contract3 may also return a negative result
 
1011
(setq sf (mapcar #'(lambda (x)
 
1012
(cond ((atom x) x) (
 
1013
 (and (or (equal (car x) '(mtimes)) (equal (car x) '(mtimes simp))) (eq (cadr x) -1))
 
1014
 (setq l1 (cons -1 l1)) (caddr x)) (t x))
 
1015
) sf ) )
 
1016
 
 
1017
 (setq l2 (cdr sf) sf (car sf))
 
1018
                      (cond ((atom sf) (setq l1 (cons sf l1)))
 
1019
                            ((rpobj sf)
 
1020
;;                           (cond ((zl-get (caar sf)
 
1021
;;                                       'contractions)
 
1022
                             (cond ((getcon (caar sf))
 
1023
                                    (setq l2 (cons sf l2)))
 
1024
                                   (t (setq l3 (cons sf l3)))))
 
1025
                            (t (setq l1 (cons sf l1))))))
530
1026
                               ;If L2 has at least 2 elements left then
531
1027
                               ;continue loop. If L2 has 1 element and CL
532
1028
                               ;is not empty and there were some contractions
533
1029
                               ;performed last time then add CL to L2 and try
534
1030
                               ;again. Otherwise add L2 to CL and quit.
535
 
             (AND L2
536
 
                  (COND ((CDR L2) (GO LOOP1))
537
 
                        ((AND CL SF)
538
 
                         (SETQ SF NIL L2 (CONS (CAR L2) CL) CL NIL)
539
 
                         (GO LOOP1))
540
 
                        (T (SETQ CL (NCONC L2 CL)))))
 
1031
             (and l2
 
1032
                  (cond ((cdr l2) (go loop1))
 
1033
                        ((and cl sf)
 
1034
                         (setq sf nil l2 (cons (car l2) cl) cl nil)
 
1035
                         (go loop1))
 
1036
                        (t (setq cl (nconc l2 cl)))))
541
1037
                               ;The following loop goes down CL trying to
542
1038
                               ;contract each member with some member in L3. If
543
1039
                               ;there is not a contraction then the element
548
1044
                               ;CONTRACT3 here if CL is known not to be null.
549
1045
                               ;If L3 is empty then there is nothing left to
550
1046
                               ;contract.
551
 
        LOOP2(AND (NULL CL) (RETURN (NCONC L1 L3)))
552
 
        LOOP2+1
553
 
             (AND (NULL L3) (RETURN (NCONC L1 CL)))
554
 
             (SETQ F (CAR CL) CL (CDR CL))
555
 
             (COND ((SETQ SF (CONTRACT3 F L3)) (SETQ L3 SF))
556
 
                   (T (SETQ L3 (CONS F L3))))
557
 
             (GO LOOP2))) 
558
 
 
559
 
(DEFUN CONTRACT1 (F G)           ;This does the actual contraction of F with G.
560
 
       (PROG (A B C D E CF)      ;If f has any derivative indices then it can't
561
 
                                 ;contract G. If F is Kronecker delta then see
562
 
                                 ;which of the covariant, contravariant, or
563
 
                                 ;derivative indices matches those in G.
564
 
             (WHEN (CDDDR F) (RETURN NIL))
565
 
             (SETQ A (CDADR F)
566
 
                   B (CDADDR F)
567
 
                   C (CADR G)
568
 
                   D (CADDR G)
569
 
                   E (CDDDR G))
570
 
             (COND
571
 
              ((OR (EQ (CAAR F) '%KDELTA) (EQ (CAAR F) '$KDELTA))
572
 
               (AND (> (LENGTH A) 1) (RETURN NIL))
573
 
               (SETQ A (CAR A) B (CAR B))
574
 
               (RETURN
575
 
                (SIMPLIFYA (COND ((AND (CDR C) (AND (NOT (NUMBERP B)) (MEMQ B (CDR C))))
576
 
                                  (SETQ C (SUBST A B (CDR C)))
577
 
                                  (AND (NOT (MEMQ (CAAR G) CHRISTOFFELS))
578
 
                                       (CDR D)
579
 
                                       (SETQ A (CONTRACT2 C (CDR D)))
580
 
                                       (SETQ C (CAR A) 
581
 
                                             D (CONS SMLIST (CDR A))))
582
 
                                  (NCONC (LIST (CAR G)
583
 
                                               (CONS SMLIST C)
584
 
                                               D)
585
 
                                         E))
586
 
                                 ((AND E (AND (NOT (NUMBERP B)) (MEMQ B E)))
587
 
                                  (NCONC (LIST (CAR G) C D)
588
 
                                         (itensor-SORT (SUBST A B E))))
589
 
                                 ((AND (CDR D) (AND (NOT (NUMBERP A)) (MEMQ A (CDR D))))
590
 
                                  (SETQ D (SUBST B A (CDR D)))
591
 
                                  (AND (CDR C)
592
 
                                       (SETQ A (CONTRACT2 (CDR C) D))
593
 
                                       (SETQ D (CDR A) 
594
 
                                             C (CONS SMLIST (CAR A))))
595
 
                                  (NCONC (LIST (CAR G)
596
 
                                               C
597
 
                                               (CONS SMLIST D))
598
 
                                         E))
599
 
                                 (T NIL))
600
 
                           NIL))))
601
 
;; VTT: No tensor should be able to contract LC or KDELTA.
602
 
             (AND (OR (EQ (CAAR G) '$KDELTA) (EQ (CAAR G) '%KDELTA) (EQ (CAAR G) '$LC) (EQ (CAAR G) '%LC)) (RETURN NIL))
603
 
 
604
 
                                    ;If G has derivative indices then F must be
605
 
             (and e                 ;constant in order to contract it.
606
 
                  (NOT (MGET (CAAR F) '$CONSTANT))
607
 
                  (RETURN NIL))
608
 
                                ;Contraction property of F is a list of (A.B)'S
609
 
;;           (COND ((SETQ CF (ZL-GET (CAAR F) 'CONTRACTIONS)))
610
 
             (COND ((SETQ CF (GETCON (CAAR F))))
611
 
                   (T (RETURN NIL)))
612
 
                          ;If G matches an A then use the B for name of result.
613
 
                          ;If an A is a space use name of G for result.
614
 
        MORE (COND ((EQ (CAAR CF) '/ ) (SETQ CF (CAR G)))
615
 
                   ((EQ (CAAR CF) (CAAR G))
616
 
                    (SETQ CF (NCONS (CDAR CF))))
617
 
                   (T (OR (SETQ CF (CDR CF)) (RETURN NIL)) (GO MORE)))
618
 
             (SETQ C (CDR C) D (CDR D))
619
 
                                ;If CONTRACT2 of F's contravariant and G's
620
 
                                ;covariant or F's covariant and G's
621
 
                                ;contravariant indicies is NIL then return NIL.
622
 
             (COND ((AND B C (SETQ F (CONTRACT2 B C)))
623
 
                    (SETQ B (CAR F) C (CDR F)))
624
 
                   ((AND A D (SETQ F (CONTRACT2 A D)))
625
 
                    (SETQ A (CAR F) D (CDR F)))
626
 
                   (T (RETURN NIL)))
627
 
                                               ;Form combined indices of result
628
 
             (AND D (SETQ B (APPEND B D)))
629
 
             (AND C (SETQ A (APPEND C A)))
630
 
                                                       ;Zl-remove repeated indices
631
 
             (AND (SETQ F (CONTRACT2 A B)) (SETQ A (CAR F) B (CDR F)))
632
 
;; VTT: Special handling of Christoffel symbols. We can only contract them
633
 
;; when we turn CHR1 into CHR2 or vice versa; other index combinations are
634
 
;; illegal. This code checks if the index pattern is a valid one and replaces
635
 
;; CHR1 with CHR2 or vice versa as appropriate.
636
 
             (COND ((OR (EQ (CAR CF) '$CHR1) (EQ (CAR CF) '%CHR1))
637
 
                      (COND      ((AND (EQ (LENGTH A) 2) (EQ (LENGTH B) 1))
638
 
                                  (SETQ CF (CONS (COND ((EQ (CAR CF) '$CHR1) '$CHR2) (T '%CHR2)) (CDR CF))))
639
 
                                 ((NOT (AND (EQ (LENGTH A) 3) (EQ (LENGTH B) 0))) (RETURN NIL)))
640
 
                   )
641
 
                   ((OR (EQ (CAR CF) '$CHR2) (EQ (CAR CF) '%CHR2))
642
 
                      (COND      ((AND (EQ (LENGTH A) 3) (EQ (LENGTH B) 0))
643
 
                                  (SETQ CF (CONS (COND ((EQ (CAR CF) '$CHR2) '$CHR1) (T '%CHR1)) (CDR CF)))
644
 
                                 )
645
 
                                 ((NOT (AND (EQ (LENGTH A) 2) (EQ (LENGTH B) 1))) (RETURN NIL)))
646
 
                   )
647
 
             )
648
 
 
649
 
             (SETQ F (MEVAL (LIST CF (CONS SMLIST A) (CONS SMLIST B))))
650
 
             (AND E
651
 
;                 (DO E E (CDR E)
652
 
;                     (NULL E)
653
 
;                     (SETQ F (SDIFF F (CAR E))))
654
 
                  (DO ((E E (CDR E)))
655
 
                      ((NULL E) )
656
 
                      (SETQ F (SDIFF F (CAR E))))
657
 
 
658
 
                  )
659
 
             (RETURN F)))
660
 
 
661
 
(DEFMFUN $UNDIFF (X) 
662
 
       (COND ((ATOM X) X)
663
 
             ((RPOBJ X)
664
 
              (COND ((CDDDR X)
665
 
                     (NCONC (LIST '(%DERIVATIVE)
666
 
                                  (LIST (CAR X) (CADR X) (CADDR X)))
667
 
                            (PUTINONES (CDDDR X))))
668
 
                    (T X)))
669
 
             (T
670
 
              (MYSUBST0 (SIMPLIFYA (CONS (NCONS (CAAR X))
671
 
                                         (MAPCAR '$UNDIFF (CDR X)))
672
 
                                   T) X))))
673
 
 
674
 
(DEFUN PUTINONES (E) 
675
 
       (COND ((CDR E) (CONS (CAR E) (CONS 1. (PUTINONES (CDR E)))))
676
 
             (T (LIST (CAR E) 1.)))) 
677
 
 
678
 
(DEFMFUN $KDELTA (L1 L2)
679
 
       (COND ((NULL (AND ($LISTP L1)
680
 
                         ($LISTP L2)
681
 
                         (= (LENGTH L1) (LENGTH L2))))
682
 
              (merror "Improper arg to DELTA: ~M"
683
 
                      (LIST '(%KDELTA) L1 L2)
684
 
                      ))
685
 
             (T (DELTA (CDR L1) (CDR L2))))) 
 
1047
        loop2(and (null cl) (return (nconc l1 l3)))
 
1048
        loop2+1
 
1049
             (and (null l3) (return (nconc l1 cl)))
 
1050
             (setq f (car cl) cl (cdr cl))
 
1051
             (cond ((setq sf (contract3 f l3))
 
1052
;;*** contract3 may also return a negative result
 
1053
(setq sf (mapcar #'(lambda (x)
 
1054
(cond ((atom x) x) (
 
1055
 (and (or (equal (car x) '(mtimes)) (equal (car x) '(mtimes simp))) (eq (cadr x) -1))
 
1056
 (setq l1 (cons -1 l1)) (caddr x)) (t x))
 
1057
) sf ) )
 
1058
 
 
1059
 (setq l3 sf))
 
1060
                   (t (setq l3 (cons f l3))))
 
1061
             (go loop2))) 
 
1062
 
 
1063
;; Create a 'normalized' (i.e., old-style) rpobj
 
1064
(defmfun $renorm (e &optional (force nil))
 
1065
  (prog (c v)
 
1066
    (and (not (rpobj e)) (merror "Not an RPOBJ: ~M" e))
 
1067
    (and $allsym (setq force t))
 
1068
    (setq c (cdaddr e) v nil)
 
1069
    (do
 
1070
      ((i (reverse (cdadr e)) (cdr i)))
 
1071
      (
 
1072
        (or (null i) (and (atom (car i)) (not force))) ; Terminating condition
 
1073
        (setq v (append (reverse i) v))          ; Remaining covariant indices
 
1074
      )
 
1075
      (cond
 
1076
        ((atom (car i)) (setq v (cons (car i) v)))
 
1077
        (t (setq c (cons (caddar i) c)))
 
1078
      )
 
1079
    )
 
1080
    (return
 
1081
      (cons (car e) (append (list (cons smlist v) (cons smlist c)) (cdddr e)))
 
1082
    )
 
1083
  )
 
1084
)
 
1085
 
 
1086
;; As above, but unconditionally. Not needed.
 
1087
;(defun renorm (e) (append (list (car e) ($covi e) ($conti e)) (cdddr e)))
 
1088
 
 
1089
;; Add a minus sign to all elements in a list
 
1090
(defun neglist (l)
 
1091
  (cond ((null l) nil)
 
1092
        (t (cons (list '(mtimes simp) -1 (car l)) (neglist (cdr l))))
 
1093
  )
 
1094
)
 
1095
 
 
1096
;; Create an 'abnormal' (i.e., new-style) rpobj
 
1097
(defun abnorm (e)
 
1098
  (append (list (car e)
 
1099
                (append ($covi e) (neglist (conti e)))
 
1100
                '((mlist simp)))
 
1101
                (cdddr e)
 
1102
  )
 
1103
)
 
1104
 
 
1105
;; Test for membership using EQUAL, to catch member lists
 
1106
(defun memlist (e l)
 
1107
  (cond ((null l) nil)
 
1108
        ((equal e (car l)) l)
 
1109
        (t (memlist e (cdr l)))
 
1110
  )
 
1111
)
 
1112
 
 
1113
;; Substitute using EQUAL, to catch member lists
 
1114
(defun substlist (b a l)
 
1115
  (cond ((null l) l)
 
1116
        ((equal a (car l)) (cons b (cdr l)))
 
1117
        (t (cons (car l) (substlist b a (cdr l))))
 
1118
  )
 
1119
)
 
1120
 
 
1121
;; And delete an element from a list, again using EQUAL
 
1122
(defun dellist (e l)
 
1123
  (cond ((null l) l)
 
1124
        ((equal e (car l)) (dellist e (cdr l)))
 
1125
        (t (cons (car l) (dellist e (cdr l))))
 
1126
  )
 
1127
)
 
1128
 
 
1129
;; Removes items not in i from l.
 
1130
(defun removenotin (i l)
 
1131
  (cond ((null l) l)
 
1132
        ((memq (car l) i) (cons (car l) (removenotin i (cdr l))))
 
1133
        (t (removenotin i (cdr l)))
 
1134
  )
 
1135
)
 
1136
 
 
1137
;; Removes items not in i from l. But the ones in l have a minus sign!
 
1138
(defun removenotinm (i l)
 
1139
  (cond ((null l) l)
 
1140
        ((atom (car l)) (cons (car l) (removenotinm i (cdr l))))
 
1141
        ((and (isprod (caar l)) (eq (cadar l) -1)
 
1142
             (not (memq (caddar l) i))) (removenotinm i (cdr l)))
 
1143
        (t (cons (car l) (removenotinm i (cdr l))))
 
1144
  )
 
1145
)
 
1146
 
 
1147
;; Removes indices duplicated once with and once without a minus sign
 
1148
(defun contractinside (c)
 
1149
  (do
 
1150
    ((i (minusi c) (cdr i)))
 
1151
    ((null i))
 
1152
    (and (memlist (car i) c) (memlist (list '(mtimes simp) -1 (car i)) c)
 
1153
         (setq c (delete (car i) (dellist (list '(mtimes simp) -1 (car i)) c)))
 
1154
    )
 
1155
  )
 
1156
  c
 
1157
)
 
1158
 
 
1159
;; This does the actual contraction of f with g. If f has any derivative
 
1160
;; indices then it can't contract g. If f is Kronecker delta then see which of
 
1161
;; the covariant, contravariant, or derivative indices matches those in g.
 
1162
(defun contract1 (f g)
 
1163
  (prog (a b c d e cf sgn)
 
1164
    (when (cdddr f) (return nil))
 
1165
    (setq a (derat (cdadr f)) b (cdaddr f)
 
1166
          c (derat (cadr g)) d (caddr g) e (cdddr g)
 
1167
    )
 
1168
    (cond                        ; This section is all Kronecker-delta code
 
1169
      (
 
1170
        (or (eq (caar f) '%kdelta) (eq (caar f) '$kdelta))
 
1171
 
 
1172
        ; We normalize the indices first
 
1173
        (setq b (append (minusi a) b) a (plusi a))
 
1174
 
 
1175
        ;We cannot contract with higher-order or malformed Kronecker deltas
 
1176
        (and (or (/= (length a) 1) (/= (length b) 1 )) (return nil))
 
1177
 
 
1178
        (setq a (car a) b (car b))
 
1179
        (return
 
1180
          (simplifya
 
1181
            (cond
 
1182
              (
 
1183
                (and (cdr c) (not (numberp b)) (memq b (cdr c)))
 
1184
                (setq c (subst a b (cdr c)))
 
1185
                (and
 
1186
                  (not (memq (caar g) christoffels))
 
1187
                  (cdr d)
 
1188
                  (setq a (contract2 c (cdr d)))
 
1189
                  (setq c (car a) d (cons smlist (cdr a)))
 
1190
                )
 
1191
                (setq c (contractinside c))
 
1192
                (nconc (list (car g) (cons smlist c) d) e)
 
1193
              )
 
1194
              (
 
1195
                (and e (not (numberp b)) (memq b e))
 
1196
                (nconc (list (car g) c d) 
 
1197
                  (cond
 
1198
                    ($iframe_flag (subst a b e))
 
1199
                    (t (itensor-sort (subst a b e)))
 
1200
                  )
 
1201
                )
 
1202
              )
 
1203
              (
 
1204
                (and (cdr d) (not (numberp a)) (memq a (cdr d)))
 
1205
                (setq d (subst b a (cdr d)))
 
1206
                (and
 
1207
                  (cdr c)
 
1208
                  (setq a (contract2 (cdr c) d))
 
1209
                  (setq d (cdr a) c (cons smlist (car a)))
 
1210
                )
 
1211
                (nconc (list (car g) c (cons smlist d)) e)
 
1212
              )
 
1213
              (
 
1214
                (and (cdr c) (not (numberp a))
 
1215
                     (memlist (list '(mtimes simp) -1 a) (cdr c))
 
1216
                )
 
1217
                (setq c (substlist (list '(mtimes simp) -1 b)
 
1218
                                   (list '(mtimes simp) -1 a)
 
1219
                                   (cdr c)
 
1220
                        )
 
1221
                )
 
1222
                (setq c (contractinside c))
 
1223
                (nconc (list (car g) (cons smlist c) d) e)
 
1224
              )
 
1225
              (t nil)
 
1226
            )
 
1227
            nil
 
1228
          )
 
1229
        )
 
1230
      )
 
1231
    )
 
1232
 
 
1233
    ;No tensor can contract Kronecker-deltas or Levi-Civita symbols.
 
1234
    (and
 
1235
      (or (eq (caar g) '$kdelta) (eq (caar g) '%kdelta)
 
1236
          (eq (caar g) '$levi_civita) (eq (caar g) '%levi_civita)
 
1237
          (eq (caar g) '$icurvature) (eq (caar g) '%icurvature)
 
1238
      )
 
1239
      (return nil)
 
1240
    )
 
1241
 
 
1242
    ;If g has derivative indices then F must be constant in order to contract it
 
1243
    (and e (not (mget (caar f) '$constant)) (return nil))
 
1244
 
 
1245
    ;Contraction property of f is a list of (a.b)'s
 
1246
    (cond
 
1247
      ((setq cf (getcon (caar f))))
 
1248
      (t (return nil))
 
1249
    )
 
1250
 
 
1251
    ; Determine the sign of the result based on the expression's symmetry
 
1252
    ; properties. We use CANFORM to sort indices in the canonical order
 
1253
    ; and then extract the resulting expression's sign.
 
1254
    (setq sgn
 
1255
      (cond ((eq -1 (cadr ($canform (list '(mtimes simp) f g)))) -1) (t 1))
 
1256
    )
 
1257
 
 
1258
    ;If g matches an a then use the b for name of result. If an a is a space
 
1259
    ;use name of G for result.
 
1260
    more
 
1261
    (cond
 
1262
      (
 
1263
        (eq (caar cf) '/ )
 
1264
        (setq cf (car g))
 
1265
      )
 
1266
      (
 
1267
        (eq (caar cf) (caar g))
 
1268
        (setq cf (ncons (cdar cf)))
 
1269
      )
 
1270
      (t
 
1271
        (or (setq cf (cdr cf)) (return nil))
 
1272
        (go more)
 
1273
      )
 
1274
    )
 
1275
    (setq c (cdr c) d (cdr d))
 
1276
 
 
1277
    ;If CONTRACT2 of f's contravariant and g's covariant or f's covariant and
 
1278
    ;g's contravariant indices is nil then return nil
 
1279
    (cond
 
1280
      (
 
1281
        (and b c (setq f (contract2 b c)))
 
1282
        (setq b (car f) c (cdr f))
 
1283
      )
 
1284
      (
 
1285
        (and a d (setq f (contract2 a d)))
 
1286
        (setq a (car f) d (cdr f))
 
1287
      )
 
1288
      (
 
1289
        (and a (minusi c) (setq f (contract2 a (minusi c))))
 
1290
        ; (cdr f) now contains the free indices in (minusi c).
 
1291
        ; what we need to do is find the corresponding items in c, and remove
 
1292
        ; all other negative indices (i.e., those that were dropped by
 
1293
        ; contract2).
 
1294
        ; What we need to do is remove items from c one by one, and substitute
 
1295
        ; an item from (car f), which we should remove from (car f):
 
1296
        ; for i thru length(c)
 
1297
        ;    if c[i] not in (cdr f)
 
1298
        ;       if (car f) is nil, remove c[i]
 
1299
        ;       otherwise subst c[i]
 
1300
        ; endfor
 
1301
        ; Now set c to what we made of c, a to whatever is left of (cdr f)
 
1302
 
 
1303
        (do
 
1304
          (
 
1305
            (i c (cdr i))
 
1306
            (j (car f))
 
1307
            (k)
 
1308
          )
 
1309
          ((null i) (setq a (removenotin j a) c (reverse k)))
 
1310
          (cond
 
1311
            (
 
1312
              (or (atom (car i)) (member (caddar i) (cdr f)))
 
1313
              (setq k (cons (car i) k))
 
1314
            )
 
1315
            (
 
1316
              (not (null j))
 
1317
              (setq k (cons (car j) k) j (cdr j))
 
1318
            )
 
1319
          )
 
1320
        )
 
1321
      )
 
1322
      (
 
1323
        (and (minusi a) c (setq f (contract2 (minusi a) c)))
 
1324
        (do
 
1325
          (
 
1326
            (i c (cdr i))
 
1327
            (j (car f))
 
1328
            (k)
 
1329
          )
 
1330
;;          ((null i) (setq c (reverse k) a (append (plusi a) j)))
 
1331
          ((null i)
 
1332
            (setq
 
1333
              c (reverse k)
 
1334
              a (append
 
1335
                (plusi a)
 
1336
                (mapcar #'(lambda (x) (list '(mtimes simp) -1 x)) j)
 
1337
              )
 
1338
            )
 
1339
          )
 
1340
          (cond
 
1341
            ((member (car i) (cdr f)) (setq k (cons (car i) k)))
 
1342
            (
 
1343
              (not (null j))
 
1344
              (setq k (cons (list '(mtimes simp) -1 (car j)) k) j (cdr j))
 
1345
            )
 
1346
          )
 
1347
        )
 
1348
      )
 
1349
      (t (return nil))
 
1350
    )
 
1351
    ;Form combined indices of result
 
1352
    (and d (setq b (append b d)))
 
1353
    (and c (setq a (append c a)))
 
1354
    ;Zl-remove repeated indices
 
1355
;;    (and (setq f (contract2 a b)) (setq a (car f) b (cdr f)))
 
1356
;;    (setq a (contractinside a))
 
1357
 
 
1358
    ;VTT: Special handling of Christoffel symbols. We can only contract them
 
1359
    ;when we turn ICHR1 into ICHR2 or vice versa; other index combinations are
 
1360
    ;illegal. This code checks if the index pattern is a valid one and replaces
 
1361
    ;ICHR1 with ICHR2 or vice versa as appropriate.
 
1362
    (cond
 
1363
      (
 
1364
        (member (car cf) christoffels1)
 
1365
        (cond
 
1366
          (
 
1367
            (and (eq (length a) 2) (eq (length b) 1))
 
1368
            (setq cf
 
1369
              (cons
 
1370
                (elt christoffels2 (position (car cf) christoffels1))
 
1371
                (cdr cf)
 
1372
              )
 
1373
            )
 
1374
          )
 
1375
          (
 
1376
            (not (and (eq (length a) 3) (eq (length b) 0)))
 
1377
            (return nil)
 
1378
          )
 
1379
        )
 
1380
      )
 
1381
      (
 
1382
        (member (car cf) christoffels2)
 
1383
        (cond
 
1384
          (
 
1385
            (and (eq (length a) 3) (eq (length b) 0))
 
1386
            (setq cf
 
1387
              (cons
 
1388
                (elt christoffels1 (position (car cf) christoffels2))
 
1389
                (cdr cf)
 
1390
              )
 
1391
            )
 
1392
          )
 
1393
          (
 
1394
            (not (and (eq (length a) 2) (eq (length b) 1)))
 
1395
            (return nil)
 
1396
          )
 
1397
        )
 
1398
      )
 
1399
      ((member (car cf) christoffels) (return nil))
 
1400
    )
 
1401
 
 
1402
    (setq f (meval (list cf (cons smlist a) (cons smlist b))))
 
1403
    (and e
 
1404
      (do
 
1405
        ((e e (cdr e)))
 
1406
        ((null e))
 
1407
        (setq f (idiff f (car e)))
 
1408
      )
 
1409
    )
 
1410
    (return (cond ((eq sgn -1) (list '(mtimes) sgn f)) (t f)))
 
1411
  )
 
1412
)
 
1413
 
 
1414
;; In what amounts to quite an abuse of the Kronecker delta concept, we
 
1415
;; permit an exceptional index combination of two contravariant indices.
 
1416
;; This helps lc2kdt convert Levi-Civita symbols in a manner that does
 
1417
;; not require resorting to numeric indices, causing all sorts of problems
 
1418
;; with RENAME and CONTRACT.
 
1419
(defmfun $kdelta (l1 l2)
 
1420
  (setq l2 (append l2 (minusi l1)) l1 (plusi l1))
 
1421
  (cond
 
1422
    (
 
1423
      (and ($listp l1) ($listp l2) (= ($length l1) 0) (= ($length l2) 2))
 
1424
      (cond
 
1425
        ((eq (cadr l2) (caddr l2)) 1)
 
1426
        (
 
1427
          (and (numberp (cadr l2)) (numberp (caddr l2)))
 
1428
          (cond
 
1429
            ((= (cadr l2) (caddr l2)) t)
 
1430
            (t 0)
 
1431
          )
 
1432
        )
 
1433
        (t (list '(%kdelta) l1 l2))
 
1434
      )
 
1435
    )
 
1436
    (
 
1437
      (and ($listp l1) ($listp l2) (= ($length l1) 2) (= ($length l2) 0))
 
1438
      (cond
 
1439
        ((eq (cadr l1) (caddr l1)) 1)
 
1440
        (
 
1441
          (and (numberp (cadr l1)) (numberp (caddr l1)))
 
1442
          (cond
 
1443
            ((= (cadr l1) (caddr l1)) t)
 
1444
            (t 0)
 
1445
          )
 
1446
        )
 
1447
        (t (list '(%kdelta) l1 l2))
 
1448
      )
 
1449
    )
 
1450
    (
 
1451
      (null (and ($listp l1) ($listp l2) (= (length l1) (length l2))))
 
1452
      (merror "Improper arg to DELTA: ~M" (list '(%kdelta) l1 l2))
 
1453
    )
 
1454
    (t (delta (cdr l1) (cdr l2)))
 
1455
  )
 
1456
)
686
1457
 
687
1458
;kdels defines the symmetric combination of the Kronecker symbols
688
1459
 
689
 
(DEFMFUN $KDELS (L1 L2)
690
 
       (COND ((NULL (AND ($LISTP L1)
691
 
                         ($LISTP L2)
692
 
                         (= (LENGTH L1) (LENGTH L2))))
 
1460
(defmfun $kdels (l1 l2)
 
1461
       (cond ((null (and ($listp l1)
 
1462
                         ($listp l2)
 
1463
                         (= (length l1) (length l2))))
693
1464
              (merror "Improper arg to DELTA: ~M"
694
 
                      (LIST '(%KDELS) L1 L2)
 
1465
                      (list '(%kdels) l1 l2)
695
1466
                      ))
696
 
             (T (DELTA (CDR L1) (CDR L2) 1)))) 
697
 
;;
698
 
;;(DECLARE-TOP (FIXNUM I)) 
699
 
;;
700
 
;;(DEFUN DELTA (LOWER UPPER &optional (eps -1))
701
 
;;       (COND ((NULL LOWER) $DIM)
702
 
;;           ((NULL (CDR LOWER))
703
 
;;            (COND ((EQUAL (CAR UPPER) (CAR LOWER))
704
 
;;                   (COND ((NUMBERP (CAR UPPER)) 1.) (T $DIM)))
705
 
;;                  ((AND (NUMBERP (CAR UPPER)) (NUMBERP (CAR LOWER))) 0.)
706
 
;;                  (T (LIST '(%KDELTA)
707
 
;;                           (CONS SMLIST LOWER)
708
 
;;                           (CONS SMLIST UPPER)))))
709
 
;;           (T (DO ((I (LENGTH LOWER) (1- I))
710
 
;;                   (SL LOWER)
711
 
;;                   (TERM)
712
 
;;                   (RESULT)
713
 
;;                   (F (NCONS (CAR UPPER)))
714
 
;;                   (R (CDR UPPER))
715
 
;;                   (SIGN (ODDP (LENGTH LOWER))))
716
 
;;                  ((= I 0.)
717
 
;;                   (SIMPLUS (CONS '(MPLUS) RESULT) 1. T))
718
 
;;                  (SETQ TERM (LIST (DELTA (NCONS (CAR SL)) F eps)
719
 
;;                                   (DELTA (CDR SL) R eps)))
720
 
;;                  (SETQ SL (CDR (APPEND SL (NCONS (CAR SL)))))
721
 
;;                  (SETQ RESULT
722
 
;;                        (CONS (SIMPTIMES (CONS '(MTIMES)
723
 
;;                                               (COND ((OR SIGN
724
 
;;                                                          (ODDP I))
725
 
;;                                                      (CONS eps
726
 
;;                                                            TERM))
727
 
;;                                                     (T TERM)))
 
1467
             (t (delta (cdr l1) (cdr l2) 1)))) 
 
1468
;;
 
1469
;;(declare-top (fixnum i)) 
 
1470
;;
 
1471
;;(defun delta (lower upper &optional (eps -1))
 
1472
;;       (cond ((null lower) $dim)
 
1473
;;           ((null (cdr lower))
 
1474
;;            (cond ((equal (car upper) (car lower))
 
1475
;;                   (cond ((numberp (car upper)) 1.) (t $dim)))
 
1476
;;                  ((and (numberp (car upper)) (numberp (car lower))) 0.)
 
1477
;;                  (t (list '(%kdelta)
 
1478
;;                           (cons smlist lower)
 
1479
;;                           (cons smlist upper)))))
 
1480
;;           (t (do ((i (length lower) (1- i))
 
1481
;;                   (sl lower)
 
1482
;;                   (term)
 
1483
;;                   (result)
 
1484
;;                   (f (ncons (car upper)))
 
1485
;;                   (r (cdr upper))
 
1486
;;                   (sign (oddp (length lower))))
 
1487
;;                  ((= i 0.)
 
1488
;;                   (simplus (cons '(mplus) result) 1. t))
 
1489
;;                  (setq term (list (delta (ncons (car sl)) f eps)
 
1490
;;                                   (delta (cdr sl) r eps)))
 
1491
;;                  (setq sl (cdr (append sl (ncons (car sl)))))
 
1492
;;                  (setq result
 
1493
;;                        (cons (simptimes (cons '(mtimes)
 
1494
;;                                               (cond ((or sign
 
1495
;;                                                          (oddp i))
 
1496
;;                                                      (cons eps
 
1497
;;                                                            term))
 
1498
;;                                                     (t term)))
728
1499
;;                                         1.
729
 
;;                                         NIL)
730
 
;;                              RESULT)))))) 
731
 
(DEFUN DELTA (LOWER UPPER &optional (eps -1))
732
 
  (COND ((NULL LOWER) $DIM)
733
 
        ((NULL (CDR LOWER))
734
 
         (COND ((EQUAL (CAR UPPER) (CAR LOWER))
735
 
                (COND ((NUMBERP (CAR UPPER)) 1.) (T $DIM)))
736
 
               ((AND (NUMBERP (CAR UPPER)) (NUMBERP (CAR LOWER))) 0.)
737
 
               (T (LIST '(%KDELTA) (CONS SMLIST LOWER) (CONS SMLIST UPPER)))))
738
 
        (T (DO ((LEFT NIL (APPEND LEFT (NCONS (CAR RIGHT))))
739
 
                (RIGHT LOWER (CDR RIGHT))
740
 
                (RESULT))
741
 
               ((NULL RIGHT) (SIMPLUS (CONS '(MPLUS) RESULT) 1. T))
742
 
               (SETQ RESULT (CONS (SIMPTIMES
743
 
                                   (LIST '(MTIMES) (DELTA (NCONS (CAR RIGHT)) (NCONS (CAR UPPER)) eps)
744
 
                                         (DELTA (APPEND LEFT (CDR RIGHT)) (CDR UPPER) eps)
745
 
                                         (COND ((ODDP (LENGTH LEFT)) eps) (T 1))
746
 
                                   ) 1. T
747
 
                                  ) RESULT)
 
1500
;;                                         nil)
 
1501
;;                              result)))))) 
 
1502
(defun delta (lower upper &optional (eps -1))
 
1503
  (cond ((null lower) $dim)
 
1504
        ((null (cdr lower))
 
1505
         (cond ((equal (car upper) (car lower))
 
1506
                (cond ((numberp (car upper)) 1.) (t $dim)))
 
1507
               ((and (numberp (car upper)) (numberp (car lower))) 0.)
 
1508
               (t (list '(%kdelta) (cons smlist lower) (cons smlist upper)))))
 
1509
        (t (do ((left nil (append left (ncons (car right))))
 
1510
                (right lower (cdr right))
 
1511
                (result))
 
1512
               ((null right) (simplus (cons '(mplus) result) 1. t))
 
1513
               (setq result (cons (simptimes
 
1514
                                   (list '(mtimes) (delta (ncons (car right)) (ncons (car upper)) eps)
 
1515
                                         (delta (append left (cdr right)) (cdr upper) eps)
 
1516
                                         (cond ((oddp (length left)) eps) (t 1))
 
1517
                                   ) 1. t
 
1518
                                  ) result)
748
1519
              )))))
749
1520
 
750
 
(DECLARE-TOP (NOTYPE I))
 
1521
(declare-top (notype i))
751
1522
 
752
 
(DECLARE-TOP (SPECIAL $OUTCHAR $DISPFLAG LINELABLE FOOBAR DERIVLIST))
 
1523
(declare-top (special $outchar $dispflag linelable foobar derivlist))
 
1524
 
753
1525
 
754
1526
;Displays P([L1],[L2],I1,I2,...) by making the elements of L2 into a single
755
1527
;atom which serves as the exponent and the elements of L1 and I1,I2,... into a
756
1528
;single atom with a comma in between which serves as the subscript.
757
1529
 
758
 
(DEFMFUN $SHOW (f)
759
 
       (progn (makelabel $LINECHAR)
760
 
              (cond ($DISPFLAG
761
 
                     (displa (list '(MLABLE) LINELABLE (ishow (specrepcheck f))))
762
 
;                     (setq $DISPFLAG nil)
 
1530
(defmfun $ishow (f)
 
1531
       (progn (makelabel $linechar)
 
1532
              (cond ($dispflag
 
1533
                     (displa (list '(mlable) linelable (ishow (specrepcheck (derat f)))))
 
1534
;                     (setq $dispflag nil)
763
1535
))
764
 
              (SET LINELABLE f)))
765
 
 
766
 
(DEFUN ISHOW (F) 
767
 
       ((LAMBDA (FOOBAR)                              ;FOOBAR intialized to NIL
768
 
                (COND ((ATOM F) F)
769
 
                      ((RPOBJ F)                      ;If an indexed object ...
770
 
                       (SETQ FOOBAR
771
 
                             (COND ((OR (CDADR F) (CDDDR F))   ;If covariant or
772
 
                                    (CONS (LIST (CAAR F)    ;derivative indices
773
 
                                                'ARRAY)
774
 
                                          (NCONS (MAKNAM (CONS '$ (SPLICE (CDADR F)
775
 
                                                         (CDDDR F)))))))
776
 
                                   (T (CAAR F))))
777
 
                       (COND ((CDADDR F)              ;If contravariant indices
778
 
                              (LIST '(MEXPT SIMP)
779
 
                                    FOOBAR
780
 
                                     (CONS '(MTIMES SIMP)  ;Make indices appear
781
 
                                          (CDADDR F))))    ;as exponents for
782
 
                             (T FOOBAR)))                  ;proper display
783
 
                      (T
784
 
                       (CONS (CAR F) (MAPCAR 'ISHOW (CDR F))))))
785
 
        NIL))                                           ;Map onto subparts of F
786
 
 
787
 
(DEFUN SPLICE (L1 L2) 
788
 
       (COND (L2 (SETQ L2 (CONS '|,| (SPLICE1 L2)))
789
 
                 (AND L1 (SETQ L2 (NCONC (SPLICE1 L1) L2)))
790
 
                 L2)
791
 
             (T (SPLICE1 L1)))) 
792
 
 
793
 
(DEFUN SPLICE1 (L)
794
 
  (COND ((NULL (CDR L))(SPLICE2 (CAR L)))
795
 
        (T (NCONC (SPLICE2 (CAR L))(CONS '| | (SPLICE1 (CDR L)))))))
796
 
 
797
 
(DEFUN SPLICE2 (X)
798
 
  (COND ((FIXP X)(EXPLODE X))
799
 
        (T (CDR (EXPLODEc X)))))
 
1536
              (set linelable f)))
 
1537
 
 
1538
(defun ishow (f) 
 
1539
       ((lambda (foobar)                              ;FOOBAR intialized to NIL
 
1540
                (cond ((atom f) f)
 
1541
                      ((rpobj f)                      ;If an indexed object ...
 
1542
                       (setq foobar
 
1543
                             (cond ((or (covi f) (cdddr f))   ;If covariant or
 
1544
                                    (cons (list (caar f)    ;derivative indices
 
1545
                                                'array)
 
1546
                                          (ncons (maknam (cons '$ (splice (covi f)
 
1547
                                                         (cdddr f)))))))
 
1548
                                   (t (caar f))))
 
1549
                       (cond ((conti f)              ;If contravariant indices
 
1550
                              (list '(mexpt simp)
 
1551
                                    foobar
 
1552
                                     (cons '(mtimes simp)  ;Make indices appear
 
1553
                                          (conti f))))    ;as exponents for
 
1554
                             (t foobar)))                  ;proper display
 
1555
                      (t
 
1556
                       (cons (car f) (mapcar 'ishow (cdr f))))))
 
1557
        nil))                                           ;Map onto subparts of F
 
1558
 
 
1559
(defun splice (l1 l2) 
 
1560
       (cond (l2 (setq l2 (cons '|,| (splice1 l2)))
 
1561
                 (and l1 (setq l2 (nconc (splice1 l1) l2)))
 
1562
                 l2)
 
1563
             (t (splice1 l1)))) 
 
1564
 
 
1565
(defun splice1 (l)
 
1566
  (cond ((null (cdr l))(splice2 (car l)))
 
1567
        (t (nconc (splice2 (car l))(cons '| | (splice1 (cdr l)))))))
 
1568
 
 
1569
(defun splice2 (x)
 
1570
  (cond ((fixp x)(explode x))
 
1571
        (t (cdr (explodec x)))))
 
1572
;       (t (cdr (explodec (print-invert-case x))))))
800
1573
 
801
 
(DEFUN DERIV (E) 
802
 
       (PROG (EXP Z COUNT V) 
803
 
             (COND ((NULL (CDR E)) (RETURN (STOTALDIFF (CAR E))))
804
 
                   ((NULL (CDDR E)) (NCONC E '(1.))))
805
 
             (SETQ EXP (CAR E) Z (SETQ E (APPEND E NIL)))
806
 
        LOOP (COND ((OR (NULL DERIVLIST) (ZL-MEMBER (CADR Z) DERIVLIST))
807
 
                    (GO DOIT)))
 
1574
(defun deriv (e) 
 
1575
       (prog (exp z count v) 
 
1576
             (cond ((null (cdr e)) (return (stotaldiff (car e))))
 
1577
                   ((null (cddr e)) (nconc e '(1.))))
 
1578
             (setq exp (car e) z (setq e (append e nil)))
 
1579
        loop (cond ((or (null derivlist) (zl-member (cadr z) derivlist))
 
1580
                    (go doit)))
808
1581
                                                       ;DERIVLIST is set by $EV
809
 
             (SETQ Z (CDR Z))
810
 
        LOOP2(COND ((CDR Z) (GO LOOP))
811
 
                   ((NULL (CDR E)) (RETURN EXP))
812
 
                   (T (GO NOUN)))
813
 
        DOIT (COND ((NULL (CDDR Z))
 
1582
             (setq z (cdr z))
 
1583
        loop2(cond ((cdr z) (go loop))
 
1584
                   ((null (cdr e)) (return exp))
 
1585
                   (t (go noun)))
 
1586
        doit (cond ((null (cddr z))
814
1587
                    (merror "Wrong number of args to DERIVATIVE"))
815
 
                   ((NOT (FIXP (SETQ COUNT (CADDR Z)))) (GO NOUN))
816
 
                   ((< COUNT 0.)
 
1588
                   ((not (fixp (setq count (caddr z)))) (go noun))
 
1589
                   ((< count 0.)
817
1590
                    (merror "Improper count to DIFF: ~M"
818
 
                            COUNT)))
819
 
        LOOP1(SETQ V (CADR Z))
820
 
             (AND (FIXP V)
821
 
                  $COORDINATES
822
 
                  (> V 0.)
823
 
                  (NOT (> V $DIM))
824
 
                  (SETQ V
825
 
                        (COND ((ATOM $COORDINATES)
826
 
                               (MEVAL1 (LIST (LIST $COORDINATES 'SIMP 'ARRAY)
827
 
                                             V)))
828
 
                              ((EQ (CAAR $COORDINATES) 'MLIST)
829
 
                               (COND ((NOT (< V
830
 
                                              (LENGTH $COORDINATES)))
 
1591
                            count)))
 
1592
        loop1(setq v (cadr z))
 
1593
             (and (fixp v)
 
1594
                  $vect_coords
 
1595
                  (> v 0.)
 
1596
                  (not (> v $dim))
 
1597
                  (setq v
 
1598
                        (cond ((atom $vect_coords)
 
1599
                               (meval1 (list (list $vect_coords 'simp 'array)
 
1600
                                             v)))
 
1601
                              ((eq (caar $vect_coords) 'mlist)
 
1602
                               (cond ((not (< v
 
1603
                                              (length $vect_coords)))
831
1604
                                      (merror
832
1605
"Coordinate list too short for derivative index"))
833
 
                                     (T (NTH V $COORDINATES))))
834
 
                              (T V))))
835
 
             (COND ((ZEROP COUNT) (RPLACD Z (CDDDR Z)) (GO LOOP2))
836
 
                   ((ZEROP1 (SETQ EXP (SDIFF EXP V))) (RETURN 0.)))
837
 
             (SETQ COUNT (1- COUNT))
838
 
             (GO LOOP1)
839
 
        NOUN (RETURN (DIFF%DERIV (CONS EXP (CDR E))))))
840
 
 
841
 
(DEFUN CHAINRULE1 (E X)                                 ; --YS 15.02.02
842
 
        (PROG (Y)
843
 
                (COND ((AND (ATOM E) (EQ (SETQ Y (CAR (MGET E 'DEPENDS)))
844
 
                        (CADR $COORD))) (RETURN (SUBST X Y (CHAINRULE E Y))))
845
 
                (T (RETURN (CHAINRULE E X))))))
 
1606
                                     (t (nth v $vect_coords))))
 
1607
                              (t v))))
 
1608
             (cond ((zerop count) (rplacd z (cdddr z)) (go loop2))
 
1609
                   ((zerop1 (setq exp (sdiff exp v))) (return 0.)))
 
1610
             (setq count (1- count))
 
1611
             (go loop1)
 
1612
        noun (return (diff%deriv (cons exp (cdr e))))))
 
1613
 
 
1614
(defun chainrule1 (e x)                                 ; --ys 15.02.02
 
1615
        (prog (y)
 
1616
                (cond ((and (atom e) (eq (setq y (car (mget e 'depends)))
 
1617
                        (cadr $coord))) (return (subst x y (chainrule e y))))
 
1618
                (t (return (chainrule e x))))))
 
1619
 
 
1620
(defun diffexpt1 (e x)
 
1621
;; RETURN: n*v^n*rename(v'/v) where e=v^n
 
1622
  (list '(mtimes) (caddr e) e
 
1623
    ($rename
 
1624
      (list '(mtimes) (list '(mexpt) (cadr e) -1)
 
1625
             (sdiff (cadr e) x)
 
1626
      )
 
1627
    )
 
1628
  )
 
1629
)
846
1630
 
847
1631
;Redefined so that the derivative of any indexed object appends on the
848
1632
;coordinate index in sorted order unless the indexed object was declared
849
1633
;constant in which case 0 is returned.
850
1634
#+Franz (sstatus translink nil) ; make sdiff take hold
851
1635
#+Franz (sstatus translink t)
852
 
(DEFUN SDIFF (E X) 
853
 
       (COND ((MNUMP E) 0.)
854
 
             ((ALIKE1 E X) 1.)
855
 
             ((OR (ATOM E) (MEMQ 'ARRAY (CDAR E)))
856
 
              (CHAINRULE1 E X))
857
 
             ((MGET (CAAR E) '$CONSTANT) 0.)                    ;New line added
858
 
             ((EQ (CAAR E) 'MRAT) (RATDX E X))
859
 
             ((EQ (CAAR E) 'MPLUS)
860
 
              (SIMPLUS (CONS '(MPLUS) (SDIFFMAP (CDR E) X))
 
1636
(defun sdiff (e x) 
 
1637
       (cond ((mnump e) 0.)
 
1638
             ((alike1 e x) 1.)
 
1639
             ((or (atom e) (memq 'array (cdar e)))
 
1640
              (chainrule1 e x))
 
1641
             ((mget (caar e) '$constant) 0.)                    ;New line added
 
1642
             ((eq (caar e) 'mrat) (ratdx e x))
 
1643
             ((eq (caar e) 'mplus)
 
1644
              (simplus (cons '(mplus) (sdiffmap (cdr e) x))
861
1645
                       1.
862
 
                       T))
863
 
             ((EQ (CAAR E) 'MEQUAL)
864
 
              (LIST (CAR E) (SDIFF (CADR E) X) (SDIFF (CADDR E) X)))
865
 
             ((EQ (CAAR E) '$MATRIX)
866
 
              (CONS (CAR E)
867
 
                    (MAPCAR 
868
 
                     (FUNCTION (LAMBDA (Y) 
869
 
                                       (CONS (CAR Y)
870
 
                                             (SDIFFMAP (CDR Y) X))))
871
 
                     (CDR E))))
872
 
             ((EQ (CAAR E) 'MTIMES)
873
 
              (ADDN (SDIFFTIMES (CDR E) X) T))
874
 
             ((EQ (CAAR E) 'MEXPT) (DIFFEXPT E X))
875
 
             ((RPOBJ E) (DIFFRPOBJ E X))                        ;New line added
876
 
             ((AND (BOUNDP '$METRIC) (EQ (CAAR E) '%DETERMINANT);New line added
877
 
                   (EQ (CADR E) $METRIC))
878
 
              ((LAMBDA (DUMMY)
879
 
                       (setq dummy ($dummy))
880
 
                       (COND ((EQ DUMMY X) (setq dummy ($dummy))))
881
 
                       (LIST '(MTIMES SIMP) 2. E
882
 
                             (LIST '($CHR2 SIMP) (CONS SMLIST (LIST DUMMY X))
883
 
                                   (CONS SMLIST (NCONS DUMMY)))))
884
 
               NIL))
885
 
             ((NOT (DEPENDS E X))
886
 
              (COND ((FIXP X) (LIST '(%DERIVATIVE) E X))
887
 
                    ((ATOM X) 0.)
888
 
                    (T (LIST '(%DERIVATIVE E X)))))
 
1646
                       t))
 
1647
             ((eq (caar e) 'mequal)
 
1648
              (list (car e) (sdiff (cadr e) x) (sdiff (caddr e) x)))
 
1649
             ((eq (caar e) '$matrix)
 
1650
              (cons (car e)
 
1651
                    (mapcar 
 
1652
                     (function (lambda (y) 
 
1653
                                       (cons (car y)
 
1654
                                             (sdiffmap (cdr y) x))))
 
1655
                     (cdr e))))
 
1656
             ((eq (caar e) 'mtimes)
 
1657
              (addn (sdifftimes (cdr e) x) t))
 
1658
             ((eq (caar e) 'mexpt) (diffexpt1 e x))
 
1659
;;           ((rpobj e) (diffrpobj e x))                        ;New line added
 
1660
;;           ((and (boundp '$imetric) (eq (caar e) '%determinant);New line added
 
1661
;;                 (eq (cadr e) $imetric))
 
1662
;;            ((lambda (dummy)
 
1663
;;                     (setq dummy ($idummy))
 
1664
;;                     (cond ((eq dummy x) (setq dummy ($idummy))))
 
1665
;;                     (list '(mtimes simp) 2. e
 
1666
;;                           (list '($ichr2 simp) (cons smlist (list dummy x))
 
1667
;;                                 (cons smlist (ncons dummy)))))
 
1668
;;             nil))
 
1669
             ((not (depends e x))
 
1670
              (cond ((fixp x) (list '(%derivative) e x))
 
1671
                    ((atom x) 0.)
 
1672
                    (t (list '(%derivative) e x))))
889
1673
                                                          ;This line moved down
890
 
             ((EQ (CAAR E) 'MNCTIMES)
891
 
              (SIMPLUS (LIST '(MPLUS)
892
 
                             (LIST '(MNCTIMES)
893
 
                                   (SDIFF (CADR E) X)
894
 
                                   (CADDR E))
895
 
                             (LIST '(MNCTIMES)
896
 
                                   (CADR E)
897
 
                                   (SDIFF (CADDR E) X)))
898
 
                       1.
899
 
                       NIL))
900
 
             ((EQ (CAAR E) 'MNCEXPT) (DIFFNCEXPT E X))
901
 
             ((EQ (CAAR E) '%INTEGRATE) (DIFFINT E X))
902
 
             ((EQ (CAAR E) '%DERIVATIVE)
903
 
              (COND ((OR (ATOM (CADR E))
904
 
                         (MEMQ 'ARRAY (CDAADR E)))
905
 
                     (CHAINRULE1 E X))
906
 
                    ((FREEL (CDR E) X) 0.)
907
 
                    (T (DIFF%DERIV (LIST E X 1.)))))
908
 
             ((MEMQ (CAAR E) '(%SUM %PRODUCT)) (DIFFSUMPROD E X))
909
 
             (T (SDIFFGRAD E X)))) 
910
 
 
911
 
(defun DIFFRPOBJ (e x)                         ;Derivative of an indexed object
912
 
       (cond ((and (memq (caar e) $COORD) (null (cdadr e))
913
 
                   (equal (length (cdaddr e)) 1) (null (cdddr e)))
914
 
              (delta (ncons x) (cdaddr e)))
915
 
             (t (NCONC (LIST (CAR E) (CADR E) (CADDR E))
916
 
                       (COND ((NULL (CDDDR E)) (NCONS X))
917
 
                             (T (itensor-SORT (APPEND (CDDDR E) (NCONS X)))))))))
918
 
 
919
 
 
920
 
 
921
 
(DEFMFUN $LC0 (L1) 
922
 
       (PROG (A B C SIGN) 
923
 
             (SETQ A (CDR L1))
924
 
             (IFNOT (AND A (CDR A)) (RETURN (LIST '(%LC) L1)))
925
 
             (SETQ B A)
926
 
        LOOP1(IFNOT (FIXP (CAR A)) (RETURN (LIST '(%LC) L1)))
927
 
             (AND (SETQ A (CDR A)) (GO LOOP1))
928
 
        LOOP3(SETQ A (CAR B) B (CDR B) C B)
929
 
        LOOP2(COND ((= (CAR C) A) (RETURN 0.))
930
 
                   ((< (CAR C) A) (SETQ SIGN (NOT SIGN))))
931
 
             (AND (SETQ C (CDR C)) (GO LOOP2))
932
 
             (AND (CDR B) (GO LOOP3))
933
 
             (RETURN (COND (SIGN -1.) (T 1.))))) 
934
 
(DEFMFUN $LC (L1 &optional (L2 nil))
935
 
        (COND
936
 
                ((EQ L2 nil) ($LC0 L1))
937
 
                ((LIKE L1 '((MLIST)))
938
 
                (PROG (l) (SETQ l nil)
939
 
                  (DO ((I ($LENGTH L2) (1- I))) ((< I 1)) (SETQ l (CONS I l)))
940
 
                  (RETURN (LIST '($KDELTA SIMP) (CONS SMLIST l) L2))
 
1674
             ((eq (caar e) 'mnctimes)
 
1675
              (simplus (list '(mplus)
 
1676
                             (list '(mnctimes)
 
1677
                                   (sdiff (cadr e) x)
 
1678
                                   (caddr e))
 
1679
                             (list '(mnctimes)
 
1680
                                   (cadr e)
 
1681
                                   (sdiff (caddr e) x)))
 
1682
                       1.
 
1683
                       nil))
 
1684
             ((eq (caar e) 'mncexpt) (diffncexpt e x))
 
1685
             ((eq (caar e) '%integrate) (diffint e x))
 
1686
             ((eq (caar e) '%derivative)
 
1687
              (cond ((or (atom (cadr e))
 
1688
                         (memq 'array (cdaadr e)))
 
1689
                     (chainrule1 e x))
 
1690
                    ((freel (cdr e) x) 0.)
 
1691
                    (t (diff%deriv (list e x 1.)))))
 
1692
             ((memq (caar e) '(%sum %product)) (diffsumprod e x))
 
1693
             (t (sdiffgrad e x)))) 
 
1694
 
 
1695
; VTT: several of these functions have been copied verbatim from comm.lisp and
 
1696
; comm2.lisp, in order to implement indicial differentiation as distinct from
 
1697
; differentiation with respect to an external variable.
 
1698
 
 
1699
(defun idiffmap (e x) (mapcar #'(lambda (term) (idiff term x)) e))
 
1700
 
 
1701
(defun idifftimes (l x)
 
1702
  (prog (term left out)
 
1703
   loop (setq term (car l) l (cdr l))
 
1704
   (setq out (cons (muln (cons (idiff term x) (append left l)) t) out))
 
1705
   (if (null l) (return out))
 
1706
   (setq left (cons term left))
 
1707
   (go loop)))
 
1708
 
 
1709
(defun idiffexpt1 (e x)
 
1710
;; RETURN: n*v^n*rename(v'/v) where e=v^n
 
1711
  (list '(mtimes) (caddr e) e
 
1712
    ($rename
 
1713
      (list '(mtimes) (list '(mexpt) (cadr e) -1)
 
1714
             (idiff (cadr e) x)
 
1715
      )
 
1716
    )
 
1717
  )
 
1718
)
 
1719
 
 
1720
(defun idiffexpt (e x)
 
1721
  (if (mnump (caddr e))
 
1722
      (mul3 (caddr e) (power (cadr e) (addk (caddr e) -1)) (idiff (cadr e) x))
 
1723
      (mul2 e (add2 (mul3 (power (cadr e) -1) (caddr e) (idiff (cadr e) x))
 
1724
            (mul2 (simplifya (list '(%log) (cadr e)) t)
 
1725
              (idiff (caddr e) x))))))
 
1726
 
 
1727
(defmfun idiffint (e x)
 
1728
  (let (a)
 
1729
    (cond ((null (cdddr e))
 
1730
       (cond ((alike1 x (caddr e)) (cadr e))
 
1731
         ((and (not (atom (caddr e))) (atom x) (not (free (caddr e) x)))
 
1732
          (mul2 (cadr e) (idiff (caddr e) x)))
 
1733
         ((or ($constantp (setq a (idiff (cadr e) x)))
 
1734
              (and (atom (caddr e)) (free a (caddr e))))
 
1735
          (mul2 a (caddr e)))
 
1736
         (t (simplifya (list '(%integrate) a (caddr e)) t))))
 
1737
      ((alike1 x (caddr e)) (addn (idiffint1 (cdr e) x x) t))
 
1738
      (t (addn (cons (if (equal (setq a (idiff (cadr e) x)) 0)
 
1739
                 0
 
1740
                 (simplifya (list '(%integrate) a (caddr e)
 
1741
                          (cadddr e) (car (cddddr e)))
 
1742
                    t))
 
1743
             (idiffint1 (cdr e) x (caddr e)))
 
1744
           t)))))
 
1745
 
 
1746
(defun idiffint1 (e x y)
 
1747
  (let ((u (idiff (cadddr e) x)) (v (idiff (caddr e) x)))
 
1748
    (list (if (pzerop u) 0 (mul2 u (maxima-substitute (cadddr e) y (car e))))
 
1749
      (if (pzerop v) 0 (mul3 v (maxima-substitute (caddr e) y (car e)) -1)))))
 
1750
 
 
1751
(defun idiff%deriv (e) (let (derivflag) (simplifya (cons '(%idiff) e) t)))
 
1752
 
 
1753
(defun ideriv (e)
 
1754
  (prog (exp z count)
 
1755
     (cond ((null e) (wna-err '$idiff))
 
1756
       ((null (cdr e)) (return (stotaldiff (car e))))
 
1757
       ((null (cddr e)) (nconc e '(1))))
 
1758
     (setq exp (car e) z (setq e (copy-top-level e)))
 
1759
     loop (if (or (null derivlist) (zl-member (cadr z) derivlist)) (go doit))
 
1760
                    ; DERIVLIST is set by $EV
 
1761
     (setq z (cdr z))
 
1762
     loop2(cond ((cdr z) (go loop))
 
1763
        ((null (cdr e)) (return exp))
 
1764
        (t (go noun)))
 
1765
     doit (cond ((nonvarcheck (cadr z) '$idiff))
 
1766
        ((null (cddr z)) (wna-err '$idiff))
 
1767
        ((not (eq (ml-typep (caddr z)) 'fixnum)) (go noun))
 
1768
        ((minusp (setq count (caddr z)))
 
1769
         (merror "Improper count to IDIFF:~%~M" count)))
 
1770
     loop1(cond ((zerop count) (rplacd z (cdddr z)) (go loop2))
 
1771
        ((equal (setq exp (idiff exp (cadr z))) 0) (return 0)))
 
1772
     (setq count (f1- count))
 
1773
     (go loop1)
 
1774
     noun (return (idiff%deriv (cons exp (cdr e))))))
 
1775
 
 
1776
 
 
1777
(defmfun idiffncexpt (e x)
 
1778
  ((lambda (base* pow)
 
1779
     (cond ((and (mnump pow) (or (not (eq (ml-typep pow) 'fixnum)) (< pow 0))) ; POW cannot be 0
 
1780
        (idiff%deriv (list e x 1)))
 
1781
       ((and (atom base*) (eq base* x) (free pow base*))
 
1782
        (mul2* pow (list '(mncexpt) base* (add2 pow -1))))
 
1783
       ((ml-typep pow 'fixnum)
 
1784
        ((lambda (deriv ans)
 
1785
           (do ((i 0 (f1+ i))) ((= i pow))
 
1786
         (setq ans (cons (list '(mnctimes) (list '(mncexpt) base* i)
 
1787
                       (list '(mnctimes) deriv
 
1788
                         (list '(mncexpt) base* (f- pow 1 i))))
 
1789
                 ans)))
 
1790
           (addn ans nil))
 
1791
         (idiff base* x) nil))
 
1792
       ((and (not (depends pow x)) (or (atom pow) (and (atom base*) (free pow base*))))
 
1793
        ((lambda (deriv index)
 
1794
           (simplifya
 
1795
        (list '(%sum)
 
1796
              (list '(mnctimes) (list '(mncexpt) base* index)
 
1797
                (list '(mnctimes) deriv
 
1798
                  (list '(mncexpt) base*
 
1799
                    (list '(mplus) pow -1 (list '(mtimes) -1 index)))))
 
1800
              index 0 (list '(mplus) pow -1)) nil))
 
1801
         (idiff base* x) (gensumindex)))
 
1802
       (t (idiff%deriv (list e x 1)))))
 
1803
   (cadr e) (caddr e)))
 
1804
 
 
1805
(defmfun idiffsumprod (e x)
 
1806
  (cond ((or (not (atom x)) (not (free (cadddr e) x)) (not (free (car (cddddr e)) x)))
 
1807
     (idiff%deriv (list e x 1)))
 
1808
    ((eq (caddr e) x) 0)
 
1809
    (t (let ((u (idiff (cadr e) x)))
 
1810
         (setq u (simplifya (list '(%sum)
 
1811
                      (if (eq (caar e) '%sum) u (div u (cadr e)))
 
1812
                      (caddr e) (cadddr e) (car (cddddr e)))
 
1813
                t))
 
1814
         (if (eq (caar e) '%sum) u (mul2 e u))))))
 
1815
 
 
1816
(defun idiffgrad (e x)
 
1817
  (let ((fun (caar e)) grad args)
 
1818
    (cond ((and (eq fun 'mqapply) (oldget (caaadr e) 'grad))
 
1819
       (idiffgrad (cons (cons (caaadr e) nil) (append (cdadr e) (cddr e)))
 
1820
              x))
 
1821
      ((or (eq fun 'mqapply) (null (setq grad (oldget fun 'grad))))
 
1822
       (if (not (depends e x)) 0 (idiff%deriv (list e x 1))))
 
1823
      ((not (= (length (cdr e)) (length (car grad))))
 
1824
       (merror "Wrong number of arguments for ~:M" fun))
 
1825
      (t (setq args (idiffmap (cdr e) x))
 
1826
         (addn (mapcar
 
1827
            #'mul2
 
1828
            (cdr (substitutel
 
1829
              (cdr e) (car grad)
 
1830
              (do ((l1 (cdr grad) (cdr l1))
 
1831
                   (args args (cdr args)) (l2))
 
1832
                  ((null l1) (cons '(mlist) (nreverse l2)))
 
1833
                (setq l2 (cons (cond ((equal (car args) 0) 0)
 
1834
                         (t (car l1)))
 
1835
                       l2)))))
 
1836
            args)
 
1837
           t)))))
 
1838
 
 
1839
(defmfun $idiff n (let (derivlist) (ideriv (listify n))))
 
1840
 
 
1841
(defmfun idiff (e x)
 
1842
  (cond
 
1843
         (($constantp e) 0.)
 
1844
             ((alike1 e x) 1.)
 
1845
             ((or (atom e) (memq 'array (cdar e)))
 
1846
;;            (ichainrule e x))
 
1847
;;        (idiff%deriv (list e x 1)))
 
1848
          0)
 
1849
             ((mget (caar e) '$constant) 0.)                    ;New line added
 
1850
             ((eq (caar e) 'mrat) (ratdx e x))
 
1851
             ((eq (caar e) 'mplus)
 
1852
              (simplus (cons '(mplus) (idiffmap (cdr e) x))
 
1853
                       1.
 
1854
                       t))
 
1855
             ((eq (caar e) 'mequal)
 
1856
              (list (car e) ($idiff (cadr e) x) ($idiff (caddr e) x)))
 
1857
             ((eq (caar e) '$matrix)
 
1858
              (cons (car e)
 
1859
                    (mapcar 
 
1860
                     (function (lambda (y) 
 
1861
                                       (cons (car y)
 
1862
                                             (idiffmap (cdr y) x))))
 
1863
                     (cdr e))))
 
1864
             ((eq (caar e) 'mtimes)
 
1865
              (addn (idifftimes (cdr e) x) t))
 
1866
             ((eq (caar e) 'mexpt) (idiffexpt1 e x))
 
1867
        ((rpobj e) (diffrpobj e x))
 
1868
    ((and (boundp '$imetric) (eq (caar e) '%determinant)
 
1869
      (eq (cadr e) $imetric))
 
1870
      ((lambda (dummy)
 
1871
       (setq dummy ($idummy))
 
1872
       (cond ((eq dummy x) (setq dummy ($idummy))))
 
1873
       (list '(mtimes simp) 2. e
 
1874
       (list '($ichr2 simp) (cons smlist (list dummy x))
 
1875
       (cons smlist (ncons dummy)))))
 
1876
       nil))
 
1877
             ((eq (caar e) 'mnctimes)
 
1878
              (simplus (list '(mplus)
 
1879
                             (list '(mnctimes)
 
1880
                                   ($idiff (cadr e) x)
 
1881
                                   (caddr e))
 
1882
                             (list '(mnctimes)
 
1883
                                   (cadr e)
 
1884
                                   ($idiff (caddr e) x)))
 
1885
                       1.
 
1886
                       nil))
 
1887
             ((eq (caar e) 'mncexpt) (idiffncexpt e x))
 
1888
             ((eq (caar e) '%integrate) (idiffint e x))
 
1889
             ((eq (caar e) '%derivative)
 
1890
              (cond ((or (atom (cadr e))
 
1891
                         (memq 'array (cdaadr e)))
 
1892
;;                   (ichainrule e x))
 
1893
;;           (idiff%deriv (list e x 1)))
 
1894
             0)
 
1895
;;                  ((freel (cdr e) x) 0.)
 
1896
                    (t (idiff%deriv (list e x 1.)))))
 
1897
             ((memq (caar e) '(%sum %product)) (idiffsumprod e x))
 
1898
             (t (idiffgrad e x))
 
1899
  )
 
1900
)
 
1901
 
 
1902
(defun diffrpobj (e x)                  ;Derivative of an indexed object
 
1903
  (cond
 
1904
    (               ; Special case: functions declared with coord()
 
1905
      (and
 
1906
        (memq (caar e) $coord) (null (cdadr e))
 
1907
        (equal (length (cdaddr e)) 1) (null (cdddr e))
 
1908
      )
 
1909
      (delta (ncons x) (cdaddr e))
 
1910
    )
 
1911
    (t              ; Everything else
 
1912
      (nconc
 
1913
        (list (car e) (cadr e) (caddr e))
 
1914
        (cond
 
1915
          (
 
1916
            (null (cdddr e))
 
1917
            (ncons x)
 
1918
          )
 
1919
          (         ; Derivative indices do not commute when frames are used
 
1920
            (or $iframe_flag $itorsion_flag)
 
1921
            (append (cdddr e) (ncons x))
 
1922
          )
 
1923
          (t
 
1924
            (itensor-sort (append (cdddr e) (ncons x)))
 
1925
          )
 
1926
        )
 
1927
      )
 
1928
    )
 
1929
  )
 
1930
)
 
1931
 
 
1932
 
 
1933
(defmfun $lc0 (l1) 
 
1934
       (prog (a b c sign) 
 
1935
             (setq a (cdr l1))
 
1936
             (ifnot (and a (cdr a)) (return (list '(%levi_civita) l1)))
 
1937
             (setq b a)
 
1938
        loop1(ifnot (fixp (car a)) (return (list '(%levi_civita) l1)))
 
1939
             (and (setq a (cdr a)) (go loop1))
 
1940
        loop3(setq a (car b) b (cdr b) c b)
 
1941
        loop2(cond ((= (car c) a) (return 0.))
 
1942
                   ((< (car c) a) (setq sign (not sign))))
 
1943
             (and (setq c (cdr c)) (go loop2))
 
1944
             (and (cdr b) (go loop3))
 
1945
             (return (cond (sign -1.) (t 1.))))) 
 
1946
(defmfun $levi_civita (l1 &optional (l2 nil))
 
1947
        (cond
 
1948
                ((eq l2 nil) ($lc0 l1))
 
1949
                ((like l1 '((mlist)))
 
1950
                (prog (l) (setq l nil)
 
1951
                  (do ((i ($length l2) (1- i))) ((< i 1)) (setq l (cons i l)))
 
1952
                  (return (list '($kdelta simp) (cons smlist l) l2))
941
1953
                 ))
942
 
                ((LIKE L2 '((MLIST)))
943
 
                (PROG (l) (SETQ l nil)
944
 
                  (DO ((I ($LENGTH L1) (1- I))) ((< I 1)) (SETQ l (CONS I l)))
945
 
                  (RETURN (LIST '($KDELTA SIMP) L1 (CONS SMLIST l)))
 
1954
                ((like l2 '((mlist)))
 
1955
                (prog (l) (setq l nil)
 
1956
                  (do ((i ($length l1) (1- i))) ((< i 1)) (setq l (cons i l)))
 
1957
                  (return (list '($kdelta simp) l1 (cons smlist l)))
946
1958
                ))
947
 
                (T (MERROR "Mixed-index Levi-Civita symbols not supported"))
 
1959
                (t (merror "Mixed-index Levi-Civita symbols not supported"))
948
1960
        )
949
1961
)
950
1962
 
951
1963
;; simplification rules for the totally antisymmetric LC symbol
952
 
(DEFUN $LC_L (E)
953
 
    (PROG (L1 L2 L N)
954
 
        (CATCH 'MATCH
955
 
          (COND ((ATOM E) (MATCHERR)))
956
 
          (COND ((ATOM (CAR E)) (MATCHERR)))
957
 
          (COND ((NOT (OR (EQ (CAAR E) '$LC) (EQ (CAAR E) '%LC))) (MATCHERR)))
958
 
          (COND ((NOT ($LISTP (SETQ L1 (CADR E)))) (MATCHERR)))
959
 
          (COND ((NOT (ALIKE1 '((MLIST SIMP)) (SETQ L2 (CADDR E)))) (MATCHERR)))
960
 
          (COND ((CDDDR E) (MATCHERR)))
961
 
          (SETQ N ($LENGTH L1))
962
 
          (SETQ L NIL)
963
 
          (DO ((I N (1- I))) ((< I 1)) (SETQ l (CONS ($DUMMY) L)))
964
 
          (RETURN (LIST '(MTIMES SIMP) -1 ($KDELTA L1 (CONS SMLIST L))
965
 
                (LIST (CONS (CAAR E) '(SIMP)) (CONS SMLIST L) (NCONS SMLIST))
966
 
                (LIST '(MEXPT SIMP) (MEVAL (LIST 'MFACTORIAL N)) -1))
967
 
          )
968
 
        )
969
 
    )
970
 
)
971
 
 
972
 
(DEFUN $LC_U (E)
973
 
    (PROG (L1 L2 L N)
974
 
        (CATCH 'MATCH
975
 
          (COND ((ATOM E) (MATCHERR)))
976
 
          (COND ((ATOM (CAR E)) (MATCHERR)))
977
 
          (COND ((NOT (OR (EQ (CAAR E) '$LC) (EQ (CAAR E) '%LC))) (MATCHERR)))
978
 
          (COND ((NOT (ALIKE1 '((MLIST SIMP)) (SETQ L1 (CADR E)))) (MATCHERR)))
979
 
          (COND ((NOT ($LISTP (SETQ L2 (CADDR E)))) (MATCHERR)))
980
 
          (COND ((CDDDR E) (MATCHERR)))
981
 
          (SETQ N ($LENGTH L2))
982
 
          (SETQ L NIL)
983
 
          (DO ((I N (1- I))) ((< I 1)) (SETQ l (CONS ($DUMMY) L)))
984
 
          (RETURN (LIST '(MTIMES SIMP) -1 ($KDELTA (CONS SMLIST L) L2)
985
 
                (LIST (CONS (CAAR E) '(SIMP)) (NCONS SMLIST) (CONS SMLIST L))
986
 
                (LIST '(MEXPT SIMP) (MEVAL (LIST 'MFACTORIAL N)) -1))
987
 
          )
988
 
        )
989
 
    )
990
 
)
991
 
 
992
 
(ADD2LNC '$LC_L $RULES)
993
 
(ADD2LNC '$LC_U $RULES)
 
1964
(defun $lc_l (e)
 
1965
    (prog (l1 l2 l nn)
 
1966
        (catch 'match
 
1967
          (cond ((atom e) (matcherr)))
 
1968
          (cond ((atom (car e)) (matcherr)))
 
1969
          (cond ((not (or (eq (caar e) '$levi_civita) (eq (caar e) '%levi_civita))) (matcherr)))
 
1970
          (cond ((not ($listp (setq l1 ($covi e)))) (matcherr)))
 
1971
          (cond ((not (alike1 '((mlist simp)) (setq l2 ($conti e)))) (matcherr)))
 
1972
          (cond ((cdddr e) (matcherr)))
 
1973
          (setq nn ($length l1))
 
1974
          (setq l nil)
 
1975
          (do ((i nn (1- i))) ((< i 1)) (setq l (cons ($idummy) l) n $icounter))
 
1976
          (return (values (list '(mtimes simp) ($kdelta l1 (cons smlist l))
 
1977
                (list (cons (caar e) '(simp)) (cons smlist l) (ncons smlist))
 
1978
                (list '(mexpt simp) (meval (list 'mfactorial nn)) -1)) t)
 
1979
          )
 
1980
        )
 
1981
    )
 
1982
)
 
1983
 
 
1984
(defun $lc_u (e)
 
1985
    (prog (l1 l2 l nn)
 
1986
        (catch 'match
 
1987
          (cond ((atom e) (matcherr)))
 
1988
          (cond ((atom (car e)) (matcherr)))
 
1989
          (cond ((not (or (eq (caar e) '$levi_civita) (eq (caar e) '%levi_civita))) (matcherr)))
 
1990
          (cond ((not (alike1 '((mlist simp)) (setq l1 ($covi e)))) (matcherr)))
 
1991
          (cond ((not ($listp (setq l2 ($conti e)))) (matcherr)))
 
1992
          (cond ((cdddr e) (matcherr)))
 
1993
          (setq nn ($length l2))
 
1994
          (setq l nil)
 
1995
          (do ((i nn (1- i))) ((< i 1)) (setq l (cons ($idummy) l) n $icounter))
 
1996
          (return (values (list '(mtimes simp) ($kdelta (cons smlist l) l2)
 
1997
                (list (cons (caar e) '(simp)) (ncons smlist) (cons smlist l))
 
1998
                (list '(mexpt simp) (meval (list 'mfactorial nn)) -1)) t)
 
1999
          )
 
2000
        )
 
2001
    )
 
2002
)
 
2003
 
 
2004
(add2lnc '$lc_l $rules)
 
2005
(add2lnc '$lc_u $rules)
994
2006
 
995
 
(DECLARE-TOP (SPECIAL E EMPTY $FLIPFLAG))
996
 
 
997
 
(SETQ $FLIPFLAG NIL EMPTY '((MLIST SIMP) ((MLIST SIMP)) ((MLIST SIMP)))) 
998
 
 
999
 
(DEFUN NONUMBER (L)
1000
 
        (COND
1001
 
                ((NUMBERP (CAR L)) (NONUMBER (CDR L)))
1002
 
                ((EQ L NIL) ())
1003
 
                (T (CONS (CAR L) (NONUMBER (CDR L))))
 
2007
(declare-top (special e empty $flipflag))
 
2008
 
 
2009
(setq $flipflag nil empty '((mlist simp) ((mlist simp)) ((mlist simp)))) 
 
2010
 
 
2011
(defun nonumber (l)
 
2012
        (cond
 
2013
                ((numberp (car l)) (nonumber (cdr l)))
 
2014
                ((eq l nil) ())
 
2015
                (t (cons (car l) (nonumber (cdr l))))
1004
2016
        )
1005
2017
)
1006
2018
 
1007
 
(DEFUN REMOVEINDEX (E L)
1008
 
 (COND  ((NULL L) NIL)
1009
 
        ((ATOM E)
1010
 
         (COND ((EQ E (CAR L)) (CDR L))
1011
 
              (T (CONS (CAR L) (REMOVEINDEX E (CDR L))))
 
2019
(defun removeindex (e l)
 
2020
 (cond  ((null l) nil)
 
2021
        ((atom e)
 
2022
         (cond ((eq e (car l)) (cdr l))
 
2023
              (t (cons (car l) (removeindex e (cdr l))))
1012
2024
        ))
1013
 
        (T (REMOVEINDEX (CDR E) (REMOVEINDEX (CAR E) L)))
 
2025
        (t (removeindex (cdr e) (removeindex (car e) l)))
1014
2026
 )
1015
2027
)
1016
2028
 
1017
 
(DEFUN INDICES (E)
1018
 
 (PROG (TOP BOTTOM X Y P Q R)
1019
 
  (SETQ TOP NIL BOTTOM NIL)
1020
 
  (COND ((RPOBJ E) (SETQ TOP (NONUMBER (CDADDR E)) BOTTOM (NONUMBER (APPEND (CDADR E) (CDDDR E)))))
1021
 
        ((ATOM E))
1022
 
        ((MEMQ (CAAR E) '(MTIMES MNCTIMES MNCEXPT))
1023
 
         (DOLIST (V (CDR E))
1024
 
          (SETQ X (INDICES V) BOTTOM (APPEND BOTTOM (CADR X)) TOP (APPEND TOP (CAR X)))
1025
 
         )
1026
 
        )
1027
 
        ((MEMQ (CAAR E) '(MPLUS MEQUAL))
1028
 
         (SETQ TOP (INDICES (CADR E)) BOTTOM (CADR TOP) TOP (CAR TOP))
1029
 
         (SETQ P (INTERSECT TOP BOTTOM) Q (REMOVEINDEX P BOTTOM) P (REMOVEINDEX P TOP))
1030
 
          (DOLIST (V (CDDR E))
1031
 
           (SETQ X (INDICES V) Y (CADR X) X (CAR X))
1032
 
           (SETQ R (INTERSECT X Y) X (REMOVEINDEX R X) Y (REMOVEINDEX R Y))
1033
 
           (WHEN (NOT (AND (SAMELISTS X P) (SAMELISTS Y Q))) (MERROR "Improper indices in ~M" V))
1034
 
           (SETQ TOP (UNION TOP R) BOTTOM (UNION BOTTOM R))
1035
 
         )
1036
 
        )
1037
 
        ((MEMQ (CAAR E) '($SUM %SUM))
1038
 
         (SETQ TOP (LIST (CADDR E)) BOTTOM (LIST (CADDR E)))
1039
 
        )
1040
 
        ((MEMQ (CAAR E) '(%DERIVATIVE $DIFF))
1041
 
         (DO ((I 1 (1+ I))) ((> I (COND ((CADDDR E) (CADDDR E)) (T 1))))
1042
 
           (SETQ BOTTOM (CONS (CADDR E) BOTTOM)))
1043
 
        )
1044
 
;;        (T (MERROR "Improper argument to INDICES: ~M" E))
 
2029
(defun indices (e)
 
2030
  (prog (top bottom x y p q r)
 
2031
    (setq top nil bottom nil)
 
2032
    (cond
 
2033
      (
 
2034
        (rpobj e)
 
2035
        (setq top (nonumber (conti e))
 
2036
              bottom (nonumber (append (covi e) (cdddr e))))
 
2037
      )
 
2038
      ((atom e))
 
2039
      (
 
2040
        (and (eq (caar e) 'mexpt) (eq (caddr e) -1))
 
2041
        (setq x (indices (cadr e)) bottom (append bottom (car x))
 
2042
                            top (append top (cadr x)))
 
2043
      )
 
2044
      (
 
2045
        (and (memq (caar e) '(%derivative $diff))
 
2046
             (or (eq (length e) 3) (eq (cadddr e) 1)))
 
2047
        (setq x (indices (cadr e)) bottom (append bottom (cadr x))
 
2048
                            top (append top (car x)))
 
2049
        (setq x (indices (caddr e)) bottom (append bottom (car x))
 
2050
                            top (append top (cadr x)))
 
2051
      )
 
2052
      (
 
2053
        (memq (caar e) '(mtimes mnctimes mncexpt))
 
2054
        (dolist (v (cdr e))
 
2055
          (setq x (indices v) bottom (append bottom (cadr x))
 
2056
                              top (append top (car x)))
 
2057
        )
 
2058
      )
 
2059
      (
 
2060
        (memq (caar e) '(mplus mequal))
 
2061
        (setq top (indices (cadr e)) bottom (cadr top) top (car top))
 
2062
        (setq p (intersect top bottom) q (removeindex p bottom)
 
2063
              p (removeindex p top))
 
2064
        (dolist (v (cddr e))
 
2065
          (setq x (indices v) y (cadr x) x (car x))
 
2066
          (setq r (intersect x y) x (removeindex r x) y (removeindex r y))
 
2067
          (when
 
2068
            (not (and (samelists x p) (samelists y q)))
 
2069
            (merror "Improper indices in ~M" v)
 
2070
          )
 
2071
          (setq top (union top r) bottom (union bottom r))
 
2072
        )
 
2073
      )
 
2074
      (
 
2075
        (memq (caar e) '($sum %sum))
 
2076
        (setq top (list (caddr e)) bottom (list (caddr e)))
 
2077
      )
 
2078
      (
 
2079
        (memq (caar e) '(%idiff $idiff))
 
2080
;;; This code would count derivative indices as covariant. However, it is
 
2081
;;; not needed. If the user wants to count derivative indices, those should
 
2082
;;; be part of the tensor expression; if the expression is undiff'd, there
 
2083
;;; must be a reason!
 
2084
;;        (do
 
2085
;;          ((f (cddr e) (cddr f)))
 
2086
;;          ((null f))
 
2087
;;          (do
 
2088
;;            ((i 1 (1+ i)))
 
2089
;;            ((> i (cond ((cadr f) (cadr f)) (t 1))))
 
2090
;;            (setq bottom (cons (car f) bottom))
 
2091
;;          )
 
2092
;;        )
 
2093
        (setq x (indices (cadr e)) bottom (append bottom (cadr x))
 
2094
              top (append top (car x)))
 
2095
      )
 
2096
;      (
 
2097
;        (memq (caar e) '(%derivative $diff))
 
2098
;        (setq x (indices (cadr e)) bottom (append bottom (cadr x))
 
2099
;              top (append top (car x)))
 
2100
;      )
 
2101
    )
 
2102
    (return (list top bottom))
1045
2103
  )
1046
 
  (RETURN (LIST TOP BOTTOM))
1047
 
 )
1048
 
)
1049
 
 
1050
 
(DEFMFUN $INDICES (E)
1051
 
 (PROG (TOP BOTTOM X)
1052
 
        (SETQ TOP (INDICES E) BOTTOM (CADR TOP) TOP (CAR TOP) X (INTERSECT TOP BOTTOM))
1053
 
        (SETQ TOP (REMOVEINDEX X TOP) BOTTOM (REMOVEINDEX X BOTTOM))
1054
 
        (RETURN (CONS SMLIST (LIST (CONS SMLIST (APPEND TOP BOTTOM)) (CONS SMLIST X))))
1055
 
 )
1056
 
)
1057
 
 
1058
 
(DEFUN SAMELISTS (A B)       ;"True" if A and B have the same distinct elements
1059
 
       (AND (= (LENGTH A) (LENGTH B))
1060
 
            (DO ((L
1061
 
                A
1062
 
                (CDR L)))
1063
 
                (NIL)
1064
 
                (COND ((NULL L) (RETURN T))
1065
 
                      ((MEMQ (CAR L) B))
1066
 
                      (T (RETURN NIL)))))) 
 
2104
)
 
2105
 
 
2106
(defmfun $indices (e)
 
2107
 (prog (top bottom x)
 
2108
;;      (setq top (indices e) bottom (cadr top) top (car top) x (intersect top bottom))
 
2109
        (setq top (indices e) bottom (cadr top) top (car top) x (cond ($flipflag (intersect bottom top)) (t (intersect top bottom))))
 
2110
        (setq top (removeindex x top) bottom (removeindex x bottom))
 
2111
        (return (cons smlist (list (cons smlist (append top bottom)) (cons smlist x))))
 
2112
 )
 
2113
)
 
2114
 
 
2115
(defun samelists (a b)       ;"True" if A and B have the same distinct elements
 
2116
       (and (= (length a) (length b))
 
2117
            (do ((l
 
2118
                a
 
2119
                (cdr l)))
 
2120
                (nil)
 
2121
                (cond ((null l) (return t))
 
2122
                      ((memq (car l) b))
 
2123
                      (t (return nil)))))) 
1067
2124
 
1068
 
(DEFMFUN $FLUSH n           ;Replaces the given (as arguments to FLUSH) indexed
 
2125
(defmfun $flush n           ;Replaces the given (as arguments to FLUSH) indexed
1069
2126
       (prog (l)          ;objects by zero if they have no derivative indices.
1070
2127
             (cond ((< n 2) (merror "FLUSH takes at least 2 arguments"))
1071
2128
                   ((not
1076
2133
                    (merror "All arguments but the first must be names of
1077
2134
indexed objects")) (t (return (flush (arg 1) l t))))))
1078
2135
 
1079
 
(DEFMFUN $FLUSHD n          ;Replaces the given (as arguments to FLUSHD) indexed
 
2136
(defmfun $flushd n          ;Replaces the given (as arguments to FLUSHD) indexed
1080
2137
       (prog (l)          ;objects by zero if they have any derivative indices.
1081
2138
             (cond ((< n 2) (merror "FLUSH takes at least 2 arguments"))
1082
2139
                   ((not
1088
2145
                    (merror "All arguments but the first must be names of
1089
2146
indexed objects")) (t (return (flush (arg 1) l nil))))))
1090
2147
 
1091
 
(defun FLUSH (e l flag)
 
2148
(defun flush (e l flag)
1092
2149
       (cond ((atom e) e)
1093
2150
             ((rpobj e)
1094
2151
              (cond ((not (memq (caar e) l)) e)
1101
2158
                              (mapcar (function (lambda (q) (flush q l flag)))
1102
2159
                                      (cdr e))) e))))
1103
2160
 
1104
 
(DEFMFUN $FLUSHND (e name n)              ;Replaces by zero all indexed objects
 
2161
(defmfun $flushnd (e name n)              ;Replaces by zero all indexed objects
1105
2162
       (cond ((atom e) e)               ;that have n or more derivative indices
1106
2163
             ((rpobj e)
1107
2164
              (cond ((and (equal (caar e) name)
1112
2169
                              (mapcar (function
1113
2170
                                       (lambda (q) ($flushnd q name n)))
1114
2171
                                      (cdr e))) e))))
1115
 
 
1116
 
(DECLARE-TOP (FIXNUM INDEX N) (SPECIAL INDEX N DUMX))
1117
 
 
1118
 
;(DEFMFUN $RENAME NARGS ((LAMBDA (INDEX) (RENAME (ARG 1)))
1119
 
;       (COND ((= NARGS 1) 1) (T (ARG 2))))) ;Sets INDEX to 1 or 2nd argument of
1120
 
;                                            ;$RENAME
1121
 
(DEFMFUN $RENAME NARGS
1122
 
 (cond ((= NARGS 1) (setq INDEX 1)) (t (setq INDEX (arg 2)))) (rename (arg 1)))
1123
 
 
1124
 
(DEFUN RENAME (E)                           ;Renames dummy indices consistently
1125
 
       (COND
1126
 
        ((ATOM E) E)
1127
 
        ((OR (RPOBJ E) (EQ (CAAR E) 'MTIMES));If an indexed object or a product
1128
 
         ((LAMBDA  (L) 
1129
 
        (SIMPTIMES (REORDER (COND (L (SUBLIS (itensor-CLEANUP L (SETQ N INDEX)) E))(T E))) 1 T))
1130
 
          (CDADDR ($INDICES E))                     ;Gets list of dummy indices
 
2172
 
 
2173
(declare-top (fixnum index n) (special index n dumx))
 
2174
 
 
2175
(defmfun $rename nargs
 
2176
 (cond ((= nargs 1) (setq index 1)) (t (setq index (arg 2)))) (rename (arg 1)))
 
2177
 
 
2178
(defun rename (e)                           ;Renames dummy indices consistently
 
2179
       (cond
 
2180
        ((atom e) e)
 
2181
        ((or (rpobj e) (eq (caar e) 'mtimes););If an indexed object or a product
 
2182
        (and (memq (caar e) '(%derivative $diff)) ; or a derivative expression
 
2183
             (or (eq (length e) 3) (eq (cadddr e) 1)))
 
2184
    )
 
2185
         ((lambda  (l) 
 
2186
        (simptimes (reorder (cond (l (sublis (itensor-cleanup l (setq n index)) e))(t e))) 1 t))
 
2187
          (cdaddr ($indices e))                     ;Gets list of dummy indices
1131
2188
          ))
1132
 
        (T            ;Otherwise map $RENAME on each of the subparts e.g. a sum
1133
 
         (MYSUBST0 (SIMPLIFYA  (CONS (NCONS (CAAR E))
1134
 
                                  (MAPCAR 'RENAME (CDR E)))
1135
 
                            T)
1136
 
                   E))
 
2189
        (t            ;Otherwise map $RENAME on each of the subparts e.g. a sum
 
2190
         (mysubst0 (simplifya  (cons (ncons (caar e))
 
2191
                                  (mapcar 'rename (cdr e)))
 
2192
                            t)
 
2193
                   e))
1137
2194
        ))
1138
2195
 
1139
 
(DEFUN REORDER (E)       ;Reorders contravariant, covariant, derivative indices
1140
 
       (MYSUBST0         ;Example: F([A,B],[C,D],E,F)
1141
 
        (CONS
1142
 
         '(MTIMES)
1143
 
         (MAPCAR
1144
 
          #'(LAMBDA (X) 
1145
 
            (COND ((RPOBJ X)
1146
 
                   (NCONC (LIST (CAR X)                              ;($F SIMP)
1147
 
                                (CONS SMLIST
1148
 
                                      (COND ($ALLSYM (itensor-SORT (COPY (CDADR X))))
1149
 
                                            (T (CDADR X))))          ;($A $B)
1150
 
                                (CONS SMLIST
1151
 
                                      (COND ($ALLSYM
1152
 
                                             (itensor-SORT (COPY (CDADDR X))))
1153
 
                                            (T (CDADDR X)))))        ;($C $D)
1154
 
                          (itensor-SORT (COPY (CDDDR X)))))                ;($E $F)
1155
 
                  (T X)))
1156
 
          (COND ((EQ (CAAR E) 'MTIMES) (CDR E))
1157
 
                (T (NCONS E)))))
1158
 
        E))
 
2196
(defun reorder (e)       ;Reorders contravariant, covariant, derivative indices
 
2197
       (mysubst0         ;Example: F([A,B],[C,D],E,F)
 
2198
        (cons
 
2199
         '(mtimes)
 
2200
         (mapcar
 
2201
          #'(lambda (x) 
 
2202
            (cond ((rpobj x)
 
2203
           (setq x ($renorm x))
 
2204
                   (nconc (list (car x)                              ;($f simp)
 
2205
                                (cons smlist
 
2206
                                      (cond ($allsym (itensor-sort (copy (cdadr x))))
 
2207
                                            (t (cdadr x))))          ;($a $b)
 
2208
                                (cons smlist
 
2209
                                      (cond ($allsym
 
2210
                                             (itensor-sort (copy (cdaddr x))))
 
2211
                                            (t (cdaddr x)))))        ;($c $d)
 
2212
              (cond ($iframe_flag (cdddr x))
 
2213
                           (t (itensor-sort (copy (cdddr x)))))))                ;($e $f)
 
2214
                  (t x)))
 
2215
          (cond ((eq (caar e) 'mtimes) (cdr e))
 
2216
                (t (ncons e)))))
 
2217
        e))
1159
2218
 
1160
 
(DEFUN itensor-CLEANUP (A N)((LAMBDA (DUMX)(CLEANUP1 A)) NIL))        ;Sets DUMX to NIL
 
2219
;;(defun itensor-cleanup (a n)((lambda (dumx)(cleanup1 a)) nil))        ;Sets DUMX to NIL
 
2220
(defun itensor-cleanup (a nn) (setq n nn dumx nil) (cleanup1 a))
1161
2221
 
1162
 
(DEFUN CLEANUP1 (A)
1163
 
  (AND A (SETQ DUMX (IMPLODE (NCONC (EXPLODEN $DUMMYX)    ;Keep proper order of
1164
 
                                    (EXPLODEN N))) N (1+ N))          ;indices
1165
 
        (COND ((EQ DUMX (CAR A)) (CLEANUP1 (CDR A)))
1166
 
              (T (CONS (CONS (CAR A) DUMX) (CLEANUP1 (CDR A)))))))
1167
 
;Make list of dotted pairs indicating substitutions i.e. ((A . #1) (B . #2))
1168
 
 
1169
 
(DECLARE-TOP (NOTYPE N INDEX)(UNSPECIAL N DUMX INDEX))
1170
 
 
1171
 
(DEFUN itensor-SORT (L) (COND ((CDR L) (SORT L 'LESS)) (T L)))
 
2222
(defun cleanup1 (a)
 
2223
  (and a (setq dumx (implode (nconc (exploden $idummyx)    ;Keep proper order of
 
2224
                                    (exploden n))) n (1+ n))          ;indices
 
2225
        (cond ((eq dumx (car a)) (cleanup1 (cdr a)))
 
2226
              (t (cons (cons (car a) dumx) (cleanup1 (cdr a)))))))
 
2227
;Make list of dotted pairs indicating substitutions i.e. ((a . #1) (b . #2))
 
2228
 
 
2229
(declare-top (notype n index)(unspecial n dumx index))
 
2230
 
 
2231
(defun itensor-sort (l) (cond ((cdr l) (sort l 'less)) (t l)))
1172
2232
;Sort into ascending order
1173
2233
 
1174
 
(DEFMFUN $REMCOMPS (TENSOR)
1175
 
       (ZL-REMPROP TENSOR 'EXPR) (ZL-REMPROP TENSOR 'CARRAYS)
1176
 
       (ZL-REMPROP TENSOR 'TEXPRS) (ZL-REMPROP TENSOR 'INDEXED)
1177
 
       (ZL-REMPROP TENSOR 'TSUBR) '$DONE)
 
2234
(defmfun $remcomps (tensor)
 
2235
       (zl-remprop tensor 'expr) (zl-remprop tensor 'carrays)
 
2236
       (zl-remprop tensor 'texprs) (zl-remprop tensor 'indexed)
 
2237
       (zl-remprop tensor 'indexed) (zl-remprop tensor 'tsubr)
 
2238
       (and (functionp tensor) (fmakunbound tensor))
 
2239
       '$done)
1178
2240
 
1179
 
(DEFMFUN $INDEXED (TENSOR)
1180
 
  (LET (FP NEW)
1181
 
    (AND (ZL-GET TENSOR 'EXPR) 
 
2241
(defmfun $indexed_tensor (tensor)
 
2242
  (let (fp new)
 
2243
    (and (zl-get tensor 'expr) 
1182
2244
         (merror "~M has expr" tensor))
1183
 
    (ARGS TENSOR  NIL)
1184
 
    (AND (SETQ FP (ZL-GET TENSOR 'SUBR))
1185
 
         (PROGN (SETQ NEW (GENSYM))(PUTPROP NEW FP 'SUBR)
1186
 
                (ZL-REMPROP TENSOR 'SUBR)(PUTPROP TENSOR NEW 'TSUBR)))
1187
 
    (PUTPROP TENSOR T 'INDEXED)
1188
 
    (PUTPROP TENSOR (SUBST TENSOR 'G '(LAMBDA N (TENSOREVAL (QUOTE G)(LISTIFY N)))) 'EXPR)
1189
 
                (eval (subst tensor 'g (quote (defmfun g n (tensoreval 'g (listify n))))))
1190
 
    '$DONE))
1191
 
 
1192
 
 
1193
 
(DEFUN ALLFIXED (L) 
1194
 
       (AND L (FIXP (CAR L)) (OR (NULL (CDR L)) (ALLFIXED (CDR L))))) 
1195
 
 
1196
 
;;(DEFUN TENSOREVAL (TENSOR INDXS)
1197
 
;;  ((LAMBDA (DER CON)
1198
 
;;    (AND (CDR INDXS) (SETQ CON (CDADR INDXS) DER (CDDR INDXS)))
1199
 
;;  (SETQ TENSOR (SELECT TENSOR (CDAR INDXS) CON))
1200
 
;;  (COND (DER (APPLY '$DIFF (CONS TENSOR (PUTINONES DER))))
1201
 
;;      (T TENSOR))) NIL NIL))
1202
 
(DEFUN TENSOREVAL (TENSOR INDXS)
1203
 
  ((LAMBDA (DER CON)
1204
 
    (AND (CDR INDXS) (SETQ CON (CDADR INDXS) DER (CDDR INDXS)))
1205
 
  (SETQ TENSOR (SELECT TENSOR (CDAR INDXS) CON DER))
1206
 
  ) NIL NIL))
1207
 
 
1208
 
;;(DEFMFUN $COMPONENTS (TENSOR COMP)
1209
 
;;  ((LAMBDA (LEN1 LEN2 NAME PROP)
1210
 
;;    (COND ((OR (NOT (RPOBJ TENSOR))(CDDDR TENSOR))
1211
 
;;         (merror "Improper 1st arg to COMPONENTS: ~M"
1212
 
;;                 TENSOR
1213
 
;;                 )))
1214
 
;;    (SETQ LEN1 (LENGTH (CDADR TENSOR)) LEN2 (LENGTH (CDADDR TENSOR)))
1215
 
;;    (AND (NOT (ATOM COMP))(EQ (CAAR COMP) '$MATRIX)
1216
 
;;       (COND ((= (f+ LEN1 LEN2) 2)(SETQ NAME (GENSYM))
1217
 
;;              (SET NAME COMP)(SETQ COMP NAME))
1218
 
;;             (T 
1219
 
;;              (merror "Needs two indices for COMPONENTS from matrix:~%~M"
1220
 
;;                      TENSOR))))
1221
 
;;    (COND ((AND (EQ (ML-TYPEP COMP) 'SYMBOL) (> (f+ LEN1 LEN2) 0))
1222
 
;;         (SETQ PROP 'CARRAYS))
1223
 
;;        ((SAMELISTS (SETQ NAME (APPEND (CDADR TENSOR) (CDADDR TENSOR)))
1224
 
;;                    (CDADR ($INDICES COMP)))
1225
 
;;         (SETQ PROP 'TEXPRS COMP (CONS COMP NAME)))
1226
 
;;        (T (merror "Args to COMPONENTS do not have the same free indices")))
1227
 
;;    (SETQ TENSOR (CAAR TENSOR) LEN1 (CONS LEN1 LEN2))
1228
 
;;    (COND ((AND (SETQ NAME (ZL-GET TENSOR PROP))
1229
 
;;              (SETQ LEN2 (ZL-ASSOC LEN1 NAME))) (RPLACD LEN2 COMP))
1230
 
;;        (T (PUTPROP TENSOR (CONS (CONS LEN1 COMP) NAME) PROP)))
1231
 
;;    (OR (ZL-GET TENSOR 'INDEXED) ($INDEXED TENSOR))
1232
 
;;    '$DONE) NIL NIL NIL NIL))
1233
 
(DEFMFUN $COMPONENTS (TENSOR COMP)
1234
 
  ((LAMBDA (LEN1 LEN2 LEN3 NAME PROP)
1235
 
    (COND ((NOT (RPOBJ TENSOR))
 
2245
    (args tensor  nil)
 
2246
    (and (setq fp (zl-get tensor 'subr))
 
2247
         (progn (setq new (gensym))(putprop new fp 'subr)
 
2248
                (zl-remprop tensor 'subr)(putprop tensor new 'tsubr)))
 
2249
    (putprop tensor t 'indexed)
 
2250
    (putprop tensor (subst tensor 'g '(lambda nn (tensoreval (quote g)(listify nn)))) 'expr)
 
2251
                (eval (subst tensor 'g (quote (defmfun g nn (tensoreval 'g (listify nn))))))
 
2252
    '$done))
 
2253
 
 
2254
 
 
2255
(defun allfixed (l) 
 
2256
       (and l (fixp (car l)) (or (null (cdr l)) (allfixed (cdr l))))) 
 
2257
 
 
2258
(defun tensoreval (tensor indxs)
 
2259
  ((lambda (der con)
 
2260
    (and (cdr indxs) (setq con (cdadr indxs) der (cddr indxs)))
 
2261
  (setq tensor (select tensor (cdar indxs) con der))
 
2262
  ) nil nil))
 
2263
 
 
2264
(defmfun $components (tensor comp)
 
2265
  ((lambda (len1 len2 len3 name prop)
 
2266
    (cond ((not (rpobj tensor))
1236
2267
           (merror "Improper 1st arg to COMPONENTS: ~M"
1237
 
                   TENSOR
 
2268
                   tensor
1238
2269
                   )))
1239
 
    (SETQ LEN1 (LENGTH (CDADR TENSOR)) LEN2 (LENGTH (CDADDR TENSOR)) LEN3 (LENGTH (CDDDR TENSOR)))
1240
 
    (AND (NOT (ATOM COMP))(EQ (CAAR COMP) '$MATRIX)
1241
 
         (COND ((= (f+ (f+ LEN1 LEN2) LEN3) 2)(SETQ NAME (GENSYM))
1242
 
                (SET NAME COMP)(SETQ COMP NAME))
1243
 
               (T 
 
2270
;    (setq len1 (length (cdadr tensor)) len2 (length (cdaddr tensor)) len3 (length (cdddr tensor)))
 
2271
    (setq len1 (length (covi tensor)) len2 (length (conti tensor)) len3 (length (deri tensor)))
 
2272
    (and (not (atom comp))(eq (caar comp) '$matrix)
 
2273
         (cond ((= (f+ (f+ len1 len2) len3) 2)(setq name (gensym))
 
2274
                (set name comp)(setq comp name))
 
2275
               (t 
1244
2276
                (merror "Needs two indices for COMPONENTS from matrix:~%~M"
1245
 
                        TENSOR))))
1246
 
    (COND ((AND (EQ (ML-TYPEP COMP) 'SYMBOL) (> (f+ (f+ LEN1 LEN2) LEN3) 0))
1247
 
           (SETQ PROP 'CARRAYS))
1248
 
          ((SAMELISTS (SETQ NAME (APPEND (CDADR TENSOR) (CDADDR TENSOR) (CDDDR TENSOR)))
1249
 
                      (CDADR ($INDICES COMP)))
1250
 
           (SETQ PROP 'TEXPRS COMP (CONS COMP NAME)))
1251
 
          (T (merror "Args to COMPONENTS do not have the same free indices")))
1252
 
    (SETQ TENSOR (CAAR TENSOR) LEN1 (LIST LEN1 LEN2 LEN3))
1253
 
    (COND ((AND (SETQ NAME (ZL-GET TENSOR PROP))
1254
 
                (SETQ LEN2 (ZL-ASSOC LEN1 NAME))) (RPLACD LEN2 COMP))
1255
 
          (T (PUTPROP TENSOR (CONS (CONS LEN1 COMP) NAME) PROP)))
1256
 
    (OR (ZL-GET TENSOR 'INDEXED) ($INDEXED TENSOR))
1257
 
    '$DONE) NIL NIL NIL NIL NIL))
1258
 
 
1259
 
;;(DEFUN SELECT (TENSOR L1 L2)
1260
 
;;  ((LAMBDA (PROP SUBS INDEX)
1261
 
;;      (COND ((AND (ALLFIXED SUBS) (SETQ PROP (ZL-GET TENSOR 'CARRAYS))
1262
 
;;                  (SETQ PROP (ZL-ASSOC INDEX PROP)))
1263
 
;;             (COND ((ALIKE1 (SETQ PROP (CONS (LIST (CDR PROP) 'ARRAY) SUBS))
1264
 
;;                            (SETQ SUBS (MEVAL PROP))) 0)
1265
 
;;                   (T SUBS)))
1266
 
;;            ((SETQ PROP (ZL-ASSOC INDEX (ZL-GET TENSOR 'TEXPRS)))
1267
 
;;             (SUBLIS (MAPCAR (FUNCTION CONS)(CDDR PROP) SUBS) (CADR PROP)))
1268
 
;;            ((SETQ PROP (ZL-GET TENSOR 'TSUBR))
1269
 
;;             (APPLY PROP (LIST (CONS SMLIST L1)(CONS SMLIST L2))))
1270
 
;;            (T (LIST (LIST TENSOR 'SIMP)(CONS SMLIST L1)(CONS SMLIST L2)))))
1271
 
;;      NIL (APPEND L1 L2)(CONS (LENGTH L1)(LENGTH L2))))
1272
 
 
1273
 
;;vtt: inconstant was an attempt to remove constant indices, but it really doesn't work out.
1274
 
;;(DEFUN INCONSTANT (L)
1275
 
;;  (COND 
1276
 
;;    ((EQ L NIL) NIL)
1277
 
;;    (($CONSTANTP (CAR L)) (AND (NOT (EQ NIL (CDR L))) (INCONSTANT (CDR L))))
1278
 
;;    (T (CONS (CAR L) (AND (NOT (EQ NIL (CDR L))) (INCONSTANT (CDR L)))))
1279
 
;;  )
1280
 
;;)
1281
 
 
1282
 
(DEFUN SELECT (TENSOR L1 L2 L3)
1283
 
  ((LAMBDA (PROP SUBS INDEX)
1284
 
        (COND ((AND (ALLFIXED SUBS) (SETQ PROP (ZL-GET TENSOR 'CARRAYS))
1285
 
                    (SETQ PROP (ZL-ASSOC INDEX PROP)))
1286
 
               (COND ((ALIKE1 (SETQ PROP (CONS (LIST (CDR PROP) 'ARRAY) SUBS))
1287
 
                              (SETQ SUBS (MEVAL PROP))) 0)
1288
 
                     (T SUBS)))
1289
 
              ((SETQ PROP (ZL-ASSOC INDEX (ZL-GET TENSOR 'TEXPRS)))
1290
 
;;;VTT         (SUBLIS (MAPCAR (FUNCTION CONS)(CDDR PROP) SUBS) (CADR PROP)))
1291
 
;;;            (SUBLIS (MAPCAR (FUNCTION CONS)(CDDR PROP) SUBS) ($RENAME (CADR PROP) (COND ((BOUNDP 'N) N) (T 1)))))
1292
 
               (SUBLIS (MAPCAR (FUNCTION CONS)(CDDR PROP) SUBS) (CAR (CONS ($RENAME (CADR PROP) (1+ $COUNTER)) (SETQ $COUNTER (1- (COND ((BOUNDP 'N) N) (T 1))))))))
1293
 
              ((SETQ PROP (ZL-GET TENSOR 'TSUBR))
1294
 
;;             (APPLY PROP (LIST (CONS SMLIST (INCONSTANT L1))(CONS SMLIST (INCONSTANT L2))(CONS SMLIST L3))))
1295
 
;;            ((NOT (EQ L3 NIL)) (APPLY '$DIFF (SELECT TENSOR (INCONSTANT L1) (INCONSTANT L2) (CDR L3)) (LIST (CAR L3))))
1296
 
;;            (T (APPEND (LIST (LIST TENSOR 'SIMP)(CONS SMLIST (INCONSTANT L1))(CONS SMLIST (INCONSTANT L2))) L3))))
1297
 
;;      NIL (APPEND (INCONSTANT L1) (INCONSTANT L2) L3)(LIST (LENGTH (INCONSTANT L1))(LENGTH (INCONSTANT L2))(LENGTH L3))))
1298
 
               (APPLY PROP (LIST (CONS SMLIST L1)(CONS SMLIST L2)(CONS SMLIST L3))))
1299
 
              ((NOT (EQ L3 NIL)) (APPLY '$DIFF (SELECT TENSOR L1 L2 (CDR L3)) (LIST (CAR L3))))
1300
 
              (T (APPEND (LIST (LIST TENSOR 'SIMP)(CONS SMLIST L1)(CONS SMLIST L2)) L3))))
1301
 
        NIL (APPEND L1 L2 L3)(LIST (LENGTH L1)(LENGTH L2)(LENGTH L3))))
1302
 
 
1303
 
 
1304
 
(DEFMFUN $ENTERTENSOR nargs 
 
2277
                        tensor))))
 
2278
    (cond ((and (eq (ml-typep comp) 'symbol) (> (f+ (f+ len1 len2) len3) 0))
 
2279
           (setq prop 'carrays))
 
2280
;         ((samelists (setq name (append (cdadr tensor) (cdaddr tensor) (cdddr tensor)))
 
2281
          ((samelists (setq name (append (covi tensor) (conti tensor) (deri tensor)))
 
2282
                      (cdadr ($indices comp)))
 
2283
           (setq prop 'texprs comp (cons comp name)))
 
2284
          (t (merror "Args to COMPONENTS do not have the same free indices")))
 
2285
    (setq tensor (caar tensor) len1 (list len1 len2 len3))
 
2286
    (cond ((and (setq name (zl-get tensor prop))
 
2287
                (setq len2 (zl-assoc len1 name))) (rplacd len2 comp))
 
2288
          (t (putprop tensor (cons (cons len1 comp) name) prop)))
 
2289
    (or (zl-get tensor 'indexed) ($indexed_tensor tensor))
 
2290
    '$done) nil nil nil nil nil))
 
2291
 
 
2292
(defun select (tensor l1 l2 l3)
 
2293
  (prog
 
2294
    nil
 
2295
    (setq l2 (append (minusi l1) l2) l1 (plusi l1))
 
2296
    (return
 
2297
      (
 
2298
        (lambda
 
2299
          (prop subs idx)
 
2300
          (cond
 
2301
            (
 
2302
              (and
 
2303
                (allfixed subs)
 
2304
                (setq prop (zl-get tensor 'carrays))
 
2305
                (setq prop (zl-assoc idx prop))
 
2306
              )
 
2307
              (cond
 
2308
                (
 
2309
                  (alike1
 
2310
                    (setq prop (cons (list (cdr prop) 'array) subs))
 
2311
                    (setq subs (meval prop))
 
2312
                  )
 
2313
                  0
 
2314
                )
 
2315
                (t subs)
 
2316
              )
 
2317
            )
 
2318
            (
 
2319
              (setq prop (zl-assoc idx (zl-get tensor 'texprs)))
 
2320
              (sublis
 
2321
                (mapcar (function cons)(cddr prop) subs)
 
2322
                ($rename (cadr prop) (cond ((boundp 'n) n) (t 1)))
 
2323
              )
 
2324
            )
 
2325
            (
 
2326
              (setq prop (zl-get tensor 'tsubr))
 
2327
              (apply
 
2328
                prop
 
2329
                (list (cons smlist l1) (cons smlist l2) (cons smlist l3))
 
2330
              )
 
2331
            )
 
2332
            (
 
2333
              (not (eq l3 nil))
 
2334
              (apply '$idiff (select tensor l1 l2 (cdr l3)) (list (car l3)))
 
2335
            )
 
2336
            (
 
2337
              t
 
2338
              (append
 
2339
                (list (list tensor 'simp) (cons smlist l1) (cons smlist l2))
 
2340
                l3
 
2341
              )
 
2342
            )
 
2343
          )
 
2344
        )
 
2345
        nil (append l1 l2 l3) (list (length l1)(length l2)(length l3))
 
2346
      )
 
2347
    )
 
2348
  )
 
2349
)
 
2350
 
 
2351
 
 
2352
(defmfun $entertensor nargs
1305
2353
  (prog (fun contr cov deriv)
1306
 
    (cond ((> nargs 1)
1307
 
           (merror "ENTERTENSOR takes 0 or 1 arguments only"))
1308
 
          ((= nargs 0)
1309
 
           (mtell "Enter tensor name: ") 
1310
 
           (setq fun (meval (retrieve nil nil))))
1311
 
          ((setq fun (arg 1))))
 
2354
    (cond
 
2355
      (
 
2356
        (> nargs 1)
 
2357
            (merror "ENTERTENSOR takes 0 or 1 arguments only")
 
2358
      )
 
2359
          (
 
2360
        (= nargs 0)
 
2361
            (mtell "Enter tensor name: ") 
 
2362
            (setq fun (meval (retrieve nil nil)))
 
2363
      )
 
2364
          ((setq fun (arg 1)))
 
2365
    )
1312
2366
    (mtell "Enter a list of the covariant indices: ")
1313
2367
    (setq cov (checkindex (meval (retrieve nil nil)) fun))
1314
2368
    (cond ((atom cov) (setq cov (cons smlist (ncons cov)))))
1317
2371
    (cond ((atom contr) (setq contr (cons smlist (ncons contr)))))
1318
2372
    (mtell "Enter a list of the derivative indices: ")
1319
2373
    (setq deriv (checkindex (meval (retrieve nil nil)) fun))
1320
 
    (setq deriv (cond ((atom deriv) (ncons deriv))
1321
 
                      (t (cdr deriv))))
1322
 
    (cond ((memberl (cdr cov) deriv)
1323
 
           (mtell "~%Warning - there are indices that are both covariant ~
1324
 
                  and derivative%")))
1325
 
    (return ($SHOW (nconc (list (list fun 'SIMP) cov contr)
1326
 
                                       deriv)))))
 
2374
    (setq deriv
 
2375
      (cond ((atom deriv) (ncons deriv))
 
2376
                    (t (cdr deriv))
 
2377
      )
 
2378
    )
 
2379
    (cond
 
2380
      (
 
2381
        (memberl (cdr cov) deriv)
 
2382
            (mtell "Warning - there are indices that are both covariant ~
 
2383
                and derivative%")
 
2384
      )
 
2385
    )
 
2386
    (return ($ishow (nconc (list (list fun 'simp) cov contr) deriv)))
 
2387
  )
 
2388
)
1327
2389
 
1328
 
(defun CHECKINDEX (e f)
 
2390
(defun checkindex (e f)
1329
2391
  (cond ((and (atom e) (not (eq e f))) e)
1330
 
        ((and (eq (caar e) 'MLIST)
 
2392
        ((and (eq (caar e) 'mlist)
1331
2393
              (sloop for v in (cdr e) always (atom v))
1332
2394
;             (apply 'and (mapcar 'atom (cdr e)))
1333
2395
              (not (memq f e))) e)
1334
2396
        (t (merror "Indices must be atoms different from the tensor name"))))
1335
2397
 
1336
 
(defun MEMBERL (a b)
 
2398
(defun memberl (a b)
1337
2399
  (do ((l a (cdr l))
1338
2400
       (carl))
1339
2401
      ((null l) nil)
1340
2402
    (setq carl (car l))
1341
 
    (cond ((and (eq (ml-typep carl) 'SYMBOL)
 
2403
    (cond ((and (eq (ml-typep carl) 'symbol)
1342
2404
                (zl-member carl b)) (return t)))))
1343
2405
 
1344
 
(defun CONSMLIST (l) (cons smlist l))                   ;Converts from Lisp list to Macsyma list
1345
 
 
1346
 
(DEFMFUN $INDICES2 (e)
 
2406
(defun consmlist (l) (cons smlist l))                   ;Converts from Lisp list to Macsyma list
 
2407
 
 
2408
;$INDICES2 is similar to $INDICES except that here dummy indices are picked off
 
2409
;as they first occur in going from left to right through the product or indexed
 
2410
;object. Also, $INDICES2 works only on the top level of a product and will
 
2411
;miss indices for products of sums (which is used to advantage by $IC_CONVERT).
 
2412
 
 
2413
(defmfun $indices2 (e)
1347
2414
  (cond ((atom e) empty)
1348
 
        ((not (or (memq (caar e) '(MTIMES MNCTIMES)) (rpobj e)))
 
2415
        ((not (or (memq (caar e) '(mtimes mnctimes)) (rpobj e)))
1349
2416
         ($indices e))
1350
2417
        (t ((lambda (indices)
1351
2418
              (do ((ind indices) (free) (dummy) (index))
1362
2429
                                         1)))
1363
2430
                      (t (setq free (cons index free)
1364
2431
                               ind (cdr ind))))))
1365
 
            (do ((e (cond ((memq (caar e) '(MTIMES MNCTIMES)) (cdr e))
 
2432
            (do ((e (cond ((memq (caar e) '(mtimes mnctimes)) (cdr e))
1366
2433
                          (t (ncons e))) (cdr e))
1367
2434
                 (a) (l))
1368
2435
                ((null e) l)
1369
2436
              (setq a (car e))
1370
 
              (and (rpobj a) (setq l (append l (cdadr a) (cdaddr a)
 
2437
              (and (rpobj a) (setq l (append l (covi a) (conti a)
1371
2438
                                             (cdddr a)))))))))
1372
2439
 
1373
 
;$INDICES2 is similar to $INDICES except that here dummy indices are picked off
1374
 
;as they first occur in going from left to right through the product or indexed
1375
 
;object. Also, $INDICES2 works only on the top level of a product and will
1376
 
;miss indices for products of sums (which is used to advantage by $GENERATE).
1377
 
 
1378
 
(DEFMFUN $CHANGENAME (a b e)                            ;Change the name of the indexed object A to B in E
 
2440
(defmfun $changename (a b e)                            ;Change the name of the indexed object A to B in E
1379
2441
  (prog (old indspec ncov ncontr)                       ;INDSPEC is INDex SPECification flag
1380
 
    (cond ((not (or (and (eq (ml-typep a) 'SYMBOL) (setq old a))
 
2442
    (cond ((not (or (and (eq (ml-typep a) 'symbol) (setq old a))
1381
2443
                    (and ($listp a) (equal (length (cdr a)) 3)
1382
 
                         (eq (ml-typep (setq old (cadr a))) 'SYMBOL)
1383
 
                         (eq (ml-typep (setq ncov (caddr a))) 'FIXNUM)
1384
 
                         (eq (ml-typep (setq ncontr (cadddr a))) 'FIXNUM)
 
2444
                         (eq (ml-typep (setq old (cadr a))) 'symbol)
 
2445
                         (eq (ml-typep (setq ncov (caddr a))) 'fixnum)
 
2446
                         (eq (ml-typep (setq ncontr (cadddr a))) 'fixnum)
1385
2447
                         (setq indspec t))))
1386
2448
           (merror "Improper first argument to CHANGENAME: ~M" a))
1387
 
          ((not (eq (ml-typep b) 'SYMBOL))
 
2449
          ((not (eq (ml-typep b) 'symbol))
1388
2450
           (merror "Second argument to CHANGENAME must be a symbol"))
1389
2451
          (t (return (changename old indspec ncov ncontr b e))))))
1390
2452
 
1391
 
(defun CHANGENAME (a indspec ncov ncontr b e)
1392
 
  (cond ((or (atom e) (eq (caar e) 'RAT)) e)
 
2453
(defun changename (a indspec ncov ncontr b e)
 
2454
  (cond ((or (atom e) (eq (caar e) 'rat)) e)
1393
2455
        ((rpobj e)
1394
2456
         (cond ((and (eq (caar e) a)
1395
2457
                     (cond (indspec (and (equal (length (cdadr e)) ncov)
1405
2467
                                                  ncontr b q)))
1406
2468
                                   (cdr e))) e))))
1407
2469
 
1408
 
(DEFMFUN $COORD n
 
2470
(defmfun $coord n
1409
2471
  (do ((l (listify n) (cdr l)) (a))
1410
 
      ((null l) '$DONE)
 
2472
      ((null l) '$done)
1411
2473
    (setq a (car l))
1412
 
    (cond ((not (eq (ml-typep a) 'SYMBOL))
 
2474
    (cond ((not (eq (ml-typep a) 'symbol))
1413
2475
           (merror "~M is not a valid name." a))
1414
 
          (t (add2lnc a $COORD)))))
 
2476
          (t (add2lnc a $coord)))))
1415
2477
 
1416
 
(DEFMFUN $REMCOORD n
1417
 
  (cond ((and (equal n 1) (eq (arg 1) '$ALL))
1418
 
         (setq $COORD '((MLIST))) '$DONE)
 
2478
(defmfun $remcoord n
 
2479
  (cond ((and (equal n 1) (eq (arg 1) '$all))
 
2480
         (setq $coord '((mlist))) '$done)
1419
2481
        (t (do ((l (listify n) (cdr l)))
1420
 
               ((null l) '$DONE)
1421
 
             (delq (car l) $COORD)))))
 
2482
               ((null l) '$done)
 
2483
             (delq (car l) $coord)))))
1422
2484
 
1423
2485
 
1424
2486
;; Additions on 5/19/2004 -- VTT
1425
2487
 
1426
 
(DEFUN MEMBERLIST (E L)
1427
 
        (COND ((NULL L) NIL)
1428
 
              ((EQUAL E (CAR L)) T)
1429
 
              (T (MEMBERLIST E (CDR L)))
1430
 
        )
1431
 
)
1432
 
 
1433
 
(DEFUN UNIONLIST (L1 L2)
1434
 
        (COND ((NULL L1) L2)
1435
 
              ((MEMBERLIST (CAR L1) L2) (UNIONLIST (CDR L1) L2))
1436
 
              (T (CONS (CAR L1) (UNIONLIST (CDR L1) L2)))
1437
 
        )
1438
 
)
1439
 
 
1440
 
(DEFMFUN $LISTOFTENS (E) (itensor-sort (CONS SMLIST (LISTOFTENS E))))
1441
 
(DEFUN LISTOFTENS (E)
1442
 
        (COND
1443
 
          ((ATOM E) NIL)
1444
 
          ((RPOBJ E) (LIST E))
1445
 
          (T (PROG (L) (SETQ L NIL)
1446
 
                (MAPCAR (LAMBDA (X) (SETQ L (UNIONLIST L (LISTOFTENS X)))) (CDR E))
1447
 
                (RETURN L)
 
2488
(defun memberlist (e l)
 
2489
        (cond ((null l) nil)
 
2490
              ((equal e (car l)) t)
 
2491
              (t (memberlist e (cdr l)))
 
2492
        )
 
2493
)
 
2494
 
 
2495
(defun unionlist (l1 l2)
 
2496
        (cond ((null l1) l2)
 
2497
              ((memberlist (car l1) l2) (unionlist (cdr l1) l2))
 
2498
              (t (cons (car l1) (unionlist (cdr l1) l2)))
 
2499
        )
 
2500
)
 
2501
 
 
2502
(defmfun $listoftens (e) (itensor-sort (cons smlist (listoftens e))))
 
2503
(defun listoftens (e)
 
2504
        (cond
 
2505
          ((atom e) nil)
 
2506
          ((rpobj e) (list e))
 
2507
          (t (prog (l) (setq l nil)
 
2508
                (mapcar (lambda (x) (setq l (unionlist l (listoftens x)))) (cdr e))
 
2509
                (return l)
1448
2510
             )
1449
2511
          )
1450
2512
        )
1451
2513
)
1452
2514
 
1453
 
(DEFUN NUMLIST (&optional (n '1)) (COND ((>= n $DIM) (LIST n)) (T (CONS n (NUMLIST (1+ n))))))
 
2515
(defun numlist (&optional (n '1)) (cond ((>= n $dim) (list n)) (t (cons n (numlist (1+ n))))))
1454
2516
 
1455
 
;;SHOWCOMPS(tensor):=BLOCK([i1,i2,ind:INDICES(tensor)[1]],
1456
 
;;      IF LENGTH(ind)=0 THEN SHOW(EV(tensor))
1457
 
;;      ELSE IF LENGTH(ind)=1 THEN SHOW(MAKELIST(EV(tensor,ind[1]=i1),i1,1,DIM))
1458
 
;;      ELSE IF LENGTH(ind)=2 THEN SHOW(tensor=APPLY('MATRIX,MAKELIST(MAKELIST(EV(tensor,[ind[1]=i1,ind[2]=i2]),i1,1,DIM),i2,1,DIM)))
1459
 
;;      ELSE FOR i1 THRU DIM DO (SHOWCOMPS(SUBST(i1,LAST(ind),tensor)),IF LENGTH(ind)=3 AND i1<DIM THEN LINENUM:LINENUM+1)
 
2517
;;showcomps(tensor):=block([i1,i2,ind:indices(tensor)[1]],
 
2518
;;      if length(ind)=0 then ishow(ev(tensor))
 
2519
;;      else if length(ind)=1 then ishow(makelist(ev(tensor,ind[1]=i1),i1,1,dim))
 
2520
;;      else if length(ind)=2 then ishow(tensor=apply('matrix,makelist(makelist(ev(tensor,[ind[1]=i1,ind[2]=i2]),i1,1,dim),i2,1,dim)))
 
2521
;;      else for i1 thru dim do (showcomps(subst(i1,last(ind),tensor)),if length(ind)=3 and i1<dim then linenum:linenum+1)
1460
2522
;;);
1461
 
(DEFMFUN $SHOWCOMPS (E)
1462
 
 (PROG (IND)
1463
 
  (SETQ IND (CDADR ($INDICES E)))
1464
 
  (COND ((> 1 (LENGTH IND)) ($SHOW (MEVAL (LIST '($EV) E))))
1465
 
        ((> 2 (LENGTH IND)) ($SHOW (CONS SMLIST (MAPCAR (LAMBDA (I) (MEVAL (LIST '($EV) E (LIST '(MEQUAL) (CAR IND) I)))) (NUMLIST)))))
1466
 
        ((> 3 (LENGTH IND)) ($SHOW (LIST '(MEQUAL) E (CONS '($MATRIX SIMP) (MAPCAR (LAMBDA (J) (CONS SMLIST (MAPCAR (LAMBDA (I) (MEVAL (LIST '($EV) E (LIST '(MEQUAL) (CAR IND) I) (LIST '(MEQUAL) (CADR IND) J)))) (NUMLIST)))) (NUMLIST))))))
1467
 
        (T (MAPCAR (LAMBDA (I)  ($SHOWCOMPS ($SUBSTITUTE I (CAR (LAST IND)) E)) (AND (> 4 (LENGTH IND)) (< I $DIM) (SETQ $LINENUM (1+ $LINENUM)))) (NUMLIST)))
 
2523
(defmfun $showcomps (e)
 
2524
 (prog (ind)
 
2525
  (setq ind (cdadr ($indices e)))
 
2526
  (cond ((> 1 (length ind)) ($ishow (meval (list '($ev) e))))
 
2527
        ((> 2 (length ind)) ($ishow (cons smlist (mapcar (lambda (i) (meval (list '($ev) e (list '(mequal) (car ind) i)))) (numlist)))))
 
2528
        ((> 3 (length ind)) ($ishow (list '(mequal) e (cons '($matrix simp) (mapcar (lambda (j) (cons smlist (mapcar (lambda (i) (meval (list '($ev) e (list '(mequal) (car ind) i) (list '(mequal) (cadr ind) j)))) (numlist)))) (numlist))))))
 
2529
        (t (mapcar (lambda (i)  ($showcomps ($substitute i (car (last ind)) e)) (and (> 4 (length ind)) (< i $dim) (setq $linenum (1+ $linenum)))) (numlist)))
1468
2530
  )
1469
2531
 )
1470
2532
)
 
2533
 
 
2534
; Implementation of the Hodge star operator. Based on the following
 
2535
; MAXIMA-language implementation:
 
2536
;
 
2537
; hodge(e):=
 
2538
; (
 
2539
;     [
 
2540
;         len:length(indices(e)[1]),
 
2541
;         idx1:makelist(idummy(),i,len+1,dim),
 
2542
;         idx2:makelist(idummy(),i,len+1,dim)
 
2543
;     ],
 
2544
;     funmake("*",makelist(funmake(imetric,[[idx1[i],idx2[i]]]),i,1,dim-len))*
 
2545
;                 funmake(levi_civita,[[],append(idx1,indices(e)[1])])*e/len!
 
2546
; )$
 
2547
 
 
2548
(defmfun $hodge (e)
 
2549
  (prog (len idx1 idx2)
 
2550
    (setq
 
2551
      len ($length (cadr ($indices e)))
 
2552
      idx1 (do ((i $dim (1- i)) l) ((eq i len) l) (setq l (cons ($idummy) l)))
 
2553
      idx2 (do ((i $dim (1- i)) l) ((eq i len) l) (setq l (cons ($idummy) l)))
 
2554
    )
 
2555
    (return
 
2556
      (append
 
2557
        (list
 
2558
          '(mtimes)
 
2559
          e
 
2560
          (list '(rat) 1 (factorial len))
 
2561
          (list
 
2562
            '($levi_civita)
 
2563
            '((mlist simp))
 
2564
            (cons '(mlist simp) (append (reverse idx1) (cdadr ($indices e))))
 
2565
          )
 
2566
        )
 
2567
        (do
 
2568
          (l)
 
2569
          ((not idx1) l)
 
2570
          (setq l (cons (list (list $imetric)
 
2571
                              (cons '(mlist) (list (car idx1) (car idx2)))) l)
 
2572
                idx1 (cdr idx1)
 
2573
                idx2 (cdr idx2)
 
2574
          )
 
2575
        )
 
2576
      )
 
2577
    )
 
2578
  )
 
2579
)
 
2580
 
 
2581
; This version of remsym remains silent when an attempt is made to remove
 
2582
; non-existent symmetries. Used by $idim below.
 
2583
 
 
2584
(defun remsym (name ncov ncontr)
 
2585
  (prog (tensor)
 
2586
    (setq tensor (implode (nconc (exploden name) (ncons 45)
 
2587
                                 (exploden ncov) (ncons 45)
 
2588
                                 (exploden ncontr)
 
2589
                          )
 
2590
                 )
 
2591
    )
 
2592
    (cond
 
2593
      ((zl-member tensor (cdr $symmetries))
 
2594
       (zl-delete tensor $symmetries)
 
2595
       (zl-remprop tensor '$sym) (zl-remprop tensor '$anti)
 
2596
       (zl-remprop tensor '$cyc)
 
2597
      )
 
2598
    )
 
2599
  )
 
2600
)
 
2601
 
 
2602
; This function sets the metric dimensions and Levi-Civita symmetries.
 
2603
 
 
2604
(defmfun $idim (n)
 
2605
  (remsym '%levi_civita $dim 0)
 
2606
  (remsym '%levi_civita 0 $dim)
 
2607
  (remsym '$levi_civita $dim 0)
 
2608
  (remsym '$levi_civita 0 $dim)
 
2609
  (setq $dim n)
 
2610
  (remsym '%levi_civita $dim 0)
 
2611
  (remsym '%levi_civita 0 $dim)
 
2612
  (remsym '$levi_civita $dim 0)
 
2613
  (remsym '$levi_civita 0 $dim)
 
2614
  ($decsym '%levi_civita n 0 '((mlist) (($anti) $all)) '((mlist)))
 
2615
  ($decsym '%levi_civita 0 n '((mlist)) '((mlist) (($anti) $all)))
 
2616
  ($decsym '$levi_civita n 0 '((mlist) (($anti) $all)) '((mlist)))
 
2617
  ($decsym '$levi_civita 0 n '((mlist)) '((mlist) (($anti) $all)))
 
2618
)
 
2619
 
 
2620
($load '$ex_calc)
 
2621
($load 'lckdt)
 
2622
($load 'iframe)