excalc.red 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634
  1. module excalc; % header for EXCALC --- a differential geometry package.
  2. % Author: Eberhard Schruefer;
  3. %************ patches ***************;
  4. % Meaning of ^ and # changed. !!!! BE AWARE OF THIS "!!!
  5. remprop('!^,'newnam);
  6. % plus and difference changed because we are dealing with non-
  7. % homogenous terms
  8. deflist('
  9. ((difference getrtypeor)
  10. (plus getrtypeor)
  11. ),'rtypefn);
  12. share bndeq!*,detm!*;
  13. %*********************************************************************;
  14. %*********************************************************************;
  15. % Differential Geometry Package ;
  16. %*********************************************************************;
  17. % This version runs in REDUCE 3.3
  18. %*********************************************************************;
  19. % Version: 2.z ;
  20. % E.Schruefer 03/12/87 ;
  21. %*********************************************************************;
  22. % testsite copy ;
  23. % ====== this program must not be redistributed or copied ====== ;
  24. %*********************************************************************;
  25. endmodule;
  26. module indxprin; % Functions for special print.
  27. % Author: Eberhard Schruefer;
  28. global '(ycoord!* ymax!* ymin!* obrkp!* !*nat orig!* !*eraise !*revpri
  29. posn!* pline!* spare!* !*nero);
  30. symbolic procedure indvarprt u;
  31. if null !*nat then <<prin2!* car u;
  32. prin2!* "(";
  33. if cddr u then inprint('!*comma!*,0,cdr u)
  34. else maprin cadr u;
  35. prin2!* ")" >>
  36. else begin scalar y; integer l;
  37. l := flatsizec flatindxl u+length cdr u-1;
  38. if l>(linelength nil-spare!*)-posn!* then terpri!* t;
  39. %avoid breaking of an indexed variable over a line;
  40. y := ycoord!*;
  41. prin2!* car u;
  42. for each j on cdr u do
  43. <<ycoord!* := y + if atom car j then 1 else -1;
  44. if ycoord!*>ymax!* then ymax!* := ycoord!*;
  45. if ycoord!*<ymin!* then ymin!* := ycoord!*;
  46. prin2!* if atom car j then car j else cadar j;
  47. if cdr j then prin2!* " ">>;
  48. ycoord!* := y
  49. end;
  50. symbolic procedure rembras u;
  51. if !*nat and (atom u or null get(car u,'infix))
  52. then <<prin2!* " ";
  53. maprin u>>
  54. else <<prin2!* "(";
  55. maprin u;
  56. prin2!* ")">>;
  57. put('form!-with!-free!-indices,'tag,'form!-with!-free!-indices);
  58. put('form!-with!-free!-indices,'prifn,'indxpri1);
  59. flag('(form!-with!-free!-indices),'sprifn);
  60. put('indvarprt,'expt,'inbrackets);
  61. endmodule;
  62. %*********************************************************************;
  63. %***** Global variables and declaration commands ****;
  64. %*********************************************************************;
  65. module exintro;
  66. % Author: Eberhard Schruefer;
  67. global '(dimex!* lftshft!* detm!*
  68. basisforml!* sgn!* wedgemtch!* bndeq!* depl!*
  69. basisvectorl!* indxl!* nosuml!* !*nosum coord!*
  70. keepl!* metricd!* metricu!* !*product!-rule);
  71. %Some initialiations;
  72. dimex!* := !*q2f simp 'dim;
  73. sgn!* := !*k2q 'sgn;
  74. !*product!-rule := t;
  75. rlistat('(pform fdomain remfdomain tvector spacedim forder remforder
  76. frame dualframe keep closedform xpnd noxpnd
  77. isolate remisolate));
  78. symbolic procedure spacedim u;
  79. begin
  80. dimex!* := !*q2f simp car u
  81. end;
  82. symbolic procedure fdomain u;
  83. %Sets up implicit dependencies;
  84. while u do
  85. <<if not eqexpr car u then errpri2(car u,'hold)
  86. else begin scalar y;
  87. rmsubs();
  88. y := get(cadar u,'rtype);
  89. remprop(cadar u,'rtype);
  90. for each x in cdr caddar u do
  91. <<if indvarp x then
  92. for each j in mkaindxc flatindxl cdr x do
  93. depend1(cadar u,prepsq simpindexvar
  94. sublis(pair(flatindxl cdr x,j),x),t)
  95. else depend1(cadar u,x,t)>>;
  96. flag(list cadar u,'impfun);
  97. if y then put(cadar u,'rtype,y)
  98. end;
  99. u := cdr u>>;
  100. smacro procedure get!-impfun!-args u;
  101. cdr assoc(u,depl!*);
  102. symbolic procedure remfdomain u;
  103. %Removes implicit dependencies;
  104. begin scalar x;
  105. for each j in u do
  106. if x := assoc(j,depl!*) then <<depl!* := delete(x,depl!*);
  107. remflag(list j,'impfun)>>
  108. else rederr list(j," had no dependencies");
  109. end;
  110. symbolic procedure putform(u,v);
  111. if atom u then put(!*a2k u,'fdegree,list !*q2f simp v)
  112. else
  113. begin scalar x,y; integer n;
  114. n := length cdr u;
  115. if (x := get(car u,'ifdegree)) and (y := assoc(n,x))
  116. then x := delete(y,x);
  117. put(car u,'ifdegree,if x then (n . !*q2f simp v) . x
  118. else list(n . !*q2f simp v));
  119. x := car u;
  120. flag(list x,'indexvar); %this should go.
  121. put(x,'rtype,'indexed!-form);
  122. put(x,'simpfn,'simpindexvar);
  123. put(x,'partitfn,'partitindexvar);
  124. flag(list x,'full);
  125. put(x,'prifn,'indvarprt);
  126. if null numr simp v then flag(list x,'covariant)
  127. end;
  128. symbolic procedure pform u;
  129. begin rmsubs();
  130. for each j in u do
  131. if not eqexpr j then errpri2(j,'hold)
  132. else putform(cadr j,caddr j)
  133. end;
  134. symbolic procedure tvector u;
  135. for each j in u do putform(j,-1);
  136. symbolic procedure getlower u;
  137. cdr atsoc(u,metricd!*);
  138. symbolic procedure getupper u;
  139. cdr atsoc(u,metricu!*);
  140. symbolic procedure xpnd u;
  141. <<rmsubs(); remflag(u,'noxpnd)>>;
  142. symbolic procedure noxpnd u;
  143. <<rmsubs(); flag(u,'noxpnd)>>;
  144. symbolic procedure closedform u;
  145. <<rmsubs(); flag(u,'closed)>>;
  146. symbolic procedure memqcar(u,v);
  147. null atom u and car u memq v;
  148. smacro procedure lowerind u;
  149. list('minus,u);
  150. smacro procedure raiseind u;
  151. list('minus,u);
  152. endmodule;
  153. %*********************************************************************;
  154. %***** Functions for calculating the degree of a form ****;
  155. %*********************************************************************;
  156. module degform;
  157. % Author: Eberhard Schruefer;
  158. global '(frlis!*);
  159. symbolic procedure deg!*farg u;
  160. %Calculates the sum of degrees of the elements of the list u;
  161. if null cdr u then deg!*form car u else
  162. begin scalar z;
  163. for each j in u do z := addf(deg!*form j,z);
  164. return z
  165. end;
  166. smacro procedure get!*fdeg u;
  167. (if x then car x else nil)
  168. where x = get!*(u,'fdegree);
  169. smacro procedure get!*ifdeg u;
  170. (if x then cdr x else nil)
  171. where x = assoc(length cdr u,get(car u,'ifdegree));
  172. symbolic procedure deg!*form u;
  173. %U is a prefix expression. Result is the degree of u;
  174. if atom u then get!*fdeg u
  175. else (if flagp(x,'indexvar) then get!*ifdeg u
  176. else if x eq 'wedge then deg!*farg cdr u
  177. else if x eq 'd then addd(1,deg!*form cadr u)
  178. else if x eq 'hodge then addf(dimex!*,negf deg!*form cadr u)
  179. else if x eq 'partdf then if cddr u then nil else -1
  180. else if x eq 'liedf then deg!*form caddr u
  181. else if x eq 'innerprod then addd(-1,deg!*form caddr u)
  182. else if x memq '(plus minus difference quotient) then
  183. deg!*form cadr u
  184. else if x eq 'times then deg!*farg cdr u
  185. else nil) where x = car u;
  186. symbolic procedure exformp u;
  187. %test for exterior forms and vectors in prefix expressions;
  188. if null u or numberp u then nil
  189. else if atom u and u memq frlis!* then t
  190. else if atom u then get(u,'fdegree)
  191. else if flagp(car u,'indexvar)
  192. then assoc(length cdr u,get(car u,'ifdegree))
  193. else if car u eq '!*sq then exformp prepsq cadr u
  194. else if car u memq '(wedge d partdf hodge innerprod liedf) then t
  195. else if get(car u,'dname) then nil
  196. else lexformp cdr u or exformp car u;
  197. symbolic procedure lexformp u;
  198. u and (exformp car u or lexformp cdr u);
  199. endmodule;
  200. %*********************************************************************;
  201. %**** Partitioned standard forms ****;
  202. %*********************************************************************;
  203. module partitsf;
  204. % Author: Eberhard Schruefer;
  205. fluid '(alglist!* !*exp);
  206. smacro procedure ldpf u;
  207. %selector for leading standard form in patitioned sf;
  208. caar u;
  209. smacro procedure tpsf u;
  210. %selector for leading term in partitioned sf;
  211. car u;
  212. smacro procedure !*k2pf u;
  213. u .* (1 ./ 1) .+ nil;
  214. smacro procedure negpf u;
  215. multpfsq(u,(-1) ./ 1);
  216. symbolic procedure partitop u;
  217. begin scalar x,alglist!*;
  218. return
  219. if atom u then if x := get(u,'avalue)
  220. then partitsq!* simp!* cadr x
  221. else if get!*fdeg u then mkupf u
  222. else if numr(x := simp!* u)
  223. then 1 .* x .+ nil
  224. else nil
  225. else if x := get(car u,'partitfn)
  226. then if flagp(car u,'full) then apply1(x,u)
  227. else apply1(x,cdr u)
  228. else if car u eq '!*sq then partitsq!* simp!* u
  229. else if car u eq 'plus then
  230. <<for each j in cdr u do
  231. x := addpf(partitop j,x); x>>
  232. else if car u eq 'minus then negpf partitop cadr u
  233. else if car u eq 'difference then
  234. addpf(partitop cadr u,
  235. negpf partitop caddr u)
  236. else if car u eq 'times then
  237. <<x := partitop cadr u;
  238. for each j in cddr u do
  239. x := multpfs(partitop j,x);
  240. x>>
  241. else if car u eq 'quotient then
  242. multpfsq(partitop cadr u,simprecip cddr u)
  243. else if car u eq 'recip then
  244. 1 .* simprecip cdr u .+ nil
  245. else if numr(x := simp!* u)
  246. then 1 .* x .+ nil
  247. else nil
  248. end;
  249. symbolic procedure mkupf u;
  250. begin scalar x;
  251. x := mksq(u,1);
  252. return if null numr x then nil
  253. else if (denr x = 1) and (lc numr x = 1)
  254. and null red numr x and null sfp mvar numr x
  255. then !*k2pf mvar numr x
  256. else partitsq!* x
  257. end;
  258. symbolic procedure partitsq(u,v);
  259. %U is a standardquotient. Result is a form in which expressions
  260. %satisfying the test v are distributed and the rest is kept
  261. %recursive. Leaves unexpanded structure if possible;
  262. (if null x then nil
  263. else if domainp x then 1 .* u .+ nil
  264. else addpsf(if sfp mvar x and apply1(v,mvar x)
  265. then multpsf(exptpsf(partitsq(mvar x ./ 1,v),
  266. ldeg x),
  267. partitsq(cancel(lc x ./ y),v))
  268. else if null sfp mvar x and apply1(v,!*k2f mvar x)
  269. then multpsf(!*p2f lpow x .* (1 ./ 1) .+ nil,
  270. partitsq(cancel(lc x ./ y),v))
  271. else multsqpsf(!*p2q lpow x,
  272. partitsq(cancel(lc x ./ y),v)),
  273. partitsq(cancel(red x ./ y),v)))
  274. where x = numr u, y = denr u;
  275. symbolic procedure exptpsf(u,n);
  276. begin scalar x;
  277. x := u;
  278. while (n := n-1) > 0 do x := multpsf(u,x);
  279. return x
  280. end;
  281. symbolic procedure exptpf(u,n);
  282. begin scalar x;
  283. x := u;
  284. while (n := n-1) > 0 do x := multpfs(u,x);
  285. return x
  286. end;
  287. symbolic procedure addpsf(u,v);
  288. if null u then v
  289. else if null v then u
  290. else if domainp ldpf u then addmpsf(u,v)
  291. else if domainp ldpf v then addmpsf(v,u)
  292. else if ldpf u = ldpf v then
  293. (lambda x,y;
  294. if null numr x then y else ldpf u .* x .+ y)
  295. (addsq(lc u,lc v),addpsf(red u,red v))
  296. else if ordpp(lpow ldpf u,lpow ldpf v) then lt u .+ addpsf(red u,v)
  297. else lt v .+ addpsf(u,red v);
  298. symbolic procedure addpf(u,v);
  299. if null u then v
  300. else if null v then u
  301. else if ldpf u = 1 then addmpf(u,v)
  302. else if ldpf v = 1 then addmpf(v,u)
  303. else if ldpf u = ldpf v then
  304. (lambda x,y;
  305. if null numr x then y else ldpf u .* x .+ y)
  306. (addsq(lc u,lc v),addpf(red u,red v))
  307. else if ordop(ldpf u,ldpf v) then lt u .+ addpf(red u,v)
  308. else lt v .+ addpf(u,red v);
  309. symbolic procedure addmpf(u,v);
  310. if null v then u
  311. else if ldpf v = 1 then 1 .* addsq(lc u,lc v) .+ nil
  312. else lt v .+ addmpf(u,red v);
  313. symbolic procedure addmpsf(u,v);
  314. if null v then u else
  315. if domainp ldpf v then 1 .* addsq(multsq(ldpf u ./ 1,lc u),
  316. multsq(ldpf v ./ 1,lc v)) .+ nil
  317. else lt v .+ addmpsf(u,red v);
  318. symbolic procedure multpsf(u,v);
  319. if null u or null v then nil
  320. else addpsf(addpsf(multtpsf(lt u,lt v),multpsf(red u,v)),
  321. multpsf(!*t2f lt u,red v));
  322. symbolic procedure multpfs(u,v);
  323. if null u or null v then nil
  324. else if ldpf u = 1 then multpfsq(v,lc u)
  325. else if ldpf v = 1 then multpfsq(u,lc v)
  326. else addpf(addpf(multttpf(lt u,lt v),multpfs(red u,v)),
  327. multpfs(lt u .+ nil,red v));
  328. symbolic procedure multttpf(u,v);
  329. if car u = 1 then car v .* multsq(tc u,tc v) .+ nil
  330. else if car v = 1 then car u .* multsq(tc u,tc v) .+ nil
  331. else rederr "illegal factor in pf";
  332. symbolic procedure multpfsq(u,v);
  333. if null u or null numr v then nil
  334. else ldpf u .* multsq(lc u,v) .+ multpfsq(red u,v);
  335. symbolic procedure multtpsf(u,v);
  336. begin scalar x,xexp;
  337. xexp := !*exp;
  338. !*exp := t;
  339. x := if car u = 1 then car v
  340. else if car v = 1 then car u
  341. else multf(tpsf u,tpsf v);
  342. !*exp := xexp;
  343. return multsqpsf(multsq(tc u,tc v),x .* (1 ./ 1) .+ nil)
  344. end;
  345. symbolic procedure multsqpsf(u,v);
  346. if null numr u or null v then nil
  347. else ldpf v .* multsq(u,lc v) .+ multsqpsf(u,red v);
  348. symbolic procedure repartit u;
  349. if null u then nil
  350. else addpf(multpfsq(partitop ldpf u,lc u),repartit red u);
  351. symbolic procedure partitsq!* u;
  352. %U is a standardquotient. Partitfunction for *sq's.
  353. %Leaves unexpanded structure if possible;
  354. (if null x then nil
  355. else if domainp x then 1 .* u .+ nil
  356. else addpf(if sfp mvar x and sfexform1p lt mvar x
  357. then multpfsq(exptpf(partitsq!*(mvar x ./ 1),
  358. ldeg x),
  359. cancel(lc x ./ y))
  360. else if null sfp mvar x and deg!*form mvar x
  361. then mvar x .* cancel(lc x ./ y) .+ nil
  362. else multpfsq(partitsq!*(lc x ./ y),
  363. !*p2q lpow x),
  364. partitsq!*(red x ./ y)))
  365. where x = numr u, y = denr u;
  366. symbolic procedure sfexform1p u;
  367. (if sfp tvar u then sfexform1p lt tvar u
  368. else deg!*form tvar u)
  369. or (null domainp tc u and sfexform1p lt tc u);
  370. symbolic procedure !*pf2sq u;
  371. begin scalar res;
  372. res := nil ./ 1;
  373. if null u then return res;
  374. for each j on u do
  375. res := addsq(multsq(if ldpf j = 1 then 1 ./ 1
  376. else !*k2q ldpf j,lc j),res);
  377. return res
  378. end;
  379. symbolic procedure mk!*sqpf u;
  380. if null u then nil
  381. else ldpf u .* mk!*sq lc u .+ mk!*sqpf red u;
  382. symbolic procedure !*pfsq2pf u;
  383. if null u then nil
  384. else (lambda x;
  385. if numr x
  386. then ldpf u .* x .+ !*pfsq2pf red u
  387. else !*pfsq2pf red u)
  388. simp!* lc u;
  389. endmodule;
  390. %*********************************************************************;
  391. %****** Functions for ordering *****;
  392. %*********************************************************************;
  393. module forder;
  394. % Author: Eberhard Schruefer;
  395. global '(wedgemtch!* lftshft!* indxl!* subfg!*);
  396. fluid '(kord!*);
  397. symbolic procedure add2l(u,v);
  398. !*a2k u . if u memq v then delete(u,v) else v;
  399. symbolic procedure forder u;
  400. forder1 u;
  401. symbolic procedure forder1 u;
  402. (lambda x;
  403. while x do
  404. <<kord!* := add2l(car x,kord!*);
  405. if eqcar(car x,'wedge) then
  406. for each j in reverse cdar x do
  407. kord!* := add2l(j,kord!*);
  408. x:=cdr x>>)
  409. reverse u;
  410. symbolic procedure remforder u;
  411. for each j in u do kord!* := delete(j,kord!*);
  412. symbolic procedure isolate u;
  413. rederr "Sorry, ISOLATE not supported in this version";
  414. % for each j in u do
  415. % <<lftshft!* := !*a2k car u . lftshft!*;
  416. % kord!* := !*a2k car u . kord!*>>;
  417. symbolic procedure remisolate u;
  418. for each j in u do lftshft!* := delete(j,lftshft!*);
  419. smacro procedure wedgeordp(u,v); worderp(u,v);
  420. symbolic procedure worderp(x,y);
  421. %Needs more work!
  422. if null atom x and flagp(car x,'indexvar) and
  423. null atom y and flagp(car y,'indexvar)
  424. then if atom cadr x and (cadr x member indxl!*) and
  425. atom cadr y and (cadr y member indxl!*)
  426. then if (car x eq car y) then indordp(cadr x,cadr y)
  427. else ordop(car x,car y)
  428. else ordop(x,y)
  429. else if atom x or (x memq kord!*) then
  430. if atom y or (y memq kord!*) then ordop(x,y)
  431. else worderp(x,peel y)
  432. else if atom y or (y memq kord!*) then worderp(peel x,y)
  433. else worderp(peel x,peel y);
  434. symbolic procedure indexvarordp(u,v);
  435. if null(car u eq car v) then ordop(car u,car v)
  436. else indordlp(flatindxl cdr u,flatindxl cdr v);
  437. symbolic procedure indordlp(u,v);
  438. if null u then nil
  439. else if null v then t
  440. else if car u eq car v then indordlp(cdr u, cdr v)
  441. else indordp(car u,car v);
  442. symbolic procedure peel u;
  443. if car u memq '(liedf innerprod) then u := caddr u
  444. else if car u eq 'quotient then
  445. if worderp(cadr u,caddr u) then u:=cadr u
  446. else u:=caddr u
  447. else u:=cadr u;
  448. symbolic procedure indordp(u,v);
  449. begin scalar x;
  450. x := indxl!*;
  451. if null(u memq x) then return t;
  452. a: if null x then return orderp(u,v);
  453. if u eq car x then return t
  454. else if v eq car x then return nil;
  455. x:=cdr x;
  456. go to a
  457. end;
  458. symbolic procedure indordn u;
  459. if null u then nil
  460. else if null cdr u then u
  461. else if null cddr u then indord2(car u,cadr u)
  462. else indordad(car u,indordn cdr u);
  463. symbolic procedure indord2(u,v);
  464. if indordp(u,v) then list(u,v) else list(v,u);
  465. symbolic procedure indordad(a,u);
  466. if null u then list a
  467. else if indordp(a,car u) then a . u
  468. else car u . indordad(a,cdr u);
  469. symbolic procedure keep u;
  470. while u do
  471. <<if not eqexpr car u then errpri2(car u,'hold)
  472. else begin scalar x,y,z;
  473. z := subfg!*;
  474. subfg!* := nil;
  475. x := !*a2k cadar u;
  476. y := !*a2k caddar u;
  477. forder1 list(x,y);
  478. keepl!* := (x . y) . keepl!*;
  479. flag(list x,'keep);
  480. put(x,'keepl,list y);
  481. subfg!* := z;
  482. putdep(x,y);
  483. if null exdfk y then flag(list x,'closed);
  484. if eqcar(y,'wedge) then
  485. <<wedgemtch!*:=(cdr y . x) . wedgemtch!*;
  486. for each j in cdr y do
  487. wedgemtch!* := (list(x,j) . nil) . wedgemtch!*>>
  488. else let2(y,x,nil,t)
  489. end;
  490. u := cdr u>>;
  491. symbolic procedure putdep(u,v);
  492. for each j in cdr v do
  493. if atom j then depend1(u,j,t) else putdep(u,j);
  494. endmodule;
  495. %*********************************************************************;
  496. %***** Exterior multiplication ****;
  497. %*********************************************************************;
  498. module wedge;
  499. % Author: Eberhard Schruefer;
  500. global '(dimex!* lftshft!* wedgemtch!*);
  501. newtok '((!^) wedge);
  502. flag('(wedge),'nary);
  503. infix wedge;
  504. precedence wedge,times;
  505. put('wedge,'simpfn,'simpwedge);
  506. put('wedge,'rtypefn,'getrtypeor);
  507. put('wedge,'partitfn,'partitwedge);
  508. symbolic procedure partitwedge u;
  509. if null cdr u then partitop car u
  510. else mkuniquewedge xpndwedge u;
  511. symbolic procedure oddp m;
  512. fixp m and remainder(m,2)=1;
  513. symbolic procedure mksgnsq u;
  514. if null (u := evenfree u) then 1 ./ 1
  515. else if u = 1 then (-1) ./ 1
  516. else simpexpt list(-1,mk!*sq(u ./ 1));
  517. symbolic procedure evenfree u;
  518. if null u then nil
  519. else if numberp u then absf cdr qremd(u,2)
  520. else addf(absf cdr qremd(!*t2f lt u,2),evenfree red u);
  521. smacro procedure lwf u;
  522. %selector for leading factor in wedge.
  523. car u;
  524. smacro procedure rwf u;
  525. %selector for the rest of factors in wedge.
  526. cdr u;
  527. smacro procedure lftshftp u;
  528. smemqlp(lftshft!*,u);
  529. symbolic procedure mkwedge u; !*k2pf u;
  530. symbolic procedure wedgemtch u;
  531. begin scalar x,y,z;
  532. y := u;
  533. a: x := car y . x;
  534. if z := assoc(reverse x,wedgemtch!*) then
  535. return if cdr z then if cdr y then
  536. 'wedge . append(cdr z,cdr y)
  537. else cdr z
  538. else 0;
  539. y := cdr y;
  540. if y then go to a else return nil
  541. end;
  542. symbolic procedure simpwedge u;
  543. !*pf2sq partitwedge u;
  544. symbolic procedure xpndwedge u;
  545. if null cdr u
  546. then mkunarywedge partitop car u
  547. else wedgepf2(partitop car u,xpndwedge cdr u);
  548. symbolic procedure mkunarywedge u;
  549. if null u then nil
  550. else list ldpf u .* lc u .+ mkunarywedge red u;
  551. symbolic procedure mkuniquewedge u;
  552. if null u then nil
  553. else addpf(multpfsq(mkuniquewedge1 ldpf u,lc u),
  554. mkuniquewedge red u);
  555. symbolic procedure mkuniquewedge1 u;
  556. if null cdr u
  557. then mkupf car u
  558. else begin scalar x;
  559. return if wedgemtch!* and (x := wedgemtch u)
  560. then partitop x
  561. else mkupf('wedge . u)
  562. end;
  563. symbolic procedure wedgepf2(u,v);
  564. %Basic binary exterior product routine.
  565. %v is an exterior product (without wedge tag), u a form.
  566. if null u or null v then nil
  567. else addpf(wedget2(lt u,lt v),
  568. addpf(wedgepf2(lt u .+ nil,red v),wedgepf2(red u,v)));
  569. smacro procedure multwedgesq(u,v);
  570. %possible entry for lazy multiplication.
  571. multsq(u,v);
  572. symbolic procedure wedget2(u,v);
  573. if car u = 1 then car v .* multsq(cdr u,cdr v) .+ nil
  574. else if caar v = 1 then list car u .* multsq(cdr u,cdr v) .+ nil
  575. else multpfsq(wedgek2(car u,car v,nil),multwedgesq(tc u,tc v));
  576. symbolic procedure wedgek2(u,v,w);
  577. if u eq car v and null eqcar(u,'wedge)
  578. then if oddp deg!*form u then nil
  579. else multpfsq(wedgef(u . v),mksgnsq w)
  580. else if eqcar(car v,'wedge) then wedgek2(u,cdar v,w)
  581. else if eqcar(u,'wedge)
  582. then multpfsq(wedgewedge(cdr u,v),mksgnsq w)
  583. else if wedgeordp(u,car v)
  584. then multpfsq(wedgef(u . v),mksgnsq w)
  585. else if cdr v
  586. then wedgepf2(!*k2pf car v,
  587. wedgek2(u,cdr v,addf(w,multf(deg!*form u,
  588. deg!*form car v))))
  589. else multpfsq(wedgef list(car v,u),
  590. mksgnsq addf(w,multf(deg!*form u,deg!*form car v)));
  591. symbolic procedure wedgewedge(u,v);
  592. if null cdr u then wedgepf2(!*k2pf car u,!*k2pf v)
  593. else wedgepf2(!*k2pf car u,wedgewedge(cdr u,v));
  594. symbolic procedure wedgef u;
  595. if dim!<deg u then nil
  596. else if eqcar(car u,'hodge) then
  597. (if m = deg!*farg cdr u then
  598. multpfsq(wedgepf2(!*k2pf cadar u,
  599. mkunarywedge
  600. hodgepf if cddr u
  601. then mkuniquewedge1 cdr u
  602. else !*k2pf cadr u),
  603. mksgnsq multf(m,addf(m,negf dimex!*)))
  604. else mkwedge u)
  605. where m = deg!*form cadar u
  606. else if eqcar(car u,'d) and (flagp('d,'noxpnd)
  607. or lftshftp cadar u) then
  608. addpf(mkunarywedge dwedge(cadar u . cdr u),
  609. multpfsq(wedgepf2(!*k2pf cadar u,
  610. mkunarywedge
  611. if cddr u
  612. then dwedge cdr u
  613. else exdfk cadr u),
  614. negsq mksgnsq deg!*form cadar u))
  615. else mkwedge u;
  616. endmodule;
  617. %*********************************************************************;
  618. %***** Exterior differentiation ****;
  619. %*********************************************************************;
  620. module exdf;
  621. % Author: Eberhard Schruefer;
  622. global '(naturalframe2coframe dbaseform2base2form basisforml!* dimex!*
  623. subfg!*);
  624. put('d,'simpfn,'simpexdf);
  625. put('d,'rtypefn,'getrtypecar);
  626. put('d,'partitfn,'partitexdf);
  627. symbolic procedure partitexdf u;
  628. exdfpf partitop car u;
  629. symbolic procedure simpexdf u;
  630. !*pf2sq partitexdf u;
  631. symbolic procedure mkexdf u;
  632. begin scalar x,y;
  633. return if x := opmtch(y := list('d,u))
  634. then partitop x
  635. else mkupf y
  636. end;
  637. symbolic procedure exdfpf u;
  638. if null u then nil
  639. else addpf(if ldpf u = 1
  640. then exdf0 lc u
  641. else addpf(multpfsq(exdfk ldpf u,lc u),
  642. mkuniquewedge wedgepf2(exdf0 lc u,
  643. !*k2pf list ldpf u)),
  644. exdfpf red u);
  645. symbolic procedure exdfk u;
  646. if u = 1 or eqcar(u,'d) or dim!<!=deg u
  647. or flagp(lid u,'closed) then nil
  648. else if flagp('d,'noxpnd) or lftshftp u then mkexdf u
  649. else if atomf u then
  650. if (not flagp('partdf,'noxpnd)) and
  651. flagp(lid u,'impfun)
  652. then dimpfun(u,get!-impfun!-args lid u)
  653. else if coordp u then
  654. if subfg!*
  655. then !*pfsq2pf cdr atsoc(u,naturalframe2coframe)
  656. else mkexdf u
  657. else if basisformp u and dbaseform2base2form then
  658. !*pfsq2pf cdr atsoc(u,dbaseform2base2form)
  659. else mkexdf u
  660. else if (car u eq 'wedge) then dwedge cdr u
  661. else if car u memq '(hodge innerprod liedf) then mkexdf u
  662. else if car u eq 'partdf then
  663. if not flagp('partdf,'noxpnd) and atomf cadr u
  664. then dimpfun(u,get!-impfun!-args lid cadr u)
  665. else mkexdf u
  666. else begin scalar x,y,z;
  667. if null(x := get(car u,'dfn)) then return mkexdf u;
  668. z := cdr u;
  669. for each j in
  670. for each k in z collect partitexdf list k do
  671. <<if j then
  672. y := addpf(multpfsq(j,simp subla(pair(caar x,z),cdar x)),
  673. y);
  674. x := cdr x>>;
  675. return y
  676. end;
  677. symbolic procedure lid u;
  678. if atom u then u else car u;
  679. symbolic procedure atomf u;
  680. atom u or flagp(car u,'indexvar);
  681. symbolic procedure dim!<!=deg u;
  682. (null x or (fixp x and x<=0))
  683. where x = addf(dimex!*,negf deg!*form u);
  684. symbolic procedure dim!<deg u;
  685. begin scalar x;
  686. x := addf(dimex!*,negf deg!*farg u);
  687. return if numberp x and minusp x then t
  688. else nil
  689. end;
  690. symbolic procedure dimpfun(u,v);
  691. if null v then nil
  692. else addpf(multpfsq(exdfp0(car v . 1),partdfsq(simp u,car v)),
  693. dimpfun(u,cdr v));
  694. symbolic procedure exdf0 u;
  695. multpfsq(addpf(exdff0 numr u,multpfsq(exdff0 negf denr u,u)),
  696. 1 ./ denr u);
  697. symbolic procedure exdff0 u;
  698. if domainp u then nil
  699. else addpf(addpf(multpfsq(exdff0 lc u,!*p2q lpow u),
  700. multpfsq(exdfp0 lpow u,lc u ./ 1)),
  701. exdff0 red u);
  702. symbolic procedure exdfp0 u; %weighted vars ??
  703. begin scalar pv,n,z;
  704. pv := car u;
  705. n := pdeg u;
  706. return if (sfp pv or exformp pv or null subfg!*)
  707. and (z := if sfp pv then exdff0 pv
  708. else exdfk pv)
  709. then if n = 1 then z
  710. else multpfsq(z,!*t2q((pv to (n - 1)) .* n))
  711. else nil
  712. end;
  713. symbolic procedure dwedge u;
  714. %u is a wedge argument, result is a pf.
  715. mkuniquewedge dwedge1(u,nil);
  716. symbolic procedure dwedge1(u,v);
  717. if null rwf u
  718. then mkunarywedge multpfsq(exdfk lwf u,mksgnsq v)
  719. else addpf(wedgepf2(!*k2pf lwf u,
  720. dwedge1(rwf u,addf(v,deg!*form lwf u))),
  721. multpfsq(wedgepf2(exdfk lwf u,!*k2pf rwf u),mksgnsq v));
  722. symbolic procedure exdfprn u;
  723. <<prin2!* "d"; rembras cadr u>>;
  724. put('d,'prifn,'exdfprn);
  725. endmodule;
  726. %*********************************************************************;
  727. %***** Partial differentiation ****;
  728. %*********************************************************************;
  729. module partdf;
  730. % Author: Eberhard Schruefer;
  731. %adapted df module;
  732. global '(naturalvector2framevector depl!* wtl!* keepl!*);
  733. fluid '(alglist!*);
  734. newtok '((!@) partdf);
  735. symbolic procedure simppartdf0 u;
  736. begin scalar v;
  737. if null cdr u then
  738. if coordp(u := reval car u)
  739. and (v := atsoc(u,naturalvector2framevector))
  740. then return !*pf2sq !*pfsq2pf cdr v
  741. else return mksq(list('partdf,u),1);
  742. if null subfg!* or freeindp car u or freeindp cadr u
  743. or (cddr u and freeindp caddr u)
  744. then return mksq('partdf . revlis u,1);
  745. v := cdr u;
  746. u := simp!* car u;
  747. for each j in v do
  748. u := partdfsq(u,!*a2k j);
  749. return u
  750. end;
  751. put('partdf,'simpfn,'simppartdf);
  752. put('partdf,'rtypefn,'getrtypeor);
  753. put('partdf,'partitfn,'partitpartdf);
  754. symbolic procedure partitpartdf u;
  755. if null cdr u then mknatvec !*a2k car u
  756. else 1 .* simppartdf0 u .+ nil;
  757. symbolic procedure simppartdf u;
  758. !*pf2sq partitpartdf u;
  759. symbolic procedure mknatvec u;
  760. begin scalar x,y;
  761. return if x := atsoc(u,naturalvector2framevector)
  762. then !*pfsq2pf cdr x
  763. else if x := opmtch(y := list('partdf,u))
  764. then partitop x
  765. else mkupf y
  766. end;
  767. symbolic procedure partdfsq(u,v);
  768. multsq(addsq(partdff(numr u,v),
  769. multsq(u,partdff(negf denr u,v))),
  770. 1 ./ denr u);
  771. symbolic procedure partdff(u,v);
  772. if domainp u then nil ./ 1
  773. else addsq(if null !*product!-rule then partdft(lt u,v)
  774. else addsq(multpq(lpow u,partdff(lc u,v)),
  775. multsq(partdfpow(lpow u,v),lc u ./ 1)),
  776. partdff(red u,v));
  777. symbolic procedure partdft(u,v);
  778. begin scalar x,y;
  779. x := partdft1(!*t2q u,v);
  780. y := nil ./ 1;
  781. for each j on x do
  782. if null domainp ldpf j then
  783. y := addsq(multsq(if domainp lc ldpf j then
  784. multsq(partdfpow(lpow ldpf j,v),
  785. lc ldpf j ./ 1)
  786. else mksq(list('partdf,prepf ldpf j,v),1),
  787. lc j),y);
  788. return y
  789. end;
  790. symbolic procedure partdft1(u,v);
  791. (if null x then nil
  792. else if domainp x then 1 .* u .+ nil
  793. else addpsf(if sfp mvar x and numr partdfpow(lpow mvar x,v)
  794. then multpsf(exptpsf(partdft1(mvar u ./ 1,v),
  795. ldeg x),
  796. partdft1(cancel(lc x ./ y),v))
  797. else if null sfp mvar x and numr partdfpow(lpow x,v)
  798. then multpsf(!*p2f lpow x .* (1 ./ 1) .+ nil,
  799. partdft1(cancel(lc x ./ y),v))
  800. else multsqpsf(!*p2q lpow x,
  801. partdft1(cancel(lc x ./ y),v)),
  802. partdft1(cancel(red x ./ y),v)))
  803. where x = numr u, y = denr u;
  804. symbolic procedure partdfpow(u,v);
  805. begin scalar x,z; integer n;
  806. n := cdr u;
  807. u := car u;
  808. z := nil ./ 1;
  809. if u eq v then z := 1 ./ 1
  810. else if atomf u then
  811. if x := assoc(u,keepl!*) then
  812. begin scalar alglist!*;
  813. z := partdfsq(simp0 cdr x,v)
  814. end
  815. else if ndepends(if x := get(lid u,'varlist)
  816. then lid u . cdr x
  817. else lid u,v)
  818. then z := mksq(list('partdf,u,v),1)
  819. else return nil ./ 1
  820. else if sfp u then z := partdff(u,v)
  821. else if car u eq '!*sq then z := partdfsq(cadr u,v)
  822. else if x := get(car u,'dfn) then
  823. for each j in
  824. for each k in cdr u collect partdfsq(simp k,v)
  825. do <<if numr j then
  826. z := addsq(multsq(j,simp
  827. subla(pair(caar x,cdr u),cdar x)),
  828. z);
  829. x := cdr x>>
  830. else if car u eq 'partdf then
  831. if ndepends(lid cadr u,v) then
  832. if assoc(list('partdf,cadr u,v),
  833. get('partdf,'kvalue)) then
  834. <<z := mksq(list('partdf,cadr u,v),1);
  835. for each j in cddr u do
  836. z := partdfsq(z,j)>>
  837. else
  838. <<z := 'partdf . cadr u . ordn(v . cddr u);
  839. z := if x := opmtch z then simp x
  840. else mksq(z,1)>>
  841. else return nil ./ 1;
  842. if x := atsoc(u,wtl!*) then z := multpq('k!* to (-cdr x),z);
  843. return if n=1 then z
  844. else multsq(!*t2q((u to (n-1)) .* n),z)
  845. end;
  846. symbolic procedure ndepends(u,v);
  847. if null u or numberp u or numberp v then nil
  848. else if u=v then u
  849. else if atom u and u memq frlis!* then t
  850. else if (lambda x; x and lndepends(cdr x,v)) assoc(u,depl!*)
  851. then t
  852. else if not atom u and idp car u and get(car u,'dname) then nil
  853. else if not atomf u
  854. and (lndepends(cdr u,v) or ndepends(car u,v)) then t
  855. else if atomf v or idp car v and get(car v,'dname) then nil
  856. else ndependsl(u,cdr v);
  857. symbolic procedure lndepends(u,v);
  858. u and (ndepends(car u,v) or lndepends(cdr u,v));
  859. symbolic procedure ndependsl(u,v);
  860. u and (ndepends(u,car v) or ndependsl(u,cdr v));
  861. symbolic procedure partdfprn u;
  862. if null !*nat then <<prin2!* '!@;
  863. prin2!* "(";
  864. if cddr u then inprint('!*comma!*,0,cdr u)
  865. else maprin cadr u;
  866. prin2!* ")" >>
  867. else begin scalar y; integer l;
  868. l := flatsizec flatindxl cdr u+1;
  869. if l>(linelength nil-spare!*)-posn!* then terpri!* t;
  870. %avoids breaking of the operator over a line;
  871. y := ycoord!*;
  872. prin2!* '!@;
  873. ycoord!* := y - if (null cddr u and indexvp cadr u) or
  874. (cddr u and indexvp caddr u) then 2
  875. else 1;
  876. if ycoord!*<ymin!* then ymin!* := ycoord!*;
  877. if null cddr u then <<maprin cadr u;
  878. ycoord!* := y>>
  879. else <<for each j on cddr u do
  880. <<maprin car j;
  881. if cdr j then prin2!* " ">>;
  882. ycoord!* := y;
  883. if atom cadr u then prin2!* cadr u
  884. else <<prin2!* "(";
  885. maprin cadr u;
  886. prin2!* ")">>>>
  887. end;
  888. put('partdf,'prifn,'partdfprn);
  889. symbolic procedure indexvp u;
  890. null atom u and flagp(car u,'indexvar);
  891. endmodule;
  892. %*********************************************************************;
  893. %***** Hodge-* duality operator ****;
  894. %*********************************************************************;
  895. module hodge;
  896. % Author: Eberhard Schruefer;
  897. global '(dimex!* sgn!* detm!* basisforml!*);
  898. symbolic procedure formhodge(u,vars,mode);
  899. if mode eq 'symbolic then 'hash . formlis(cdr u,vars,mode)
  900. else 'list . mkquote 'hodge . formlis(cdr u,vars,mode);
  901. put('hash,'formfn,'formhodge);
  902. put('hodge,'simpfn,'simphodge);
  903. put('hodge,'rtypefn,'getrtypecar);
  904. put('hodge,'partitfn,'partithodge);
  905. symbolic procedure partithodge u;
  906. hodgepf partitop car u;
  907. symbolic procedure simphodge u;
  908. !*pf2sq partithodge u;
  909. symbolic procedure mkhodge u;
  910. begin scalar x,y;
  911. return if x := opmtch(y := list('hodge,u))
  912. then partitop x
  913. else if deg!*form u = dimex!*
  914. then 1 .* mksq(y,1) .+ nil
  915. else mkupf y
  916. end;
  917. smacro procedure mkbaseform u;
  918. mkupf list(caar basisforml!*,u);
  919. symbolic procedure basisformp u;
  920. null atom u and (u memq basisforml!*);
  921. symbolic procedure hodgepf u;
  922. if null u then nil
  923. else addpf(multpfsq(hodgek ldpf u,lc u),hodgepf red u);
  924. symbolic procedure hodgek u;
  925. if eqcar(u,'hodge)
  926. then cadr u .* multsq(mksgnsq multf(deg!*form cadr u,
  927. addf(dimex!*,negf deg!*form cadr u)),
  928. sgn!*) .+ nil
  929. else if basisformp u then dual list u
  930. else if eqcar(u,'wedge) and boundindp(cdr u,basisforml!*) then
  931. dual cdr u
  932. else mkhodge u;
  933. symbolic procedure dual u;
  934. (multpfsq(mkdual xpnddual u,
  935. simpexpt list(mk!*sq(absf numr x ./
  936. absf denr x),'(quotient 1 2))))
  937. where x = simp!* detm!*;
  938. symbolic procedure !*met2pf u;
  939. metpf1 getupper cadr u;
  940. symbolic procedure xpnddual u;
  941. if null cdr u
  942. then mkunarywedge !*met2pf car u
  943. else wedgepf2(!*met2pf car u,xpnddual cdr u);
  944. symbolic procedure metpf1 u;
  945. if null u then nil
  946. else addpf(multpfsq(mkbaseform caar u,simp cdar u),metpf1 cdr u);
  947. symbolic procedure mkdual u;
  948. if null u then nil
  949. else addpf(multpfsq(((if null x then nil
  950. else if cdr ldpf x
  951. then multpfsq(mkuniquewedge1 ldpf x,
  952. lc x)
  953. else car ldpf x .* lc x .+ nil)
  954. where x = dualk ldpf u),
  955. lc u),mkdual red u);
  956. symbolic procedure dualk u;
  957. begin scalar x;
  958. x := !*k2pf basisforml!*;
  959. a: x := dualk2(car u,x);
  960. if null(u := cdr u) then return x;
  961. go to a
  962. end;
  963. symbolic procedure dualk2(u,v);
  964. dualk0(u,v,nil);
  965. symbolic procedure dualk0(u,v,w);
  966. if u eq car ldpf v
  967. then if null cdr ldpf v
  968. then list 1 .* multsq(mksgnsq w,lc v) .+ nil
  969. else cdr ldpf v .* multsq(mksgnsq w,lc v) .+ nil
  970. else if null cdr ldpf v then nil
  971. else wedgepf2(!*k2pf ldpf car v,
  972. dualk0(u,cdr ldpf v .* lc v .+ nil,addf(w,1)));
  973. symbolic procedure hodgeprn u;
  974. <<prin2!* "#"; rembras cadr u>>;
  975. put('hodge,'prifn,'hodgeprn);
  976. endmodule;
  977. %*********************************************************************;
  978. %***** Inner product ****;
  979. %*********************************************************************;
  980. module innerprod;
  981. % Author: Eberhard Schruefer;
  982. newtok '((!_ !|) innerprod);
  983. infix innerprod;
  984. precedence innerprod,times;
  985. %flag('(innerprod),'nary); %not done for now, but might be worthwhile.
  986. put('innerprod,'simpfn,'simpinnerprod);
  987. put('innerprod,'rtypefn,'getrtypeor);
  988. put('innerprod,'partitfn,'partitinnerprod);
  989. symbolic procedure partitinnerprod u;
  990. innerprodpf(partitop car u,
  991. partitop cadr u);
  992. symbolic procedure mkinnerprod(u,v);
  993. begin scalar x,y;
  994. return if x := opmtch(y := list('innerprod,u,v))
  995. then partitop x
  996. else if deg!*form v = 1
  997. then if numr(x := mksq(y,1)) then 1 .* x .+ nil
  998. else nil
  999. else mkupf y
  1000. end;
  1001. symbolic procedure simpinnerprod u;
  1002. !*pf2sq partitinnerprod u;
  1003. symbolic procedure innerprodpf(u,v);
  1004. if null u or null v then nil
  1005. else if ldpf v = 1 then nil
  1006. else
  1007. begin scalar res,x;
  1008. for each j on u do
  1009. for each k on v do
  1010. if x := innerprodf(ldpf j,ldpf k)
  1011. then res := addpf(multpfsq(x,multsq(lc j,lc k)),res);
  1012. return res
  1013. end;
  1014. symbolic procedure basisvectorp u;
  1015. null atom u and u memq basisvectorl!*;
  1016. symbolic procedure tvectorp u;
  1017. (numberp x and x<0) where x = deg!*form ldpf u;
  1018. symbolic procedure innerprodf(u,v);
  1019. %Inner product dispatching routine.
  1020. if null tvectorp !*k2pf u then
  1021. rederr "first argument of inner product must be a vector"
  1022. else if v = 1 then nil %is this test necessary??
  1023. else if eqcar(v,'wedge)
  1024. then innerprodwedge(u,cdr v)
  1025. else if eqcar(u,'partdf) and null freeindp cadr u
  1026. then innerprodnvec(u,v)
  1027. else if basisvectorp u and basisformp v
  1028. then innerprodbasis(u,v)
  1029. else if eqcar(v,'innerprod)
  1030. then if u eq cadr v then nil
  1031. else if ordop(u,cadr v) then mkinnerprod(u,v)
  1032. else negpf innerprodpf(!*k2pf cadr v,
  1033. innerprodf(u,caddr v))
  1034. else mkinnerprod(u,v);
  1035. symbolic procedure innerprodwedge(u,v);
  1036. mkuniquewedge innerprodwedge1(u,v,nil);
  1037. symbolic procedure innerprodwedge1(u,v,w);
  1038. if null rwf v then mkunarywedge
  1039. multpfsq(innerprodf(u,lwf v),mksgnsq w)
  1040. else addpf(if null rwf rwf v and (deg!*form lwf rwf v = 1)
  1041. then multpfsq(!*k2pf list lwf v,
  1042. multsq(mksgnsq addf(deg!*form lwf v,w),
  1043. !*pf2sq innerprodf(u,lwf rwf v)))
  1044. else wedgepf2(!*k2pf lwf v,
  1045. innerprodwedge1(u,rwf v,
  1046. addf(w,deg!*form lwf v))),
  1047. if deg!*form lwf v = 1
  1048. then multpfsq(!*k2pf rwf v,
  1049. multsq(!*pf2sq innerprodf(u,lwf v),
  1050. mksgnsq w))
  1051. else wedgepf2(innerprodf(u,lwf v),
  1052. rwf v .* mksgnsq w .+ nil));
  1053. symbolic procedure innerprodnvec(u,v);
  1054. if eqcar(v,'d) and null deg!*form cadr v
  1055. and null freeindp cadr v
  1056. then if cadr u eq cadr v then 1 .* (1 ./ 1) .+ nil
  1057. else nil
  1058. else if basisformp v
  1059. then begin scalar x,osubfg;
  1060. osubfg := subfg!*;
  1061. subfg!* := nil;
  1062. x := innerprodpf(!*k2pf u,
  1063. partitop cdr assoc(v,keepl!*));
  1064. subfg!* := osubfg;
  1065. return repartit x
  1066. end;
  1067. symbolic procedure innerprodbasis(u,v);
  1068. if freeindp u or freeindp v then mkinnerprod(u,v)
  1069. else if cadadr u eq cadr v then 1 .* (1 ./ 1) .+ nil
  1070. else nil;
  1071. endmodule;
  1072. %*********************************************************************;
  1073. %***** Lie derivative ****;
  1074. %*********************************************************************;
  1075. module liedf;
  1076. % Author: Eberhard Schruefer;
  1077. global '(commutator!-of!-framevectors);
  1078. newtok '((!| !_ ) liedf);
  1079. infix liedf;
  1080. %flag('(liedf),'nary); %Not done for now, but should be considered.
  1081. precedence liedf,innerprod;
  1082. put('liedf,'simpfn,'simpliedf);
  1083. put('liedf,'rtypefn,'getrtypeor);
  1084. symbolic procedure simpliedf u;
  1085. !*pf2sq partitliedf u;
  1086. put('liedf,'partitfn,'partitliedf);
  1087. symbolic procedure partitliedf u;
  1088. liedfpf(partitop car u,partitop cadr u);
  1089. symbolic procedure mkliedf(u,v);
  1090. begin scalar x,y;
  1091. return if x := opmtch(y := list('liedf,u,v))
  1092. then partitop x
  1093. else mkupf y
  1094. end;
  1095. symbolic procedure liedfpf(u,v);
  1096. if null tvectorp u then
  1097. rederr "first argument of lie derivative must be a vector"
  1098. else if null tvectorp v then
  1099. addpf(exdfpf innerprodpf(u,v),
  1100. innerprodpf(u,exdfpf v))
  1101. else begin scalar x;
  1102. for each k on u do
  1103. for each l on v do
  1104. x := addpf(liedftt(lt k,lt l),x);
  1105. return x
  1106. end;
  1107. symbolic procedure liedftt(u,v);
  1108. begin scalar x;
  1109. return addpf(multpfsq(liedfk(car u,car v),multsq(tc u,tc v)),
  1110. addpf(if x := innerprodpf(!*k2pf car u,exdf0 tc v)
  1111. then car v .*
  1112. multsq(!*pf2sq x,tc u) .+ nil
  1113. else nil,
  1114. if x := innerprodpf(!*k2pf car v,exdf0 tc u)
  1115. then car u .*
  1116. negsq multsq(!*pf2sq x,tc v) .+ nil
  1117. else nil))
  1118. end;
  1119. symbolic procedure liedfk(u,v);
  1120. if u eq v then nil
  1121. else if eqcar(u,'partdf) and eqcar(v,'partdf) then nil
  1122. else if basisvectorp u and basisvectorp v
  1123. then if null ordop(u,v)
  1124. then negpf liedfk(v,u)
  1125. else if commutator!-of!-framevectors
  1126. then get!-structure!-const(u,v)
  1127. else mkliedf(u,v)
  1128. else if eqcar(v,'liedf)
  1129. then if ordop(u,cadr v) then mkliedf(u,v)
  1130. else addpf(liedfpf(liedfk(u,cadr v),!*k2pf caddr v),
  1131. liedfpf(!*k2pf cadr v,
  1132. liedfpf(!*k2pf u,!*k2pf caddr v)))
  1133. else if worderp(u,v) then mkliedf(u,v)
  1134. else negpf mkliedf(v,u);
  1135. symbolic procedure get!-structure!-const(u,v);
  1136. %We currently assume that only the basis has structure consts.
  1137. begin scalar x;
  1138. return if x := assoc(list(cadadr u,cadadr v),
  1139. commutator!-of!-framevectors)
  1140. then !*pfsq2pf cdr x
  1141. else nil
  1142. end;
  1143. endmodule;
  1144. %*********************************************************************;
  1145. %***** Variational derivative ****;
  1146. %*********************************************************************;
  1147. module vardf;
  1148. % Author: Eberhard Schruefer;
  1149. global '(depl!* keepl!* bndeq!*);
  1150. fluid '(kord!*);
  1151. symbolic procedure simpvardf u;
  1152. if indvarpf numr simp0 cadr u then mksq('vardf . u,1)
  1153. else begin scalar b,r,v,w,x,y,z;
  1154. v := !*a2k cadr u;
  1155. if null cddr u
  1156. then w := intern compress append(explode '!',
  1157. explode if atom v then v
  1158. else car v)
  1159. else w := caddr u;
  1160. if null atom v then w := w . cdr v;
  1161. putform(w,deg!*form v);
  1162. kord!* := append(list(w := !*a2k w),kord!*);
  1163. if x := assoc(v,depl!*) then
  1164. for each j in cdr x do depend1(w,j,t);
  1165. x := varysq(simp!* car u,v,w);
  1166. b := y := nil ./ 1;
  1167. while x do
  1168. if (z := mvar ldpf x) eq w then
  1169. <<y := addsq(lc x,y);
  1170. x := red x>>
  1171. else if eqcar(z,'wedge) then
  1172. if cadr z eq w then
  1173. <<y := addsq(multsq(!*k2q('wedge . cddr z),
  1174. lc x),y);
  1175. x := red x>>
  1176. else if eqcar(cadr z,'d) then
  1177. <<y := addsq(simp list('wedge,list('d,
  1178. list('times,'wedge . cddr z,
  1179. prepsq lc x))),y);
  1180. b := addsq(multsq(!*k2q('wedge . w .
  1181. cddr z),lc x),
  1182. b);
  1183. x := red x>>
  1184. else rederr list("wrong ordering ",z)
  1185. else if eqcar(z,'partdf) then
  1186. <<r := reval list('innerprod,
  1187. list('partdf,caddr z),
  1188. prepsq lc x);
  1189. x := addpsf((if cdddr z then
  1190. !*k2f('partdf . w . cdddr z)
  1191. else !*k2f w)
  1192. .* negsq simp list('d,r)
  1193. .+ nil,red x);
  1194. b := addsq(multsq(if cdddr z then
  1195. !*k2q('partdf . w . cdddr z)
  1196. else !*k2q w,simp r),b)>>
  1197. else << b := addsq(multsq(simp cadr z,lc x),b);
  1198. x := red x>>;
  1199. kord!* := cdr kord!*;
  1200. bndeq!* := mk!*sq b;
  1201. return y
  1202. end;
  1203. put('vardf,'simpfn,'simpvardf);
  1204. put('vardf,'rtypefn,'getrtypeor);
  1205. put('vardf,'partitfn,'partitvardf);
  1206. symbolic procedure partitvardf u;
  1207. partitsq!* simpvardf u;
  1208. symbolic procedure varysq(u,v,w);
  1209. multpsf(addpsf(varyf(numr u,v,w),
  1210. multpsf(1 .* u .+ nil,varyf(negf denr u,v,w))),
  1211. 1 .* (1 ./ denr u) .+ nil);
  1212. symbolic procedure varyf(u,v,w);
  1213. if domainp u then nil
  1214. else addpsf(addpsf(multpsf(1 .* !*p2q lpow u .+ nil,
  1215. varyf(lc u,v,w)),
  1216. multpsf(varyp(lpow u,v,w),
  1217. 1 .* (lc u ./ 1) .+ nil)),
  1218. varyf(red u,v,w));
  1219. symbolic procedure varyp(u,v,w);
  1220. begin scalar x,z; integer n;
  1221. n := cdr u;
  1222. u := car u;
  1223. if u eq v then z := !*k2f w .* (1 ./ 1) .+ nil
  1224. else if atomf u then
  1225. if x := assoc(u,keepl!*) then
  1226. begin scalar alglist!*;
  1227. z := varysq(simp0 cdr x,v,w)
  1228. end
  1229. else if null atom u and null atom v then
  1230. if u=v then !*k2f w .* (1 ./ 1) .+ nil
  1231. else nil
  1232. else if null atom v then nil
  1233. else if depends(u,v) then
  1234. z := !*k2f w .* simp list('partdf,u,v) .+ nil
  1235. else nil
  1236. else if sfp u then z := varyf(u,v,w)
  1237. else if car u eq '!*sq then z := varysq(cadr u,v,w)
  1238. else if x := get(car u,'dfn) then
  1239. for each j in
  1240. for each k in cdr u collect varysq(simp k,v,w)
  1241. do <<if j then
  1242. z := addpsf(multpsf(j,1 .* simp
  1243. subla(pair(caar x,cdr u),cdar x)
  1244. .+ nil),z);
  1245. x := cdr x>>
  1246. else if x := get(car u,'varyfn) then z := apply3(x,cdr u,v,w)
  1247. else if ndepends(u,v) then
  1248. z := !*k2f w .* simp list('partdf,u,v) .+ nil
  1249. else nil;
  1250. return if n=1 then z
  1251. else multpsf(1 .* !*t2q((u to (n-1)) .* n) .+ nil,z)
  1252. end;
  1253. symbolic procedure varywedge(u,v,w);
  1254. begin scalar x,y,z;
  1255. x := list 'wedge;
  1256. for each j on u do
  1257. <<y := varysq(simp car j,v,w);
  1258. if y then
  1259. z := addpsf(if deg!*form w then
  1260. !*a2f append(x,prepf ldpf y . cdr j)
  1261. .* lc y .+ nil
  1262. else ldpf y .* multsq(1 ./ denr lc y,simp
  1263. append(x,prepf numr lc y . cdr j))
  1264. .+ nil,z);
  1265. x := append(x,list car j)>>;
  1266. return z
  1267. end;
  1268. put('wedge,'varyfn,'varywedge);
  1269. symbolic procedure varyexdf(u,v,w);
  1270. begin scalar x;
  1271. for each j on varysq(simp car u,v,w) do
  1272. if j then
  1273. x := addpsf(!*a2f list('d,mvar ldpf j) .* lc j .+ nil,x);
  1274. return x
  1275. end;
  1276. put('d,'varyfn,'varyexdf);
  1277. symbolic procedure varyhodge(u,v,w);
  1278. begin scalar x;
  1279. for each j on varysq(simp car u,v,w) do
  1280. if j then
  1281. x := addpsf(!*a2f list('hodge,mvar ldpf j) .* lc j .+ nil,x);
  1282. return x
  1283. end;
  1284. put('hodge,'varyfn,'varyhodge);
  1285. symbolic procedure varypartdf(u,v,w);
  1286. begin scalar x;
  1287. for each j on varysq(simp car u,v,w) do
  1288. if j then
  1289. x := addpsf(!*a2f('partdf . mvar ldpf j . cdr u) .* lc j .+ nil,
  1290. x);
  1291. return x
  1292. end;
  1293. put('partdf,'varyfn,'varypartdf);
  1294. symbolic procedure simpnoether u;
  1295. if indvarpf numr simp0 caddr u then mksq('noether . u,1)
  1296. else begin scalar x,y;
  1297. simpvardf list(car u,cadr u);
  1298. x := simp!* bndeq!*;
  1299. y := intern compress append(explode '!',
  1300. explode if atom cadr u
  1301. then cadr u
  1302. else caadr u);
  1303. if null atom cadr u then y := y . cdadr u;
  1304. y := list(y . list('liedf,caddr u,cadr u));
  1305. return addsq(multsq(subf(numr x,y),1 ./ denr x),
  1306. negsq simp list('innerprod,caddr u,car u))
  1307. end;
  1308. put('noether,'simpfn,'simpnoether);
  1309. symbolic procedure noetherind u;
  1310. caddr u;
  1311. put('noether,'indexfun,'noetherind);
  1312. put('noether,'rtypefn,'getrtypeor);
  1313. endmodule;
  1314. %**********************************************************************;
  1315. %****** Non-scalar valued forms ******;
  1316. %**********************************************************************;
  1317. module indices;
  1318. % Author: Eberhard Schruefer;
  1319. fluid '(!*exp !*sub2 alglist!*);
  1320. global '(!*msg frasc!* mcond!*);
  1321. symbolic procedure indexeval(u,u1);
  1322. %toplevel evaluation function for indexed quantities;
  1323. begin scalar v,x,alglist!*;
  1324. v := simp!* u;
  1325. x := subfg!*;
  1326. subfg!* := nil;
  1327. %we don't substitute values here, since indexsymmetries can
  1328. %save us a lot of work;
  1329. v := quotsq(xpndind partitsq(numr v ./ 1,'indvarpf),
  1330. xpndind partitsq(denr v ./ 1,'indvarpf));
  1331. subfg!* := x;
  1332. %if there are no free indices, we have already the result;
  1333. %otherwise indxlet does the further simplification;
  1334. if numr v and
  1335. null indvarpf !*t2f lt numr v then v := exc!-mk!*sq2 resimp v
  1336. else v := prepsqxx v;
  1337. % We have to convert to prefix here, since we don't have a tag.
  1338. % This is a big source of inefficency.
  1339. return v
  1340. end;
  1341. symbolic procedure exc!-mk!*sq2 u; %this is taken from matr;
  1342. begin scalar x;
  1343. x := !*sub2; %since we need value for each element;
  1344. u := subs2 u;
  1345. !*sub2 := x;
  1346. return mk!*sq u
  1347. end;
  1348. symbolic procedure xpndind u;
  1349. %performs the implied summation over repeated indices;
  1350. begin scalar x,y;
  1351. y := nil ./ 1;
  1352. a: if null u then return y;
  1353. if null(x := contind ldpf u) then
  1354. y := addsq(multsq(!*f2q ldpf u,lc u),y)
  1355. else for each k in mkaindxc x do
  1356. y := addsq(multsq(subcindices(ldpf u,pair(x,k)),lc u),y);
  1357. u := red u;
  1358. go to a
  1359. end;
  1360. symbolic procedure subcindices(u,l);
  1361. %Substitutes dummy indices from a-list l into s.f. u;
  1362. %discriminates indices from variables;
  1363. begin scalar alglist!*;
  1364. return if domainp u then u ./ 1
  1365. else addsq(multsq(
  1366. exptsq(if flagp(car mvar u,'indexvar) then
  1367. simpindexvar subla(l,mvar u)
  1368. else simp subindk(l,mvar u),ldeg u),
  1369. subcindices(lc u,l)),
  1370. subcindices(red u,l))
  1371. end;
  1372. symbolic procedure subindk(l,u);
  1373. %Substitutes indices from a-list l into kernel u;
  1374. %discriminates indices from variables;
  1375. car u . for each j in cdr u collect
  1376. if atom j then j
  1377. else if idp car j and get(car j,'dname) then j
  1378. else if flagp(car j,'indexvar) then
  1379. car j . subla(l,cdr j)
  1380. else subindk(l,j);
  1381. put('form!-with!-free!-indices,'evfn,'indexeval);
  1382. put('indexed!-form,'rtypefn,'freeindexchk);
  1383. put('form!-with!-free!-indices,'setprifn,'indxpri);
  1384. symbolic procedure freeindexchk u;
  1385. if u and indxl!* and indxchk u then 'form!-with!-free!-indices
  1386. else nil;
  1387. symbolic procedure indvarp u;
  1388. %typechecking for variables with free indices on prefix forms;
  1389. null !*nosum and indxl!* and
  1390. if eqcar(u,'!*sq) then
  1391. indvarpf numr cadr u or indvarpf denr cadr u
  1392. else freeindp u;
  1393. symbolic procedure indvarpf u;
  1394. %typechecking for free indices in s.f.'s;
  1395. if domainp u then nil
  1396. else or(if sfp mvar u then indvarpf mvar u
  1397. else freeindp mvar u,
  1398. indvarpf lc u,indvarpf red u);
  1399. symbolic procedure freeindp u;
  1400. begin scalar x;
  1401. return if null u or numberp u then nil
  1402. else if atom u then nil
  1403. else if car u eq '!*sq then freeindp prepsq cadr u
  1404. else if idp car u and get(car u,'dname) then nil
  1405. else if flagp(car u,'indexvar) then indxchk cdr u
  1406. else if (x := get(car u,'indexfun)) then
  1407. freeindp apply1(x,cdr u)
  1408. else if car u eq 'partdf then
  1409. if null cddr u then freeindp cadr u
  1410. else freeindp cadr u or freeindp caddr u
  1411. else lfreeindp cdr u or freeindp car u
  1412. end;
  1413. symbolic procedure lfreeindp u;
  1414. u and (freeindp car u or lfreeindp cdr u);
  1415. symbolic procedure indxchk u;
  1416. %returns t if u contains at least one free index;
  1417. begin scalar x,y;
  1418. x := u;
  1419. y := union(indxl!*,nosuml!*);
  1420. a: if null x then return nil;
  1421. if null ((if atom car x
  1422. then if numberp car x then !*num2id abs car x
  1423. else car x
  1424. else if numberp cadar x then !*num2id cadar x
  1425. else cadar x) memq y)
  1426. then return t;
  1427. x := cdr x;
  1428. go to a
  1429. end;
  1430. symbolic procedure indexrange u;
  1431. <<indxl!* := mkindxl u; nil>>;
  1432. symbolic procedure nosum u;
  1433. <<nosuml!* := union(mkindxl u,nosuml!*); nil>>;
  1434. symbolic procedure renosum u;
  1435. <<nosuml!* := setdiff(mkindxl u,nosuml!*); nil>>;
  1436. symbolic procedure mkindxl u;
  1437. for each j in u collect if numberp j then !*num2id j
  1438. else j;
  1439. rlistat('(indexrange nosum renosum));
  1440. smacro procedure upindp u;
  1441. %tests if u is a contravariant index;
  1442. atom revalind u;
  1443. symbolic procedure allind u;
  1444. %returns a list of all unbound indices found in standard form u;
  1445. allind1(u,nil);
  1446. symbolic procedure allind1(u,v);
  1447. if domainp u then v
  1448. else allind1(red u,allind1(lc u,append(v,allindk mvar u)));
  1449. symbolic procedure allindk u;
  1450. begin scalar x;
  1451. return if atom u then nil
  1452. else if flagp(car u,'indexvar) then
  1453. <<for each j in cdr u do
  1454. if atom(j := revalind j)
  1455. then if null(j memq indxl!*)
  1456. then x := j . x
  1457. else nil
  1458. else if null(cadr j memq indxl!*)
  1459. then x := j . x;
  1460. reverse x>>
  1461. else if (x := get(car u,'indexfun)) then
  1462. allindk apply1(x,cdr u)
  1463. else if car u eq 'partdf then
  1464. if null cddr u then
  1465. for each j in allindk cdr u collect lowerind j
  1466. else append(allindk cadr u,
  1467. for each j in allindk cddr u collect
  1468. lowerind j)
  1469. else append(allindk car u,allindk cdr u)
  1470. end;
  1471. symbolic procedure contind u;
  1472. %returns a list of indices over which summation has to be performed;
  1473. begin scalar dnlist,uplist;
  1474. for each j in allind u do
  1475. if upindp j then uplist := j . uplist
  1476. else dnlist := cadr j . dnlist;
  1477. return setdiff(xn(uplist,dnlist),nosuml!*)
  1478. end;
  1479. symbolic procedure mkaindxc u;
  1480. %u is a list of free indices. result is a list of lists of all
  1481. %possible index combinations;
  1482. begin scalar r,x;
  1483. r := list u;
  1484. for each k in u do
  1485. if x := getindexr k then r := mappl(x,k,r);
  1486. return r
  1487. end;
  1488. symbolic procedure mappl(u,v,w);
  1489. if null u then nil
  1490. else append(subst(car u,v,w),mappl(cdr u,v,w));
  1491. symbolic procedure getindexr u;
  1492. %Kludge to indexclasses;
  1493. if memq(u,indxl!*) then nil else indxl!*;
  1494. symbolic procedure flatindxl u;
  1495. for each j in u collect if atom j then j else cadr j;
  1496. symbolic procedure indexlet(u,v,ltype,b,rtype);
  1497. if flagp(car u,'indexvar) then
  1498. if b then setindexvar(u,v)
  1499. else begin scalar y,z,msg;
  1500. msg := !*msg;
  1501. !*msg := nil; %for now.
  1502. u := mvar numr simp0 u; %is this right?
  1503. z := flatindxl cdr u;
  1504. for each j in if flagp(car u,'antisymmetric) then
  1505. comb(indxl!*,length z)
  1506. else mkaindxc z do
  1507. let2(mvar numr simp0 subla(pair(z,j),u),nil,nil,nil);
  1508. !*msg := msg;
  1509. y := get(car u,'ifdegree);
  1510. z := assoc(length cdr u,y);
  1511. y := delete(z,y);
  1512. remprop(car u,'ifdegree);
  1513. if y then put(car u,'ifdegree,y)
  1514. else <<remprop(car u,'rtype);
  1515. remflag(list car u,'indexvar)>>
  1516. end
  1517. else if subla(frasc!*,u) neq u then
  1518. put(car(u := subla(frasc!*,u)),'opmtch,
  1519. xadd!*((for each j in cdr u collect revalind j) .
  1520. list(nil . (if mcond!* then mcond!* else t),v,nil),
  1521. get(car u,'opmtch),b))
  1522. else setindexvar(u,v);
  1523. put('form!-with!-free!-indices,'typeletfn,'indexlet);
  1524. symbolic procedure setindexvar(u,v);
  1525. begin scalar r,s,w,x,y,z,z1,alglist!*;
  1526. x := metricu!* . flagp(car u,'covariant);
  1527. metricu!* := nil; %index position must not be changed here;
  1528. if cdr x then remflag(list car u,'covariant);
  1529. u := simp0 u;
  1530. if red numr u
  1531. or (denr u neq 1) then rederr "illegal assignment";
  1532. u := numr u;
  1533. r := cancel(1 ./ lc u);
  1534. u := mvar u;
  1535. metricu!* := car x;
  1536. if cdr x then flag(list car u,'covariant);
  1537. z1 := allindk u;
  1538. z := flatindxl z1;
  1539. if indxl!* and metricu!* then
  1540. <<z1 := for each j in z1 collect
  1541. if flagp(car u,'covariant)
  1542. then if upindp j then
  1543. <<u := car u . subst(lowerind j,j,cdr u);
  1544. 'lower . j>>
  1545. else cadr j
  1546. else if upindp j then j
  1547. else <<u := car u . subst(j,cadr j,cdr u);
  1548. 'raise . cadr j>>;
  1549. u := car u . for each j in cdr u collect revalind j>>
  1550. else z1 := z;
  1551. r := multsq(simp!* v,r);
  1552. w := for each j in if flagp(car u,'antisymmetric) then
  1553. comb(indxl!*,length z)
  1554. else mkaindxc z collect
  1555. <<x := mkletindxc pair(z1,j);
  1556. s := nil ./ 1;
  1557. y := subfg!*;
  1558. subfg!* := nil;
  1559. for each k in x do
  1560. s := addsq(multsq(car k,subfindices(numr r,cdr k)),s);
  1561. subfg!* := y;
  1562. y := !*q2f simp0 subla(pair(z,j),u);
  1563. mvar y . exc!-mk!*sq2 multsq(subf(if minusf y then negf numr s
  1564. else numr s,nil),
  1565. invsq subf(multf(denr r,denr s),nil))>>;
  1566. for each j in w do let2(car j,cdr j,nil,t)
  1567. end;
  1568. symbolic procedure mkletindxc u;
  1569. %u is a list of dotted pairs. Left part is unbound index and action.
  1570. %Right part is bound index.
  1571. begin scalar r; integer n;
  1572. r := list((1 ./ 1) . for each j in u collect
  1573. if atom car j then car j else cdar j);
  1574. for each k in u do
  1575. <<n := n + 1;
  1576. if atom car k then
  1577. r := for each j in r collect car j . subindexn(k,n,cdr j)
  1578. else r := mapletind(if caar k eq 'raise then getupper cdr k
  1579. else getlower cdr k,
  1580. cdar k,r,n)>>;
  1581. return r
  1582. end;
  1583. symbolic procedure subindexn(u,n,v);
  1584. if n=1 then u . cdr v
  1585. else car v . subindexn(u,n-1,cdr v);
  1586. symbolic procedure mapletind(u,v,w,n);
  1587. if null u then nil
  1588. else append(for each j in w collect
  1589. multsq(simp!* cdar u,car j) .
  1590. subindexn(v . caar u,n,cdr j),
  1591. mapletind(cdr u,v,w,n));
  1592. put('form!-with!-free!-indices,'setelemfn,'setindexvar);
  1593. symbolic procedure clear u;
  1594. begin
  1595. rmsubs();
  1596. remflag('(t),'reserved); %t is very often used as a coordinate;
  1597. for each x in u do
  1598. <<let2(x,nil,nil,nil); let2(x,nil,t,nil);
  1599. if atom x and get(x,'fdegree) then
  1600. <<remprop(x,'fdegree); remprop(x,'rtype)>>>>;
  1601. mcond!* := frasc!* := nil;
  1602. flag('(t),'reserved)
  1603. end;
  1604. symbolic procedure subfindices(u,l);
  1605. %Substitutes free indices from a-list l into s.f. u;
  1606. %discriminates indices from variables;
  1607. begin scalar alglist!*;
  1608. return if domainp u then u ./ 1
  1609. else addsq(multsq(if atom mvar u then !*p2q lpow u
  1610. else if sfp mvar u then
  1611. exptsq(subfindices(mvar u,l),ldeg u)
  1612. else if flagp(car mvar u,'indexvar)
  1613. then exptsq(simpindexvar
  1614. subla(l,mvar u),ldeg u)
  1615. else if car mvar u memq
  1616. '(wedge d partdf innerprod
  1617. liedf hodge vardf) then
  1618. exptsq(simp
  1619. subindk(l,mvar u),ldeg u)
  1620. else !*p2q lpow u,subfindices(lc u,l)),
  1621. subfindices(red u,l))
  1622. end;
  1623. symbolic procedure indxpri1 u;
  1624. begin scalar metricu,il,dnlist,uplist,r,x,y,z;
  1625. metricu := metricu!*;
  1626. metricu!* := nil;
  1627. il := allind !*t2f lt numr simp0 u;
  1628. for each j in il do
  1629. if upindp j
  1630. then uplist := j . uplist
  1631. else dnlist := cadr j . dnlist;
  1632. for each j in xn(uplist,dnlist) do
  1633. il := delete(j,delete(revalind
  1634. lowerind j,il));
  1635. metricu!* := metricu;
  1636. y := flatindxl il;
  1637. r := simp!* u;
  1638. for each j in mkaindxc y do
  1639. <<x := pair(y,j);
  1640. z := exc!-mk!*sq2 multsq(subfindices(numr r,x),1 ./ denr r);
  1641. maprin list('setq,subla(x,'ns . il),z);
  1642. if not !*nat then prin2!* "$";
  1643. terpri!* t>>
  1644. end;
  1645. symbolic procedure indxpri(v,u);
  1646. begin scalar x,y,z;
  1647. y := flatindxl allindk v;
  1648. for each j in if flagp(car v,'antisymmetric) and
  1649. coposp cdr v then comb(indxl!*,length y)
  1650. else mkaindxc y do
  1651. <<x := pair(y,j);
  1652. z := aeval subla(x,v);
  1653. maprin list('setq,subla(x,v),z);
  1654. if not !*nat then prin2!* "$";
  1655. terpri!* t>>
  1656. end;
  1657. symbolic procedure coposp u;
  1658. %checks if all indices in list u are either in a covariant or
  1659. %a contravariant position.;
  1660. null cdr u or if atom car u then contposp cdr u
  1661. else covposp cdr u;
  1662. symbolic procedure contposp u;
  1663. %checks if all indices in list u are contravariant;
  1664. null u or (atom car u and contposp cdr u);
  1665. symbolic procedure covposp u;
  1666. %checks if all indices in list u are covariant;
  1667. null u or (null atom car u and covposp cdr u);
  1668. put('ns,'prifn,'indvarprt);
  1669. symbolic procedure simpindexvar u;
  1670. %simplification function for indexed quantities;
  1671. !*pf2sq partitindexvar u;
  1672. symbolic procedure partitindexvar u;
  1673. %partition function for indexed quantities;
  1674. begin scalar freel,x,y,z,v,sgn,w;
  1675. x := for each j in cdr u collect
  1676. (if atom k then
  1677. if numberp k then
  1678. if minusp k then lowerind !*num2id abs k
  1679. else !*num2id k
  1680. else k
  1681. else if numberp cadr k then lowerind !*num2id cadr k
  1682. else k) where k = revalind j;
  1683. w := deg!*form u;
  1684. if null metricu!* then go to a;
  1685. z := x;
  1686. if null flagp(car u,'covariant) then
  1687. <<while z and (atom car z or
  1688. not(cadar z memq indxl!*)) do
  1689. <<y := car z . y;
  1690. if null atom car z then freel := cadar z . freel;
  1691. z := cdr z>>;
  1692. if z then <<v := nil;
  1693. y := reverse y;
  1694. for each j in getlower cadar z do
  1695. v := addpf(multpfsq(partitindexvar(car u .
  1696. append(y,car j . cdr z)),
  1697. simp cdr j),v);
  1698. return v>>>>
  1699. else
  1700. <<while z and (null atom car z or
  1701. not(car z memq indxl!*)) do
  1702. <<y := car z . y;
  1703. if atom car z then freel := car z . freel;
  1704. z := cdr z>>;
  1705. if z then <<v := nil;
  1706. y := reverse y;
  1707. for each j in getupper car z do
  1708. v := addpf(multpfsq(partitindexvar(car u .
  1709. append(y,lowerind car j . cdr z)),
  1710. simp cdr j),v);
  1711. return v>>>>;
  1712. a: if null coposp x or (null flagp(car u,'symmetric) and
  1713. null flagp(car u,'antisymmetric)) then
  1714. return if w then mkupf(car u . x)
  1715. else 1 .* mksq(car u . x,1) .+ nil;
  1716. x := for each j in x collect if atom j then j else cadr j;
  1717. if flagp(car u,'symmetric) then x := indordn x
  1718. else if flagp(car u,'antisymmetric) then
  1719. <<if repeats x then return nil
  1720. else if not permp(z := indordn x,x) then sgn := t;
  1721. x := z>>;
  1722. if flagp(car u,'covariant) then
  1723. x := for each j in x collect
  1724. if j memq freel then j else lowerind j
  1725. else if null metricu!* and null atom cadr u then
  1726. x := for each j in x collect lowerind j
  1727. else
  1728. x := for each j in x collect
  1729. if j memq freel then lowerind j else j;
  1730. return if w then if sgn then negpf mkupf(car u . x)
  1731. else mkupf(car u . x)
  1732. else if sgn then 1 .* negsq mksq(car u . x,1) .+ nil
  1733. else 1 .* mksq(car u . x,1) .+ nil
  1734. end;
  1735. symbolic procedure !*num2id u;
  1736. %converts a numeric index to an id;
  1737. %if u = 0 then rederr "0 not allowed as index" else
  1738. if u<10 then intern cdr assoc(u,
  1739. '((0 . !0) (1 . !1) (2 . !2) (3 . !3) (4 . !4)
  1740. (5 . !5) (6 . !6) (7 . !7) (8 . !8) (9 . !9)))
  1741. else intern compress append(explode '!!,explode u);
  1742. symbolic procedure revalind u;
  1743. begin scalar x,y,alglist!*;
  1744. alglist!* := list(0 . (nil . mksq(!*num2id 0,1)));
  1745. %the above line is used to avoid the simplifaction of -0 to 0.
  1746. x := subfg!*;
  1747. subfg!* := nil;
  1748. y := prepsq simp u;
  1749. subfg!* := x;
  1750. return y
  1751. end;
  1752. endmodule;
  1753. %**********************************************************************;
  1754. %***** Cartan frames ******;
  1755. %**********************************************************************;
  1756. module frames;
  1757. % Author: Eberhard Schruefer;
  1758. global '(naturalframe2coframe dbaseform2base2form dimex!* indxl!*
  1759. naturalvector2framevector subfg!*
  1760. metricd!* metricu!* coord!* cursym!* detm!*
  1761. commutator!-of!-framevectors);
  1762. fluid '(alglist!* kord!*);
  1763. symbolic procedure coframestat;
  1764. begin scalar framel,metric;
  1765. flag('(with),'delim);
  1766. framel := cdr rlis();
  1767. remflag('(with),'delim);
  1768. if cursym!* eq '!*semicol!* then go to a;
  1769. if scan() eq 'metric then metric := xread t
  1770. else if cursym!* eq 'signature then metric := rlis()
  1771. else symerr('coframe,t);
  1772. a: cofram(framel,metric)
  1773. end;
  1774. put('coframe,'stat,'coframestat);
  1775. %put('cofram,'formfn,'formcofram);
  1776. symbolic procedure cofram(u,v);
  1777. begin scalar alglist!*;
  1778. rmsubs();
  1779. u := for each j in u collect
  1780. if car j eq 'equal then cdr j else list j;
  1781. putform(caar u,1);
  1782. basisforml!* := for each j in u collect !*a2k car j;
  1783. indxl!* := for each j in basisforml!* collect cadr j;
  1784. dimex!* := length u;
  1785. basisvectorl!* := nil;
  1786. if null v then
  1787. metricd!* := nlist(1,dimex!*)
  1788. else if car v eq 'signature then
  1789. metricd!* := for each j in cdr v collect aeval j;
  1790. if null v or (car v eq 'signature) then
  1791. <<detm!* := simp car metricd!*;
  1792. for each j in cdr metricd!* do
  1793. detm!* := multsq(simp j,detm!*);
  1794. detm!* := mk!*sq detm!*;
  1795. metricu!* := metricd!*:= pair(indxl!*,for each j in
  1796. pair(indxl!*,metricd!*) collect list j)>>
  1797. else mkmetric v;
  1798. if flagp('partdf,'noxpnd) then remflag('(partdf),'noxpnd);
  1799. putform('eps . indxl!*,0);
  1800. flag('(eps),'antisymmetric);
  1801. flag('(eps),'covariant);
  1802. setk('eps . for each j in indxl!* collect lowerind j,1);
  1803. if null cdar u then return;
  1804. keepl!* := append(for each j in u collect
  1805. !*a2k car j . cadr j,keepl!*);
  1806. coframe1 for each j in u collect cadr j
  1807. end;
  1808. symbolic procedure coframe1 u;
  1809. begin scalar osubfg,coords,v,y,w;
  1810. osubfg := subfg!*;
  1811. subfg!* := nil;
  1812. v := for each j in u collect
  1813. <<y := partitop j;
  1814. coords := pickupcoords(y,coords);
  1815. y>>;
  1816. if length coords neq dimex!* then rederr "badly formed basis";
  1817. w := !*pf2matwrtcoords(v,coords);
  1818. naturalvector2framevector := v;
  1819. subfg!* := nil;
  1820. naturalframe2coframe := pair(coords,
  1821. for each j in lnrsolve(w,for each k in basisforml!*
  1822. collect list !*k2q k)
  1823. collect mk!*sqpf partitsq!* car j);
  1824. subfg!* := osubfg;
  1825. coord!* := coords;
  1826. dbaseform2base2form := pair(basisforml!*,
  1827. for each j in v collect mk!*sqpf repartit exdfpf j)
  1828. end;
  1829. symbolic procedure pickupcoords(u,v);
  1830. %u is a pf, v a list. Picks up vars in exdf and declares them as
  1831. %zero forms.
  1832. if null u then v
  1833. else if null eqcar(ldpf u,'d)
  1834. then rederr "badly formed basis"
  1835. else if null v then <<putform(cadr ldpf u,0);
  1836. pickupcoords(red u,cadr ldpf u . nil)>>
  1837. else if ordop(cadr ldpf u,car v)
  1838. then if cadr ldpf u eq car v
  1839. then pickupcoords(red u,v)
  1840. else <<putform(cadr ldpf u,0);
  1841. pickupcoords(red u,cadr ldpf u . v)>>
  1842. else pickupcoords(red u,car v . pickupcoords(!*k2pf ldpf u,cdr v));
  1843. symbolic procedure !*pf2matwrtcoords(u,v);
  1844. if null u then nil
  1845. else !*pf2colwrtcoords(car u,v) . !*pf2matwrtcoords(cdr u,v);
  1846. symbolic procedure !*pf2colwrtcoords(u,v);
  1847. if null v then nil
  1848. else if u and (cadr ldpf u eq car v)
  1849. then lc u . !*pf2colwrtcoords(red u,cdr v)
  1850. else (nil ./ 1) . !*pf2colwrtcoords(u,cdr v);
  1851. symbolic procedure coordp u;
  1852. u memq coord!*;
  1853. symbolic procedure mkmetric u;
  1854. begin scalar x,y,okord;
  1855. putform(list(cadr u,nil,nil),0);
  1856. flag(list cadr u,'symmetric);
  1857. flag(list cadr u,'covariant);
  1858. okord := kord!*;
  1859. kord!* := basisforml!*;
  1860. x := simp!* caddr u;
  1861. y := indxl!*;
  1862. metricu!* := t; %to make simpindexvar work;
  1863. for each j in indxl!* do
  1864. <<for each k in y do
  1865. setk(list(cadr u,lowerind j,lowerind k),0);
  1866. y := cdr y>>;
  1867. for each j on partitsq(x,'basep) do
  1868. if ldeg ldpf j = 2 then
  1869. setk(list(cadr u,lowerind cadr mvar ldpf j,
  1870. lowerind cadr mvar ldpf j),
  1871. mk!*sq lc j)
  1872. else
  1873. setk(list(cadr u,lowerind cadr mvar ldpf j,
  1874. lowerind cadr mvar lc ldpf j),
  1875. mk!*sq multsq(lc j,1 ./ 2));
  1876. kord!* := okord;
  1877. x := for each j in indxl!* collect
  1878. for each k in indxl!* collect
  1879. simpindexvar list(cadr u,lowerind j,lowerind k);
  1880. y := lnrsolve(x,generateident length indxl!*);
  1881. metricd!* := mkasmetric x;
  1882. metricu!* := mkasmetric y;
  1883. detm!* := mk!*sq detq x
  1884. end;
  1885. symbolic procedure mkasmetric u;
  1886. for each j in pair(indxl!*,u) collect
  1887. car j . begin scalar w,z;
  1888. w := indxl!*;
  1889. for each k in cdr j do
  1890. <<if numr k then
  1891. z := (car w . mk!*sq k) . z;
  1892. w := cdr w>>;
  1893. return z
  1894. end;
  1895. symbolic procedure frame u;
  1896. begin scalar y;
  1897. putform(list(car u,nil),-1);
  1898. flag(list car u,'covariant);
  1899. basisvectorl!* :=
  1900. for each j in indxl!* collect !*a2k list(car u,lowerind j);
  1901. if null dbaseform2base2form then return;
  1902. commutator!-of!-framevectors :=
  1903. for each j in pickupwedges dbaseform2base2form collect
  1904. list(cadadr j,cadadr cdr j) . mk!*sqpf mkcommutatorfv(j,
  1905. dbaseform2base2form);
  1906. y := pair(basisvectorl!*,
  1907. naturalvector2framevector);
  1908. naturalvector2framevector := for each j in coord!* collect
  1909. j . mk!*sqpf mknat2framv(j,y)
  1910. end;
  1911. symbolic procedure pickupwedges u;
  1912. pickupwedges1(u,nil);
  1913. Symbolic procedure pickupwedges1(u,v);
  1914. if null u then v
  1915. else if null cdar u then pickupwedges1(cdr u,v)
  1916. else if null v then pickupwedges1((caar u . red cdar u) . cdr u,
  1917. ldpf cdar u . nil)
  1918. else if ldpf cdar u memq v
  1919. then pickupwedges1(if red cdar u
  1920. then (caar u . red cdar u) . cdr u
  1921. else cdr u,v)
  1922. else pickupwedges1(if red cdar u
  1923. then (caar u . red cdar u) . cdr u
  1924. else cdr u,ldpf cdar u . v);
  1925. symbolic procedure mkbasevector u;
  1926. !*a2k list(caar basisvectorl!*,lowerind u);
  1927. symbolic procedure mkcommutatorfv(u,v);
  1928. if null v then nil
  1929. else addpf(mkcommutatorfv1(u,mkbasevector cadaar v,cdar v),
  1930. mkcommutatorfv(u,cdr v));
  1931. symbolic procedure mkcommutatorfv1(u,v,w);
  1932. if null w then nil
  1933. else if u eq ldpf w
  1934. then v .* negsq simp!* lc w .+ nil
  1935. else if ordop(u,ldpf w) then nil
  1936. else mkcommutatorfv1(u,v,red w);
  1937. symbolic procedure mknat2framv(u,v);
  1938. if null v then nil
  1939. else addpf(mknat2framv1(u,caar v,cdar v),mknat2framv(u,cdr v));
  1940. symbolic procedure mknat2framv1(u,v,w);
  1941. if null w then nil
  1942. else if u eq cadr ldpf w
  1943. then v .* lc w .+ nil
  1944. else if ordop(u,cadr ldpf w) then nil
  1945. else mknat2framv1(u,v,red w);
  1946. symbolic procedure dualframe u;
  1947. rederr "dualframe no longer supported - use frame instead";
  1948. symbolic procedure riemannconx u;
  1949. riemconnection car u;
  1950. put('riemannconx,'stat,'rlis);
  1951. smacro procedure mkbasformsq u;
  1952. mksq(list(caar basisforml!*,u),1);
  1953. symbolic procedure riemconnection u;
  1954. %calculates the riemannian connection and stores it in u;
  1955. begin scalar indx1,indx2,indx3,covbaseform,varl,w,x,z,dgkl;
  1956. putform(list(u,nil,nil),1);
  1957. flag(list u,'covariant);
  1958. flag(list u,'antisymmetric);
  1959. for each j in indxl!* do
  1960. for each k in indxl!* do if (j neq k) and indordp(j,k) then
  1961. setk(list(u,lowerind j,lowerind k),0);
  1962. for each l in dbaseform2base2form do
  1963. <<covbaseform := partitindexvar list(caar l,
  1964. lowerind cadar l);
  1965. for each j on cdr l do
  1966. <<varl := cdr ldpf j;
  1967. indx1 := cadar varl;
  1968. indx2 := cadadr varl;
  1969. for each y on covbaseform do
  1970. <<w := list(u,lowerind indx1,lowerind indx2);
  1971. z := multsq(-1 ./ 2,!*pf2sq multpfsq(lt y .+ nil,
  1972. simp!* lc j));
  1973. setk(w,mk!*sq addsq(z,mksq(w,1)));
  1974. indx3 := cadr ldpf y;
  1975. z := multsq(-1 ./ 2,multsq(lc y,simp!* lc j));
  1976. if indx1 neq indx3 then
  1977. if indordp(indx1,indx3) then
  1978. <<w := list(u,lowerind indx1,lowerind indx3);
  1979. setk(w,mk!*sq addsq(multsq(z,mkbasformsq indx2),
  1980. mksq(w,1)))>>
  1981. else
  1982. <<w := list(u,lowerind indx3,lowerind indx1);
  1983. setk(w,mk!*sq addsq(multsq(negsq z,
  1984. mkbasformsq indx2),mksq(w,1)))>>;
  1985. if indx2 neq indx3 then
  1986. if indordp(indx2,indx3) then
  1987. <<w := list(u,lowerind indx2,lowerind indx3);
  1988. setk(w,mk!*sq addsq(multsq(negsq z,
  1989. mkbasformsq indx1),mksq(w,1)))>>
  1990. else
  1991. <<w := list(u,lowerind indx3,lowerind indx2);
  1992. setk(w,mk!*sq addsq(multsq(z,
  1993. mkbasformsq indx1),mksq(w,1)))>>
  1994. >>>>>>;
  1995. if dgkl := mkmetricconx metricd!* then
  1996. <<for each j in dgkl do
  1997. <<for each y on cdr j do
  1998. <<varl := ldpf y;
  1999. indx1 := cadar varl;
  2000. indx2 := cadadr varl;
  2001. w := list(u,lowerind indx1,lowerind indx2);
  2002. z := multsq(-1 ./ 2,multsq(!*k2q car j,lc y));
  2003. setk(w,mk!*sq addsq(z,mksq(w,1)))>>>>;
  2004. remflag(list u,'antisymmetric);
  2005. for each j in indxl!* do
  2006. for each k in indxl!* do
  2007. if indordp(j,k) then
  2008. <<w := list(u,lowerind j,lowerind k);
  2009. x := if j eq k then nil ./ 1 else mksq(w,1);
  2010. z := atsoc(j,cdr atsoc(k,metricd!*));
  2011. if z then z := exdf0 simp!* cdr z;
  2012. z := multsq(1 ./ 2,!*pf2sq z);
  2013. setk(w,mk!*sq addsq(z,x));
  2014. w := list(u,lowerind k,lowerind j);
  2015. setk(w,mk!*sq addsq(z,negsq x))>>>>
  2016. end;
  2017. symbolic procedure mkmetricconx u;
  2018. if null u then nil
  2019. else (if x then (ldpf mkupf list(caar basisforml!*,caar u) . x)
  2020. . mkmetricconx cdr u
  2021. else mkmetricconx cdr u)
  2022. where x = mkmetricconx1 cdar u;
  2023. symbolic procedure mkmetricconx1 u;
  2024. if null u then nil
  2025. else addpf(wedgepf2(exdf0 simp!* cdar u,
  2026. !*k2pf list ldpf mkupf list(caar basisforml!*,caar u)),
  2027. mkmetricconx1 cdr u);
  2028. symbolic procedure basep u;
  2029. if domainp u then nil
  2030. else or(if sfp mvar u then basep mvar u
  2031. else eqcar(mvar u,caar basisforml!*),
  2032. basep lc u,basep red u);
  2033. symbolic procedure wedgefp u;
  2034. if domainp u then nil
  2035. else or(if sfp mvar u then wedgefp mvar u
  2036. else eqcar(mvar u,'wedge),
  2037. wedgefp lc u,wedgefp red u);
  2038. endmodule;
  2039. %**********************************************************************;
  2040. %********** Auxiliary functions ************;
  2041. %**********************************************************************;
  2042. module aux;
  2043. % Author: Eberhard Schruefer;
  2044. symbolic procedure boundindp(u,v);
  2045. if null u then t else member(car u,v) and boundindp(cdr u,v);
  2046. symbolic procedure memblp(u,v);
  2047. if null u then nil
  2048. else if atom u then member(u,v)
  2049. else memblp(car u,v) or memblp(cdr u,v);
  2050. symbolic procedure displayframe;
  2051. begin scalar x,coords;
  2052. terpri!* t;
  2053. coords := coord!*;
  2054. coord!* := nil;
  2055. for each j in basisforml!* do
  2056. <<x := assoc(j,keepl!*);
  2057. maprin car x;
  2058. prin2!* " = ";
  2059. maprin reval cdr x;
  2060. terpri!* t>>;
  2061. %was varpri(reval cdr x,list mkquote car x,t)>>;
  2062. if !*nat then terpri!* t;
  2063. coord!* := coords
  2064. end;
  2065. put('displayframe,'stat,'endstat);
  2066. %symbolic procedure form!*coeff u;
  2067. %begin scalar x,inds; %integer n;
  2068. %inds:=cdr u;
  2069. %n:=length inds;
  2070. %x:=simp!* car u;
  2071. %y:=dstrsdf numr x;
  2072. %put('fcoeff,'simpfn,'form!*coeff);
  2073. endmodule;
  2074. %*********************************************************************;
  2075. % Lie-Algebra valued forms ;
  2076. %*********************************************************************;
  2077. module lievalform;
  2078. % Author: Eberhard Schruefer
  2079. symbolic procedure liebrackstat;
  2080. begin scalar x;
  2081. x := xread nil;
  2082. scan();
  2083. return 'lie . cdr x
  2084. end;
  2085. flag(list '!},'delim); %Since Liebrackets can be nested we can't
  2086. %remove the flag in the stat proc;
  2087. put('!{,'stat,'liebrackstat); %We'd rather liked to use squarebrackets;
  2088. %but they are not available on most terminals;
  2089. put('lie,'prifn,'lieprn);
  2090. symbolic procedure lieprn u;
  2091. <<prin2!* "{";
  2092. inprint('!*comma!*,0,u);
  2093. prin2!* "}">>;
  2094. endmodule;
  2095. %********************************************************************;
  2096. %**** Exterior Ideals *****;
  2097. %********************************************************************;
  2098. module idexf;
  2099. % Author: Eberhard Schruefer
  2100. global '(exfideal!*);
  2101. symbolic procedure exterior!-ideal u;
  2102. begin scalar x,y;
  2103. rmsubs();
  2104. for each j in u do
  2105. if indexvp j then
  2106. for each k in mkaindxc(y := flatindxl cdr j) do
  2107. x := partitsq(simpindexvar(car j . subla(pair(y,k),cdr j)),
  2108. 'wedgefp) . x
  2109. else x := partitsq(simp!* j,'wedgefp) . x;
  2110. exfideal!* := append(x,exfideal!*);
  2111. end;
  2112. rlistat '(exterior!-ideal);
  2113. symbolic procedure remexf(u,v);
  2114. begin scalar lu,lv,x,y,z;
  2115. lv := ldpf v;
  2116. a: if null u or domainp(lu := ldpf u) then
  2117. return u;
  2118. if x := divexf(lu,lv) then
  2119. <<y := partitsq(simp list('wedge,prepf v,x),'wedgefp);
  2120. z := negsq quotsq(lc u,lc y);
  2121. u := addpsf(u,multpsf(1 .* z .+ nil,y))>>
  2122. else return u;
  2123. go to a
  2124. end;
  2125. symbolic procedure divexf(u,v);
  2126. begin scalar x,y;
  2127. x := prepf u;
  2128. y := prepf v;
  2129. if atom x then x := list x
  2130. else if car x eq 'wedge then x := cdr x;
  2131. if atom y then y := list y
  2132. else if car y eq 'wedge then y := cdr y;
  2133. a: if null y then return 'wedge . x;
  2134. if null(x := delform(car y,x)) then return nil;
  2135. y := cdr y;
  2136. go to a
  2137. end;
  2138. symbolic procedure delform(u,v);
  2139. delform1(u,v,nil);
  2140. symbolic procedure delform1(u,v,w);
  2141. if null v then nil
  2142. else if u = car v then if w or cdr v
  2143. then append(reverse w,cdr v)
  2144. else list 1
  2145. else delform1(u,cdr v,car v . w);
  2146. symbolic procedure exf!-mod!-ideal u;
  2147. begin
  2148. for each j in exfideal!* do u := remexf(u,j);
  2149. return u
  2150. end;
  2151. endmodule;
  2152. %*********************************************************************;
  2153. % 3-d Vectoranalysis Interface ;
  2154. %*********************************************************************;
  2155. module vectoranalys;
  2156. %author: Eberhard Schruefer;
  2157. symbolic procedure basis u;
  2158. cofram(for each j in u collect cdr j,nil);
  2159. rlistat '(basis);
  2160. symbolic procedure simpgrad u;
  2161. simp!*('d . u);
  2162. put('grad,'simpfn,'simpgrad);
  2163. symbolic procedure simpcurl u;
  2164. simp!* list('hodge,'d . u);
  2165. put('curl,'simpfn,'simpcurl);
  2166. symbolic procedure simpdiv u;
  2167. simp!* list('hodge,list('d,'hodge . u));
  2168. put('div,'simpfn,'simpdiv);
  2169. newtok '((!. !* !.) crossprod);
  2170. infix crossprod;
  2171. symbolic procedure simpcrossprod u;
  2172. simp!* list('hodge,'wedge . u);
  2173. put('crossprod,'simpfn,'simpcrossprod);
  2174. symbolic procedure simpdotprod u;
  2175. simp!* list('hodge,list('wedge,car u,list('hodge,cadr u)));
  2176. put('cons,'simpfn,'simpdotprod);
  2177. symbolic procedure hodge3dpri u;
  2178. %converts the form notation to vector notation for output;
  2179. if caar u eq 'd then
  2180. if eqcar(cadar u,'hodge) then maprin('div . cdadar u)
  2181. else maprin('curl . cdar u)
  2182. else if caar u eq 'wedge then
  2183. if eqcar(cadar u,'hodge) then
  2184. inprint('cons,0,cdadar u)
  2185. else inprint('crossprod,0,cdar u);
  2186. endmodule;
  2187. end;