partitns.red 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. module partitns;
  2. % definitions of particular tensors.
  3. global '(dimex!* sgn!* signat!* spaces!* numindxl!* pair_id_num!*);
  4. fluid('(dummy_id!* g_dvnames epsilon!*));
  5. % epsilon!* keeps track of the various epsilon tensors
  6. % which may be defined when onespace is OFF
  7. % It is a list pairs (<space-name> . <name>)
  8. switch exdelt; % default is OFF
  9. switch onespace;
  10. !*onespace:=t; % working inside a unique space is the default.
  11. flag(list('delta,'epsilon,'del,'eta,'metric), 'reserved); % they are keywords.
  12. symbolic flag(list('make_partic_tens),'opfn);
  13. symbolic procedure make_partic_tens(u,v);
  14. % u is a bare identifier (free of properties)
  15. % the result is T(rue) when it suceeds to create
  16. % the properties of being a particular tensor on u.
  17. % can be trivially generalized to other tensors.
  18. if v memq {'delta,'eta,'epsilon,'del,'metric} then
  19. <<
  20. if get(u,'avalue)
  21. % or (get(u,'reserved) and null flagp(u,'tensor))
  22. or getrtype u or (gettype u eq 'procedure) or
  23. % is this necessary?
  24. (u memq list('sin,'cos,'tan,'atan,'acos,'asin,'df,'int)) then
  25. rerror(cantens,5,list(u,"may not be defined as tensor"))
  26. else
  27. if flagp(u,'tensor) then
  28. <<lpri {"*** Warning:", u,"redefined as particular tensor"};
  29. remprop(u,'kvalue);
  30. remprop(u,'simpfn);
  31. remprop(u,'bloc_diagonal);
  32. remflag(list u,'generic);
  33. >>;
  34. % the 'name' indicator allows to find
  35. % the name chosen for a particular tensor from the keyword
  36. % associated to it.
  37. % Only ONE tensor of type 'delta' and 'eta' are allowed so:
  38. (if x and v memq {'delta,'eta,'del} then rem_tensor1 x)where x=get(v,'name);
  39. make_tensor(u,nil); % contains the action of rem_tensor
  40. put(u,'partic_tens, if v = 'delta then 'simpdelt
  41. else
  42. if v = 'eta then 'simpeta
  43. else
  44. if v = 'epsilon then 'simpepsi
  45. else
  46. if v = 'del then 'simpdel
  47. else
  48. if v= 'metric then 'simpmetric);
  49. if null !*onespace and v = 'epsilon
  50. then
  51. if epsilon!*
  52. then <<put(v,'name,u);
  53. lpri {"*** Warning:", u,"MUST belong to a space"};>>
  54. else nil;
  55. put(v,'name, u);
  56. if v memq {'metric,'delta} then <<flag(list u,'generic);
  57. make_bloc_diagonal u>>;
  58. t
  59. >>
  60. else "unknown keyword";
  61. symbolic procedure find_name u;
  62. % find the name of a particular tensor whose keyword is u.
  63. % Must still be extended for u=epsilon
  64. (if null x then
  65. rerror(cantens,6,{" no name found for", list u})
  66. else x)where x=get(u,'name);
  67. % **** Simplification functions for particular tensors
  68. symbolic procedure simpdelt (x,varl);
  69. % x is is a list {<tensor> indices}
  70. % for instance (tt a (minus b)) for tt(a,-b)
  71. % varl is the set of variables {v1,v2, ...}
  72. % result is the simplified form of the Dirac delta function if varl is nil
  73. % and cdr x is nil.
  74. If varl and null cdr x then !*k2f(car x . varl . nil) else
  75. if null varl or null cdr varl then
  76. begin scalar delt,ind,y,yv,yc;
  77. delt := car x; ind:= cdr x;
  78. y:=split_cov_cont_ids ind;
  79. if (length car y * length cadr y) neq 1 then
  80. rerror(cantens,7, "bad choice of indices for DELTA tensor");
  81. yv:=caar y;
  82. yc:=caadr y;
  83. % The conditional statement below can be suppressed if
  84. % 'wholespace' can be defined with an indexrange.
  85. % if get(delt,'belong_to_space) eq 'wholespace then
  86. % if get_sign_space('wholespace) = 0 then
  87. % if yv='!0 or yc ='!0 then
  88. % rerror(cantens,2,"bad value of indices for DELTA tensor");
  89. if !*id2num yv and !*id2num yc then return
  90. if yv=yc then 1
  91. else 0
  92. else
  93. if !*onespace then return
  94. if yv eq yc then dimex!*
  95. else !*k2f(delt . append(cadr y,lowerind_lst car y))
  96. else return
  97. if null get(yv,'space) and yv eq yc then
  98. if assoc('wholespace,spaces!*) then !*k2f get_dim_space 'wholespace
  99. else "not meaningful"
  100. else
  101. if yv eq yc then !*k2f space_dim_of_idx yv
  102. else !*k2f(delt . append(cadr y,lowerind_lst car y))
  103. end
  104. else "not meaningful";
  105. symbolic procedure simpdel u;
  106. % u is the list {<del-name> <covariant indices>
  107. % <contravariant indices>}
  108. % when 'DEL' is used by the system through simpepsi,
  109. % indices are already ordered and, when 'canonical' is entered,
  110. % they are again ordered after contractions. So ordering is
  111. % necessary only if the user enters it from the start.
  112. % in spite of this, the procedure is made to order them
  113. % in all cases. REFINEMENTS to avoid that are possible.
  114. % returns a standard form.
  115. begin scalar del,ind,x,idv,idc,idvn,idcn,bool,spweight;
  116. integer free_ind,tot_ind,dim_space;
  117. del:= car u;
  118. ind:=cdr u;
  119. spweight:=1;
  120. % though it is antisymmetric separately with respect to the cov
  121. % and cont indices we do not declare it as such for the time being.
  122. x:=split_cov_cont_ids ind;
  123. idv:= car x; idc:=cadr x;
  124. if length idv neq length idc then
  125. rerror(cantens,7, "bad choice of indices for DEL tensor")
  126. else
  127. if null !*onespace then
  128. if null symb_ids_belong_same_space!:(
  129. append(idv,idc),nil) then
  130. rerror(cantens,7, "all indices should belong to the SAME space")
  131. else
  132. if repeats idv or repeats idc then return 0
  133. else
  134. if length idc =1 then return
  135. apply2('simpdelt, find_name('delta) . append(lowerind_lst idv,idc),nil);
  136. % here we shall start to find the dummy indices which are internal
  137. % to 'del' as in the case del(a,b,a1..an, -a,-b,-c1, ...-cn) which
  138. % can be simplified to del(a1,...an,-c1, ...,-cn)*polynomial in the
  139. % space-dimension or a number if N_space=number
  140. % first arrange each list so that dummy indices are at the beginning
  141. % of idv and idc.
  142. idv:=for each y in idv collect %au lieu de idvn
  143. if null !*id2num y and memq(y,idc) then list('dum,y)
  144. else y;
  145. idc:=for each y in idc collect
  146. if null !*id2num y and memq(y,car x) then list('dum,y)
  147. else y;
  148. if permp!:(idvn:=ordn idv,idv)=permp!:(idcn:=ordn idc,idc) then bool:=t;
  149. % the form of these new lists is ((dum a) (dum b) ..ak..) etc ...
  150. % 1. they contain only numeric indices:
  151. if num_indlistp append(idvn,idcn) then
  152. return simpdelnum(idvn,idcn,bool);
  153. % 2. some indices are symbolic:
  154. tot_ind:=length idvn;
  155. % dummy indices can be present:
  156. idv:=splitlist!:(idvn,'dum); % if no dummy indices, it is nil.
  157. free_ind:=tot_ind - length idv;
  158. % now search the space in which we are working.
  159. dim_space:= if idv then %% since, may be, no dummy indices
  160. if null spaces!* then dimex!*
  161. else !*k2f space_dim_of_idx cadar idv;
  162. for i:=free_ind : (tot_ind -1) do
  163. <<spweight:=multf(addf(dim_space,negf !*n2f i),spweight);
  164. idvn:=cdr idvn; idcn:=cdr idcn;
  165. >>;
  166. spweight:=!*a2f reval prepf spweight;
  167. if null idvn then
  168. return
  169. if bool then spweight
  170. else negf spweight;
  171. % left indices can again be all numeric indices
  172. if num_indlistp append(idvn,idcn) then
  173. return
  174. multf(spweight,simpdelnum(idvn,idcn,bool));
  175. % 3. There is no more internal dummy indices, so
  176. return
  177. % if !*exdelt then
  178. % if bool then
  179. % multf(spweight,extract_delt(del,idvn,idcn,1))
  180. % else negf multf(spweight,extract_delt(del,idvn,idcn,1))
  181. % else
  182. if !*exdelt then
  183. if bool then
  184. multf(spweight,extract_delt(del,idvn,idcn,'full))
  185. else negf multf(spweight,extract_delt(del,idvn,idcn,'full))
  186. else
  187. if length idvn=1 then
  188. if bool then
  189. multf(spweight,
  190. !*k2f(find_name('delta) . append(lowerind_lst idvn,idcn)))
  191. else
  192. negf multf(spweight,
  193. !*k2f(find_name('delta) . append(lowerind_lst idvn,idcn)))
  194. else
  195. if bool then
  196. multf(spweight,!*k2f(del . append(lowerind_lst idvn ,idcn)))
  197. else
  198. multf(spweight,negf
  199. !*k2f(del . append(lowerind_lst idvn , idcn)))
  200. end;
  201. symbolic procedure simpdelnum(idvn,idcn,bool);
  202. % simplification of 'DEL' when all indices are numeric.
  203. if idvn=idcn then
  204. if bool then 1
  205. else -1
  206. else 0;
  207. symbolic procedure extract_delt(del,idvn,idcn,depth);
  208. % we deal with already ordered lists. Numeric indices
  209. % come first like (!1 !2 a). So, extraction is done from
  210. % the left because the result simplify more.
  211. if length idcn =1 then
  212. apply2(function simpdelt,
  213. get('delta,'name) . lowerind car idvn . car idcn . nil,nil)
  214. else
  215. begin scalar uu,x,ind;
  216. ind:=car idcn;
  217. idcn:=cdr idcn;
  218. if depth =1 then
  219. for i:=1:length idvn do
  220. <<x:=multf(exptf(-1,i-1),
  221. multf(apply2(function simpdelt,
  222. get('delta,'name) . (ind . list lowerind nth(idvn,i)),nil),
  223. !*q2f mksq((if length idvn=2 then get('delta,'name)
  224. else del) . append(idcn,
  225. lowerind_lst remove(idvn,i)),1)
  226. )
  227. );
  228. uu:=addf(x,uu)
  229. >>
  230. else
  231. if depth='full then
  232. for i:=1:length idvn do
  233. <<x:= multf(exptf(-1,i-1),
  234. multf(apply2(function simpdelt,
  235. get('delta,'name) . (ind . list lowerind nth(idvn,i)),nil),
  236. extract_delt(del,remove(idvn,i),idcn,depth)
  237. )
  238. );
  239. uu:=addf(x,uu)
  240. >>;
  241. return uu
  242. end;
  243. symbolic procedure idx_not_member_whosp u;
  244. % u is an index
  245. (if x then x neq 'wholespace) where x=get(u,'space);
  246. symbolic procedure ids_not_member_whosp u;
  247. % U is a list of indices.
  248. if null u then t
  249. else
  250. if idx_not_member_whosp car u then ids_not_member_whosp cdr u
  251. else nil;
  252. symbolic procedure simpeta u;
  253. % u is a list {<tensor> indices}
  254. % for instance tt(a b) or tt(a -b) or tt(-a,-b)
  255. % result is the simplified form of the Minkowski metric tensor.
  256. if (!*onespace and signat!*=0)
  257. then msgpri(nil,nil,
  258. "signature must be defined equal to 1 for ETA tensor",nil,t)
  259. else
  260. if
  261. (null !*onespace and null get_sign_space get(car u,'belong_to_space))
  262. then
  263. msgpri(nil,nil,
  264. "ETA tensor not properly assigned to a space",nil,nil)
  265. else
  266. begin scalar eta,ind,x;
  267. eta := car u; ind:= cdr u;
  268. flag(list eta,'symmetric);
  269. x:=split_cov_cont_ids ind;
  270. if car x and cadr x then return
  271. apply2('simpdelt,find_name('delta) . ind,nil);
  272. % Now BOTH indices are up or down, so
  273. x:=if null car x then cadr x else car x;
  274. if length x neq 2 then
  275. rerror(cantens,8, "bad choice of indices for ETA tensor");
  276. x:=for each y in x collect !*id2num y;
  277. return if numlis x then num_eta x
  278. else
  279. if !*onespace then !*k2f(eta . ordn ind)
  280. else
  281. if ids_not_member_whosp {car ind,cadr ind} and
  282. get(car ind,'space) neq get(cadr ind,'space) then 0
  283. else !*k2f(eta . ordn ind)
  284. end;
  285. symbolic procedure num_eta u;
  286. % u is the list of covariant or contravariant indices of ETA.
  287. if car u = cadr u then
  288. if car u = 0 then sgn!*
  289. else negf sgn!*
  290. else 0;
  291. symbolic procedure simpepsi u;
  292. % Simplification procedure for the epsilon tensor.
  293. begin scalar epsi,ind,x,spx,bool;
  294. epsi := car u;
  295. % spx is the space epsi belongs to.
  296. % so we can define SEVERAL epsi tensors.
  297. spx:= get(epsi,'belong_to_space); % In case several spaces are used.
  298. % otherwise it is nil
  299. ind:= cdr u;
  300. flag(list epsi,'antisymmetric);
  301. x:=split_cov_cont_ids ind;
  302. if null car x then x:='cont . cadr x
  303. else
  304. if null cadr x then x:= 'cov . car x
  305. else
  306. x:= 'mixed . append(car x, cadr x);
  307. % If the space has a definite dimension we must take care of the number
  308. % of indices:
  309. (if fixp y and y neq length cdr x then
  310. rerror(cantens,9,
  311. list("bad number of indices for ", list car u," tensor"))
  312. )where y= if spx then get_dim_space spx
  313. else (if fixp z then z)where z=wholespace_dim '?;
  314. if repeats x then return 0;
  315. % if null !*onespace then one must verify that all
  316. % indices belong to the same space as epsi.
  317. if null !*onespace and spx then
  318. if null ind_same_space_tens(cdr u,car u) then
  319. rerror(cantens,9, list("some indices are not in the space of",epsi));
  320. return
  321. if car x eq 'mixed or not num_indlistp cdr x then
  322. begin scalar xx,xy;
  323. xx:=ordn ind;
  324. bool:=permp!:(xx,ind);
  325. if car x eq 'mixed then
  326. <<xy:=cont_before_cov ind;
  327. if null permp!:(xy,xx) then bool:=not bool>>;
  328. return if bool then
  329. !*k2f(epsi . if car x eq 'mixed then
  330. xy else xx)
  331. else negf !*k2f(epsi . if car x eq 'mixed then
  332. xy else xx)
  333. end
  334. else
  335. % cases where all indices are numeric ones must be handled separately
  336. % Take the case where either no space is defined or declared. Then
  337. % space is euclidean.
  338. % look out ! spx is EUCLIDEAN by default. To avoid it, use
  339. % 'make_tensor_belong_space'.
  340. if !*onespace or null spx then
  341. if signat!* =0 then num_epsi_euclid(x)
  342. else
  343. if signat!* =1 then num_epsi_non_euclid (epsi,x)
  344. else nil
  345. else
  346. if null get_sign_space spx or get_sign_space spx=0
  347. then num_epsi_euclid (cdr x)
  348. else
  349. if get_sign_space spx =1 then num_epsi_non_euclid (epsi,x)
  350. else
  351. "undetermined signature or signature bigger then 1";
  352. end;
  353. symbolic procedure num_epsi_non_euclid(epsi,ind);
  354. % epsi is the name of the epsilon tensor
  355. % ind is the list (cont n1 n2 nk) or (cov n1 n2 .. nk)
  356. % result is either 0 OR +- (epsi 0 1 2 .... k))
  357. % i.e. in terms of contravariant indices.
  358. % So, in case of covariant indices we must take care of the
  359. % product eta(0,0)*... *eta(spx,spx) and the convention
  360. % sgn!* enters the game.
  361. begin scalar x;
  362. x:=ordn cdr ind;
  363. return if car ind eq 'cont then
  364. (if y then y
  365. else if permp!:(x,cdr ind) then !*k2f(epsi . x)
  366. else negf !*k2f(epsi . x))where
  367. y=!*q2f match_kvalue(epsi,x,nil)
  368. else
  369. if car ind eq 'cov then
  370. if sgn!* = 1 then
  371. if evenp length cdr x then
  372. (if y then y
  373. else if permp!:(x,cdr ind) then !*k2f(epsi . x)
  374. else negf !*k2f(epsi . x))where
  375. y=!*q2f match_kvalue(epsi,x,nil)
  376. else
  377. (if y then negf y
  378. else if permp!:(x,cdr ind) then negf !*k2f(epsi . x)
  379. else !*k2f(epsi . x))where
  380. y=!*q2f match_kvalue(epsi,x,nil)
  381. else
  382. if sgn!* =-1 then
  383. (if y then negf y
  384. else if permp!:(x,cdr ind) then negf !*k2f(epsi . x)
  385. else !*k2f(epsi . x))where
  386. y=!*q2f match_kvalue(epsi,x,nil)
  387. else nil
  388. else nil;
  389. end;
  390. flag({'show_epsilons},'opfn);
  391. symbolic procedure show_epsilons();
  392. (if null x then {'list}
  393. else 'list . for each y in x collect
  394. list('list,mk!*sq !*k2q car y,mk!*sq !*k2q cdr y))where x=epsilon!*;
  395. symbolic procedure match_kvalue(te,ind,varl);
  396. % te is a tensor, result is nil or a standard form.
  397. % Must return a standard quotient.
  398. (if x then simp!* cadr x)where
  399. x= if varl then
  400. assoc(te . varl . ind,get(te,'kvalue))
  401. else assoc(te . ind,get(te,'kvalue));
  402. symbolic procedure num_epsi_euclid(ind);
  403. % ind is the list (i1, ...,in), therefore
  404. % here epsi(1,2, n)=1=epsi(-1,-2, ... -n)
  405. begin scalar x;
  406. x:=ordn ind;
  407. return if permp!:(x,ind) then 1
  408. else -1
  409. end;
  410. symbolic procedure simpmetric(u,var);
  411. % generic definition of the metric tensor
  412. % covers the possibility of several spaces.
  413. % may depend of any number of variables if needed.
  414. % 'var' is {x1, .. xn}.
  415. % receives an SF and sends back an SQ.
  416. % CORRECTED
  417. begin scalar g,ind,x;
  418. if x:=opmtch u then return simp x;
  419. g:=car u; ind:=cdr u;
  420. flag(list g,'symmetric);
  421. x:=split_cov_cont_ids ind;
  422. if car x and cadr x then return
  423. apply2('simpdelt,find_name('delta) . ind,nil) ./ 1;
  424. % Now BOTH indices are up or down, so
  425. x:=if null car x then cadr x else car x;
  426. if length x neq 2 then
  427. rerror(cantens,10, "bad choice of indices for a METRIC tensor");
  428. % case of numeric indices.
  429. x:=for each y in x collect !*id2num y;
  430. return if numlis x then
  431. if !*onespace then
  432. if x:= match_kvalue(g,ordn ind,var) then x
  433. else !*k2f(g . if var then var . ordn ind
  434. else ordn ind) ./ 1
  435. else mult_spaces_num_metric(g,ind,var) ./ 1
  436. else
  437. if !*onespace then
  438. if x:= match_kvalue(g,ordn ind,var) then x
  439. else !*k2f(g . if var then var . ordn ind
  440. else ordn ind) ./ 1
  441. else
  442. if get(car ind,'space) neq get(cadr ind,'space) then 0
  443. else
  444. if x:= match_kvalue(g,ordn ind,var) then x
  445. else !*k2f(g . if var then var . ordn ind
  446. else ordn ind) ./ 1
  447. end;
  448. symbolic procedure mult_spaces_num_metric(g,ind,var);
  449. % g, is the name of the metric tensor
  450. % ind its numeric indices (both covariant or contravariant)
  451. begin scalar x,y;
  452. x:=if pairp car ind then raiseind_lst ind else ind;
  453. return
  454. if numindxl!* and null numids2_belong_same_space(car x,cadr x,g) then 0
  455. else
  456. if y:= match_kvalue(g,if var then var . ordn ind
  457. else ordn ind,var) then y
  458. else !*k2f(g . if var then var . ordn ind
  459. else ordn ind)
  460. end;
  461. endmodule;
  462. end;