spaces.red 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. module spaces; % definition and general properties
  2. % of spaces.
  3. lisp remflag(list 'minus,'intfn);
  4. global '(dimex!* sgn!* signat!* spaces!* numindxl!* pair_id_num!*) ;
  5. lisp (pair_id_num!*:= '((!0 . 0) (!1 . 1) (!2 . 2) (!3 . 3) (!4 . 4)
  6. (!5 . 5) (!6 . 6) (!7 . 7) (!8 . 8) (!9 . 9)
  7. (!10 . 10) (!11 . 11) (!12 . 12) (!13 . 13)));
  8. fluid('(dummy_id!* g_dvnames epsilon!*));
  9. % g_dvnames is a vector.
  10. switch onespace;
  11. !*onespace:=t; % working inside a unique space is the default.
  12. fluid('(indxl_tens!* dummy_id!* g_dvnames)); % g_dvnames is a vector.
  13. % dimex!* = global space dimension. Standard form.
  14. % sgn!* = Choice of "global sign". Equals 1 or -1.
  15. % 1 for high energy physicists, -1 for astrophysicists.
  16. % !*onespace = when OFF allows to introduce a space
  17. % which is the direct product of two or more spaces.
  18. % numindxl!* := nil initially. Contains all indexranges: ((sp min max) ..)
  19. dimex!*:= !*k2f 'dim;
  20. sgn!* := 1; % Global sign: determine the convention (+---) ou (-+++)
  21. % High energy physicists convention is chosen by default.
  22. signat!* :=0; % number of time-like coordinates.
  23. fluid '(alglist!*);
  24. smacro procedure get_prop_space u;
  25. % To get properties of a given space (subspace).
  26. subla(spaces!*,u);
  27. symbolic procedure charnump!: x;
  28. if x memq
  29. list('!0,'!1,'!2,'!3,'!4,'!5,'!6,'!7,'!8,'!9,'!10,'!11,'!12,'!13)
  30. then t ;
  31. symbolic procedure get_dim_space u;
  32. if null u then nil
  33. else
  34. (if not atom x then car x)where x=subla(spaces!*,u);
  35. symbolic procedure get_sign_space u;
  36. % To get the signature of a given space (subspace).
  37. % result is nil if space is 'affine'
  38. if null u then nil else
  39. (if atom cadr x and null cddr x then
  40. if cadr x eq 'euclidian then 0
  41. else nil
  42. else caddr x)where x=subla(spaces!*,u);
  43. symbolic procedure affinep u;
  44. % u is a tensor kernel
  45. % returns T if the the tensor belongs to an affine space.
  46. (if x then null get_sign_space x)where x=get(car u,'belong_to_space);
  47. symbolic procedure get_indexrange_space u;
  48. % To get the signature of a given space (subspace).
  49. if null spaces!* then nil
  50. else
  51. (if x then
  52. if not atom x and cddr x and cdddr x then cadddr x
  53. else
  54. if cddr x and not atom caddr x then caddr x)
  55. where x=if spaces!* then subla(spaces!*,u);
  56. symbolic procedure onespace u;
  57. % Defined specifically for the user. tells if
  58. % one or several spaces are active.
  59. % By default, a UNIQUE space is supposed.
  60. if u eq '? then
  61. if !*onespace then symb_to_alg 'YES else symb_to_alg 'NO
  62. else nil;
  63. symbolic procedure wholespace_dim u;
  64. % if u is ? gives the space-dimension. else sets the space-dim.
  65. begin
  66. if u eq '? then return
  67. prepsq!* !*f2q dimex!*
  68. else
  69. if null get('wholespace,'spacedef) then
  70. <<dimex!* := !*q2f simp u ;
  71. return prepsq!* !*f2q dimex!*>>;
  72. end;
  73. symbolic procedure global_sign u;
  74. % if u is ? gives the global sign else sets it.
  75. begin
  76. if u eq '? then return sgn!*
  77. else return
  78. sgn!* := u
  79. end;
  80. symbolic procedure signature u;
  81. % if u is ? gives the number of time-like coordinates else sets it.
  82. if u eq '? then signat!*
  83. else
  84. if !*onespace and fixp u then signat!*:=u
  85. else "non-active in OFF ONESPACE";
  86. flag({'onespace,'show_spaces,'wholespace_dim ,
  87. 'global_sign ,'signature},'opfn);
  88. % The notion of indexrange for numeric indices is now implemented:
  89. % taken from INEQ
  90. newtok '( (!. !.) !*interval!*);
  91. % first, introduction of interval through the command a .. b
  92. if null get('!*interval!*,'simpfn) then
  93. <<precedence .., or;
  94. algebraic operator ..;
  95. put('!*interval!*,'prtch,'! !.!.! );
  96. >>;
  97. symbolic procedure mkinterval(u,v);
  98. % u et v sont des entiers
  99. % utility function not yet used for the algebraic mode
  100. symb_to_alg list('!*interval!*,u,v);
  101. symbolic procedure lst_belong_interval(lst,int);
  102. if null lst then t
  103. else
  104. if idx_belong_interval(car lst,int) then lst_belong_interval(cdr lst,int)
  105. else nil;
  106. symbolic procedure idx_belong_interval(idx,int);
  107. % t if numeric index 'idx' belongs to the interval 'int'.
  108. if null int or atom int then t
  109. else idx geq car int and idx leq cadr int;
  110. symbolic procedure numids2_belong_same_space(i1,i2,tens);
  111. % basic function to determine if two numeric indices
  112. % belong or not to the same space. Boolean.
  113. % tens is the name of the tensor
  114. (if x and y then
  115. begin scalar ind,sp;
  116. if null numindxl!* then return t;
  117. ind:=if (sp:=get(tens,'belong_to_space)) then
  118. list subla(numindxl!*,sp)
  119. else for each x in numindxl!* collect cdr x;
  120. loop: if null ind then return nil
  121. else
  122. if idx_belong_interval(x,car ind)
  123. and idx_belong_interval(y,car ind)
  124. then return t
  125. else ind:=cdr ind;
  126. go to loop;
  127. end)where x=!*id2num i1,y=!*id2num i2;
  128. symbolic procedure num_ids_belong_same_space(u,tens);
  129. % u is a list of numeric indices
  130. % tens is the name of a tensor
  131. << if oddp length u then u:= car u . u;
  132. while u and numids2_belong_same_space(car u,cadr u,tens)
  133. do u:=cddr u; if null u then t else nil>>;
  134. symbolic procedure symb_ids_belong_same_space(u,v);
  135. % u is a list of indices.
  136. % nil is the current starting value for v but may be the
  137. % name of one space. In that case, it verifies that all indices
  138. % in u belong to the v space.
  139. if null u or v = 'wholespace then t
  140. else
  141. if null get(car u,'space) or get(car u,'space) = v
  142. then symb_ids_belong_same_space(cdr u,v)
  143. else
  144. if null v then symb_ids_belong_same_space(cdr u,get(car u,'space))
  145. else
  146. if get(car u,'space) neq v then nil;
  147. symbolic procedure symb_ids_belong_same_space!:(u,v);
  148. % This is a variant of the previous procedure.
  149. % needed for DEL-like tensors when working in OFF onespace
  150. % u is a list of indices.
  151. % nil is the current starting value for v but may be the
  152. % name of one space. In that case, it verifies that all indices
  153. % in u belong to the v space.
  154. if null u then t
  155. % v = 'wholespace then t NOT VALID in general since some indices
  156. % may have a restricted range while BELONGING to a
  157. % WELL DEFINED space. Should most probably replace it.
  158. else
  159. if null get(car u,'space) or get(car u,'space) = v
  160. then symb_ids_belong_same_space!:(cdr u,v)
  161. else
  162. if null v then symb_ids_belong_same_space!:(cdr u,get(car u,'space))
  163. else
  164. if get(car u,'space) neq v then nil;
  165. symbolic procedure ind_same_space_tens(u,tens);
  166. % u are the indices of tens.
  167. % verify that they belong to the same space
  168. % !!! if some indices belong to no space or to the
  169. % wholespace it does not take them into account.
  170. begin scalar lst,lstnum;
  171. lst := clean_numid u;
  172. lstnum:=extract_num_id u;
  173. return
  174. if num_ids_belong_same_space(lstnum,tens) and
  175. symb_ids_belong_same_space(lst,get(tens,'belong_to_space))
  176. then t
  177. else nil;
  178. end;
  179. rlistat ('(define_spaces rem_spaces));
  180. symbolic procedure define_spaces u;
  181. % Define subspaces by the commands:
  182. % define_spaces s={ds,affine}
  183. % or
  184. % define_spaces s={ds,euclidean}
  185. % or
  186. % define_spaces s={ds,signature=<number>,indexrange=a .. b}
  187. if !*onespace then nil
  188. else
  189. if not fixp sgn!* then rederr "set the global sign please" else
  190. begin scalar sp;rmsubs();
  191. for each j in u do
  192. if not eqexpr j then errpri2(j,'hold)
  193. else
  194. if get(sp:=cadr j,'spacedef) or
  195. flagp(sp,'reserved) or getrtype sp or gettype sp
  196. then
  197. lpri{"*** Warning:",sp,
  198. " cannot be (or is already) defined as space identifier"}
  199. else <<(put(sp,'spacedef,
  200. if eqexpr caddr y then sp . cadr y . whole_space(sp,y)
  201. else sp . whole_euclid_space(sp,y)))where y=caddr j;
  202. spaces!*:=if null assoc(sp,spaces!*) then
  203. union(list get(sp,'spacedef),spaces!*);
  204. numindxl!* := if space_index_range sp then
  205. union( list (sp . space_index_range sp),numindxl!*);>>;
  206. return t
  207. end;
  208. symbolic procedure whole_euclid_space(sp,u);
  209. % u is the y of define_spaces
  210. % {ds,euclidean,indexrange=a .. b}
  211. (if sp eq 'wholespace then
  212. <<dimex!*:=!*k2f car w; signat!*:=0; w>> else w)where w=cdr u;
  213. symbolic procedure whole_space(sp, u);
  214. % u is y of define_spaces
  215. % {ds,signature=<number>,indexrange=a .. b}
  216. (if sp eq 'wholespace then
  217. <<dimex!*:=!*k2f car w; signat!*:=caddr cadr w;
  218. if cddr w then cadadr w . cadr cdadr w . list caddr w
  219. else cdadr w
  220. >>
  221. else
  222. if cddr w then cadadr w . cadr cdadr w . list caddr w
  223. else cdadr w )where w=cdr u;
  224. %symbolic procedure whole_space(sp, u);
  225. % In case of emergency, I keep it!
  226. % u is y of define_spaces
  227. % {ds,signature=<number>,indexrange=a .. b}
  228. % (if sp eq 'wholespace then
  229. % <<dimex!*:=!*k2f car w; signat!*:=caddr cadr w;cdadr w>>
  230. % else
  231. % if cddr w then cadadr w . cadr cdadr w . list caddr w
  232. % else cdadr w )where w=cdr u;
  233. symbolic procedure space_index_range u;
  234. % u is the name of a given space
  235. % result is
  236. begin scalar x;
  237. x:=get_indexrange_space u;
  238. return
  239. if null x then nil
  240. else bubblesort1( caddr cadr x . caddr x . nil)
  241. end;
  242. symbolic procedure rem_spaces u;
  243. <<for each j in u do
  244. <<remprop(j,'spacedef);
  245. spaces!*:=delete(assoc(j, spaces!*),spaces!*);
  246. numindxl!*:=delete(assoc(j,numindxl!*),numindxl!*);
  247. remflag(list j,'reserved);
  248. if j eq 'wholespace then
  249. <<dimex!*:=!*k2f 'dim; signat!*:=0;>>
  250. >>;
  251. t>>;
  252. symbolic procedure mkequal u;
  253. % u is an element of spaces!*
  254. {'equal,'signature,cadr u};
  255. symbolic procedure insert_sign_equal u;
  256. % u is an element of spaces!*
  257. begin scalar l;
  258. loop: if null u then return reverse l ;
  259. if car u neq 'signature then <<l:=car u . l; u:=cdr u>>
  260. else <<l:=mkequal u . l; u:=cddr u>>;
  261. go to loop;
  262. end;
  263. symbolic procedure show_spaces();
  264. % Gives the properties of already defined spaces
  265. begin scalar x;
  266. x:=for each i in spaces!* collect insert_sign_equal i;
  267. x:=for each y in x collect 'list .
  268. for each z in y collect if pairp z then z else mk!*sq !*k2q z;
  269. return 'list . reverse x
  270. end;
  271. flag(list 'mk_ids_belong_space,'opfn);
  272. symbolic procedure mk_ids_belong_space(u,v);
  273. % u is a list of identifiers which are indices
  274. % v is the name of an already defined (sub)space
  275. % Make all indices belong to v.
  276. % Works ONLY when the swith onespace is OFF.
  277. if !*onespace then nil
  278. else
  279. if idp u then <<put(u,'space,v),t>>
  280. else <<for each x in u do put(x,'space,v),t>>;
  281. rlistat('(mk_ids_belong_anyspace));
  282. symbolic procedure mk_ids_belong_anyspace u;
  283. % makes all x in u belong to the global space.
  284. <<for each x in u do remprop(x,'space); t>>;
  285. symbolic procedure space_of_idx u;
  286. % try to detect the space to which an index belongs to.
  287. begin scalar sp;
  288. return
  289. if sp:=get(u,'space) then sp
  290. else
  291. if assoc('wholespace,spaces!*) then 'wholespace
  292. else if length spaces!* = 1 then
  293. if yesp list("Does ",u," belong to ",caar spaces!*,"?")
  294. then put(u,'space,caar spaces!*)
  295. else rerror(cantensor,4,list("Space of index ",u," unknown"))
  296. else
  297. % it is not clear that this error message should be maintained:
  298. msgpri(nil,nil,u, "MUST belong to a (sub)space",t);
  299. end;
  300. symbolic procedure space_dim_of_idx u;
  301. % u is the name of an index
  302. % result is the dimension of the space to which it belongs
  303. % or an error message.
  304. if null !*onespace then
  305. begin scalar sp;
  306. sp:=get(u,'space);
  307. if null sp then return mvar dimex!*
  308. else return get_dim_space sp
  309. end;
  310. symbolic procedure extract_dummy_ids u;
  311. % extracts the dummy indices from a given list
  312. if null u then nil
  313. else if car u memq dummy_id!* then
  314. car u . extract_dummy_ids cdr u
  315. else extract_dummy_ids cdr u;
  316. rlistat('(rem_dummy_indices));
  317. symbolic procedure rem_dummy_indices u ;
  318. % remove property 'dummy' of all indices in u.
  319. % redefines g_dvnames.
  320. <<for each x in u do
  321. <<dummy_id!* := delete(x,dummy_id!*);
  322. remprop(x,'space);
  323. remflag(list x,'dummy); remflag(list x,'reserved)>>;
  324. dummy_nam dummy_id!*; t>>;
  325. symbolic procedure dummy_indices;
  326. symb_to_alg dummy_id!*;
  327. flag(list('dummy_indices),'opfn);
  328. symbolic procedure mk_dummy_ids u;
  329. % u is the output of split_cov_cont_ids
  330. % constructs the 'dummy_id!*' and the g_dvnames globals
  331. % variable.
  332. begin scalar y;
  333. y:=clean_numid intersection(car u,cadr u);
  334. flag(y,'dummy);
  335. flag(y,'reserved);
  336. dummy_id!*:= union(y,dummy_id!*);
  337. % dummy_nam(dummy_id!*)
  338. end;
  339. symbolic procedure mk_lst_for_dummy u;
  340. % u is the output of index_list
  341. % It eliminates the minus sign
  342. for each x in u collect
  343. if atom x then x
  344. else
  345. if cadr x memq dummy_id!* then cadr x
  346. else x;
  347. symbolic procedure multiplicity_elt(ob,l);
  348. % ob is an arbitrary index, l is a list of indices
  349. % returns the multiplicity of ob in l.
  350. begin integer n;
  351. while l:=memq(ob,l) do <<l:=cdr l;n:=n+1>>;
  352. return n
  353. end;
  354. symbolic procedure mult_leq_onep u;
  355. % u is a list of indices
  356. if null u then t else
  357. if multiplicity_elt(car u,u) leq 1 then
  358. mult_leq_onep(cdr u);
  359. symbolic procedure eqn_indices(u,v);
  360. % verify if two indices are fixed (pseudo-numbers) and equal.
  361. (x and y and eqn(x,y))where x=!*id2num u, y=!*id2num v;
  362. endmodule;
  363. end;