crack2.red 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403
  1. % Applications of CRACK
  2. %********************************************************************
  3. module decomposition$
  4. %********************************************************************
  5. % Routines for decomposition of PDE's
  6. % Author: Thomas Wolf
  7. % June 1991
  8. fluid '(fname_ nfct_);
  9. algebraic procedure decomp(problem,runmode);
  10. begin scalar i,j,k,de,m,n,x,y,yy,yyy,new!_d!_yk,as,sol,h1,h2,dep$
  11. lisp put('d!_y,'simpfn, 'simpiden)$
  12. lisp put('u!#,'simpfn, 'simpiden)$
  13. de:=first problem$ problem:=rest problem$
  14. y :=first problem$ problem:=rest problem$
  15. x :=first problem$ problem:=0$
  16. as:=first runmode$ runmode:=rest runmode$
  17. fl:=first runmode$ runmode:=0$
  18. symbolic write "Differential factorization of: "$
  19. lisp terpri()$
  20. write de$
  21. % order of the de
  22. n :=lisp highdiff(reval algebraic de, reval algebraic y,
  23. reval algebraic x)$
  24. k:=1; % factorization into a first-order ODE + ...
  25. clear d1!_,d2!_,d3!_;
  26. de:=rhs de - lhs de;
  27. for i:=2:n do <<de:=sub(df(y,x,i)=d!_y(i),de);
  28. as:=sub(df(y,x,i)=d!_y(i),as)>>;
  29. de:=sub(df(y,x)=d!_y(1),de);
  30. as:=sub(df(y,x)=d!_y(1),as);
  31. yy:=lisp if atom (yyy:=reval algebraic y) then yyy
  32. else car yyy;
  33. if (y neq yy) then << let y=yy; de:=de; as:=as; clear y; y:=yy >>;
  34. depend a!#,x;
  35. depend b!#,x;
  36. depend c!#,x;
  37. depend d!#,y;
  38. d!_y(k):=
  39. if as=1 then <<fl:={a!#,d!#}; a!#*d!# >> else
  40. if as=2 then <<fl:={a!#,b!#}; a!#*y+b!# >> else
  41. if as=3 then <<fl:={a!#,b!#}; a!#*y**d1!_+b!#*y >> else
  42. if as=4 then <<fl:={a!#,b!#,c!#}; a!#*y**2+b!#*y+c!# >> else
  43. as$
  44. vl:={y,x};
  45. for i:=1:(k-1) do vl:=.(d!_y(i),vl);
  46. new!_d!_yk:=d!_y(k)$
  47. write "The ansatz: ", df(y,x)," = ",d!_y(k);
  48. if df(yy,x) neq 0 then <<dep:=1;nodepend yy,x>> else dep:=0;
  49. for m:=k+1:n do
  50. d!_y(m):=df(d!_y(m-1),x)+df(d!_y(m-1),y)*d!_y(1)+
  51. for j:=1:k-1 sum df(d!_y(m-1),d!_y(j))*d!_y(j+1);
  52. de:=de;
  53. for m:=k:n do clear d!_y(m);
  54. sol:=crack({de},{},fl,vl); % first, because {a} is linear
  55. if sol={} then <<
  56. write"There exists no such factorization.";
  57. return {} >>
  58. else <<
  59. sol:=first sol;
  60. h1:=second sol;
  61. for each h2 in h1 do
  62. if symbolic (not atom algebraic h2) then
  63. if symbolic (equal(car algebraic h2,'equal)) then
  64. new!_d!_yk:=sub(h2,new!_d!_yk)$
  65. if dep=1 then depend yy,x;
  66. new!_d!_yk:=sub(d!_y(1)=df(y,x),new!_d!_yk);
  67. for i:=2:n do new!_d!_yk:=sub(d!_y(i)=df(y,x,i),new!_d!_yk);
  68. h1:=first sol$
  69. if h1 neq {} then
  70. <<write "Remaining conditions:";
  71. while h1 neq {} do <<write"0 = ",first h1;h1:=rest h1>> >>;
  72. !!arbconst:=0;
  73. h1:=df(y,x,k)-new!_d!_yk ;
  74. h2:=first odesolve(h1,y,x);
  75. if h1=h2 then write "The solution of ",df(y,x,k)," = ",new!_d!_yk
  76. else
  77. <<yyy:=mkid(lisp fname!_,lisp nfct!_);
  78. h2:=sub(arbconst(1)=yyy,h2);
  79. lisp(nfct!_:=add1 nfct!_);
  80. write "The solution ",h2>>;
  81. if length third sol<(n-k) then
  82. write "is a special solution of the original ODE" else
  83. if length first sol = 0 then
  84. write "is the general solution of the original ODE" else
  85. write "is a solution of the original ODE";
  86. h1:=first sol;
  87. return {h1,new!_d!_yk,third sol} >>
  88. end$
  89. symbolic procedure lesedec;
  90. begin scalar c;
  91. <<rds nil;wrs nil;
  92. terpri();write "Input: "$
  93. c:=xread(nil);
  94. if ifl!* then rds cadr ifl!*;
  95. if ofl!* then wrs cdr ofl!* >>;
  96. return c
  97. end$
  98. endmodule$
  99. %********************************************************************
  100. module firstintegral$
  101. %********************************************************************
  102. % Routines for finding first integrals of PDE's
  103. % Author: Thomas Wolf
  104. % June 1991
  105. fluid '(print_);
  106. algebraic procedure firint(problem,runmode);
  107. %de...das DGL-Problem, n...Ordnung der DGL, r...Grad des Ansatzes
  108. begin scalar de,n,x,y,yy,yyy,fl,vl,f!_new,a,sol,h1,h2,co,newfl,fi,dg,
  109. dep$
  110. symbolic put('d!_y,'simpfn,'simpiden)$
  111. de:=first problem$ problem:=rest problem$
  112. y:=first problem$ problem:=rest problem$
  113. x:=first problem$ problem:=0$
  114. fi:=first runmode$ runmode:=rest runmode$
  115. fl:=first runmode$ runmode:=rest runmode$
  116. dg:=first runmode$ runmode:=0$
  117. vl:={}$
  118. lisp terpri()$
  119. write "Determination of a first integral for: ";
  120. write de;
  121. n :=lisp highdiff(reval algebraic de, reval algebraic y,
  122. reval algebraic x)$
  123. de:=rhs de;
  124. for i:=2:n do <<de:=sub(df(y,x,i)=d!_y(i),de);
  125. fi:=sub(df(y,x,i)=d!_y(i),fi)>>;
  126. de:=sub(df(y,x)=d!_y(1),de);
  127. fi:=sub(df(y,x)=d!_y(1),fi);
  128. yy:=lisp if atom (yyy:=caaar caadr algebraic y) then yyy
  129. else car yyy;
  130. if (y neq yy) then << let y=yy; de:=de; fi:=fi; clear y; y:=yy >>;
  131. if freeof(de,d!_y(n)) then
  132. <<d!_y(n):=de;
  133. if fi=0 then begin
  134. fi:=polyans(n-1,dg,x,y,d!_y,h!_);
  135. fl:=second fi;
  136. fi:=first fi
  137. end;
  138. symbolic if print_ then
  139. algebraic write "of the type: ",sub(d!_y(1)=df(y,x),fi) ;
  140. if df(yy,x) neq 0 then <<dep:=1;nodepend yy,x>> else dep:=0;
  141. a:=df(fi,x)+df(fi,y)*d!_y(1)+
  142. for k:=1:n-1 sum (df(fi,d!_y(k))*d!_y(k+1));
  143. vl:=.(d!_y(n-1),vl);
  144. clear d!_y(n);
  145. sol:=crack({a},{},fl,vl); % first, because {a} is linear
  146. if sol={} then <<
  147. write"There exists no such first integral.";
  148. return {} >>
  149. else <<
  150. sol:=first sol;
  151. h1:=second sol;
  152. for each h2 in h1 do
  153. % if symbolic (not atom algebraic h2) then
  154. % if symbolic (equal(car algebraic h2,'equal)) then
  155. fi:=sub(h2,fi)$
  156. h1:=third sol;
  157. newfl:={};
  158. for each h2 in h1 do
  159. if (df(h2,y) eq 0) and (df(h2,x) eq 0) and (df(h2,d!_y 1) eq 0) then
  160. <<on ratarg;
  161. co:=coeffn(fi,h2,1);
  162. if freeof(co,x) and freeof(co,y) and freeof(co,d!_y 1) and
  163. deg(fi-co*h2,h2)=0 then fi:=sub(h2=0,fi)
  164. else newfl:=.(h2,newfl)>>;
  165. h1:=newfl;
  166. newfl:={};
  167. for each h2 in h1 do
  168. if (df(h2,y) eq 0) and (df(h2,x) eq 0) and (df(h2,d!_y 1) eq 0) then
  169. if df(fi/h2,h2)=0 then fi:=sub(h2=1,fi)
  170. else newfl:=.(h2,newfl);
  171. if freeof(fi,x) and freeof(fi,y) and freeof(fi,d!_y 1) then fi:=0;
  172. printco(first(sol));
  173. if dep=1 then depend yy,x;
  174. if fi neq 0 then
  175. <<co:=df(fi,d!_y 1);
  176. fi:=sub(d!_y(1)=df(y,x),fi);
  177. co:=sub(d!_y(1)=df(y,x),co);
  178. for i:=2:n do
  179. <<fi:=sub(d!_y(i)=df(y,x,i),fi);
  180. co:=sub(d!_y(i)=df(y,x,i),co)>>;
  181. write"A first integral is: ",fi;
  182. write"and an integrating factor: ",co;
  183. if (third sol neq {}) then
  184. <<lisp terpri();
  185. if (first sol neq {})
  186. then lisp write "functions and constants to be determined: "
  187. else lisp write "free constants: ";
  188. lisp fctprint(cdr reval algebraic newfl)>>
  189. >>
  190. else write"There exists no such first integral.";
  191. return {first sol,fi,newfl}>> >>
  192. else
  193. <<write "Implicit d.e. ! "$
  194. return {{},{},{}}>>
  195. end$
  196. algebraic procedure printco(sol);
  197. if (sol neq {}) then
  198. <<write "Remaining conditions:";
  199. while sol neq {} do <<write"0 = ",first sol;sol:=rest sol>> >>$
  200. endmodule$
  201. %********************************************************************
  202. module lagrangian$
  203. %********************************************************************
  204. % Routines for finding a Lagrangian for a given PDE
  205. % Author: Thomas Wolf
  206. % June 1991
  207. fluid '(nfct_ print_);
  208. symbolic operator deprint$
  209. symbolic operator newfct$
  210. symbolic operator freeoflist$
  211. algebraic procedure Hamilton(L,qlist,x)$
  212. comment:
  213. This is a procedure which for a given first order Lagrangian L in the
  214. unknown functions given in the list q of the variable x
  215. - calculates the velocities in terms of the corresponding generalized
  216. impulses p_ and the Hamiltonian H(p_,q,x),
  217. - formulates the corresponding Hamilton Jacobi equation for a
  218. for an action function S_.
  219. After execution the q's in qlist are scalars independent of x! ;
  220. begin
  221. scalar qcopy,i,j,q,dq,plist,n,dqlist,found,SF,sans,solved,H;
  222. symbolic put('p_,'simpfn,'simpiden)$ % p_(i) : general. impulses
  223. symbolic put('dq_,'simpfn,'simpiden)$ % dq(i) : dq/dx
  224. n:=length qlist; % the number of functions q
  225. % substitution of df(qi,x) by dq_(i) in the Lagrangian
  226. qcopy:=qlist;
  227. for i:=1:n do <<
  228. q:=first qcopy; qcopy:=rest qcopy;
  229. L:=sub(df(q,x)=dq_(i),L)>>;
  230. % expressing dq_(i) by the general. impulses p_(j) and the q's
  231. plist:={}; dqlist:={};
  232. for i:=1:n do <<plist:=.(df(L,dq_(i)) - p_(i), plist);
  233. dqlist:=.(dq_(i),dqlist)>>;
  234. dqlist:=solve(plist,dqlist);
  235. dq:=first dqlist;
  236. if symbolic(car algebraic(dq))=LIST then dqlist:=dq;
  237. if lisp(print_) then write"The velocities: ",dqlist;
  238. % Test for solubility:
  239. solved:=t;
  240. if length dqlist = 0 then solved:=nil
  241. else <<
  242. for i:=1:n do <<
  243. qcopy:=dqlist;
  244. found:=nil;
  245. while (not found) and (qcopy neq {}) do <<
  246. dq:=first qcopy; qcopy:=rest qcopy;
  247. if (lhs dq) = dq_(i) then found:=t >> >>;
  248. if found=nil then solved:=nil>>;
  249. if solved=nil then <<
  250. if lisp(print_) then
  251. write
  252. " The equations p_ = dL/d(dq/dx) could not be solved for the dq/dx.";
  253. return nil
  254. >> else <<
  255. % the Hamiltonian as a function of p_, q, x
  256. H := sub(dqlist, -L + for i:=1:n sum p_(i)*dq_(i));
  257. if lisp(print_) then <<
  258. write "The Hamiltonian with P_(i) as the canonical impulses: ";
  259. on factor,mcd;
  260. write "H = ",H;
  261. off factor,mcd
  262. >>;
  263. % The Hamiltonian-Jacobi equation
  264. HJ := H;
  265. SF:=first sepans(0,{},.(x,qlist),s);
  266. qcopy:=qlist;
  267. for i:=1:n do <<q:=first qcopy;qcopy:=rest qcopy;
  268. HJ:=sub(p_(i) = df(SF,q), HJ)>>;
  269. HJ := num(df(SF,x) + HJ);
  270. if lisp(print_) then <<
  271. write "The general Hamilton-Jacobi equation for the action S_:";
  272. write " 0 = ",HJ
  273. >>;
  274. % The q's of qlist are becomming independent of x
  275. qcopy:=qlist;
  276. while qcopy neq {} do <<
  277. nodepend first qcopy, x;
  278. qcopy:=rest qcopy >>;
  279. return {HJ, SF, H, dqlist}
  280. >>
  281. end$ % of Hamilton
  282. %----------------------------
  283. algebraic procedure drop_const(oldsoln, varlist, additive)$
  284. comment
  285. oldsoln is the output of a CRACK call. In all solutions functions
  286. which are independent of all elements of varlist are dropped from
  287. the list of free functions/constants and
  288. - set to zero if additive=t and they are additive or
  289. - set to 1 if additive=nil and they are multiplicative;
  290. begin
  291. scalar soln, sl, fncn, h1, h2, newfl, vcopy, constnt, v, fcopy,f1,co;
  292. soln := {};
  293. off mcd;
  294. while oldsoln neq {} do <<
  295. sl := first oldsoln; oldsoln := rest oldsoln;
  296. fncn := second sl;
  297. h1 := third sl;
  298. newfl:={};
  299. for each h2 in h1 do <<
  300. % is h2 constant ?
  301. vcopy := varlist;
  302. constnt := t;
  303. while constnt and (vcopy neq {}) do <<
  304. v := first vcopy; vcopy := rest vcopy;
  305. if not freeof(co,v) then constnt := nil
  306. >>;
  307. if constnt then
  308. if (not freeof(first sl, h2)) or freeof(fncn, h2)
  309. then constnt := nil;
  310. if constnt then <<
  311. % is the coefficient of h2 constant in all solved expressions
  312. % and occurs h2 only linear ?
  313. fcopy := fncn;
  314. while constnt and (fcopy neq {}) do <<
  315. f1 := rhs first fcopy; fcopy := rest fcopy;
  316. co:=coeffn(f1,h2,1);
  317. if (not freeof(co,h2)) or
  318. ( additive and (not freeof(f1 - co*h2, h2))) or
  319. ((not additive) and ((f1 - co*h2) neq 0))
  320. then constnt := nil;
  321. if constnt and additive then <<
  322. vcopy := varlist;
  323. while constnt and (vcopy neq {}) do <<
  324. v := first vcopy; vcopy := rest vcopy;
  325. if not freeof(co,v) then constnt := nil
  326. >>
  327. >>
  328. >>
  329. >>;
  330. if constnt then if additive then fncn := sub(h2=0, fncn)
  331. else fncn := sub(h2=1, fncn)
  332. else newfl := cons(h2, newfl)
  333. >>;
  334. soln := cons({first sl, fncn, newfl}, soln)
  335. >>;
  336. on mcd;
  337. return soln
  338. end$ % of drop_add_const
  339. %----------------------------
  340. algebraic procedure solve_HJ(L,qlist,x)$
  341. comment This Procedure
  342. - makes a separation ansatz for S:
  343. S(x,qi,Qj) = S1(x,q1,Qj) + S2(x,q2,Qj) +...+ Sn(x,qn,Qj), or
  344. S( qi,Qj) = S1( q1,Qj) + S2( q2,Qj) +...+ Sn( qn,Qj)
  345. if dL/dx = 0 or
  346. S(x,q) = S1(x) + S2(q) or
  347. S(x,q) = S1(x)*S2(q) + ...
  348. if qlist contains only one function q of x.
  349. - calls the package CRACK for solving the resulting conditions
  350. for the Si,
  351. - finds the general solution for qi(x) from
  352. dS/dQi = - Pi = constant (*)
  353. d .. partial derivative, D .. total derivative
  354. where the Qi are the (non-trivial and non-additive) constants of
  355. integration provided by the package CRACK when solving for Si where
  356. Pi are further constants of integration. The qi have to be solved
  357. algebraically from (*).
  358. (*) follows according to the general theory if one regards S(x,qi,Qj)
  359. as the generating function S(x,qi,Qj) of a canonical transformation
  360. such that after the transformation the new Hamiltonian is a function
  361. of Qi only such that DQi/Dt = 0 --> new Qj = constants -->
  362. new H = constant --> DPj/Dx = 0 -->
  363. new Pi = constant;
  364. begin
  365. scalar Ham, sans, a, SF, SFans, xcycl, SAnsatz, undet,
  366. clist, reslt, el1, el2, K_, fnlsys, xqlist;
  367. Ham := Hamilton(L,qlist,x);
  368. if Ham neq nil then <<
  369. SF := second Ham;
  370. % special simplified treatment if x is a cyclix variable
  371. if freeof(third Ham,x) then xcycl:=t
  372. else xcycl:=nil;
  373. % Chosing a suitable ansatz
  374. if length(qlist)=1 then
  375. if xcycl then sans:=sepans(8, qlist ,{},s) % S=K_*x + S2(q1)
  376. else sans:=sepans(8,cons(x,qlist),{},s) % S=S1(x) + S2(q1)
  377. else
  378. if xcycl then sans:=sepans(8,qlist, {},s)
  379. % S = K_*x + S1(q1) +...+ Sn(qn)
  380. else sans:=sepans(8,qlist,{x},s);
  381. % S = S1(q1,x) + ... + Sn(qn,x)
  382. if xcycl then begin
  383. K_:=newfct(c,nil,lisp nfct_);
  384. lisp(nfct_:=add1 nfct_);
  385. SAnsatz := K_*x + first sans;
  386. end else begin
  387. SAnsatz := first sans;
  388. end;
  389. % The Hamilton-Jacobi equation
  390. a:= sub(SF=SAnsatz, first Ham);
  391. if lisp(print_) then <<
  392. write "The ansatz for the action: S_ = ",SAnsatz;
  393. if xcycl then
  394. write " with ",K_,
  395. " = constant ( = H because ",x," is cyclic)";
  396. write "gives for the Hamilton-Jacobi equation:";
  397. write " 0 = ",a;
  398. write "which is to be solved.";
  399. >>;
  400. % Solving it and dropping additive constants
  401. sans := second sans;
  402. xqlist := .(x,qlist);
  403. if xcycl then sans:=.(K_, sans);
  404. reslt := drop_const(crack({a}, {}, sans, {}), xqlist, t);
  405. if reslt neq {} then <<
  406. % first because only one solution is expected for the linear HJ
  407. reslt := first reslt;
  408. undet := third reslt;
  409. if lisp(print_) then write "result = ",reslt;
  410. SAnsatz := sub(second reslt, SAnsatz);
  411. if lisp(print_) then write "The action S_ = ", SAnsatz;
  412. % Formulating the final solution by differentiating S
  413. fnlsys:={};
  414. clist:={}; % undet muss K_ enthalten
  415. % if xcycl then undet:=.(K_, undet);
  416. for each el1 in undet do
  417. if freeoflist(el1,xqlist) then clist:=.(el1,clist);
  418. for each el1 in undet do
  419. if (not freeof(sans,el1)) and
  420. freeof(clist,el1) and
  421. (not freeof(first reslt,el1)) then
  422. for each el2 in clist do depend el1,el2;
  423. for each el1 in clist do <<
  424. fnlsys:=.(newfct(c,nil,lisp nfct_)-df(SAnsatz,el1),fnlsys);
  425. lisp(nfct_:=add1 nfct_);
  426. >>;
  427. if lisp(print_) then <<
  428. write"The solution in implicit form is:";
  429. for each el1 in fnlsys do write"0 = ",el1$
  430. >>;
  431. % fnlsys:=solve(fnlsys,qlist);
  432. % if lisp(print_) and (fnlsys neq {}) then <<
  433. % write
  434. % "The solution in explicit form is (if SOLVE could solve it):";
  435. % for each el1 in fnlsys do write el1$
  436. % >>
  437. >>
  438. >>
  439. end$ % of solve_HJ
  440. %----------------------------
  441. algebraic procedure lagran(problem,runmode)$
  442. % sol = false : determination of the Lagrangian only
  443. % sol = true : also transformation to L = y^'2
  444. % returns return of lagfcn
  445. begin scalar de,n,fl,vl,lg,x,y,yy,yyy,loes,k,a,b,ll,h1,h2,dep$
  446. scalar imp,y!',ham,sf$ % for the Hamiltonian part
  447. symbolic put('d!_y,'simpfn,'simpiden)$
  448. de:=first problem$ problem:=rest problem$
  449. y :=first problem$ problem:=rest problem$
  450. x :=first problem$ problem:=0$
  451. lg:=first runmode$ runmode:=rest runmode$
  452. fl:=first runmode$ runmode:=0$
  453. vl:={};
  454. symbolic write "Determination of a Lagrangian L for:";
  455. lisp terpri()$
  456. write de$
  457. n :=lisp car reverse caaar caadr algebraic lhs de$
  458. if n eq x then n:=1;
  459. de:=rhs de;
  460. for i:=2:n do <<de:=sub(df(y,x,i)=d!_y(i),de);
  461. lg:=sub(df(y,x,i)=d!_y(i),lg)>>;
  462. de:=sub(df(y,x)=d!_y(1),de);
  463. lg:=sub(df(y,x)=d!_y(1),lg);
  464. yy:=lisp if atom (yyy:=caaar caadr algebraic y) then yyy
  465. else car yyy;
  466. if (y neq yy) then << let y=yy; de:=de; lg:=lg; clear y; y:=yy >>;
  467. if lg=0 then
  468. <<depend u!_,x,y;
  469. depend v!_,x,y;
  470. lg:=u!_*d!_y 1**2+v!_;
  471. fl:=append({u!_,v!_},fl)>>$
  472. if n>1 then vl:=.(d!_y(n-1),vl)$
  473. symbolic(if print!_ neq nil then
  474. algebraic write "The ansatz: L = ",sub(d!_y(1)=df(y,x),lg) )$
  475. if df(yy,x) neq 0 then <<dep:=1;nodepend yy,x>> else dep:=0;
  476. loes:=lagfcn(de,n,x,y,fl,vl,lg);
  477. lg:=second loes;
  478. if dep=1 then depend yy,x;
  479. if (lg eq 0) then write"No Lagrangian of this structure!" else
  480. <<on factor,mcd;
  481. lg := sub(d!_y(1)=df(y,x),lg)$
  482. write "The solution: L = ",lg$
  483. off factor; % ,mcd;
  484. if (first loes neq {}) then
  485. <<write "Remaining conditions: "$
  486. for each s in first loes do symbolic deprint list algebraic s>>
  487. else
  488. if nil then
  489. solve_HJ(lg,{y},x);
  490. >>;
  491. return loes
  492. end$ % of lagran
  493. %----------------------------
  494. algebraic procedure lagfcn(p,n,x,y,fl,vl,lg);
  495. %determines the Lagrangian
  496. %returns {{necessary eq.s},{suff. equ.s},Lagrangian,{free functions}}
  497. begin scalar h1,h2,newfl,co$
  498. h1:=df(lg,d!_y 1,x)+df(lg,d!_y 1,y)*d!_y 1-df(lg,y)+df(lg,d!_y 1,2)*p;
  499. p:= crack({h1},{},fl,vl)$ % first, because {h1} is linear
  500. p:=drop_const(p, {d!_y,y}, t); % dropping the divergenz term
  501. p:=drop_const(p, {d!_y,y,x}, nil); % dropping the multipli. constant
  502. if p={} then p:={{},{v_=0,u_=0},{}}
  503. else p:=first p;
  504. h1:=second p;
  505. for each h2 in h1 do
  506. if symbolic (not atom algebraic h2) then
  507. if symbolic (equal(car algebraic h2,'equal)) then
  508. lg:=sub(h2,lg)$
  509. return {first p,lg,third p}
  510. end$
  511. endmodule$
  512. load_package odesolve$
  513. load_package ezgcd$
  514. load_package factor$
  515. %********************************************************************
  516. module pdesymmetry$
  517. %********************************************************************
  518. % Routines for finding Symmetries for PDE's
  519. % Author: Thomas Wolf
  520. % August 1993
  521. fluid '(logoprint_ print_);
  522. % The algebraic operator NPRIMITIVE returns the
  523. % numerically-primitive part of any expression.
  524. % It is defined as a simpfn in EZGCD.
  525. symbolic operator ncontent$
  526. symbolic procedure ncontent p$
  527. % Return numeric content of expression p
  528. % based on simpnprimitive in ezgcd.
  529. << p := simp!* p;
  530. if polyzerop(numr p) then 0 else
  531. mk!*sq(numeric!-content numr p ./ numeric!-content denr p)
  532. >>$
  533. symbolic operator totdeg$
  534. symbolic procedure totdeg(p,f)$
  535. % Ordnung (total) der hoechsten Ableitung von f im Ausdruck p
  536. eval(cons('PLUS,ldiff1(car ldifftot(reval p,reval f),fctargs reval f)))$
  537. symbolic procedure diffreltot(p,q,v)$
  538. % liefert komplizierteren Differentialausdruck$
  539. if diffreltotp(p,q,v) then q
  540. else p$
  541. symbolic procedure diffreltotp(p,q,v)$
  542. % liefert t, falls p einfacherer Differentialausdruck, sonst nil
  543. % p, q Paare (liste.power), v Liste der Variablen
  544. % liste Liste aus Var. und Ordn. der Ableit. in Diff.ausdr.,
  545. % power Potenz des Differentialausdrucks
  546. begin scalar n,m$
  547. m:=eval(cons('PLUS,ldiff1(car p,v)))$
  548. n:=eval(cons('PLUS,ldiff1(car q,v)))$
  549. return
  550. if m<n then t
  551. else if n<m then nil
  552. else diffrelp(p,q,v)$
  553. end$
  554. symbolic procedure ldifftot(p,f)$
  555. % leading derivative total degree ordering
  556. % liefert Liste der Variablen + Ordnungen mit Potenz
  557. % p Ausdruck in LISP - Notation, f Funktion
  558. ldifftot1(p,f,fctargs f)$
  559. symbolic procedure ldifftot1(p,f,vl)$
  560. % liefert Liste der Variablen + Ordnungen mit Potenz
  561. % p Ausdruck in LISP - Notation, f Funktion, lv Variablenliste
  562. begin scalar a$
  563. a:=cons(nil,0)$
  564. if not atom p then
  565. if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,
  566. 'QUOTIENT,'DF,'EQUAL)) then
  567. % erlaubte Funktionen
  568. <<if (car p='PLUS) or (car p='TIMES) or (car p='QUOTIENT)
  569. or (car p='EQUAL) then
  570. <<p:=cdr p$
  571. while p do
  572. <<a:=diffreltot(ldifftot1(car p,f,vl),a,vl)$
  573. p:=cdr p>> >>
  574. else if car p='MINUS then
  575. a:=ldifftot1(cadr p,f,vl)
  576. else if car p='EXPT then % Exponent
  577. if numberp caddr p then
  578. <<a:=ldifftot1(cadr p,f,vl)$
  579. a:=cons(car a,times(caddr p,cdr a))>>
  580. else a:=cons(nil,0)
  581. % Poetenz aus Basis wird mit
  582. % Potenz multipliziert
  583. else if car p='DF then % Ableitung
  584. if cadr p=f then a:=cons(cddr p,1)
  585. % f wird differenziert?
  586. else a:=cons(nil,0)>> % sonst Konstante bzgl. f
  587. else if p=f then a:=cons(nil,1)
  588. % Funktion selbst
  589. else a:=cons(nil,0) % alle uebrigen Fkt. werden
  590. else if p=f then a:=cons(nil,1)$ % wie Konstante behandelt
  591. return a
  592. end$
  593. % ---------------------------------------------------------------------
  594. % Bei jedem totdiff-Aufruf pruefen, ob evtl. kuerzere dylist reicht
  595. % evtl die combidiff-Kette und combi nicht mit in dylist, sond. erst in
  596. % prolong jedesmal frisch generieren.
  597. symbolic operator desort;
  598. algebraic procedure nextdy(revx,xlist,dy)$
  599. % generates all first order derivatives of lhs dy
  600. % revx = reverse xlist; xlist is the list of variables;
  601. % dy the old derivative
  602. begin
  603. scalar x,n,ldy,rdy,ldyx,sublist;
  604. x:=first revx; revx:=rest revx;
  605. sublist:={};
  606. ldy:=lhs dy;
  607. rdy:=rhs dy;
  608. while lisp(not member(prepsq simp!* algebraic x,
  609. prepsq simp!* algebraic ldy))
  610. and (revx neq {}) do
  611. <<x:=first revx; revx:=rest revx>>;
  612. n:=length xlist;
  613. if revx neq {} then % dy is not the function itself
  614. while first xlist neq x do xlist:=rest xlist;
  615. xlist:=reverse xlist;
  616. % New higher derivatives
  617. while xlist neq {} do
  618. <<x:=first xlist;
  619. ldyx:=df(ldy,x);
  620. sublist:=cons(ldyx=mkid(mkid(rdy,!|),n), sublist);
  621. n:=n-1;
  622. xlist:=rest xlist
  623. >>;
  624. return sublist
  625. end$
  626. algebraic procedure subdif1(xlist,ylist,ordr)$
  627. % A list of lists of derivatives of one order for all functions
  628. begin
  629. scalar allsub,revx,i,el,oldsub,newsub;
  630. revx:=reverse xlist;
  631. allsub:={};
  632. oldsub:= for each y in ylist collect y=y;
  633. for i:=1:ordr do % i is the order of next substitutions
  634. <<oldsub:=for each el in oldsub join nextdy(revx,xlist,el);
  635. allsub:=cons(oldsub,allsub)
  636. >>;
  637. return allsub
  638. end$
  639. algebraic procedure subdif2(xlist,ylist,ordr)$
  640. % A list of for each function one list of lists of derivatives of one
  641. % order
  642. begin
  643. scalar allsub,revx,i,el,oldsub,newsub;
  644. revx:=reverse xlist;
  645. return
  646. for each y in ylist collect
  647. <<allsub:={};
  648. oldsub:={y=y};
  649. for i:=1:ordr do % i is the order of next substitutions
  650. <<oldsub:=for each el in oldsub join nextdy(revx,xlist,el);
  651. allsub:=cons(oldsub,allsub)
  652. >>;
  653. allsub
  654. >>
  655. end$
  656. symbolic operator combidif$
  657. symbolic procedure combidif(s)$
  658. % we want to extract the list of derivatives from
  659. begin scalar temp,ans,no,n1,done;
  660. s:=reval s; % to guarantee s is in true prefix form
  661. temp:=reverse explode s;
  662. while not null temp do
  663. <<n1:=<<no:=nil;
  664. while (not null temp) and (not eqcar(temp,'!|)) do
  665. <<no:=car temp . no;temp:=cdr temp>>;
  666. compress no
  667. >>;
  668. if (not fixp n1) then n1:=intern n1;
  669. ans:=n1 . ans;
  670. if eqcar(temp,'!|) then <<temp:=cdr temp; temp:=cdr temp>>;
  671. >>;
  672. return ans
  673. end$
  674. symbolic operator combi;
  675. symbolic procedure combi(ilist)$
  676. % ilist is a list of indexes (of variables of a partial derivative)
  677. % and returns length!/k1!/k2!../ki! where kj! is the multiplicity of j.
  678. begin
  679. integer n0,n1,n2,n3;
  680. n1:=1;
  681. ilist:=cdr ilist;
  682. while ilist do
  683. <<n0:=n0+1;n1:=n1*n0;
  684. if car ilist = n2 then <<n3:=n3+1; n1:=n1/n3>>
  685. else <<n2:=car ilist; n3:=1>>;
  686. ilist:=cdr ilist>>;
  687. return n1
  688. end$
  689. symbolic operator dif$
  690. symbolic procedure dif(s,n)$
  691. % e.g.: dif(fnc!|1!|3!|3!|4, 3) --> fnc!|1!|3!|3!|3!|4
  692. begin scalar temp,ans,no,n1,n2,done;
  693. s:=reval s; % to guarantee s is in true prefix form
  694. temp:=reverse explode s;
  695. n2:=reval n;
  696. n2:=explode n2;
  697. while (not null temp) and (not done) do
  698. <<n1:=<<no:=nil;
  699. while (not null temp) and (not eqcar(temp,'!|)) do
  700. <<no:=car temp . no;temp:=cdr temp>>;
  701. compress no
  702. >>;
  703. if (not fixp n1) or ((fixp n1) and (n1 leq n)) then
  704. <<ans:=nconc(n2,ans); ans:='!| . ans; ans:='!! . ans; done:=t>>;
  705. ans:=nconc(no,ans);
  706. if eqcar(temp,'!|) then <<ans:='!| . ans; ans:='!! . ans;
  707. temp:=cdr temp; temp:=cdr temp>>;
  708. >>;
  709. return intern compress nconc(reverse temp,ans);
  710. end$
  711. symbolic operator totdif;
  712. symbolic procedure totdif(s,x,n,dylist)$
  713. % total derivative of s(x,dylist) w.r.t. x which is the n'th variable
  714. begin
  715. scalar tdf,el1,el2;
  716. tdf:=simpdf {s,x};
  717. <<dylist:=cdr dylist;
  718. while dylist do
  719. <<el1:=cdar dylist;dylist:=cdr dylist;
  720. while el1 do
  721. <<el2:=car el1;el1:=cdr el1;
  722. tdf:=addsq(tdf ,multsq( simp!* dif(el2,n), simpdf {s,el2}))
  723. >>
  724. >>
  725. >>;
  726. return prepsq tdf
  727. end$
  728. symbolic operator totdiff$
  729. symbolic procedure totdiff(s,n,dysublist)$
  730. % total derivative of s(x,dylist) w.r.t. the n'th x-variable and
  731. % using only highest derivatives
  732. begin
  733. scalar tdf,el2;
  734. tdf:=simp!* 0;
  735. dysublist:=cdr dysublist;
  736. while dysublist do
  737. <<el2:=car dysublist;dysublist:=cdr dysublist;
  738. tdf:=addsq(tdf ,multsq( simp!* dif(el2,n), simpdf {s,el2}))
  739. >>;
  740. return prepsq tdf
  741. end$
  742. algebraic procedure depnd(y,xlist)$
  743. for each xx in xlist do
  744. for each x in xx do depend y,x$
  745. algebraic procedure transeq(eqn,xlist,ylist,sb)$
  746. <<for each el1 in sb do eqn:=sub(el1,eqn);
  747. for each el1 in ylist do
  748. for each el2 in xlist do nodepend el1,el2;
  749. eqn>>$
  750. algebraic procedure dirdiv(problem,runmode)$
  751. comment
  752. problem ~ {eqn % equation
  753. { y1, y2, ...}, % functions
  754. { x1, x2, ...} } % variables
  755. runmode ~ {ansatz, flist}
  756. ansatz=nil then
  757. standard ansatz:
  758. H_(all variables + all functions + all derivatives < ordr.)
  759. v_x1, v_x2, ..., v_(n+1) (all variables)
  760. else
  761. ansatz={H_=...,v_x1=...,v_x2=...}
  762. flist ={unknown functions in ansatz}
  763. ansatz: equ = v_(n+1) + for all i sum v_xi*df(h_,xi);
  764. begin
  765. scalar sb,el1,el2,dy1list,dy2list,flist,eqlist,h,
  766. xlist, ylist, ordr, ansatz, cpu, gc;
  767. cpu:=lisp time()$ gc:=lisp gctime()$
  768. eqn := first problem$
  769. ylist :=second problem$
  770. xlist := third problem$
  771. ansatz:= first runmode$
  772. flist :=second runmode$
  773. problem:=runmode:=0;
  774. lisp(<<
  775. write "----------------------------------------------------",
  776. "----------------------"$ terpri()$terpri()$
  777. write"This is DIRDIV - a program for writing a PDE as a directional ";
  778. write"derivative with a vector depending only on the independent ",
  779. "variables"$
  780. terpri()>>);
  781. write "The PDE under investigation is :";
  782. write"0 = ",eqn;
  783. write "for the function(s) : ";
  784. lisp(<<terpri()$fctprint cdr reval algebraic ylist;
  785. terpri()$terpri()>>);
  786. ordr:=0;
  787. for each e1 in ylist do
  788. <<n:=totdeg(eqn,e1);
  789. if n>ordr then ordr:=n>>;
  790. % Generating a substitution list and doing the substitutions
  791. % and Functions of ylist become variables
  792. sb:=subdif1(xlist,ylist,ordr)$
  793. eqn:=transeq(eqn,xlist,ylist,sb);
  794. % Lists of partial derivatives
  795. dy1list:=for each el2 in first sb collect rhs el2;
  796. dy2list:=ylist . for each el1 in rest sb collect
  797. for each el2 in el1 collect rhs el2;
  798. % Generating the equations
  799. depnd(h!_,xlist . dy2list);
  800. if ansatz eq nil then flist:={h!_};
  801. n:=1;
  802. for each el1 in xlist do
  803. <<h:=mkid(v!_,el1);
  804. depnd(h,{xlist});
  805. if ansatz eq nil then flist:=h . flist;
  806. eqn:=eqn-h*totdif(h!_,el1,n,dy2list);
  807. n:=n+1
  808. >>;
  809. h:=mkid(v!_,n);
  810. depnd(h,{xlist});
  811. if ansatz eq nil then flist:=h . flist;
  812. eqn:=eqn-h;
  813. eqlist:=for each el1 in dy1list collect
  814. <<h:=coeffn(eqn,el1,1);
  815. eqn:=eqn-h*el1;h>>;
  816. eqlist:=eqn . eqlist;
  817. % Test whether eqn is quasi-linear
  818. if
  819. (for each el1 in dy1list product
  820. if not freeof(eqlist,el1) then 0 else 1)=0
  821. then return <<write"The equation is not quasilinear! ";
  822. for each el1 in ylist do depnd(el1,{xlist});
  823. {}>>;
  824. if ansatz neq nil then eqlist:=sub(ansatz,eqlist);
  825. sb:=l1:=el2:=dy1list:=dy2list:=h:=0;
  826. eqlist:=crack(eqlist,{},flist,{});
  827. for each el1 in ylist do depnd(el1,{xlist});
  828. return eqlist
  829. end$
  830. symbolic operator drop$
  831. symbolic procedure drop(a,vl)$
  832. % liefert summe aller terme aus a, die von elementen von vl abhaengen
  833. begin scalar b$
  834. if not((pairp a) and (car a='PLUS)) then b:=a
  835. else
  836. <<vl:=cdr vl; % because vl is an algebraic list
  837. for each c in cdr a do
  838. if not freeoflist(c,vl) then b:=cons(c,b)$
  839. if b then b:=cons('PLUS,reverse b)>>$
  840. return b$
  841. end$
  842. symbolic operator etamn;
  843. symbolic procedure etamn(u,indxlist,xilist,etalist,revdylist,
  844. contact,full)$
  845. % determines etamn recursively
  846. % If length(indxlist)=k then it is assumed that etamn contains at most
  847. % k'th order derivatives, i.e. in revdylist only derivatives up to k'th
  848. % order need to be included. Exception: contact symmetries and k=0 then
  849. % still first oder derivatives are included.
  850. begin
  851. scalar etam,x,h1,h2,ulist,el,r,cplist,pneta;
  852. return
  853. if (length indxlist)<2 then
  854. <<cplist:=etalist;
  855. while u neq caddar cplist do cplist:=cdr cplist;
  856. pneta:=car cplist; % = (LIST,eta_yi,yi)
  857. if null indxlist then cdr pneta
  858. else
  859. <<ulist:=nil;
  860. cplist:=xilist;
  861. for h1:=1:(car indxlist)-1 do cplist:=cdr cplist;
  862. x:=cddar cplist; % e.g. x := (v3,3)
  863. r:=simp!*
  864. if contact
  865. then totdif(cadr pneta,car x,cadr x, 'LIST . revdylist)
  866. else
  867. if full
  868. then totdif(cadr pneta,car x,cadr x, 'LIST . cdr revdylist)
  869. else totdiff(cadr pneta,cadr x,cadr revdylist);
  870. cplist:=xilist;
  871. while cplist do
  872. <<el:=cdar cplist; % e.g. el=(xi_z,z,3)
  873. cplist:=cdr cplist;
  874. h1:=dif(u,caddr el);
  875. ulist:=h1 . ulist;
  876. r:=subtrsq(r, multsq(simp!* h1,simp!*
  877. if contact
  878. then totdif(car el,car x,cadr x, 'LIST . revdylist)
  879. else if full then
  880. totdif(car el,car x,cadr x, 'LIST . cdr revdylist)
  881. else totdiff(car el,cadr x,cadr revdylist) ))
  882. >>;
  883. % (if not full then drop(r,'LIST . car revdylist) else r) .
  884. % (reverse ulist)
  885. prepsq r . (reverse ulist)
  886. >>
  887. >> else
  888. <<etam:=etamn(u, cdr indxlist, xilist, etalist,cdr revdylist,
  889. contact,full);
  890. ulist:=nil;
  891. cplist:=xilist;
  892. for h1:=1:(car indxlist)-1 do cplist:=cdr cplist;
  893. x:=cddar cplist; % e.g. x := (v3,3)
  894. r:=simp!*
  895. if full then totdif(car etam,car x,cadr x,
  896. 'LIST . cdr revdylist)
  897. else totdiff(car etam,cadr x,cadr revdylist);
  898. etam:=cdr etam;
  899. cplist:=xilist;
  900. while cplist do
  901. <<el:=cadar cplist; % e.g. el=xi_z
  902. cplist:=cdr cplist;
  903. h1:=dif(car etam,car indxlist); % e.g. h1:=u!|i!|m!
  904. etam:=cdr etam;
  905. ulist:=h1 . ulist;
  906. r:=subtrsq(r, multsq(simp!* h1,simp!*
  907. if full then totdif(el,car x,cadr x,'LIST . cdr revdylist)
  908. else totdiff(el,cadr x,cadr revdylist) ))
  909. >>;
  910. % (if not full then drop(r,'LIST . car revdylist) else r) .
  911. % (reverse ulist)
  912. prepsq r . (reverse ulist)
  913. >>
  914. end$ % of etamn
  915. symbolic operator prolong;
  916. symbolic procedure prolong(uik,xilist,etalist,revdylist,minord,
  917. contact)$
  918. begin
  919. scalar indxlist, u, full, l1, l2, i;
  920. indxlist:=combidif(uik);
  921. u:=car indxlist; indxlist:=cdr indxlist;
  922. revdylist:=cdr revdylist;
  923. l1:=length(indxlist);
  924. l2:=length(revdylist)-1;
  925. for i:=1:(l2-l1) do revdylist:=cdr revdylist;
  926. % revdylist does not need higher derivatives than of order l1
  927. if minord=0 then full:=t
  928. else full:=nil;
  929. return (car etamn(u,indxlist,cdr xilist,cdr etalist,revdylist,contact,
  930. full))
  931. end$ % of prolong
  932. algebraic procedure liepde(problem,runmode)$
  933. comment
  934. problem ~ {{eq1,eq2, ...}, % equations
  935. { y1, y2, ...}, % functions
  936. { x1, x2, ...} } % variables
  937. runmode ~ {symord, ansatz, flist}
  938. if symord=nil then default order of symmetry, i.e.
  939. if (one function ) and
  940. (only one equation ) and
  941. (order of equation > 1 ) and
  942. ((>1 variable) or (order>2))
  943. then symord:=1 (contact s.)
  944. else symord:=0 (point s.)
  945. else symord determines the differential order of xi,
  946. eta but must not exceed 0 if more than one
  947. dependent variable v
  948. if ansatz=nil then default ansatz, i.e. xi, eta are functions
  949. of xi, yj and derivatives of yj of order upto symord
  950. else if point symm. then ansatz has to have the form
  951. {xi!_x1=...,...,eta!_y3=...} else
  952. if contact- or higher order symm. then ansatz has
  953. form
  954. {spot!_=...}
  955. flist ={unknown functions in ansatz} ;
  956. begin
  957. scalar eqlist, ylist, xlist, xilist, etalist, eqn, sb,
  958. dylist, e1, e2, n, n1,
  959. n2, n3, symcon, h, flist, deplist, symord, freelist,
  960. minord, dylen,
  961. eqlen, subdy, ordr, allsub, truesub, eqcopy1, eqcopy2,
  962. dycopy, vl,
  963. occurlist, revdylist, ansatz, cpu, gc, contact;
  964. cpu:=lisp time()$ gc:=lisp gctime()$
  965. %--------- extracting input data
  966. eqlist:= first problem;
  967. if lisp(atom algebraic eqlist) then eqlist:={eqlist} else
  968. if lisp(car algebraic eqlist neq 'LIST) then eqlist:={eqlist};
  969. ylist :=second problem;
  970. if lisp(atom algebraic ylist) then ylist:={ylist} else
  971. if lisp(car algebraic ylist neq 'LIST) then ylist:={ylist};
  972. xlist := third problem;
  973. if lisp(atom algebraic xlist) then xlist:={xlist} else
  974. if lisp(car algebraic xlist neq 'LIST) then xlist:={xlist};
  975. symord:= first runmode$
  976. ansatz:=second runmode$
  977. flist := third runmode$
  978. problem:=runmode:=0;
  979. eqlist:=for each e1 in eqlist collect
  980. if lisp(atom e1) then e1 else
  981. if lisp(car e1 = 'EQUAL) then lhs e1 - rhs e1
  982. else e1;
  983. if length eqlist > 1 then eqlist:=desort eqlist;
  984. %--------- initial printout
  985. lisp(if print_ and logoprint_ then <<
  986. write "-----------------------------------------------",
  987. "---------------------------"$ terpri()$terpri()$
  988. write
  989. "This is LIEPDE - a program for calculating infinitesimal symmetries";
  990. write "of single ODEs/PDEs and ODE/PDE - systems"; terpri()
  991. >> else terpri());
  992. write "The ODE/PDE (-system) under investigation is :";
  993. for each e1 in eqlist do write"0 = ",e1;
  994. write "for the function(s) : ";
  995. lisp(<<terpri()$fctprint cdr reval algebraic ylist;
  996. terpri()$terpri()>>);
  997. %--------- initializations
  998. ordr:=0;
  999. for each e1 in eqlist do
  1000. for each e2 in ylist do
  1001. <<n:=totdeg(e1,e2);
  1002. if n>ordr then ordr:=n>>;
  1003. if symord and (length ylist > 1) and (symord > 0) then
  1004. <<symord:=0;
  1005. write"Only point symmetries are determined if more than one",
  1006. "dependent variable!";
  1007. if ansatz then <<write"Restart with symord=0";halt>>
  1008. >>;
  1009. if symord eq nil then
  1010. if (length ylist = 1 ) and
  1011. ((length xlist > 1) or (ordr>2)) and
  1012. (ordr>1 ) and
  1013. (length(eqlist)=1 ) then symord:=1
  1014. else symord:=0;
  1015. if symord>0 then contact:=t
  1016. else contact:=nil;
  1017. sb:=subdif1(xlist,ylist,ordr)$
  1018. eqlist:=%for each eqn in eqlist collect
  1019. transeq(eqlist,xlist,ylist,sb);
  1020. dylist:=ylist . reverse for each e1 in sb collect
  1021. for each e2 in e1 collect e3:=rhs e2;
  1022. revdylist:=reverse dylist; % dylist with decreasing order
  1023. vl:=append(xlist,for each e1 in dylist join e1);
  1024. deplist:=for n:=0:symord collect part(dylist,n+1);
  1025. % list of xi-, eta-variab.
  1026. if not ansatz then flist:={};
  1027. if not contact then <<
  1028. n:=0;
  1029. xilist :=for each e1 in xlist collect
  1030. <<n:=n+1;
  1031. h:=mkid(xi!_ ,e1);
  1032. depnd(h,xlist . deplist);
  1033. if not ansatz then flist:=h . flist;
  1034. {h,e1,n}>>;
  1035. n:=0;
  1036. etalist:=for each e1 in ylist collect
  1037. <<n:=n+1;
  1038. h:=mkid(eta!_,e1);
  1039. depnd(h,xlist . deplist);
  1040. if not ansatz then flist:=h . flist;
  1041. {h,e1}>>
  1042. >> else <<
  1043. n1:=spot!_;
  1044. depnd(n1,xlist . deplist);
  1045. if ansatz eq nil then flist:=n1 . flist;
  1046. e2:=-n1;
  1047. n:=0;
  1048. xilist:= for each e1 in xlist collect
  1049. <<n:=n+1;
  1050. h:=dif(first ylist,n);
  1051. e2:=e2+df(n1,h)*h;
  1052. {df(n1,h),e1,n}
  1053. >>;
  1054. etalist:={{e2,first ylist}}
  1055. %;write"xilist=",xilist," etalist=",etalist
  1056. >>;
  1057. if ansatz neq nil then <<xilist:=sub(ansatz,xilist);
  1058. etalist:=sub(ansatz,etalist)>>;
  1059. % Determining a substitution list for highest derivatives from eqlist
  1060. % Substitutions may not be optimal if starting system is not in
  1061. % standard form
  1062. comment: Counting in how many equations each highest
  1063. derivative occurs. Those which do not occur allow Stephani-Trick,
  1064. those which do occur once and there linearly are substituted by that
  1065. equation.
  1066. Because one derivative shall be assigned it must be one of
  1067. the highest derivatives. It could be a lower order derivative
  1068. if substitution is done only finally before solving the
  1069. determining system which would be enough for point symmetries.
  1070. Each equation must be used only once
  1071. Each derivative must be substituted by only one equation
  1072. At first determining the number of occurences of each highest
  1073. derivative.
  1074. If SUB is used for substitution then derivatives could come in
  1075. which are already substituted before. If LET is used, infinite loops
  1076. can occur. ;
  1077. eqcopy1:=eqlist;
  1078. eqlen:=length eqlist;
  1079. dycopy:=part(dylist,length dylist); % the highest derivatives
  1080. dylen:=length dycopy;
  1081. occurlist:={};
  1082. freelist:={};
  1083. allsub:={};
  1084. truesub:={};
  1085. for n1:=1:dylen do
  1086. <<e1:=part(dycopy,n1);
  1087. n2:=0; % number of equations in which the derivative e1 occurs
  1088. subdy:={};
  1089. for n3:=1:eqlen do
  1090. if not freeof(part(eqlist,n3),e1) then
  1091. <<n2:=n2+1;
  1092. eqn:=part(eqcopy1,n3);
  1093. if eqn neq 0 then
  1094. <<e2:=coeff(eqn,e1);
  1095. if hipow!*=1 then
  1096. subdy:={n1,n3,e1 = - first e2/second e2} . subdy
  1097. >>
  1098. >>;
  1099. if n2=0 then freelist:=e1 . freelist else
  1100. <<occurlist:=e1 . occurlist;
  1101. if subdy neq {} then if n2=1 then
  1102. <<h:=first subdy;
  1103. truesub:=(third h) . truesub;
  1104. dycopy:=part(dycopy,n1):=0;
  1105. eqcopy1:=part(eqcopy1,second(h)):=0>>
  1106. else allsub:=append(subdy,allsub)
  1107. >>
  1108. >>;
  1109. % Taking the remaining known substitutions
  1110. eqn:=h:=subdy:=0;
  1111. for each subdy in allsub do
  1112. if (part( dycopy, first subdy) neq 0) and
  1113. (part(eqcopy1,second subdy) neq 0) then
  1114. <<truesub:=(third subdy) . truesub;
  1115. dycopy :=part( dycopy, first subdy):=0;
  1116. eqcopy1:=part(eqcopy1,second subdy):=0>>;
  1117. allsub:=0;
  1118. % To get the remaining unused equations for substitution as eqcopy2
  1119. % one could
  1120. % eqcopy2:={};
  1121. % for each e1 in eqcopy1 do if e1 neq 0 then eqcopy2:=e1 . eqcopy2;
  1122. eqcopy1:=0;dycopy:=0;
  1123. % Determining first short determining equations and solving them
  1124. symcon:={};
  1125. if freelist neq {} then
  1126. for each eqn in eqlist do
  1127. <<eqn:=drop(eqn,first revdylist);
  1128. %dropping all terms without a highest deriv.
  1129. minord:=(length dylist) - 1;
  1130. % Derivatives of freelist cannot be substituted --> no substitution
  1131. h:=for each e2 in occurlist sum
  1132. if freeof(eqn,e2) then 0
  1133. else prolong(e2,xilist,etalist,revdylist,minord,
  1134. contact)
  1135. * df(eqn,e2);
  1136. for each e2 in freelist do <<e1:=coeffn(h,e2,1);
  1137. if e1 neq 0 then symcon:=e1 . symcon>>;
  1138. if lisp(!*time) then
  1139. write "time to formulate conditions: ", lisp time() - cpu,
  1140. " ms GC time : ", lisp gctime() - gc," ms"$
  1141. h:=first crack(symcon,{},flist,vl);
  1142. cpu:=lisp time()$
  1143. gc:=lisp gctime()$
  1144. % FIRST because the homog. system has at least one and at most
  1145. % one solution
  1146. % Assigning or updating the xi's and eta's:
  1147. symcon:=first h;
  1148. xilist :=sub(second h,xilist);
  1149. etalist:=sub(second h,etalist);
  1150. flist:=third h;
  1151. if lisp(print_ eq nil) then
  1152. <<write"";
  1153. write"Remaining free functions after the last CRACK-run:";
  1154. lisp(fctprint cdr reval algebraic flist);write"">>;
  1155. >>;
  1156. %------------ Determining the full symmetry conditions
  1157. minord:=0;
  1158. h:=1;
  1159. for each eqn in eqlist do
  1160. if h neq {} then
  1161. <<symcon:=((for each e1 in xilist sum first e1 * df(eqn,second e1)) +
  1162. for each e1 in dylist sum
  1163. for each e2 in e1 sum if freeof(eqn, e2) then 0
  1164. else
  1165. prolong(e2,xilist,etalist,revdylist,minord,contact) *
  1166. df(eqn,e2)
  1167. ) . symcon;
  1168. n:=0;
  1169. symcon:=sub(truesub,symcon);
  1170. if lisp(!*time) then
  1171. write "time to formulate conditions: ", lisp time() - cpu,
  1172. " ms GC time : ", lisp gctime() - gc," ms"$
  1173. h:=crack(symcon,{},flist,vl);
  1174. cpu:=lisp time()$ gc:=lisp gctime()$
  1175. if h neq {} then
  1176. <<h:=first h;
  1177. symcon:=first h;
  1178. xilist :=sub(second h,xilist);
  1179. etalist:=sub(second h,etalist);
  1180. flist:=third h;
  1181. if nil and lisp(print_ eq nil) then
  1182. <<write"";
  1183. write"Remaining free functions after the last CRACK-run:";
  1184. lisp(fctprint cdr reval algebraic flist);write"">>;
  1185. >>
  1186. >>;
  1187. eqn:=sb:=dylist:=e1:=e2:=n:=h:=deplist:=occurlist:=symord:=0;
  1188. %------- Calculation finished
  1189. if h neq {} then
  1190. <<% Dropping free funct.s/const. which do not occur in the xi's
  1191. % or eta's or
  1192. % remaining equations, absorbing numerical constants into free
  1193. % constants
  1194. h:={};
  1195. for each e1 in flist do
  1196. if not freeof({xilist,etalist,symcon},e1) then h:=e1 . h;
  1197. flist:=h;
  1198. for each e1 in flist do <<
  1199. n1:=nil;
  1200. for each e2 in append(xilist,etalist) do <<
  1201. n:=coeffn(first e2,e1,1);
  1202. if n neq 0 then
  1203. if n1=nil then <<n1:=num n; n2:=den n>>
  1204. else <<
  1205. n:=ncontent(n);
  1206. n1:=gcd(n1,num(n));
  1207. n2:=gcd(n2,den(n))
  1208. >>
  1209. >>;
  1210. if n1 then
  1211. <<xilist :=sub(e1=e1*n2/n1,xilist);
  1212. etalist:=sub(e1=e1*n2/n1,etalist);
  1213. symcon :=sub(e1=e1*n2/n1,symcon)
  1214. >>
  1215. >>;
  1216. %-------- output
  1217. write"The symmetries are: ";
  1218. xilist:=for each el in xilist collect
  1219. <<e1:=mkid( xi!_,second el); e1:= e1 = first el;write e1;e1>>;
  1220. etalist:=for each el in etalist collect
  1221. <<e1:=mkid(eta!_,second el); e1:= e1 = first el;write e1;e1>>;
  1222. lisp(terpri())$
  1223. if flist neq {} then <<
  1224. write"with constants/functions: ";
  1225. lisp(fctprint cdr reval algebraic flist);write"">>;
  1226. if symcon={} then if flist neq {} then write"which are free." else
  1227. else
  1228. if lisp(print_) then
  1229. <<write"which still have to satisfy: ";
  1230. lisp(deprint cdr algebraic symcon);
  1231. >> else
  1232. <<write"which have to satisfy conditions. To see them set ";
  1233. write
  1234. "lisp(print_:= max. number of terms of an equation to print);"
  1235. >>
  1236. >>;
  1237. for each e1 in ylist do depnd(e1,{xlist});
  1238. return {symcon,xilist,etalist,flist}
  1239. end$ % of liepde
  1240. endmodule$
  1241. end$ % of file