tensor.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. %======================================================
  2. % Name: tensor - tensor arithmetics
  3. % Author: A.Kryukov (kryukov@npi.msu.su)
  4. % Copyright: (C), 1993-1996, A.Kryukov
  5. % Version: 2.02 28/03/96
  6. %------------------------------------------------------
  7. % Release: Nov. 13, 1993 th_match, th_match1
  8. % Jul. 13, 1994 symmetry generated by multiplication.
  9. % Mar. 28, 1996 t_gcd, t_prep, t_times4
  10. %======================================================
  11. module tensor$
  12. fluid '(!*debug)$
  13. switch debug$
  14. %=================================================
  15. % tensor::=(!:tensor . ((th1 . pv1) (th2 . pv2) ...))
  16. % th::=(tn . il . dl)
  17. % tn::=(id1 id2 ...)
  18. %==================================================
  19. global '(!*basis)$
  20. symbolic procedure t_simp v$
  21. begin scalar x;
  22. if !*debug then << terpri()$ print list('t_simp . v) >>$
  23. if (x:=get(car v,'!:tensor))=99
  24. then put(car v,'!:tensor,length cdr v)
  25. else if null(x = length cdr v)
  26. then rederr list('t_simp,"*** Invalid number of indices:",v)$
  27. % v:='!:tensor . list((list car v . il_simp cdr v . nil)
  28. % -AK 28/03/96
  29. v:='!:tensor . list((list car v . il_simp cdr v . 1)
  30. % +AK 28/03/96
  31. . list(1 . mkunitp length cdr v)
  32. )$
  33. return (((if cdr z then z else nil)
  34. where z=sieve_t(v,!*basis)) ./ 1
  35. )$
  36. end$
  37. global '(domainlist!*)$
  38. switch tensor$
  39. domainlist!*:=union('(!:tensor),domainlist!*)$
  40. put('tensor,'tag,'!:tensor)$
  41. put('!:tensor,'dname,'tensor)$
  42. %flag('(!:tensor),'field)$ % !:tensor is not a field!
  43. put('!:tensor,'minus,'t_minus)$
  44. put('!:tensor,'minusp,'t_minusp)$
  45. put('!:tensor,'plus,'t_plus)$
  46. put('!:tensor,'times,'t_times)$ % v*c
  47. put('!:tensor,'difference,'t_difference)$
  48. put('!:tensor,'zerop,'t_zerop)$
  49. put('!:tensor,'onep,'t_onep)$
  50. put('!:tensor,'prepfn,'t_prep)$
  51. put('!:tensor,'prifn,'t_pri)$
  52. put('!:tensor,'intequivfn,'t_intequiv)$
  53. put('!:tensor,'i2d,'i2tensor)$
  54. put('!:tensor,'expt,'t_expt)$
  55. put('!:tensor,'quotient,'t_quotient)$
  56. put('!:tensor,'divide,'t_divide)$
  57. put('!:tensor,'gcd,'t_gcd)$
  58. flag('(!:tensor),'tmode)$
  59. symbolic procedure t_minus u$
  60. if atom cdr u then -cdr u
  61. else sieve_t(car u . t_minus1(cdr u,nil),!*basis)$
  62. symbolic procedure t_minus1(u,v)$
  63. if null u then reversip v
  64. else t_minus1(cdr u,(caar u . pv_neg cdar u) . v)$
  65. symbolic procedure t_minusp u$ nil$
  66. symbolic procedure t_plus(u,v)$
  67. if atom cdr u
  68. then rederr list('t_plus,"*** Tensor can't be added to:",cdr u)
  69. else if atom cdr v then t_plus(v,u)
  70. else sieve_t(car u . t_plus1(cdr u,cdr v),!*basis)$
  71. symbolic procedure t_plus1(u,v)$
  72. if null u then v
  73. else if null v then u
  74. else t_plus1(cdr u,t_plus2(car u,v,nil))$
  75. symbolic procedure t_plus2(x,v,w)$
  76. if null v then reversip(x . w)
  77. else if th_match(car x,caar v)
  78. then append(cdr v, reversip(t_add2(x,car v) . w))
  79. else t_plus2(x,cdr v, car v . w)$
  80. symbolic procedure t_times(u,v)$
  81. % u,v - tensor::=(!:tensor . tlist)
  82. if t_intequiv u then t_times(v,u)
  83. else if atom cdr v then car u . t_timesc(cdr u,cdr v,nil)
  84. else (sieve_t(x,!*basis)
  85. where x=car u . t_times1(cdr u,cdr v,nil)
  86. % ,y=b_expand(u,v)
  87. )$
  88. symbolic procedure t_timesc(tt,c,w)$
  89. % tt,w - tlist::=((th1 . pv1) ...)
  90. % c - integer
  91. if null tt then reversip w
  92. else t_timesc(cdr tt
  93. ,c
  94. ,(caar tt . pv_multc(cdar tt,c)) . w
  95. )$
  96. symbolic procedure t_times1(u,v,w)$
  97. % u,v,w - tlist::=((th1 . pv1) ...)
  98. if null u then reversip w
  99. else t_times1(cdr u,v,t_times2(v,car u,w))$
  100. symbolic procedure t_times2(v,x,w)$
  101. % u,w - tlist::=((th1 . pv1) ...)
  102. % x - (th . pv)
  103. if null v then w
  104. % else t_times2(cdr v,x,t_plus2(t_times3(car v,x),w,nil))$
  105. else t_times2(cdr v,x,t_plus2(t_times4(car v,x),w,nil))$
  106. symbolic procedure t_times3(y,x)$
  107. % x,y - (th . pv)
  108. if null ordp(caar y,caar x) then t_times3(x,y)
  109. else (append(caar y,caar x)
  110. . il_simp append(cadar y,cadar x)
  111. . append(cddar y,cddar x)
  112. ) . cdr pv_times('!:pv . cdr y,'!:pv . cdr x)$
  113. symbolic procedure t_times4(x,y)$ % mod. AK 28/03/96
  114. % x,y - (th . pv)
  115. % return product of x by y.
  116. % side effect: the !*basis will be updated by symmetry properties
  117. % generate by multiplication.
  118. begin scalar tf1,tf2,z,den$
  119. den := cddar x * cddar y$ % + AK 28/03/96
  120. tf1 := t_split(x)$
  121. tf2 := t_split(y)$
  122. z := t_fuse(tf1,tf2)$
  123. rplacd(cdar z,den)$ % + AK 28/03/96
  124. return z$
  125. end$
  126. symbolic procedure t_split(x)$
  127. % x - (th . pv)
  128. % r.v. - list of tensor factors: (tf1 ...)
  129. % where tf - (th . pv) and th is a simple tname, i.e. (id)
  130. if null cdaar x then list x
  131. else (t_split1(caar x,pappl(p,cadar x)
  132. ,unpkpv pappl_pv(p,cdr x),nil
  133. )
  134. where p = prev(cdadr x)
  135. )$
  136. symbolic procedure t_split1(tn,il,pv,tfl)$
  137. % tfl (r.v.) - list of tfactors.
  138. if null tn then reversip tfl
  139. else if cdr pv then rederr list('t_split1,": too long pvector ",pv)
  140. else (
  141. (t_split1(cdr tn,cdr ils,list(caar pv . cdr pvs),
  142. ((list car tn . list car ils)
  143. . list(1 . p_rescale car pvs)
  144. ) . tfl
  145. )
  146. where ils = l_split(il,n,nil),
  147. pvs = l_split(cdar pv,n,nil)
  148. ) where n = get(car tn,'!:tensor)
  149. )$
  150. symbolic procedure pv_rescale(pv)$ pv_rescale1(pv,nil)$
  151. symbolic procedure pv_rescale1(pv,pv1)$
  152. if null pv then reversip pv1
  153. else pv_rescale1(cdr pv,(caar pv . p_rescale cdar pv). pv1)$
  154. symbolic procedure p_rescale p$
  155. (for each x in p collect (x-n)) where n = car p - 1$
  156. symbolic procedure l_split(lst,n,lst1)$
  157. % Split list lst into two lists where first one contain n items.
  158. % (r.v.) - (lst1 . lst_rest)
  159. if n<=0 then (reversip lst1) . lst
  160. else l_split(cdr lst,n-1,car lst . lst1)$
  161. symbolic procedure unpkpv(pv)$
  162. unpkpv1(pv,nil)$
  163. symbolic procedure unpkpv1(pv,upv)$
  164. if null pv then reversip upv
  165. else unpkpv1(cdr pv,(caar pv . unpkp cdar pv) . upv)$
  166. symbolic procedure t_fuse(tf1,tf2)$
  167. % tf1, tf2 - list of tensor factors
  168. % r.v. - the result of "multiplication" of them with order.
  169. t_fuse1(reversip tf1,reversip tf2,nil)$
  170. symbolic procedure t_fuse1(tf1,tf2,tf3)$
  171. % r.v. - tf3 - total ordered tensor factor list.
  172. (if null tf1 then t_fuse2(reversip append(reversip tf2,tf3),nil)
  173. else if null tf2 then t_fuse2(reversip append(reversip tf1,tf3),nil)
  174. else if null ordp(caaar tf1,caaar tf2)
  175. then t_fuse1(cdr tf1,tf2,car tf1 . tf3)
  176. else t_fuse1(tf1,cdr tf2,car tf2 . tf3)
  177. )
  178. % where x=if tf1 and tf3 and caaar tf1 = caaar tf3
  179. % then addmultsym(car tf1,car tf3)
  180. % else if tf2 and tf3 and caaar tf2 = caaar tf3
  181. % then addmultsym(car tf2,car tf3)
  182. % else if tf3
  183. % then !*basis:=b_expand1(if tf1 then car tf1 else car tf2
  184. % ,car tf3,!*basis,!*basis
  185. % )
  186. % else nil
  187. $
  188. symbolic procedure t_fuse2(tf,te)$
  189. if null tf then te
  190. else t_fuse2(cdr tf,t_fuse3(car tf,te))$
  191. symbolic procedure t_fuse3(t1,t2)$
  192. % t1,t2 - tensors
  193. % r.v. - it's product.
  194. % side effect: !*basis will be updated.
  195. if null t2 then pkt t1
  196. else if null caar t1 then pkt t2
  197. else ((( ((caaar t1 . caar t2)
  198. .il_simp append(cadar t1,cadar t2)
  199. .nil
  200. )
  201. . cdr pv_times('!:pv . cdr t1,'!:pv . cdr t2)
  202. )
  203. where x=addmultsym(t1,t2)
  204. )
  205. where zz = b_expand(list('!:tensor,t1),list('!:tensor,t2))
  206. % Aug. 06, 1994
  207. )$
  208. symbolic procedure addmultsym(t1,t2)$ % AK, Nov. 20, 1994
  209. addmsym(t1,t2,caar t1,caar t2)$
  210. symbolic procedure addmsym(t1,t2,k1,k2)$
  211. % t1,t2 - tensors the product of them generate new symmtries.
  212. % k1,k2 - current name of t1,t2.
  213. if null k2 then !*basis:=b_expand1(t1,t2,!*basis,!*basis)
  214. else if null k1 then addmsym(t1,t2,caar t1,cdr k2)
  215. else if null(car k1 eq car k2) then addmsym(t1,t2,cdr k1,k2)
  216. else (addmsym(t1,t2,cdr k1,k2)
  217. where zz:=addmsym0(t1,t2,msymperm0(car t1,car t2,k1,k2))
  218. )$
  219. symbolic procedure addmsym0(t1,t2,pz)$
  220. (addmultsym1(th . cdr pv_difference(z,'!:pv . pappl_pv(car pz,cdr z)))
  221. )where th = ((caaar t1 . caar t2) . cdr pz . nil),
  222. z = pv_times('!:pv . cdr t1,'!:pv . cdr t2)$
  223. symbolic procedure msymperm0(th1,th2,k1,k2)$
  224. begin scalar il1,il2,n0,nam1,nam2,w1,w2,zl$
  225. nam1:=car th1$
  226. nam2:=car th2$
  227. il1:=cadr th1$
  228. il2:=cadr th2$
  229. n0:=length il1$
  230. il2:=il_simp append(il1,il2)$
  231. zl:=il2$
  232. il1:=nil$
  233. for i:=1:n0 do << il1:=car il2 . il1$ il2:=cdr il2 >>$
  234. il1:=reversip il1$
  235. w1:=nil$
  236. while null(nam1 eq k1) do <<
  237. n0:=get(car nam1,'!:tensor)$
  238. for i:=1:n0 do << w1:=car il1 . w1$ il1:=cdr il1 >>$
  239. nam1:=cdr nam1$
  240. >>$
  241. w2:=nil$
  242. while null(nam2 eq k2) do <<
  243. n0:=get(car nam2,'!:tensor)$
  244. for i:=1:n0 do << w2:=car il2 . w2$ il2:=cdr il2 >>$
  245. nam2:=cdr nam2$
  246. >>$
  247. n0:=get(car nam1,'!:tensor)$
  248. for i:=1:n0 do <<
  249. w1:=car il2 . w1$
  250. w2:=car il1 . w2$
  251. il1:=cdr il1$
  252. il2:=cdr il2$
  253. >>$
  254. w1:=append(reversip w1,il1)$
  255. w2:=append(reversip w2,il2)$
  256. return pfind(append(w1,w2),zl) . zl$
  257. end$
  258. symbolic procedure addmultsym_(t1,t2)$ nil$
  259. symbolic procedure addmultsym__(t1,t2)$
  260. if caaar t1 neq caaar t2
  261. then !*basis:=b_expand1(t1,t2,!*basis,!*basis)
  262. else((addmultsym1(th .
  263. cdr pv_difference(z,'!:pv . pappl_pv(car pz,cdr z)))
  264. )where th = ((caaar t1 . caar t2) . cdr pz . nil),
  265. z = pv_times('!:pv . cdr t1,'!:pv . cdr t2)
  266. )where pz = msymperm(cadar t1,cadar t2)
  267. % ,zz = b_expand1(t1,t2,!*basis,!*basis) % Aug. 06, 1994
  268. $
  269. symbolic procedure msymperm(il1,il2)$
  270. begin scalar zl,w,k;
  271. k:=length il1;
  272. zl:=il_simp append(il1,il2)$
  273. il2:=zl;
  274. for i:=1:k do << w:=car il2 . w; il2:=cdr il2>>;
  275. il1:=reversip w;
  276. w:=nil;
  277. for i:=1:k do << w:=car il2 . w; il2:=cdr il2>>;
  278. w:=reversip w;
  279. return pfind(append(w,append(il1,il2)),zl) . zl;
  280. end$
  281. symbolic procedure addmultsym2(t1,t2,bs)$
  282. if null bs then nil
  283. else if null th_match0(car t2,caar bs)
  284. then addmultsym2(t1,t2,cdr bs)
  285. else rederr list "b_xpand?"$
  286. symbolic procedure addmultsym1(te)$
  287. !*basis:=tsym2(list te,!*basis,nil)$
  288. symbolic procedure pkt(t1)$ car t1 . pkpv(cdr t1,nil)$
  289. symbolic procedure pkpv(pv,ppv)$
  290. if null pv then reversip ppv
  291. else pkpv(cdr pv,(caar pv . pkp cdar pv) . ppv)$
  292. symbolic procedure t_difference(u,v)$
  293. t_plus(u,t_minus v)$
  294. symbolic procedure t_zerop(u)$ null cdr u$
  295. symbolic procedure t_onep u$ cdr u = 1$
  296. symbolic procedure t_prep u$ % mod. AK 28/03/96
  297. (if not(cddr caadr u = 1) then 'quotient . x . list cddr caadr u
  298. else x)
  299. where x=t_prep1(cdr u,nil)$
  300. symbolic procedure t_prep1(u,v)$
  301. if null u
  302. then if null v then nil
  303. else if cdr v then 'plus . reversip v
  304. else car v
  305. else t_prep1(cdr u,th2pe(caar u,cdar u) . v)$
  306. %symbolic procedure t_prep u$ th2pe(cadr u,cddr u)$
  307. symbolic procedure t_pri(u)$ t_pri1(u,nil)$
  308. symbolic procedure t_intequiv u$
  309. atom cdr u$
  310. symbolic procedure i2tensor n$
  311. '!:tensor . n$
  312. symbolic procedure t_expt(u,n)$
  313. if n=1 then u
  314. else if atom cdr u then cdr u^n
  315. else rederr list('t_expt,"*** Can't powered tensor")$
  316. symbolic procedure t_quotient(u,c)$
  317. if t_intequiv c and cdr c = 1 then u
  318. else rederr list('t_quotient,"*** Tensor can't be divided by: ",c)$
  319. symbolic procedure t_divide(u,v)$
  320. rederr list('t_divide,"*** Can't divide tensor by tensor")$
  321. symbolic procedure t_gcd(u,v)$ % AK 28/03/96
  322. if atom cdr v then 1
  323. else rederr list('t_gcd,"*** Can't find gcd of two tensors")$
  324. initdmode 'tensor$
  325. endmodule;
  326. end;