liepde.red 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459
  1. %********************************************************************
  2. % *
  3. % The program LIEPDE for computing point-, contact- and higher *
  4. % order symmetries of individual ODEs/PDEs or systems of ODEs/PDEs *
  5. % *
  6. % Author: Thomas Wolf *
  7. % Date: 20.July 1996 *
  8. % *
  9. % For details of how to use LIEPDE see the file LIEPDE.TXT or the *
  10. % header of the procedure LIEPDE below. *
  11. % *
  12. %********************************************************************
  13. create!-package('(liepde), nil); % FJW
  14. % FJW: Load support packages, but not when compiling:
  15. !#if (getd 'packages_to_load)
  16. packages_to_load crack;
  17. !#else % for REDUCE 3.6
  18. apply1('load!-package, 'crack);
  19. !#endif
  20. symbolic procedure adjoin(elm, set);
  21. %% Add Element to SET if it is not already a member.
  22. %% FJW: Defined and flagged lose in PSL only.
  23. %% FJW: This implementation from the PSL manual.
  24. if member(elm, set) then set else elm . set$
  25. symbolic fluid '(print_ logoprint_ nfct_ fname_ adjust_fnc proc_list_
  26. prelim_ individual_)$
  27. lisp << prelim_:=nil$ individual_:=nil >>$
  28. %----------------------------
  29. % Nachfolgende 2 Prozeduren aus crack1.48:
  30. symbolic procedure diffdeg(p,v)$
  31. % liefert Ordnung der Ableitung von p nach v$
  32. % p Liste Varible+Ordnung der Ableitung, v Variable (Atom)
  33. if null p then 0 % alle Variable bearbeitet ?
  34. else if car p=v then % v naechste Variable ?
  35. if cdr p then
  36. if numberp(cadr p) then cadr p % folgt eine Zahl ?
  37. else 1
  38. else 1
  39. else diffdeg(cdr p,v)$ % weitersuchen
  40. symbolic procedure ldiff1(l,v)$
  41. % liefert Liste der Ordnungen der Ableitungen nach den Variablen aus v
  42. % l Liste (Variable + Ordnung)$ v Liste der Variablen
  43. if null v then nil % alle Variable abgearbeitet ?
  44. else cons(diffdeg(l,car v),ldiff1(l,cdr v))$
  45. % Ordnung der Ableitung nach
  46. % erster Variable anhaengen
  47. %----------------------------
  48. algebraic procedure equ_to_expr(a)$
  49. % converts an equation into an expression
  50. begin scalar lde;
  51. return
  52. if a=nil then a else
  53. <<lisp(lde:=reval algebraic a);
  54. if lisp(atom lde) then a else num
  55. if lisp(car lde = 'EQUAL) then lhs a - rhs a
  56. else a
  57. >>
  58. end$ % of equ_to_expr
  59. %----------------------------
  60. algebraic procedure maklist(ex)$
  61. % making a list out of an expression if not already
  62. if lisp(atom algebraic ex) then {ex} else
  63. if lisp(car algebraic ex neq 'LIST) then ex:={ex}
  64. else ex$
  65. %********************************************************************
  66. module pdesymmetry$
  67. %********************************************************************
  68. % Routines for finding Symmetries of single or systems of ODEs/PDEs
  69. % Author: Thomas Wolf
  70. % July 1996
  71. % The algebraic operator NPRIMITIVE returns the
  72. % numerically-primitive part of any expression.
  73. % It is defined as a simpfn in EZGCD.
  74. %% FJW: This procedure is already defined (differently but
  75. %% equivalently!) in module crsimpso:
  76. %% symbolic operator ncontent$
  77. %% symbolic procedure ncontent p$
  78. %% % Return numeric content of expression p
  79. %% % based on simpnprimitive in ezgcd.
  80. %% << p := simp!* p;
  81. %% if polyzerop(numr p) then 0 else
  82. %% mk!*sq(numeric!-content numr p ./ numeric!-content denr p)
  83. %% >>$
  84. symbolic operator totdeg$
  85. symbolic procedure totdeg(p,f)$
  86. % Ordnung (total) der hoechsten Ableitung von f im Ausdruck p
  87. eval(cons('PLUS,ldiff1(car ldifftot(reval p,reval f),fctargs reval f)))$
  88. symbolic procedure diffreltot(p,q,v)$
  89. % liefert komplizierteren Differentialausdruck$
  90. if diffreltotp(p,q,v) then q
  91. else p$
  92. symbolic procedure diffreltotp(p,q,v)$
  93. % liefert t, falls p einfacherer Differentialausdruck, sonst nil
  94. % p, q Paare (liste.power), v Liste der Variablen
  95. % liste Liste aus Var. und Ordn. der Ableit. in Diff.ausdr.,
  96. % power Potenz des Differentialausdrucks
  97. begin scalar n,m$
  98. m:=eval(cons('PLUS,ldiff1(car p,v)))$
  99. n:=eval(cons('PLUS,ldiff1(car q,v)))$
  100. return
  101. if m<n then t
  102. else if n<m then nil
  103. else diffrelp(p,q,v)$
  104. end$
  105. symbolic procedure ldifftot(p,f)$
  106. % leading derivative total degree ordering
  107. % liefert Liste der Variablen + Ordnungen mit Potenz
  108. % p Ausdruck in LISP - Notation, f Funktion
  109. ldifftot1(p,f,fctargs f)$
  110. symbolic procedure ldifftot1(p,f,vl)$
  111. % liefert Liste der Variablen + Ordnungen mit Potenz
  112. % p Ausdruck in LISP - Notation, f Funktion, lv Variablenliste
  113. begin scalar a$
  114. a:=cons(nil,0)$
  115. if not atom p then
  116. if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,
  117. 'QUOTIENT,'DF,'EQUAL)) then
  118. % erlaubte Funktionen
  119. <<if (car p='PLUS) or (car p='TIMES) or (car p='QUOTIENT)
  120. or (car p='EQUAL) then
  121. <<p:=cdr p$
  122. while p do
  123. <<a:=diffreltot(ldifftot1(car p,f,vl),a,vl)$
  124. p:=cdr p>> >>
  125. else if car p='MINUS then
  126. a:=ldifftot1(cadr p,f,vl)
  127. else if car p='EXPT then % Exponent
  128. if numberp caddr p then
  129. <<a:=ldifftot1(cadr p,f,vl)$
  130. a:=cons(car a,times(caddr p,cdr a))>>
  131. else a:=cons(nil,0)
  132. % Poetenz aus Basis wird mit
  133. % Potenz multipliziert
  134. else if car p='DF then % Ableitung
  135. if cadr p=f then a:=cons(cddr p,1)
  136. % f wird differenziert?
  137. else a:=cons(nil,0)>> % sonst Konstante bzgl. f
  138. else if p=f then a:=cons(nil,1)
  139. % Funktion selbst
  140. else a:=cons(nil,0) % alle uebrigen Fkt. werden
  141. else if p=f then a:=cons(nil,1)$ % wie Konstante behandelt
  142. return a
  143. end$
  144. %---------------------
  145. % Bei jedem totdf2-Aufruf pruefen, ob evtl. kuerzere dylist reicht
  146. % evtl die combidiff-Kette und combi nicht mit in dylist, sond. erst in
  147. % prolong jedesmal frisch generieren.
  148. %symbolic operator desort$
  149. algebraic procedure nextdy(revx,xlist,dy)$
  150. % generates all first order derivatives of lhs dy
  151. % revx = reverse xlist; xlist is the list of variables;
  152. % dy the old derivative
  153. begin
  154. scalar x,n,ldy,rdy,ldyx,sublist;
  155. x:=first revx; revx:=rest revx;
  156. sublist:={};
  157. ldy:=lhs dy;
  158. rdy:=rhs dy;
  159. while lisp(not member(prepsq simp!* algebraic x,
  160. prepsq simp!* algebraic ldy))
  161. and (revx neq {}) do
  162. <<x:=first revx; revx:=rest revx>>;
  163. n:=length xlist;
  164. if revx neq {} then % dy is not the function itself
  165. while first xlist neq x do xlist:=rest xlist;
  166. xlist:=reverse xlist;
  167. % New higher derivatives
  168. while xlist neq {} do
  169. <<x:=first xlist;
  170. ldyx:=df(ldy,x);
  171. sublist:=cons((lisp reval algebraic ldyx)=
  172. mkid(mkid(rdy,!`),n), sublist);
  173. n:=n-1;
  174. xlist:=rest xlist
  175. >>;
  176. return sublist
  177. end$
  178. %---------------------
  179. algebraic procedure subdif1(xlist,ylist,ordr)$
  180. % A list of lists of derivatives of one order for all functions
  181. begin
  182. scalar allsub,revx,i,el,oldsub,newsub;
  183. revx:=reverse xlist;
  184. allsub:={};
  185. oldsub:= for each y in ylist collect y=y;
  186. for i:=1:ordr do % i is the order of next substitutions
  187. <<oldsub:=for each el in oldsub join nextdy(revx,xlist,el);
  188. allsub:=cons(oldsub,allsub)
  189. >>;
  190. return allsub
  191. end$
  192. %---------------------
  193. symbolic procedure combidif(s)$
  194. % extracts the list of derivatives from s: % u`1`1`2 --> (u, 1, 1, 2)
  195. begin scalar temp,ans,no,n1;
  196. s:=reval s; % to guarantee s is in true prefix form
  197. temp:=reverse explode s;
  198. while not null temp do
  199. <<n1:=<<no:=nil;
  200. while (not null temp) and (not eqcar(temp,'!`)) do
  201. <<no:=car temp . no;temp:=cdr temp>>;
  202. compress no
  203. >>;
  204. if (not fixp n1) then n1:=intern n1;
  205. ans:=n1 . ans;
  206. if eqcar(temp,'!`) then <<temp:=cdr temp; temp:=cdr temp>>;
  207. >>;
  208. return ans
  209. end$
  210. %---------------------
  211. symbolic procedure comparedif1(u1l,u2l)$
  212. % u1l, u2l are lists of indicees of differentiation variables
  213. % checks whether u2l has more or at least equally many 1's, 2's, ...
  214. % contained as u1l.
  215. % returns a list of 1's, 2's, ... which are in excess in u2l
  216. % compared with u1l. The returned value is 0 if both are identical
  217. begin
  218. scalar ul;
  219. if u2l=nil then if u1l neq nil then return nil
  220. else return 0
  221. else if u1l=nil then return u2l
  222. else % both are non-nil
  223. if car u1l < car u2l then return nil else
  224. if car u1l = car u2l then return comparedif1(cdr u1l,cdr u2l) else <<
  225. ul:=comparedif1(u1l,cdr u2l);
  226. return if not ul then nil else
  227. if zerop ul then list car u2l else
  228. cons(car u2l,ul)
  229. >>
  230. end$ % of comparedif1
  231. %---------------------
  232. symbolic procedure comparedif2(u1,u1list,du2)$
  233. % checks whether du2 is a derivative of u1 differentiated
  234. % wrt. u1list
  235. begin
  236. scalar u2l;
  237. u2l:=combidif(du2)$ % u2l=(u2, 1, 1, ..)
  238. if car u2l neq u1 then return nil else
  239. return comparedif1(u1list, cdr u2l)
  240. end$ % of comparedif2
  241. %---------------------
  242. symbolic procedure comparedif3(du1,u2,u2list)$
  243. % checks whether u2 differentiated wrt. u2list
  244. % is a derivative of du1
  245. begin
  246. scalar u1l;
  247. u1l:=combidif(du1)$ % u1l=(u1, 1, 1, ..)
  248. if car u1l neq u2 then return nil else
  249. return comparedif1(cdr u1l, u2list)
  250. end$ % of comparedif3
  251. %---------------------
  252. symbolic procedure listdifdif1(du1,deplist)$
  253. % lists all elements of deplist which are *not* derivatives
  254. % of du1
  255. begin
  256. scalar u1,u1list,res,h$
  257. h:=combidif(du1);
  258. u1:=car h;
  259. u1list:=cdr h;
  260. for each h in deplist do
  261. if not comparedif2(u1,u1list,h) then res:=cons(h,res);
  262. return res
  263. end$ % of listdifdif1
  264. %---------------------
  265. symbolic operator dif$
  266. symbolic procedure dif(s,n)$
  267. % e.g.: dif(fnc!`1!`3!`3!`4, 3) --> fnc!`1!`3!`3!`3!`4
  268. begin scalar temp,ans,no,n1,n2,done;
  269. s:=reval s; % to guarantee s is in true prefix form
  270. temp:=reverse explode s;
  271. n2:=reval n;
  272. n2:=explode n2;
  273. while (not null temp) and (not done) do
  274. <<n1:=<<no:=nil;
  275. while (not null temp) and (not eqcar(temp,'!`)) do
  276. <<no:=car temp . no;temp:=cdr temp>>;
  277. compress no
  278. >>;
  279. if (not fixp n1) or ((fixp n1) and (n1 leq n)) then
  280. <<ans:=nconc(n2,ans); ans:='!` . ans; ans:='!! . ans; done:=t>>;
  281. ans:=nconc(no,ans);
  282. if eqcar(temp,'!`) then <<ans:='!` . ans; ans:='!! . ans;
  283. temp:=cdr temp; temp:=cdr temp>>;
  284. >>;
  285. return intern compress nconc(reverse temp,ans);
  286. end$
  287. %---------------------
  288. %symbolic procedure orderofderiv(du)$
  289. %if atom du then (length combidif(du))-1
  290. % else nil$
  291. %---------------------
  292. symbolic procedure mergedepli(li1,li2)$
  293. % li1,li2 are lists of lists
  294. % mergedepli merges the sublists to make one list of lists
  295. begin scalar newdep;
  296. while li1 and li2 do <<
  297. newdep:=union(car li1, car li2) . newdep;
  298. li1:=cdr li1; li2:=cdr li2
  299. >>;
  300. return if li1 then nconc(reversip newdep,li1) else
  301. if li2 then nconc(reversip newdep,li2) else reversip newdep
  302. end$
  303. %---------------------
  304. symbolic procedure adddepli(ex,revdylist)$
  305. begin scalar a,b,c,d;
  306. for each a in revdylist do <<
  307. c:=nil;
  308. for each b in a do
  309. if not my_freeof(ex,b) then c:=b . c;
  310. if c or d then d:=c . d;
  311. >>;
  312. return list(ex,d)
  313. end$
  314. %---------------------
  315. symbolic procedure add_xi_eta_depli(xilist,etalist,revdylist)$
  316. begin
  317. scalar e1,g,h$
  318. for e1:=1:(length xilist) do <<
  319. g:=nth(xilist,e1);
  320. h:=pnth(g,4);
  321. rplaca(h,cadr adddepli(car g,revdylist))
  322. >>;
  323. for e1:=1:(length etalist) do <<
  324. g:=nth(etalist,e1);
  325. h:=pnth(g,3);
  326. rplaca(h,cadr adddepli(car g,revdylist))
  327. >>
  328. end$
  329. %---------------------
  330. symbolic procedure subtest(uik,sb,xlist,ordok,subordinc)$
  331. begin
  332. scalar el5,el6,el7,el8,el9,el10,sbc$
  333. el5:=combidif(uik);
  334. el6:=car el5; el5:=cdr el5; % el6..function name, el5..var.list
  335. el7:=nil; el8:=100; el9:=nil;
  336. sbc:=sb;
  337. while sbc and
  338. ((caaar sbc neq el6) or
  339. (0 neq <<el7:=comparedif1(cdaar sbc,el5);
  340. if el7 and (not zerop el7) and
  341. (length(el7)<el8) then
  342. <<el8 :=length el7;
  343. el9 :=el7;
  344. el10:=car sbc>> else
  345. el7
  346. >>)
  347. ) do sbc:=cdr sbc;
  348. return
  349. if sbc then (cadar sbc . caddar sbc) % simple substitution
  350. else
  351. if el9 then << % uik is total deriv of car el10 wrt el9
  352. uik:=cadr el10 . caddr el10;
  353. % car uik becomes the expr. to replace the former uik
  354. while el9 do <<
  355. uik:=totdf3(car uik, cdr uik, nth(xlist, car el9),
  356. car el9, sb, xlist, ordok, subordinc);
  357. el9:=cdr el9
  358. >>;
  359. uik
  360. >> else % no substitution
  361. nil
  362. end$
  363. %---------------------
  364. symbolic procedure totdf3(s,depli,x,n,sb,xlist,ordok,subordinc)$
  365. % s is the expression to be differentiated wrt. x which is the nth
  366. % variable in xlist
  367. % depli is a list of lists, each being the list of jet-variables
  368. % of order 0,1,2,..., such that s=s(xlist,depli), but
  369. % as little as possible jet-variables in depli
  370. % xlist, depli are lisp lists, i.e. without 'LIST
  371. % - totdf3 calculates total derivative of s(xlist,depli) w.r.t. x which
  372. % is the n'th variable, it returns (df(s,x), newdepli)
  373. % - totdf3 drops jet-variables on which s does not depend
  374. % - totdf3 automatically does substitutions using the list sb which
  375. % is updated if prolongations of substitutions are calculated,
  376. % i.e. sb is destructively changed!!
  377. % - structure of sb: lisp list of lisp lists:
  378. % ((to_be_replaced_jet_var_name, to_be_replaced_jet_var_deriv_1,..),
  379. % subst_expr_in_jet_space_coord, list_of_jet_vars_in_subst_expr)
  380. % - subordinc is a number by how much the order may increase due to
  381. % substitutions sb.
  382. % - ordok is the lowest order which must be accurate. If ordok>0 and
  383. % s is of lower order than ordok then from depli only derivatives
  384. % of order ordok-1-subordinc to ordok-1 are used.
  385. begin
  386. scalar tdf,el1,el2,el3,el4,el5,newdepli,
  387. newdy,dy,ddy,s;
  388. newdepli:=nil; % the new dependence list
  389. newdy:=nil; % the new dep.list due to chain rule
  390. ddy:=nil; % ddy .. derivatives of jet-variables
  391. % resulting from diff. of lower order
  392. %--- Should only terms in the result be acurate that include
  393. %--- derivatives of order>=ordok?
  394. if ordok>0 then <<
  395. tdf:=simp!* 0;
  396. depli:=copy depli;
  397. el2:=length depli;
  398. if el2<(ordok-subordinc) then depli:=nil
  399. else
  400. for el1:=1:(ordok-1-subordinc) do <<
  401. dy:=pnth(depli,el1);
  402. rplaca(dy,nil);
  403. >>
  404. >> else tdf:=simpdf {s,x};
  405. %--- The differentiations wrt. u-derivatives
  406. for each el1 in depli do % for each order do
  407. <<dy:=union(ddy,el1); ddy:=nil;% dy .. occuring jet-var. of this order
  408. while el1 do
  409. <<el2:=car el1; el1:=cdr el1;% el2 is one jet-variable of this order
  410. el3:=simpdf {s,el2};
  411. if zerop el3 then dy:=delete(el2,dy)
  412. else <<
  413. el4:=dif(el2,n); % el4=df(el2,x)
  414. %----- Is el4 to be substituted by sb?
  415. if el5:=subtest(el4,sb,xlist,ordok,subordinc) then <<
  416. el4:=car el5;
  417. newdepli:=mergedepli(newdepli,cdr el5)
  418. >> else ddy:=el4 . ddy;
  419. tdf:=addsq(tdf, multsq(simp!* el4, el3))
  420. >>
  421. >>;
  422. newdy:=dy . newdy
  423. >>;
  424. if ddy then newdy:=ddy . newdy;
  425. newdepli:=mergedepli(reversip newdy,newdepli);
  426. % possibly drop at the end
  427. return (prepsq tdf . newdepli)
  428. end$ % of totdf3
  429. %---------------------
  430. symbolic procedure joinsublists(a)$
  431. % It is assumed, a is either nil or a list of lists or nils which
  432. % have to be joined
  433. if null a then nil
  434. else append(car a,joinsublists(cdr a))$
  435. %---------------------
  436. symbolic procedure depnd(y,xlist)$
  437. for each xx in xlist do
  438. for each x in xx do depend y,x$
  439. %---------------------
  440. algebraic procedure transeq(eqn,xlist,ylist,sb)$
  441. <<for each el1 in sb do eqn:=sub(el1,eqn);
  442. for each el1 in ylist do
  443. for each el2 in xlist do nodepend el1,el2;
  444. eqn>>$
  445. %---------------------
  446. symbolic operator drop$
  447. symbolic procedure drop(a,vl)$
  448. % liefert summe aller terme aus a, die von elementen von vl abhaengen
  449. begin scalar b$
  450. if not((pairp a) and (car a='PLUS)) then b:=a
  451. else
  452. <<vl:=cdr vl; % because vl is an algebraic list
  453. for each c in cdr a do
  454. if not freeoflist(c,vl) then b:=cons(c,b)$
  455. if b then b:=cons('PLUS,reverse b)>>$
  456. return b$
  457. end$
  458. %---------------------
  459. symbolic procedure etamn(u,indxlist,xilist,etalist,
  460. ordok,truesub,subordinc,xlist)$
  461. % determines etamn recursively
  462. % At the end, ulist= list of df(u,i,cdr indxlist) for all i
  463. begin
  464. scalar etam,x,h1,h2,h3,h4,ulist,el,r,cplist,depli;
  465. if (null indxlist) or ((length indxlist)=1) then
  466. <<cplist:=etalist;
  467. while u neq cadar cplist do cplist:=cdr cplist;
  468. etam:=(caar cplist . caddar cplist) . nil;
  469. >> else
  470. etam:=etamn(u,cdr indxlist,xilist,etalist,ordok,truesub,
  471. subordinc,xlist)$
  472. return
  473. if null indxlist then etam
  474. else <<
  475. ulist:=nil;
  476. x:=cdr nth(xilist,car indxlist); % e.g. x := (v3,3,dylist)
  477. r:=if zerop caar etam then simp!* <<depli:=nil;0>>
  478. else simp!* <<
  479. h2:=totdf3(caar etam,cdar etam,car x,cadr x,truesub,xlist,
  480. ordok,subordinc)$
  481. depli:=cdr h2;
  482. car h2
  483. >>;
  484. etam:=cdr etam; % = reverse ulist
  485. cplist:=xilist;
  486. h3:=nil;
  487. while cplist do
  488. <<el:=car cplist; % e.g. el=xi_z
  489. cplist:=cdr cplist;
  490. if (length indxlist)=1 then h1:=dif(u,caddr el)
  491. else <<
  492. h1:=dif(car etam,cadr indxlist); % e.g. h1:=u!`i!`n
  493. etam:=cdr etam;
  494. >>;
  495. ulist:=h1 . ulist;
  496. if not zerop car el then <<
  497. %--- substitution of h1?
  498. if h4:=subtest(h1,truesub,xlist,ordok,subordinc) then
  499. h1:=car h4;
  500. r:=subtrsq(r,
  501. multsq(simp!* h1,
  502. simp!* <<h2:=totdf3(car el,cadddr el,car x,
  503. cadr x,truesub,xlist,0,0)$
  504. if zerop car h2 then 0
  505. else
  506. <<if h4 then
  507. depli:=mergedepli(depli,cdr h4)
  508. else h3:=h1 . h3;
  509. depli:=mergedepli(depli,cdr h2);
  510. car h2
  511. >>
  512. >>
  513. )
  514. );
  515. >>
  516. >>;
  517. if h3 then <<
  518. h3:=list h3;
  519. for h2:=1:(length indxlist) do h3:=nil . h3;
  520. depli:=mergedepli(depli,h3);
  521. >>;
  522. % (if not full then drop(r,'LIST . car revdylist) else r) .
  523. % (reverse ulist)
  524. (prepsq r . depli) . (reverse ulist)
  525. >>
  526. end$ % of etamn
  527. %---------------------
  528. symbolic procedure prolong(uik,xilist,etalist,ordok,truesub,subordinc,
  529. xlist)$
  530. begin
  531. scalar h;
  532. h:=combidif(uik);
  533. h:=car etamn(car h,cdr h,xilist,etalist,ordok,truesub,
  534. subordinc,xlist)$
  535. return (simp!* car h) . cdr h
  536. end$ % of prolong
  537. %---------------------
  538. symbolic procedure callcrack(!*time,cpu,gc,lietrace_,symcon,
  539. flist,vl,xilist,etalist)$
  540. begin
  541. scalar g,h;
  542. if !*time then <<terpri()$
  543. write "time to formulate conditions: ", time() - cpu,
  544. " ms GC time : ", gctime() - gc," ms"$
  545. >>;
  546. if lietrace_ then algebraic <<
  547. write"Symmetry conditions before CRACK: ";
  548. write lisp ('LIST . symcon);
  549. >>;
  550. h:=crack('LIST . symcon,list('LIST),'LIST . flist,'LIST . vl);
  551. if h neq list('LIST) then
  552. <<h:=cadr h;
  553. symcon:=cdadr h;
  554. for each g in cdaddr h do <<
  555. xilist :=subst(caddr g, cadr g, xilist);
  556. etalist:=subst(caddr g, cadr g, etalist);
  557. %--> Erkennung von 'e, 'x siehe:
  558. % h:=intern car explode cadr e1;
  559. %write"h=",h;terpri()$
  560. % if (h='x) or (h='X) then
  561. % xilist :=subst(caddr e1, cadr e1, xilist) else
  562. % if (h='e) or (h='E) or (h="e") or (h="E") then
  563. % etalist:=subst(caddr e1, cadr e1, etalist) else
  564. % rederr("One ansatz does not specify XI_ nor ETA_.")
  565. >>;
  566. if lietrace_ then <<
  567. write"symcon nachher: ",symcon;
  568. write"xilist=", xilist;
  569. write"etalist=", etalist;
  570. >>;
  571. flist:=cdr reval cadddr h;
  572. if print_ then
  573. <<terpri()$terpri()$
  574. write"Remaining free functions after the last CRACK-run:";
  575. terpri()$
  576. fctprint flist;terpri()$terpri()>>;
  577. >>;
  578. return list(symcon,xilist,etalist,flist)
  579. end$ % of callcrack
  580. %---------------------
  581. symbolic operator liepde$
  582. symbolic procedure liepde(problem,symtype,flist)$
  583. comment
  584. problem: {{eq1,eq2, ...}, % equations
  585. { y1, y2, ...}, % functions
  586. { x1, x2, ...} } % variables
  587. % Equations `eqi' can be given as single differential
  588. % expressions which have to vanish or they can be given
  589. % in the form df(..,..[,..]) = .. .
  590. % If the equations are given as single differential
  591. % expressions then the program will try to bring it into
  592. % the `solved form' ..=.. automatically.
  593. % The solved forms (either from input or generated within
  594. % LIEPDE) will be used for substitutions, to find
  595. % all symmetries satisfied by solutions of the equations.
  596. % Sufficient conditions for this procedure to be correct,
  597. % i.e. to get *all* symmetries of the specified type on the
  598. % solution space are:
  599. % - There are equally many equations and functions.
  600. % - Each function is used once for a substitution and
  601. % each equation is used once for a substitution.
  602. % - All functions differentiated on the left hand sides
  603. % (lhs) depend on all variables.
  604. % - In no equation df(..,..[,..]) = .. does the right hand
  605. % side contain the derivative on the lhs nor any
  606. % derivative of it.
  607. % - No equation does contain a lhs or the derivative
  608. % of a lhs of another equation.
  609. % These conditions are checked in LIEPDE and execution
  610. % is stoped if they are not satisfied, i.e. if the input
  611. % was not correct, or if the program was not able to
  612. % write the input expressions properly the solved
  613. % form ..=.. . One then should find for each function
  614. % one derivative which occurs linearly in one equation.
  615. % The chosen derivatives should be as high as possible,
  616. % at least there must no derivative of them occur in any
  617. % equation. An easy way to get the equations in the
  618. % desired form is to use
  619. % FIRST SOLVE({eq1,eq2,...},{list of derivatives})
  620. % NOTE that to improve efficiency it is advisable not to
  621. % express lower order derivatives on the left hand side
  622. % through higher order derivatives on the right hand side.
  623. % SEE also the implications on completeness for the
  624. % determination of generalized symmetries with
  625. % characteristic functions of a given order, as described
  626. % below and the two examples with the Burgers equation.
  627. symtype: {"point"} % for point symmetries
  628. {"contact"} % for contact symmetries, is only
  629. % applicable if only one function,
  630. % only one equation of order>1
  631. {"general",order} % for generalized symmetries of
  632. % order `order' which is an integer>0
  633. % NOTE: Characteristic functions of
  634. % generalized symmetries (i.e. the
  635. % eta_.. if xi_..=0) are equivalent
  636. % if they are equal on the solution
  637. % manifold. Therefore all dependencies
  638. % of characteristic functions on
  639. % the substituted derivatives and their
  640. % derivatives are dropped. This has the
  641. % consequence that if, e.g. for the heat
  642. % equation df(u,t)=df(u,x,2), df(u,t) is
  643. % substituted by df(u,x,2) then
  644. % {"general",2) would not include
  645. % characteristic functions depending
  646. % on df(u,t,x), or df(u,x,3). THEREFORE:
  647. % If you want to find all symmetries up
  648. % to a given order then
  649. % - either avoid substituting lower
  650. % order derivatives by expressions
  651. % involving higher derivatives, or,
  652. % - go up in the order specified in
  653. % symtype.
  654. %
  655. % Example:
  656. %
  657. % depend u,t,x
  658. % liepde({{df(u,t)=df(u,x,2)+df(u,x)**2},
  659. % {u},{t,x}},
  660. % {"general",3},{})
  661. %
  662. % will give 10 symmetries + one infinite
  663. % family of symmetries whereas
  664. %
  665. % liepde({{df(u,x,2)=df(u,t)-df(u,x)**2},
  666. % {u},{t,x}},
  667. % {"general",3},{})
  668. %
  669. % will give 28 symmetries + one infinite
  670. % family of symmetries.
  671. {xi!_x1 =...,
  672. ...
  673. eta!_y3=... } % - An ansatz must specify all xi!_.. for
  674. % all indep. variables and all eta!_..
  675. % for all dep. variables in terms of
  676. % differential expressions which may
  677. % involve unknown functions/constants.
  678. % The dependencies of the unknown
  679. % functions have to declared earlier
  680. % using the DEPEND command.
  681. % - If the ansatz should consist of the
  682. % characteristic functions then set
  683. % all xi!_..=0 and assign the charac-
  684. % teristic functions to the eta!_.. .
  685. flist: {- all parameters and functions in the equations which are to
  686. be determined, such that there exist symmetries,
  687. - if an ansatz has been made in symtype then flist contains
  688. all unknown functions and constants in xi!_.. and eta!_..}
  689. Further comments:
  690. The syntax of input is the usual REDUCE syntax. For example, the
  691. derivative of y3 wrt x1 once and x2 twice would be df(y3,x1,x2,2).
  692. --> One exception: If in the equations or in the ansatz the dependence
  693. of a free function F on a derivative, like df(y3,x1,x2,2) shall be
  694. declared then the declaration has to have the form:
  695. DEPEND F, Y3!`1!`2!`2
  696. - the ! has to preceede each special character, like `,
  697. - `i stands for the derivative with respect to the i'th variable in
  698. the list of variables (the third list in the problem above)
  699. If the flag individual_ is t then conditions are investigated for
  700. each equation of a system of equations at first individually before
  701. conditions resulting from other equations are added.
  702. If the flag prelim_ is t then preliminary conditions for equations
  703. of higher than 1st order are formulated and investigated before the
  704. full condition is formulated and investigated by CRACK.
  705. If the REDUCE switch TIME is set on with ON TIME then times for the
  706. individual steps in the calculation are shown.
  707. Further switches and parameters which can be changed to affect the
  708. output and performance of CRACK in solving the symmetry conditions
  709. are listed in the file CRINIT.RED.
  710. ;
  711. begin
  712. scalar cpu, gc, lietrace_, oldadj, eqlist, ylist, xlist, pointp,
  713. contactp, generalp, ansatzp, symord, e1, e2, ordr, sb,
  714. dylist, revdylist, xi, eta, eqordr, eqordrcop, no, eqcopy1,
  715. truesub, deplist, xilist, etalist, dycopy, freelist, eqlen,
  716. dylen, truesubno, minordr, n1, n2, n3, n4, n, h, jetord,
  717. allsub, subdy, lhslist, symcon, subordinc, eqn, depli,
  718. vl, occli, revdycopy, subordinclist, xicop, etacop, flcop;
  719. cpu:=time()$ gc:=gctime()$
  720. lietrace_:=nil;
  721. oldadj:=adjust_fnc;
  722. adjust_fnc:=nil;
  723. %--------- extracting input data
  724. eqlist:= cdr maklist cadr problem;
  725. ylist := reval maklist caddr problem;
  726. xlist := reval maklist cadddr problem;
  727. eqlen:=length eqlist;
  728. if 1+eqlen neq length(ylist) then rederr(
  729. "Number of equations does not match number of unknown functions.");
  730. for each e1 in cdr ylist do
  731. for each e2 in cdr xlist do
  732. if my_freeof(e1,e2) then rederr(
  733. "Not all functions do depend on all variables.");
  734. if atom cadr symtype then % default case
  735. if cadr symtype = "point" then <<pointp :=t;symord:=0>> else
  736. if cadr symtype = "contact" then <<contactp:=t;symord:=1;
  737. if eqlen>1 then rederr(
  738. "Contact symmetries only in case of one equation for one function.")
  739. >> else
  740. if cadr symtype = "general" then <<generalp:=t;symord:=caddr symtype;
  741. if (not fixp symord) or (symord<1) then rederr(
  742. "The order of the generalized symmetry must be an integer > 0.")
  743. >> else rederr("Inconclusive symmetry type.")
  744. else <<
  745. ansatzp:=t; % an ansatz has been made
  746. if length(ylist)+length(xlist) neq length(symtype)+1 then
  747. rederr("Number of assignments in the ansatz is wrong.");
  748. symord:=0;
  749. for each e1 in cdr symtype do
  750. for each e2 in ylist do
  751. <<n:=totdeg(e1,e2);
  752. if n>symord then symord:=n>>;
  753. if symtype = 0 then pointp :=t else
  754. if (symtype = 1) and (length(ylist)=2) then contactp:=t else
  755. generalp:=t
  756. >>$
  757. if flist then flist:=cdr flist;
  758. problem:=0;
  759. %---- Are substitutions already given in the input?
  760. eqcopy1:=eqlist;
  761. while eqcopy1 and (pairp car eqcopy1) and (caar eqcopy1='EQUAL) and
  762. (pairp cadar eqcopy1) and (caadar eqcopy1='DF) do
  763. eqcopy1:=cdr eqcopy1;
  764. if null eqcopy1 then truesub:=eqlist;
  765. eqcopy1:=nil;
  766. %--------- initial printout
  767. if print_ and logoprint_ then <<terpri()$
  768. write "-----------------------------------------------",
  769. "---------------------------"$ terpri()$terpri()$
  770. write"This is LIEPDE - a program for calculating infinitesimal",
  771. " symmetries"; terpri()$
  772. write "of single differential equations or systems of de's";
  773. >>;
  774. terpri();terpri();
  775. if length xlist=2 then write"The ODE"
  776. else write"The PDE";
  777. if length ylist>2 then write"-system";
  778. write " under investigation is :";terpri();
  779. % for each e1 in eqlist do algebraic write"0 = ",lisp e1;
  780. for each e1 in eqlist do algebraic write lisp e1;
  781. terpri()$write "for the function(s) : ";terpri()$
  782. terpri()$fctprint cdr reval ylist;
  783. terpri()$terpri();
  784. eqlist:=for each e1 in eqlist collect algebraic equ_to_expr(lisp e1);
  785. if eqlen > 1 then eqlist:=desort eqlist;
  786. if !*time then <<terpri()$
  787. terpri()$terpri()$
  788. write"=============== Initializations" ;
  789. >>;
  790. %--------- initializations
  791. ordr:=0;
  792. for each e1 in eqlist do <<
  793. h:=0;
  794. for each e2 in cdr ylist do
  795. <<n:=totdeg(e1,e2);
  796. if n>h then h:=n>>;
  797. eqordr:=h . eqordr;
  798. if h>ordr then ordr:=h
  799. >>;
  800. eqordr:=reversip eqordr;
  801. if ordr>symord then jetord:=ordr
  802. else jetord:=symord$
  803. sb:=subdif1(xlist,ylist,jetord)$
  804. eqlist:=cons('LIST,eqlist);
  805. if ansatzp then eqlist:=list('LIST,symtype,eqlist);
  806. if truesub then eqlist:=list('LIST,cons('LIST,truesub),eqlist);
  807. on evallhseqp;
  808. eqlist:=transeq(eqlist,xlist,ylist,sb);
  809. off evallhseqp;
  810. if truesub then <<truesub:=cdadr eqlist;eqlist:=caddr eqlist>>;
  811. if ansatzp then <<symtype:=cdadr eqlist;eqlist:=cdaddr eqlist>>
  812. else eqlist:=cdr eqlist;
  813. ylist:=cdr ylist;
  814. xlist:=cdr xlist;
  815. if lietrace_ and ansatzp then write"ansatz=",symtype;
  816. dylist:=ylist . reverse for each e1 in cdr sb collect
  817. for each e2 in cdr e1 collect caddr e2;
  818. revdylist:=reverse dylist; % dylist with decreasing order
  819. vl:=xlist;
  820. for each e1 in dylist do vl:=append(e1,vl);
  821. vl:='LIST . vl;
  822. if not ansatzp then
  823. deplist:=for n:=0:symord collect nth(dylist,n+1);
  824. % list of variables the xi_, eta_ depend on
  825. xi :=reval algebraic xi!_;
  826. eta:=reval algebraic eta!_;
  827. n:=0;
  828. xilist :=for each e1 in xlist collect
  829. <<n:=n+1;
  830. if pointp or ansatzp then <<
  831. h:=mkid(xi,e1);
  832. if not ansatzp then <<
  833. depnd(h,xlist . deplist);
  834. flist:=h . flist;
  835. depli:=deplist;
  836. >> else depli:=nil
  837. >> else <<h:=0;depli:=nil>>;
  838. {h,e1,n,depli}
  839. >>;
  840. depli:=if (not ansatzp) and (not generalp) then deplist
  841. else nil;
  842. n:=0;
  843. etalist:=for each e1 in ylist collect
  844. <<n:=n+1;
  845. h:=mkid(eta,e1);
  846. if not ansatzp then <<
  847. if not generalp then depnd(h,xlist . deplist);
  848. % the generalp-case is done below when substitutions are known
  849. flist:=h . flist;
  850. >>;
  851. {h,e1,depli}
  852. >>;
  853. if ansatzp then <<
  854. for each e1 in symtype do <<
  855. xilist :=subst(caddr e1, cadr e1, xilist);
  856. etalist:=subst(caddr e1, cadr e1, etalist);
  857. %--> Erkennung von 'e, 'x siehe:
  858. % h:=intern car explode cadr e1;
  859. %write"h=",h;terpri()$
  860. % if (h='x) or (h='X) then
  861. % xilist :=subst(caddr e1, cadr e1, xilist) else
  862. % if (h='e) or (h='E) or (h="e") or (h="E") then
  863. % etalist:=subst(caddr e1, cadr e1, etalist) else
  864. % rederr("One ansatz does not specify XI_ nor ETA_.")
  865. >>;
  866. add_xi_eta_depli(xilist,etalist,revdylist)$
  867. >>;
  868. if lietrace_ then write"xilist=",xilist," etalist=",etalist;
  869. %---- Determining a substitution list for highest derivatives
  870. %---- from eqlist. Substitutions may not be optimal if starting
  871. %---- system is not in standard form
  872. comment: Counting in how many equations each highest
  873. derivative occurs. Those which do not occur allow Stephani-Trick,
  874. those which do occur once and there linearly are substituted by that
  875. equation.
  876. Because one derivative shall be assigned it must be one of
  877. the highest derivatives from each equation used, or one such that
  878. no other derivative in the equation is a derivative of it.
  879. Each equation must be used only once.
  880. Each derivative must be substituted by only one equation.
  881. At first determining the number of occurences of each highest
  882. derivative.
  883. The possiblity of substitutions is checked in each total derivative.
  884. $
  885. if truesub then << %--- determination of freelist %and occurlist
  886. dycopy:=car revdylist; %--- the highest derivatives
  887. while dycopy do
  888. <<e1:=car dycopy; dycopy:=cdr dycopy;
  889. eqcopy1:=eqlist;
  890. while eqcopy1 and my_freeof(car eqcopy1,e1) do
  891. eqcopy1:=cdr eqcopy1;
  892. if null eqcopy1 then freelist :=e1 . freelist
  893. %else occurlist:=e1 . occurlist;
  894. >>
  895. >> else <<
  896. no:=0; % counter of the following repeat-loop
  897. % freelist (and occurlist) are determined
  898. % only in the first run
  899. eqordrcop:=copy eqordr;
  900. % for bookkeeping which equation have been used
  901. repeat <<
  902. no:=no+1; %--- incrementing the loop counter
  903. %--- truesubno is the number of substitutions so far found.
  904. %--- It is necessary at the end to check whether new substitutions
  905. %--- have been found.
  906. if null truesub then truesubno:=0
  907. else truesubno:=length truesub;
  908. %--- substitutions of equations of minimal order are searched first
  909. minordr:=1000; %--- minimal order of the so far unused equations
  910. for each e1 in eqordrcop do
  911. if (e1 neq 0) and (e1<minordr) then minordr:=e1;
  912. dycopy:=copy nth(dylist,minordr+1); %-- all deriv. of order minordr
  913. dylen:=length dycopy;
  914. allsub:=nil;
  915. for n1:=1:dylen do %--- checking all deriv. of order minordr
  916. <<e1:=nth(dycopy,n1); %--- e1 is the current candidate
  917. %--- here test, whether e1 is not a derivative of a lhs of one
  918. %--- of the substitutions car e2 found so far
  919. h:=combidif(e1); n:=car h; h:=cdr h;
  920. e2:=truesub;
  921. while e2 and (null comparedif3(cadar e2,n,h)) do e2:=cdr e2;
  922. if null e2 then <<
  923. n2:=0; %-- number of equations in which the derivative e1 occurs
  924. subdy:=nil;
  925. for n3:=1:eqlen do
  926. if not my_freeof(nth(eqlist,n3),e1) then
  927. % here should also be tested whether derivatives of e1 occur
  928. % and not just my_freeof
  929. %-->
  930. <<n2:=n2+1;
  931. if nth(eqordrcop,n3)=minordr then
  932. %--- equation is not used yet and of the right order
  933. <<e2:=cdr algebraic coeff(lisp nth(eqlist,n3),lisp e1);
  934. if hipow!*=1 then
  935. subdy:=list(n1,n3,list('EQUAL,e1,list('MINUS,
  936. list('QUOTIENT, car e2, cadr e2)))) . subdy
  937. >>
  938. >>;
  939. if n2=0 then if no=1 then freelist:=e1 . freelist else
  940. else
  941. <<%if no=1 then occurlist:=e1 . occurlist;
  942. if subdy then if n2=1 then
  943. <<h:=car subdy;
  944. truesub:=(caddr h) . truesub;
  945. n:=pnth(dycopy ,car h);rplaca(n,0);
  946. n:=pnth(eqordrcop,cadr h);rplaca(n,0);
  947. >> else
  948. allsub:=nconc(allsub,subdy);
  949. >>
  950. >>
  951. >>;
  952. %---- Taking the remaining known substitutions of highest deriv.
  953. h:=subdy:=0;
  954. for each h in allsub do
  955. if (nth(dycopy , car h) neq 0) and
  956. (nth(eqordrcop,cadr h) neq 0) then
  957. <<truesub:=(caddr h) . truesub;
  958. n:=pnth(dycopy ,car h);rplaca(n,0);
  959. n:=pnth(eqordrcop,cadr h);rplaca(n,0);
  960. >>;
  961. >> until (truesub and (length(truesub)=eqlen)) % complete
  962. or (truesubno=length(truesub))$ % no progress
  963. allsub:=eqordrcop:=dycopy:=nil;
  964. if (null truesub) or
  965. (eqlen neq length(truesub)) then rederr(
  966. "Unable to find all substitutions. Input equations as df(..,..)=..!");
  967. >>;
  968. lhslist:=for each e1 in truesub collect cadr e1;
  969. %-- Bringing truesub into a specific form: lisp list of lisp lists:
  970. % ((to_be_replaced_jet_var_name, to_be_replaced_jet_var_deriv_1,..),
  971. % subst_expr_in_jet_space_coord, list_of_jet_vars_in_subst_expr)
  972. truesub:=for each e1 in truesub collect
  973. cons(combidif cadr e1, adddepli(caddr e1,revdylist))$
  974. %--- Checking that no rhs of a substitution contains any lhs or
  975. %--- derivative of a lhs
  976. h:=t; %--- h=nil if lhs's are derivatives of each other
  977. no:=t; %--- no=nil if one lhs can be substituted in a rhs
  978. for each e1 in truesub do
  979. if h and no then <<
  980. n1:=caar e1; n2:=cdar e1; dylen:=length n2;
  981. for each e2 in truesub do <<
  982. %--- comparison of two lhs's
  983. if not(e1 eq e2) and (n1=caar e2) and
  984. comparedif1(n2,cdar e2) then h:=nil; %--- truesub is not ok
  985. %--- can the lhs of e1 be substituted on the rhs?
  986. dycopy:=caddr e2;
  987. for n:=1:dylen do if dycopy then dycopy:=cdr dycopy;
  988. for each e3 in dycopy do
  989. for each e4 in e3 do
  990. if comparedif2(n1,n2,e4) then no:=nil;
  991. >>
  992. >>;
  993. if null h then rederr(
  994. "One substitution can be made in the lhs of another substitution!");
  995. if null no then rederr(
  996. "One substitution can be made in the rhs of another substitution!");
  997. %--- Checking that a derivative of each dependent variable is
  998. %--- substituted once. This is a sufficient condition for having
  999. %--- a de-system that is a differential Groebner basis
  1000. h:=nil;
  1001. for each e1 in lhslist do h:=adjoin(car combidif e1,h);
  1002. if length(h) neq length(lhslist) then rederr(
  1003. "For at least one function there is more that one substituion!")$
  1004. %--- Determine of how much the order may increase by a substitution
  1005. subordinc:=0;
  1006. subordinclist:=for each h in truesub collect <<
  1007. n:=(length caddr h) - (length car h);
  1008. if n>subordinc then subordinc:=n;
  1009. n
  1010. >>;
  1011. if lietrace_ then <<terpri()$write"truesub=",truesub;
  1012. terpri()$write"freelist=",freelist;
  1013. %terpri()$write"occurlist=",occurlist
  1014. >>;
  1015. %--- To avoid non-uniqueness in the case of the investigation of
  1016. %--- generalized symmetries let the characteristics eta_.. (xi_..=0)
  1017. %--- not depend on substituted derivatives
  1018. if generalp and (null ansatzp) then <<
  1019. deplist:=ylist .
  1020. for each dycopy in cdr deplist collect <<
  1021. for each h in lhslist do
  1022. %---- delete h and derivatives of h
  1023. dycopy:=listdifdif1(h,dycopy);
  1024. dycopy
  1025. >>;
  1026. for e1:=1:(length etalist) do <<
  1027. h:=nth(etalist,e1);
  1028. depnd(car h,xlist . deplist);
  1029. h:=pnth(h,3);
  1030. rplaca(h,deplist)
  1031. >>
  1032. >>;
  1033. % reduced set of solution techniques for preliminary conditions
  1034. proc_list_:=delete('multintfac,proc_list_)$
  1035. if !*time then <<terpri()$
  1036. write "time for initializations: ", time() - cpu,
  1037. " ms GC time : ", gctime() - gc," ms"$
  1038. cpu:=time()$ gc:=gctime()$
  1039. >>;
  1040. %------ Determining first short determining equations and solving them
  1041. symcon:=nil;
  1042. n1:=0;
  1043. if prelim_ then
  1044. for each eqn in eqlist do
  1045. <<n1:=n1+1;
  1046. if !*time then <<terpri()$
  1047. terpri()$terpri()$
  1048. write"=============== Preconditions for the ",n1,". equation" ;
  1049. >>;
  1050. revdycopy:=revdylist;
  1051. for e1:=(nth(eqordr,n1) + 1):ordr do revdycopy:=cdr revdycopy;
  1052. n2:=cadr adddepli(eqn,revdycopy); % jet-variables in eqn
  1053. vl:=n2;
  1054. occli:=lastcar n2;
  1055. freelist:=setdiff(car revdycopy,occli);
  1056. if pointp and (subordinc=0) then
  1057. eqn:=drop(eqn,occli) % dropp all terms without a highest deriv.
  1058. else occli:=joinsublists n2$
  1059. % freelist must not contain substituted variables
  1060. freelist:=setdiff(freelist,lhslist);
  1061. % It must be possible to separate wrt freelist variables
  1062. for each n4 in freelist do
  1063. if not freeof(depl!*,n4) then freelist:=delete(n4,freelist);
  1064. If freelist then <<
  1065. n:=nth(eqordr,n1); % order of this equation
  1066. h:=simp!* 0;
  1067. for each e1 in xilist do
  1068. if (cadddr e1) and ((length cadddr e1) > n) then
  1069. % xi (=car e1) is of order n
  1070. h:=addsq(h,
  1071. if car e1 = 0 then simp!* 0
  1072. else <<n3:=mergedepli(n3,cadddr e1);
  1073. multsq(simp!* car e1,
  1074. simpdf {eqn,cadr e1})
  1075. >>
  1076. );
  1077. for each e2 in occli do
  1078. h:=addsq(h,
  1079. multsq(<<n4:=prolong(e2,xilist,etalist,nth(eqordr,n1),
  1080. truesub,subordinc,xlist);
  1081. vl:=mergedepli(vl,cdr n4);
  1082. car n4
  1083. >>,
  1084. simpdf {eqn,e2}
  1085. )
  1086. );
  1087. for each e2 in freelist do
  1088. <<
  1089. e1:=algebraic num lisp coeffn(prepsq h,e2,1);
  1090. if not zerop e1 then symcon:=e1 . symcon>>;
  1091. vl:=joinsublists(xlist . vl)$
  1092. for n2:=1:eqlen do
  1093. <<n4:=nth(lhslist,n2);
  1094. if not my_freeof(eqn,n4) then
  1095. symcon:=subst(cadr nth(truesub,n2), n4, symcon);
  1096. vl:=delete(n4,vl)
  1097. >>;
  1098. if symcon and (individual_ or (n1=eqlen)) then <<
  1099. flist:=callcrack(!*time,cpu,gc,lietrace_,symcon,
  1100. flist,vl,xilist,etalist)$
  1101. symcon :=car flist; xilist:=cadr flist;
  1102. etalist:=caddr flist; flist :=cadddr flist;
  1103. cpu:=time()$ gc:=gctime()$
  1104. >>
  1105. >>
  1106. >>;
  1107. %------------ Determining the full symmetry conditions
  1108. n1:=0;
  1109. vl:=nil;
  1110. for each eqn in eqlist do
  1111. <<n1:=n1+1;
  1112. if !*time then <<terpri()$
  1113. terpri()$terpri()$
  1114. write"=============== Full conditions for the ",n1,". equation" ;
  1115. >>;
  1116. n2:=cadr adddepli(eqn,revdylist);
  1117. n3:=n2; % n3 are the variables in the new condition
  1118. symcon:=(reval algebraic num lisp prepsq addsq(
  1119. <<h:=simp!* 0;
  1120. for each e1 in xilist do
  1121. h:=addsq(h,
  1122. if car e1 = 0 then simp!* 0
  1123. else <<n3:=mergedepli(n3,cadddr e1);
  1124. multsq(simp!* car e1,
  1125. simpdf {eqn,cadr e1})
  1126. >>
  1127. );
  1128. h
  1129. >>,
  1130. <<h:=simp!* 0;
  1131. for each e1 in n2 do
  1132. for each e2 in e1 do
  1133. h:=addsq(h,
  1134. multsq(<<n4:=prolong(e2,xilist,etalist,0,truesub,
  1135. 0,xlist );
  1136. n3:=mergedepli(n3,cdr n4);
  1137. car n4
  1138. >>,
  1139. simpdf {eqn,e2}
  1140. )
  1141. );
  1142. h
  1143. >> )) . symcon;
  1144. n3:=joinsublists(xlist . n3)$
  1145. for n2:=1:eqlen do
  1146. <<n4:=nth(lhslist,n2);
  1147. if not my_freeof(eqn,n4) then
  1148. symcon:=subst(cadr nth(truesub,n2), n4, symcon);
  1149. n3:=delete(n4,n3)
  1150. >>;
  1151. vl:=union(vl,n3);
  1152. if individual_ or (n1=eqlen) then <<
  1153. flist:=callcrack(!*time,cpu,gc,lietrace_,symcon,
  1154. flist,vl,xilist,etalist)$
  1155. symcon :=car flist; xilist:=cadr flist;
  1156. etalist:=caddr flist; flist :=cadddr flist;
  1157. cpu:=time()$ gc:=gctime()$
  1158. >>
  1159. >>;
  1160. eqn:=sb:=dylist:=e1:=e2:=n:=h:=deplist:=symord:=nil;%occurlist:=nil;
  1161. lisp(adjust_fnc:=oldadj);
  1162. %------- Calculation finished, simplification of the result
  1163. h:='LIST . append(for each el in xilist collect car el,
  1164. for each el in etalist collect car el );
  1165. %------- droping redundant constants or functions
  1166. if null symcon then
  1167. sb:=reval dropredundant(h,'LIST . flist,vl,list('LIST));
  1168. if sb then <<
  1169. flist:=cdr cadddr sb;
  1170. h:=caddr sb;
  1171. sb:=cadr sb;
  1172. e1:=nil
  1173. >>;
  1174. %------- absorbing numerical constants into free constants
  1175. h:=reval absorbconst(h,'LIST . flist);
  1176. if h then if sb then sb:=append(sb,cdr h)
  1177. else sb:='LIST . cdr h;
  1178. %------- doing the substitutions
  1179. if sb then <<
  1180. if print_ then <<terpri()$
  1181. write"Free constants and/or functions have been rescaled. ">>$
  1182. for each e1 in cdr sb do <<
  1183. xilist :=subst(caddr e1, reval cadr e1, xilist);
  1184. etalist:=subst(caddr e1, reval cadr e1, etalist);
  1185. symcon :=subst(caddr e1, reval cadr e1, symcon);
  1186. % h:=intern car explode cadr e1;
  1187. %write"h=",h;terpri()$
  1188. % if (h='x) or (h='X) then
  1189. % xilist :=subst(caddr e1, cadr e1, xilist) else
  1190. % if (h='e) or (h='E) or (h="e") or (h="E") then
  1191. % etalist:=subst(caddr e1, cadr e1, etalist) else
  1192. % rederr("One ansatz does not specify XI_ nor ETA_.")
  1193. >>;
  1194. >>;
  1195. %------- output
  1196. if length flist>1 then n:=t
  1197. else n:=nil;
  1198. terpri()$terpri()$
  1199. if null flist then write"No such symmetry does exist. "
  1200. else write"The symmetr",
  1201. if n then "ies are:" else "y is:";
  1202. terpri()$
  1203. xilist:=for each el in xilist collect
  1204. <<e1:=mkid( xi,second el);
  1205. for each e2 in fctargs(e1) do nodepend(e1,e2);
  1206. e1:=list('EQUAL,e1,reval car el);
  1207. e1>>;
  1208. etalist:=for each el in etalist collect
  1209. <<e1:=mkid(eta,second el);
  1210. for each e2 in fctargs(e1) do nodepend(e1,e2);
  1211. e1:=list('EQUAL,e1,reval car el);
  1212. e1>>;
  1213. %--- Backsubstitution of e.g. u`1`1 --> df(u,x,2)
  1214. for each e1 in ylist do depnd(e1,list(xlist));
  1215. on evallhseqp;
  1216. sb:=subdif1(cons('LIST,xlist),cons('LIST,ylist),jetord)$
  1217. algebraic(
  1218. sb:=for each e1 in sb join
  1219. for each e2 in e1 collect(rhs e2 = lhs e2));
  1220. off evallhseqp;
  1221. xicop :=cdr algebraic(sub(sb,cons('LIST, xilist)));
  1222. etacop:=cdr algebraic(sub(sb,cons('LIST,etalist)));
  1223. sb:=nil$
  1224. flcop:=flist;
  1225. n1:=0;
  1226. for each e1 in flcop do
  1227. <<n2:=cdr fargs e1;
  1228. if null n2 then n2:=not freeof(symcon,e1);
  1229. if null n2 then n2:=freeof(xicop,e1) and freeof(etacop,e1)$
  1230. if null n2 then <<
  1231. n1:=n1+1;
  1232. xi:=xicop;eta:=etacop;
  1233. for each e2 in flcop do
  1234. if e2 neq e1 then <<xi:=subst(0,e2,xi);eta:=subst(0,e2,eta)>>
  1235. else <<xi:=subst(1,e2,xi);eta:=subst(1,e2,eta)>>;
  1236. terpri()$write"-------- ",n1,". Symmetry:";terpri()$
  1237. for each e2 in xi do algebraic write reval e2;
  1238. for each e2 in eta do algebraic write reval e2;
  1239. xicop :=subst(0,e1,xicop );
  1240. etacop:=subst(0,e1,etacop);
  1241. flcop:=delete(e1,flcop);
  1242. depl!*:=delete(assoc(e1,depl!*),depl!*)$
  1243. >>;
  1244. >>;
  1245. if flcop neq flist then <<
  1246. terpri()$write"-------- ";terpri()$
  1247. >>;
  1248. if flcop then <<
  1249. if length flist>1 then n:=t
  1250. else n:=nil;
  1251. terpri()$
  1252. if flcop=flist then write"S"
  1253. else write"Further s";
  1254. write"ymmetr",if n then "ies:" else "y:"$
  1255. terpri()$
  1256. for each e1 in xicop do algebraic write reval e1;
  1257. for each e1 in etacop do algebraic write reval e1;
  1258. >>;
  1259. terpri()$
  1260. if flcop then
  1261. <<write"with ";fctprint cdr reval ('LIST . flcop)>>;
  1262. if null symcon then if flcop then
  1263. <<write" which ",if n then "are" else "is"," free. ";
  1264. terpri()>> else
  1265. else
  1266. <<h:=print_;print_:=500$
  1267. if print_ then
  1268. <<terpri()$
  1269. write"which still ",if n then "have" else "has"," to satisfy: ";
  1270. terpri()$
  1271. deprint symcon;
  1272. >> else
  1273. <<terpri()$
  1274. write"which ",if n then "have" else "has",
  1275. " to satisfy conditions. To see them set ";
  1276. terpri()$
  1277. write
  1278. "lisp(print_= max. number of terms of an equation to print);";
  1279. terpri()$
  1280. >>;
  1281. print_:=h
  1282. >>;
  1283. return list('LIST,'LIST . symcon,'LIST . append(xilist,etalist),
  1284. 'LIST . flist);
  1285. end$ % of liepde
  1286. endmodule$
  1287. end$