crint.red 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919
  1. %*********************************************************************
  2. module integration$
  3. %*********************************************************************
  4. % Routines for integration of pde's
  5. % Author: Thomas Wolf, Andreas Brand
  6. % 1993 1995
  7. %
  8. % $Id: crint.red,v 1.13 1998/06/25 18:21:25 tw Exp tw $
  9. %
  10. symbolic procedure ldlist(p,f,vl)$
  11. % provides a reverse list of leading derivatives of f in p, vl is list
  12. % of variables
  13. begin scalar a$
  14. if not atom p then
  15. if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,'QUOTIENT,'DF,'EQUAL))
  16. then <<
  17. if (car p='PLUS) or (car p='TIMES) or
  18. (car p='QUOTIENT) or (car p='EQUAL) then
  19. <<p:=cdr p$
  20. while p do
  21. <<a:=diffincl(a,ldlist(car p,f,vl))$
  22. p:=cdr p>>
  23. >> else
  24. if car p='MINUS then a:=ldlist(cadr p,f,vl) else
  25. if car p='EXPT then % if numberp caddr p then
  26. a:=ldlist(cadr p,f,vl) else % fuehrende Abl. aus der Basis
  27. % else a:=nil
  28. if car p='DF then if cadr p=f then
  29. <<p:=cddr p;
  30. while vl do
  31. <<a:=cons(dfdeg(p,car vl),a);
  32. vl:=cdr vl>>;
  33. a:=list a
  34. >>
  35. >>$
  36. return a
  37. end$
  38. symbolic procedure diffincl(a,b)$
  39. % a,b are lists of leading derivatives which are to be united
  40. begin
  41. scalar p;
  42. while a and b do
  43. <<a:=ddroplow(a,car b);
  44. if car a then p:=cons(car a,p);
  45. a:=cdr a;
  46. b:=cdr b>>;
  47. return
  48. if null a then if p then nconc(p,b)
  49. else b
  50. else if p then a:=nconc(p,a)
  51. else a
  52. end$
  53. symbolic procedure ddroplow(a,cb)$
  54. % loescht Elemente von a, von denen cb eine Ableitung ist, loescht cb,
  55. % wenn ein Element von a eine Ableitung von cb ist
  56. begin
  57. scalar h;
  58. return
  59. if null a then list(cb)
  60. else
  61. <<h:=compdiffer(car a,cb);
  62. if numberp(h) then if h>0 then cons(nil,a) % car a=df(cb,..
  63. else ddroplow(cdr a,cb) % cb=df(car a,..
  64. else <<h:=ddroplow(cdr a,cb); % neither
  65. cons(car h,cons(car a,cdr h))>>
  66. >>
  67. end$
  68. symbolic procedure compdiffer(p,q)$
  69. % finds whether p is a derivative of q or q of p or neither
  70. begin
  71. scalar p!>q,q!>p;
  72. while p and ((null p!>q) or (null q!>p)) do
  73. <<if car p>car q then p!>q:=t else % compare orders of derivatives
  74. if car p<car q then q!>p:=t;
  75. p:=cdr p;q:=cdr q
  76. >>;
  77. return
  78. if q!>p then if p!>q then nil % neither
  79. else 0 % q is derivative of p
  80. else if p!>q then 2 % p is derivative of q
  81. else 1 % p equal q
  82. end$
  83. symbolic procedure ldintersec(a)$
  84. % determines the intersection of derivatives in the list a
  85. begin
  86. scalar b;
  87. return
  88. if null a then nil else
  89. <<b:=car a;a:=cdr a;
  90. while a do
  91. <<b:=isec(b,car a)$
  92. a:=cdr a
  93. >>;
  94. b
  95. >>
  96. end$
  97. symbolic procedure isec(ca,b)$
  98. % determines the minimum derivatives between ca and b
  99. begin
  100. scalar newb;
  101. while ca do
  102. <<newb:=cons(if car b<car ca then car b else car ca, newb);
  103. ca:=cdr ca;b:=cdr b
  104. >>;
  105. return reverse newb
  106. end$
  107. symbolic procedure disjun(a,b)$
  108. <<while a do
  109. if (car a neq 0) and (car b neq 0) then a:=nil
  110. else <<a:=cdr a;b:=cdr b>>;
  111. if b then nil else t
  112. >>$
  113. symbolic procedure ddrophigh(a,cb)$
  114. % loescht Elemente von a, die Ableitung von cb sind,
  115. % loescht cb, wenn cb Ableitung eines Elements von a ist oder =a ist,
  116. % haengt cb ansonsten an
  117. begin
  118. scalar h;
  119. return
  120. if null a then list(cb)
  121. else
  122. <<h:=compdiffer(car a,cb);
  123. if numberp(h) then if h<2 then a % cb is deriv or = car a
  124. else ddrophigh(cdr a,cb) % car a=df(cb,..
  125. else cons(car a,ddrophigh(cdr a,cb)) % neither
  126. >>
  127. end$
  128. symbolic procedure elibar(l1,l2,lds)$
  129. begin
  130. scalar found1,found2,h;
  131. % found1=t if an LD=l1 is found, found2=t if contradiction found
  132. while lds and (not found2) do
  133. <<if car lds=l1 then found1:=t else
  134. <<h:=compdiffer(l2,car lds);
  135. if (null h) or (h eq 2) then found2:=t
  136. >>;
  137. lds:=cdr lds
  138. >>;
  139. return found1 and (not found2)
  140. end$
  141. symbolic procedure intminderiv(p,ftem,vlrev,maxvanz,nfsub)$
  142. % yields a list {nv1,nv2, ... } such that nvi is the minimum
  143. % of the highest derivatives w.r.t. vi of all the leading derivatives
  144. % of all functions of ftem which are functions of all maxvanz variables.
  145. % Only those are kept for which nvi>0.
  146. % further a list ((f1 ld's of f1) (f2 ld's of f2)...),
  147. begin scalar l,a,listoflds$
  148. while ftem do
  149. <<if (maxvanz=(fctlength car ftem)) or (nfsub=0) then
  150. <<l:=ldlist(p,car ftem,vlrev);
  151. listoflds:=cons(cons(car ftem,l),listoflds)$
  152. a:=if a then ldintersec(cons(a,l))
  153. else ldintersec(l)
  154. >>$
  155. ftem:=cdr ftem
  156. >>$
  157. return list(a,listoflds)
  158. end$
  159. symbolic procedure potintegrable(listoflds)$
  160. begin
  161. scalar h,l1,l2,f,n,lds,f1,f2$
  162. if tr_genint then write "Does a potential exist?"$
  163. %------- Determining 2 minimal sets of integration variables
  164. % There must be two disjunct LDs such that all others are in their
  165. % ideal. This is necessary if we want to eliminate 2 functions.
  166. h:=listoflds;
  167. l1:=nil;
  168. while h do
  169. <<l2:=cdar h; % the list of LDs for the function caar h
  170. while l2 do
  171. <<l1:=ddrophigh(l1,car l2)$
  172. l2:=cdr l2>>;
  173. h:=cdr h
  174. >>;
  175. return
  176. if length l1 neq 2 then nil else
  177. if not disjun(car l1,cadr l1) then nil else
  178. % if there would be an overlap between l1 and l2 then it would have
  179. % to be integrated for elimination but it cannot --> no overlap
  180. % possible
  181. <<% selecting interesting functions for which one LD is = l1 and all
  182. % others are derivatives of l2 or equal l2 and vice versa. Two
  183. % necessary (one with an LD=l1 and one with an LD=l2) from which at
  184. % least one function (f) has no further LD.
  185. % Exception: 2 functions with each 2 LDs equal to (l1,l2) (these
  186. % functions are counted by n)
  187. l2:=cadr l1;l1:=car l1;
  188. f:=nil;f1:=nil;f2:=nil;n:=0;
  189. h:=listoflds;
  190. while h and ((not f1) or (not f2) or ((not f) and (n neq 2))) do
  191. <<lds:=cdar h;
  192. if (not f1) or (not f) then
  193. if elibar(l1,l2,lds) then
  194. <<f1:=cons(caar h,f1);
  195. if length lds eq 1 then f:=caar h else
  196. if length lds eq 2 then
  197. if (car lds = l2) or (cadr lds = l2) then n:=n+1
  198. >>;
  199. if (not f2) or (not f) then
  200. if elibar(l2,l1,lds) then
  201. <<f2:=cons(caar h,f2);
  202. if length lds eq 1 then f:=caar h
  203. >>;
  204. h:=cdr h
  205. >>;
  206. if f1 and ((n>1) or (f2 and f)) then list(l1,l2)
  207. else nil
  208. >>
  209. end$ % of potintegrable
  210. symbolic procedure vlofintlist(vl,intlist)$
  211. % provides a list of elements of vl for which the corresponding
  212. % elements of intlist are non-zero
  213. begin scalar a;
  214. while intlist do
  215. <<if (car intlist) and (not zerop car intlist) then a:=cons(car vl,a);
  216. vl:=cdr vl;
  217. intlist:=cdr intlist
  218. >>;
  219. return a
  220. end$
  221. symbolic procedure vlofintfaclist(vl,intfaclist)$
  222. % determining the list of all variables of vl in intfaclist
  223. begin scalar e1,a;
  224. for each e1 in vl do
  225. if not my_freeof(intfaclist,e1) then a:=cons(e1,a);
  226. return a
  227. end$
  228. symbolic procedure multipleint(intvar,ftem,q,vari,vl,genflag,
  229. potflag,partial,doneintvar)$
  230. % multiple integration of q wrt. variables in vl, max. number of
  231. % integrations specified by intvar
  232. % integrating factors must not depend on doneintvar, doneintvar is
  233. % a list of integration variables so far
  234. % partial=t then as much as possible of an expression is integrated
  235. % even if there is a remainder
  236. begin
  237. scalar pri,vlcop,v,nmax,geni,intlist,iflag,n,nges,newcond,
  238. intfaclist,ph,pih,qh,qih,intfacdepnew,intfacdep$
  239. % intfacdep is a list of variables on which factors of integration
  240. % depend so far, other than the integration variable in their
  241. % integration --> no integration wrt. these variables by potint
  242. % because there the diff. operators wrt. to different variables
  243. % need not commute because the integrations are not done
  244. % pri:=t$
  245. if (not vari) and (zerop q) then return nil;
  246. nges:=0;
  247. vlcop:=vl;
  248. pih:=t;
  249. % Splitting of the equation into the homogeneous and inhomogeneous
  250. % part which is of advantage for finding integrating factors
  251. q:=splitinhom(q,ftem,vl)$
  252. qh:=car q; qih:=cdr q; q:=nil;
  253. while (vari or vlcop) and (pih or (not potflag)) do
  254. %------- if for potflag=t one variable can not be integrated the
  255. %------- maximal number of times (nmax) then immediate stop because
  256. %------- then no elimination of two functions will be possible
  257. << %-- The next integration variable: x, no of integrations: nmax
  258. if vari then <<v:=vari;nmax:=1>>
  259. else <<v:=car vlcop; vlcop:=cdr vlcop;
  260. nmax:=car intvar; intvar:=cdr intvar>>;
  261. if zerop nmax then intlist:=cons(nil,intlist)
  262. else
  263. <<if pri then write"anf: intvar=",intvar," vari=",vari," q=",q$
  264. if vari and (not member(v,vl)) then
  265. <<qh :=reval list('INT,qh ,v)$
  266. if freeof(qh,'INT) then <<
  267. qih:=reval list('INT,qih,v)$
  268. iflag:=if freeint_ and
  269. (null freeof(qih,'INT)) then nil
  270. else <<
  271. intlist:=cons(list(1),intlist)$
  272. 'success>>$
  273. if pri then <<write"232323 qh=",qh;terpri();
  274. write"qih=",qih;terpri()>>
  275. >>
  276. >> else
  277. <<n:=0$
  278. if pri then write"333"$
  279. intfaclist:=nil; %-- the list of integr. factors in v-integr.
  280. if potflag or my_freeof(intfacdep,v) then
  281. % otherwise v-integration not allowed because one integrating
  282. % factor already depends on v
  283. % for potflag=t this `commutativity'-demand plays no role
  284. repeat << %--- max nmax integrations of qh and qih wrt. v
  285. if pri then <<write"444 vor intpde:"$eqprint q$terpri()$
  286. write"potflag=",potflag," v=",v,
  287. " ftem=",ftem>>$
  288. % At first trying a direct integration of the homog. part qh
  289. ph:=intpde(qh,ftem,vl,v,partial)$ % faster if potflag=nil
  290. if pri then <<write"nach intpde(qh):"$deprint ph>>$
  291. %------ At first the integration of the homogeneous part
  292. intfacdepnew:=intfacdep;
  293. if ph and (partial or (zerop cadr ph)) then <<
  294. %---- For the homogen. part cadr ph must be zero
  295. intfaclist:=cons(1,intfaclist);
  296. ph:=car ph;
  297. if pri then <<write"565656 ph=",ph;terpri()>>;
  298. >> else
  299. if vari then ph:=nil
  300. else
  301. if facint_ then <<
  302. ph:=findintfac(list(qh),ftem,vl,v,doneintvar,intfacdep,
  303. not zerop n,not potflag);
  304. % factorize before ivestig., no report of int. factors
  305. if ph then << %--- Complete integr. of qh was possible
  306. if print_ then write"of the homogeneous part"$terpri()$
  307. %--- update the list of variables on which all integr.
  308. %--- factors depend apart from the integration variable
  309. intfacdepnew:=caddr ph;
  310. %--- extend the list of integrating factors, cadr ph
  311. %--- is a list of integr. factors, here only one
  312. intfaclist:=cons(caadr ph,intfaclist);
  313. %--- multiply the inhomogeneous part with integ. factor
  314. qih:=reval reval reval list('TIMES,car intfaclist,qih);
  315. if pri then <<write"454545 qih=",qih;terpri()>>;
  316. ph:=car ph % the integral of qh
  317. >>
  318. >>;
  319. %------ Now the integration of the inhomogeneous part
  320. if not ph then pih:=nil %--- no integration possible
  321. else <<
  322. if zerop qih then pih:=list(0,0) else
  323. pih:=intpde(qih,ftem,vl,v,partial)$
  324. if null pih then
  325. write"error2: inhom. expr. can not be integrated"$
  326. if pri then <<write"nach intpde(qih):",pih$terpri()$
  327. write"genflag=",genflag$terpri()>>$
  328. if pih then
  329. if zerop cadr pih then
  330. <<qih:=car pih$n:=add1 n$iflag:='success$
  331. if pri then write" success "$
  332. >>
  333. else if not genflag then pih:=nil
  334. else
  335. <<if pri then write"555"$
  336. geni:=partint(cadr pih,smemberl(ftem,cadr pih),
  337. vl,v,genflag)$
  338. if geni then
  339. <<qih:=reval list('PLUS,car pih,car geni)$
  340. n:=add1 n$
  341. ftem:=union(fnew_,ftem)$
  342. newcond:=append(cdr geni,newcond)$ % additional de's
  343. if pri then
  344. <<terpri()$write"nach gen newcond:",newcond>>$
  345. iflag:='genint
  346. >> else
  347. if partial then qih:=car pih
  348. else pih:=nil
  349. >>;
  350. if pih then <<
  351. if pri then write"AAA"$
  352. qh:=ph;
  353. if (not potflag) and (n neq 1) then
  354. intfacdep:=intfacdepnew
  355. %-The first integr. factor of all v-integrations does not
  356. % depend on any earlier integration variables and can
  357. % therefore be taken out of all integrals --> no incease
  358. % of intfacdep for n=1.
  359. %-For potential integration the integration variables and
  360. % extra-dependencies-variables of integr. factors need not
  361. % be disjunct therefore the intfacdep-update only for
  362. % not-potflag
  363. >> else <<
  364. if pri then write"BBB"$
  365. % inhomogeneous part can not be integrated therefore
  366. % reversing the succesful integration of the hom. part
  367. if car intfaclist neq 1 then
  368. qih:=reval list('QUOTIENT,qih,car intfaclist);
  369. intfaclist:=cdr intfaclist
  370. >>;
  371. >>; %-- end of the integration of the inhomog. part
  372. if pri then write"n=",n," nmax=",nmax," not pih=",not pih$
  373. >> until (n=nmax) or (not pih)$ %---- end of v-integration
  374. %------- variables of done integrations are collected for
  375. %------- determining integrating factors in later integr.
  376. if not zerop n then doneintvar:=cons(v,doneintvar)$
  377. nges:=nges+n;
  378. intlist:=cons(intfaclist,intlist)
  379. >>$ % of not ( vari and (not member(v,vl)))
  380. if vari then <<vari:=nil;vlcop:=nil>>;
  381. if pri then write"ende: intvar=",intvar," vari=",vari,
  382. " qh=",qh," qih=",qih$
  383. >> % of (nmax neq zero)
  384. >>$ % of ( while (vari or vlcop) and (pih or (not potflag)) )
  385. % intlist and its elements intfaclist are in the inverse order
  386. % to vl and the sequence of integrations done
  387. q:=reval list('PLUS,qh,qih)$ %--- adding homog. and inhomog. part
  388. if pri then <<terpri()$write"\\\ newcond:"$deprint newcond;
  389. write"multiple result:",if null iflag then nil
  390. else list(q,intlist,newcond,nges)
  391. >>;
  392. return if null iflag then nil
  393. else list(q,intlist,newcond,nges)
  394. end$ % of multipleint
  395. symbolic procedure uplistoflds(intlist,listoflds)$
  396. begin
  397. scalar f,h1,h2,h3,h4,lds,itl;
  398. while listoflds do
  399. <<f:=caar listoflds;
  400. lds:=cdar listoflds;
  401. listoflds:=cdr listoflds;
  402. h2:=nil; % h2 becomes the new list of lds of f
  403. while lds do
  404. <<h3:=car lds; lds:=cdr lds;
  405. itl:=intlist;
  406. h4:=nil; % h4 becomes one new ld of f
  407. while h3 do
  408. <<h4:=cons(car h3 - if null car itl then 0
  409. else length car itl, h4);
  410. h3:=cdr h3;itl:=cdr itl
  411. >>;
  412. h2:=cons(reverse h4,h2)
  413. >>;
  414. h1:=cons(cons(f,h2),h1)
  415. >>;
  416. return h1 % updated listoflds
  417. end$ % of uplistoflds
  418. symbolic procedure addintco(q, ftem, ifac, vl, vari)$
  419. begin scalar v,f,l,vl1;
  420. % multi.ing factors to the constants/functions of integration
  421. if zerop q then l:=1
  422. else
  423. <<ftem:=fctsort ftem$
  424. while ftem do
  425. if fctlength car ftem<length vl then ftem:=nil
  426. else if fctlinear(q,f) then
  427. <<f:=car ftem$ ftem:=nil>> else
  428. ftem:=cdr ftem$
  429. if f then
  430. <<l:=lderiv(q,f,fctargs f)$
  431. l:=reval coeffn(q,reval car l,cdr l)
  432. >> else l:=1
  433. >>;
  434. % the constants and functions of integration
  435. if vari then q:=list('PLUS,q,intconst(l,vl,vari,list(1)))
  436. else
  437. <<vl1:=vl;
  438. while vl1 do
  439. <<v:=car vl1; vl1:=cdr vl1;
  440. if car ifac then
  441. q:=list('PLUS,q,intconst(l,vl,v,car ifac))$
  442. % l..product of factors in the coefficient of the function to be
  443. % eliminated, car ifac .. list of integrating factors
  444. ifac:=cdr ifac;
  445. >>
  446. >>$
  447. return reval q
  448. end$ % of addintco
  449. symbolic procedure integratepde(p,ftem,vari,genflag,potflag)$
  450. % Generalized integration of the expression p
  451. % if not genflag then "normal integration"
  452. % Equation p must not be directly separable, otherwise the depen-
  453. % dencies of functions of integration on their variables is wrong,
  454. % i.e. no dependence on explicit variables
  455. % ftem are all functions from the `global' ftem which occur in p, i.e.
  456. % ftem:=smemberl(ftem,p)$
  457. % if vari=nil then integration w.r.t. all possible variables within
  458. % the equation
  459. % else only w.r.t. vari one time
  460. begin
  461. scalar vl,vlrev,v,intlist,
  462. ili1a,ili2a,maxvanz,fsub,h,hh,nfsub,iflag,newcond,
  463. n1,n2,pot1,pot2,p1,p2,listoflds,secnd,ifac0,
  464. ifac1a,ifac1b,ifac2a,ifac2b,cop,v1a,v2a,pri$
  465. % pri:=t;
  466. if pri then <<terpri()$write"Start Integratepde">>$
  467. vl:=argset ftem$
  468. vlrev:=reverse vl;
  469. if vari then <<potflag:=nil;
  470. if zerop p then iflag:='success>>
  471. else
  472. <<%------- determining fsub=list of functions of all variables
  473. maxvanz:=length vl$
  474. fsub:=nil;
  475. h:=ftem;
  476. while h do
  477. <<if fctlength car h=maxvanz then
  478. fsub:=cons(car h,fsub)$
  479. h:=cdr h
  480. >>$
  481. nfsub:=length fsub$ % must be >1 for potential-integration
  482. h:=intminderiv(p,ftem,vlrev,maxvanz,nfsub)$ % fsub is also for below
  483. intlist:=car h$
  484. %-- list of necessary integrations of the whole equation to solve
  485. %-- for a function of all variables
  486. listoflds:=cadr h$ %-- list of leading derivatives
  487. >>$
  488. if pri then <<terpri()$
  489. write"complete integrations:",intlist," for:",vl>>;
  490. %-- n1 is the number of integrations which must be done to try
  491. %-- potential integration which must enable to eliminate 2 functions
  492. %-- n2 is the number of integrations actually done
  493. n1:=for each h in intlist sum h;
  494. if (not vari) and (zerop n1) then
  495. <<n2:=0;
  496. if potflag then % else not necessary
  497. for h:=1:(length vl) do ifac0:=cons(nil,ifac0)
  498. >> else
  499. <<if tr_genint then
  500. <<terpri()$write "integration of the expression : "$
  501. eqprint p>>$
  502. if pri then
  503. <<terpri()$write"at first all multiple complete integration">>;
  504. %-- At first if possible n2 integrations of the whole equation
  505. h:=multipleint(intlist,ftem,p,vari,vl,genflag,nil,nil,nil)$
  506. % potflag=nil, partial=nil, doneintvar=nil
  507. if h then
  508. <<p:=car h;
  509. ifac0:=cadr h; % ifac0 is the list of lists of integr. factors
  510. newcond:=caddr h;
  511. n2:=cadddr h; % number of done integrations
  512. % doneintvar & intfacdep for the two halfs of integrations
  513. % from the two parts of ifac0
  514. h:=nil;
  515. iflag:='success;
  516. >> else n2:=0;
  517. ftem:=union(fnew_,ftem)$
  518. >>;
  519. %------------ Existence of a potential ?
  520. if (n1=n2) and potflag and (nfsub>1) then
  521. %---- at least 2 functions to solve for
  522. <<if not zerop n2 then %---- update listoflds
  523. listoflds:=uplistoflds(reverse ifac0,listoflds)$
  524. if pri then <<terpri()$write"uplistoflds:",listoflds>>$
  525. if h:=potintegrable(listoflds) then
  526. <<ili1a:=car h; ili2a:=cadr h;
  527. % The necess. differentiations of the potential
  528. if pri then
  529. <<terpri()$write"potintegrable:",ili1a," ",ili2a>>$
  530. if pri then <<write"+++ intlist=",intlist,
  531. " ili1a=",ili1a,
  532. " ili2a=",ili2a>>$
  533. %-- distributing the integrating factors of ifac0 among
  534. %-- the two lists ifac1b and ifac2b which are so far nil
  535. %-- such that (ifac1b and ili1a are disjunct) and
  536. %-- (ifac2b and ili2a are disjunct)
  537. v1a:=vlofintlist(vl,ili1a);
  538. v2a:=vlofintlist(vl,ili2a);
  539. hh:=t;
  540. cop:=reverse ifac0;
  541. ifac1a:=ili1a;ifac2a:=ili2a;
  542. while hh and cop do <<
  543. % cop is a list of lists of integr. factors
  544. if car cop then h:=vlofintfaclist(vl,cdar cop)
  545. else h:=nil;
  546. if freeoflist(h,v2a) and (car ifac2a=0) then <<
  547. ifac1b:=cons( nil, ifac1b);
  548. ifac2b:=cons( reverse car cop, ifac2b)
  549. >> else
  550. if freeoflist(h,v1a) and (car ifac1a=0) then <<
  551. ifac2b:=cons( nil, ifac2b);
  552. ifac1b:=cons( reverse car cop, ifac1b)
  553. >> else
  554. if car cop then hh:=nil;
  555. ifac1a:=cdr ifac1a;
  556. ifac2a:=cdr ifac2a;
  557. cop:=cdr cop;
  558. >>;
  559. % the elements of ifac1b,ifac2b are in reverse order to
  560. % ifac1a,ifac2a and are in the same order as vl, also
  561. % the elements in the infac-lists are in inverse order,
  562. % i.e. in the order the integrations have been done
  563. if pri then <<terpri()$
  564. write "ifac1a=",ifac1a," ifac1b=",ifac1b,
  565. " ifac2a=",ifac2a," ifac2b=",ifac2b >>$
  566. %-- lists of integrations to be done to both parts
  567. if hh then
  568. repeat % possibly a second try with part2 integrated first
  569. <<n1:=for each n1 in ili1a sum n1;
  570. % n1 .. number of remaining integrations of the first half
  571. p1:=multipleint(ili1a,ftem,p,nil,vl,genflag,t,t,
  572. % potflag=t, partial=t
  573. union(vlofintlist(vl,ili2a),
  574. vlofintlist(vl,ifac1b)))$
  575. % that the variables of integration are not in ifac1b
  576. % was already checked. Only restriction: the integrating
  577. % factors must not depend on the last argument.
  578. ftem:=union(fnew_,ftem)$
  579. if p1 then <<
  580. ifac1a:=cadr p1;
  581. % ifac1a is now the list of integrating factors
  582. if newcond then newcond:=nconc(newcond,caddr p1)
  583. else newcond:=caddr p1;
  584. if pri then <<terpri()$write"mul2: newcond=",newcond>>$
  585. n2:=cadddr p1;
  586. p1:=car p1
  587. >>;
  588. if p1 and (n1=n2) then
  589. %--- if the first half has been integrated suff. often
  590. <<%--- integrating the second half sufficiently often
  591. n1:=for each n1 in ili2a sum n1;
  592. % calculation of the 2. part which is not contained in p1
  593. p2:=p1;
  594. cop:=ifac1a; hh:=vlrev; % because ifac1a is reversed
  595. while cop do <<
  596. h:=car cop;cop:=cdr cop;
  597. v:=car hh;hh:=cdr hh;
  598. % h is the list of integrating factors of the v-integr.
  599. while h do <<
  600. p2:=reval list('QUOTIENT,list('DF,p2,v),car h);
  601. h:=cdr h
  602. >>
  603. >>;
  604. p2:=reval reval list('PLUS,p,list('MINUS,p2));
  605. p2:=multipleint(ili2a,ftem,p2,nil,vl,genflag,t,nil,
  606. % potflag=t, partial=nil
  607. union(vlofintlist(vl,ili1a),
  608. vlofintlist(vl,ifac2b)))$
  609. ftem:=union(fnew_,ftem)$
  610. if p2 then <<
  611. ifac2a:=cadr p2;
  612. % ifac2a is now list of integrating factors
  613. if newcond then newcond:=nconc(newcond,caddr p2)
  614. else newcond:=caddr p2;
  615. if pri then <<terpri()$write"mul3: newcond=",newcond>>$
  616. n2:=cadddr p2;
  617. p2:=car p2
  618. >>;
  619. if p2 and (n1=n2) then
  620. % if the second half has been integrated sufficiently often
  621. <<% can both halfes be solved for different functions
  622. % i.e. are they algebraic and linear in different functions?
  623. pot1:=nil;
  624. pot2:=nil;
  625. for each h in fsub do <<
  626. if ld_deriv_search(p1,h,vl) = (nil . 1) then
  627. pot1:=cons(h,pot1);
  628. if ld_deriv_search(p2,h,vl) = (nil . 1) then
  629. pot2:=cons(h,pot2);
  630. >>$
  631. if (null not_included(pot1,pot2)) or
  632. (null not_included(pot2,pot1)) then p2:=nil
  633. >>$
  634. if p2 and (n1=n2) then
  635. <<iflag:='potint;
  636. % ifac1b,ifac2b are in reverse order to ifac1a,ifac2a!
  637. pot1:=newfct(fname_,vl,nfct_)$ % the new potential fct.
  638. pot2:=pot1;
  639. nfct_:=add1 nfct_$
  640. fnew_:=cons(pot1,fnew_);
  641. v:=vlrev;
  642. while v do
  643. <<cop:=car ifac1a; ifac1a:=cdr ifac1a;
  644. while cop do <<
  645. pot1:=reval list('QUOTIENT,list('DF,pot1,car v),car cop);
  646. cop:=cdr cop
  647. >>;
  648. cop:=car ifac2a; ifac2a:=cdr ifac2a;
  649. while cop do <<
  650. pot2:=reval list('QUOTIENT,list('DF,pot2,car v),car cop);
  651. cop:=cdr cop
  652. >>;
  653. v:=cdr v;
  654. >>;
  655. p:=addintco(list('PLUS,p1,reval pot2),
  656. ftem,ifac1b,vlrev,nil)$
  657. newcond:=cons(addintco(list('PLUS,p2,
  658. list('MINUS,reval pot1)),
  659. ftem,ifac2b,vlrev,nil),
  660. newcond) % vari=nil
  661. >>
  662. ;if pri then write":::"$
  663. >>;
  664. secnd:=not secnd;
  665. % retry in different order of integration, p is still the same
  666. if (iflag neq 'potint) and secnd then
  667. <<cop:=ili1a;ili1a:=ili2a;ili2a:=cop>>
  668. >> until (iflag eq 'potint) or (not secnd)
  669. >>;
  670. >>$
  671. %--------- returning the result
  672. return if not iflag then nil
  673. else
  674. <<if iflag neq 'potint then % constants of integration
  675. p:=addintco(p, ftem, % the completely reversed ifac0
  676. <<h:=nil;
  677. while ifac0 do <<h:=cons(reverse car ifac0,h);ifac0:=cdr ifac0>>;
  678. h
  679. >>, vl, vari)$
  680. if pri then
  681. <<terpri()$write"ENDE INTEGRATEPDE"$deprint(cons(p,newcond))>>$
  682. cons(p,newcond)
  683. >>
  684. end$ % of integratepde
  685. symbolic procedure intpde(p,ftem,vl,x,potint)$
  686. % integration of an polynomial expr. p w.r.t. x
  687. begin scalar f,ft,l,l1,l2,vl,k,s,a,iflag,flag$
  688. ft:=ftem$
  689. vl:=cons(x,delete(x,vl))$
  690. while ftem and not flag do
  691. <<f:=car ftem$ % integrating all terms including car ftem
  692. if member(x,fctargs f) then
  693. <<l1:=l:=lderiv(p,f,vl)$
  694. while not (flag or (iflag:=intlintest(l,x))) do
  695. <<k:=reval coeffn(p,car l,cdr l)$
  696. if intcoefftest(car lderiv(k,f,vl),car l,vl) then
  697. <<a:=decderiv(car l,x)$
  698. k:=reval list('INT,subst('v_a_r_,a,k),'v_a_r_)$
  699. k:=reval subst(a,'v_a_r_,k)$
  700. s:=cons(k,s)$
  701. p:=reval aeval list('DIFFERENCE,p,list('DF,k,x))$
  702. if (l:=lderiv(p,f,vl))=l1 then flag:='neverending
  703. else l1:=l
  704. >> else
  705. flag:='coeffld
  706. >>$
  707. % iflag='nofct is the so far integrable case
  708. % the non-integrable cases are: flag neq nil,
  709. % (iflag neq nil) and (iflag neq 'nofct), an exception to the
  710. % second case is potint where non-integrable rests are allowed
  711. if iflag='nofct then ftem:=smemberl(ftem,p)
  712. else if potint or (fctlength f<length vl) then
  713. <<ftem:=cdr ftem$flag:=nil>> else
  714. flag:=(iflag or flag)
  715. >> else
  716. ftem:=cdr ftem
  717. >>$
  718. return
  719. if not flag then
  720. <<l:=explicitpart(p,ft,x)$
  721. l1:=list('INT,l,x)$
  722. s:=reval aeval cons('PLUS,cons(l1,s))$
  723. if freeint_ and
  724. (null freeof(s,'INT)) then nil
  725. else <<
  726. k:=start_let_rules()$
  727. l2 := reval {'DF,l1,x} where !*precise=nil;
  728. if 0 neq (reval {'DIFFERENCE,l,l2} where !*precise=nil) then <<
  729. write"REDUCE integrator error:"$terpri()$
  730. algebraic write "int(",l,",",x,") neq ",l1;terpri()$
  731. write"Result ignored.";terpri()$
  732. stop_let_rules(k)$
  733. nil
  734. >> else <<
  735. p:=reval reval aeval list('DIFFERENCE,p,l2)$
  736. stop_let_rules(k)$
  737. if poly_only then if ratexp(s,ft) then list(s,p)
  738. else nil
  739. else list(s,p)
  740. >>
  741. >>
  742. >> else nil$
  743. end$ % of intpde
  744. symbolic procedure explicitpart(p,ft,x)$
  745. % part of a sum p which only explicitly depends on a variable x
  746. begin scalar l$
  747. if not member(x,argset smemberl(ft,p)) then l:=p
  748. else if pairp p then
  749. <<if car p='MINUS then
  750. l:=reval list('MINUS,explicitpart(cadr p,ft,x))$
  751. if (car p='QUOTIENT) and not member(x,argset smemberl(ft,caddr p))
  752. then
  753. l:=reval list('QUOTIENT,explicitpart(cadr p,ft,x),caddr p)$
  754. if car p='PLUS then
  755. <<for each a in cdr p do
  756. if not member(x,argset smemberl(ft,a)) then l:=cons(a,l)$
  757. if pairp l then l:=reval cons('PLUS,l)>> >>$
  758. if not l then l:=0$
  759. return l$
  760. end$
  761. symbolic procedure intconst(co,vl,x,ifalist)$
  762. % The factors in ifalist must be in the order of integrations done
  763. if null ifalist then 0 else
  764. begin scalar l,l2,f,coli,cotmp$
  765. while ifalist do <<
  766. cotmp:=coli;
  767. coli:=nil;
  768. while cotmp do <<
  769. coli:=cons(list('INT,list('TIMES,car ifalist,car cotmp),x),coli);
  770. cotmp:=cdr cotmp
  771. >>;
  772. coli:=cons(1,coli);
  773. ifalist:=cdr ifalist
  774. >>;
  775. while coli do
  776. <<f:=newfct(fname_,delete(x,vl),nfct_)$
  777. nfct_:=add1 nfct_$
  778. fnew_:=cons(f,fnew_)$
  779. l:=cons(list('TIMES,f,car coli),l)$
  780. coli:=cdr coli
  781. >>$
  782. if length l>1 then l:=cons('PLUS,l)
  783. else if pairp l then l:=car l
  784. else l:=0$
  785. if co and co neq 1 then
  786. if pairp co then
  787. <<if car co='TIMES then co:=cdr co
  788. else co:=list co$
  789. while co do <<if my_freeof(car co,x) then l2:=cons(car co,l2)$
  790. co:=cdr co>>
  791. >>
  792. else if co neq x then l2:=list co$
  793. return reval if l2 then cons('TIMES,cons(l,l2))
  794. else l
  795. end$
  796. symbolic procedure intcoefftest(l,l1,vl)$
  797. begin scalar s$
  798. return if not pairp l then t
  799. else if car l='DF then
  800. <<s:=decderiv(l1,car vl)$
  801. if pairp s and pairp cdr s then s:=cddr s
  802. else s:=nil$
  803. if diffrelp(cons(cddr l,1),cons(s,1),vl) then t
  804. else nil>>
  805. else t$
  806. end$
  807. symbolic procedure fctlinear(p,f)$
  808. <<p:=ldiffp(p,f)$
  809. (null car p) and (cdr p=1)>>$
  810. symbolic procedure intlintest(l,x)$
  811. % Test,ob in einem Paar (fuehrende Ableitung.Potenz)
  812. % eine x-Ableitung linear auftritt
  813. if not car l then
  814. if zerop cdr l then 'nofct
  815. else 'nonlin
  816. else % Fkt. tritt auf
  817. if (car l) and (cdr l=1) then % fuehr. Abl. tritt linear auf
  818. if pairp car l then % Abl. der Fkt. tritt auf
  819. if caar l='DF then
  820. if member(x,cddar l) then nil
  821. % x-Abl. tritt auf
  822. else if member(x,fctargs cadar l) then 'noxdrv
  823. else 'noxdep
  824. else 'nodrv
  825. else 'nodrv
  826. else 'nonlin$
  827. symbolic procedure decderiv(l,x)$
  828. % in Diff.ausdr. l wird Ordn. d. Abl. nach x um 1 gesenkt
  829. begin scalar l1$
  830. return if l then if car l='DF then
  831. <<l1:=decderiv1(cddr l,x)$
  832. if l1 then cons('DF,cons(cadr l,l1))
  833. else cadr l>>
  834. else l
  835. else nil$
  836. end$
  837. symbolic procedure decderiv1(l,x)$
  838. if null l then nil
  839. else
  840. if car l=x then
  841. if cdr l then
  842. if numberp cadr l then
  843. if cadr l>2 then cons(car l,cons(sub1 cadr l,cddr l))
  844. else cons(car l,cddr l)
  845. else cdr l
  846. else nil
  847. else cons(car l,decderiv1(cdr l,x))$
  848. symbolic procedure integratede(q,ftem,genflag)$
  849. % Integration of a de
  850. % result: newde if successfull, nil otherwise
  851. begin scalar l,l1,l2,fl$
  852. ftem:=smemberl(ftem,q)$
  853. again:
  854. if l1:=integrableode(q,ftem) then % looking for an integrable ode
  855. if l1:=integrateode(q,car l1,cadr l1,caddr l1,ftem) then
  856. % trying to integrate it
  857. <<l:=append(cdr l1,l);
  858. q:=simplifypde(car l1,ftem,nil)$
  859. ftem:=smemberl(union(fnew_,ftem),q)$
  860. fl:=t
  861. >>$
  862. if l1:=integratepde(q,ftem,nil,genflag,potint_) then
  863. % trying to integrate a pde
  864. <<q:=car l1$
  865. for each a in cdr l1 do
  866. <<ftem:=union(fnew_,ftem)$
  867. if (l2:=integratede(a,ftem,nil)) then l:=append(l2,l)
  868. else l:=cons(a,l)
  869. >>$
  870. fl:=t$
  871. if null genflag then l1:=nil$
  872. ftem:=smemberl(union(fnew_,ftem),q);
  873. goto again
  874. >>$
  875. if fl then
  876. <<l:=cons(q,l)$
  877. l:=for each a in l collect reval aeval a$
  878. l:=for each a in l collect
  879. if pairp a and (car a='QUOTIENT) then cadr a
  880. else a>>$
  881. return l$
  882. end$
  883. symbolic procedure intflagtest(q,fullint)$
  884. if flagp(q,'to_int) then
  885. if fullint then
  886. if get(q,'full_int) then t else
  887. if get(q,'starde) then nil else
  888. begin scalar fl,vl,dl,l,n,mi$
  889. n:=get(q,'nvars)$
  890. for each f in get(q,'rational) do % only rational fcts
  891. if fctlength f=n then fl:=cons(f,fl)$
  892. if null fl then return nil$
  893. vl:=get(q,'vars)$
  894. dl:=get(q,'derivs)$
  895. for each d in dl do
  896. if member(caar d,fl) then
  897. put(caar d,'maxderivs,maxderivs(get(caar d,'maxderivs),cdar d,vl))$
  898. dl:=fl$
  899. while vl do
  900. <<mi:=car get(car fl,'maxderivs)$
  901. l:=list car fl$
  902. put(car fl,'maxderivs,cdr get(car fl,'maxderivs))$
  903. for each f in cdr fl do
  904. <<if (n:=car get(f,'maxderivs))=mi then l:=cons(f,l)
  905. else if n<mi then
  906. <<l:=list f$
  907. mi:=n>>$
  908. put(f,'maxderivs,cdr get(f,'maxderivs))
  909. >>$
  910. dl:=intersection(l,dl)$
  911. if dl then vl:=cdr vl
  912. else vl:=nil>>$
  913. for each f in fl do remprop(f,'maxderivs)$
  914. return dl
  915. end
  916. else t$
  917. symbolic procedure integrate(q,genintflag,fullint)$
  918. % integrate pde q; if genintflag is not nil then indirect
  919. % integration is allowed
  920. % if fullint is not nil then only full integration is allowed
  921. % Es wird noch nicht ausgenutzt:
  922. % 1) Fcts, die rational auftreten
  923. % 2) starde
  924. begin scalar l$
  925. if intflagtest(q,fullint) then
  926. <<if (l:=integratede(get(q,'val),get(q,'fcts),genintflag)) then
  927. <<ftem_:=reverse ftem_$
  928. for each f in reverse fnew_ do
  929. ftem_:=fctinsert(f,ftem_)$
  930. ftem_:=reverse ftem_$
  931. fnew_:=nil$
  932. flag1(q,'to_eval)$
  933. update(q,car l,ftem_,get(q,'vars),t,list(0))$
  934. l:=cons(q,mkeqlist(cdr l,ftem_,get(q,'vars),
  935. allflags_,t,get(q,'orderings)))$
  936. remflag1(q,'to_int)$
  937. if print_ then
  938. <<terpri()$
  939. if cdr l
  940. then write "Indirect integration of ",q," yields ",l
  941. else write "Integration of ",q>>$
  942. >>$
  943. remflag1(q,'to_int)>>$
  944. return l$
  945. end$
  946. symbolic procedure quick_integrate_one_pde(pdes)$
  947. begin scalar m,q,p$
  948. % find the lowest order derivative wrt. only one variable
  949. while pdes and
  950. (get(car pdes,'length) = 1) do << % only 1 term
  951. q:=caar get(car pdes,'derivs)$
  952. if ( length q = 2 ) or
  953. ((length q = 3) and
  954. (fixp caddr q) and
  955. ((null p) or
  956. (caddr q<m) ) ) then
  957. <<p:=car pdes;
  958. m:=if (length q = 2) then 1
  959. else caddr q>>;
  960. pdes:=cdr pdes
  961. >>$
  962. if p then p:=integrate(p,nil,t)$
  963. return p
  964. end$
  965. symbolic procedure integrate_one_pde(pdes,genintflag,fullint)$
  966. % trying to integrate one pde
  967. begin scalar l,l1,m,p$
  968. % at first selecting all eligible de's
  969. m:=-1$
  970. while pdes do <<
  971. if flagp(car pdes,'to_int) and not(get(car pdes,'starde)) then <<
  972. l:=cons(car pdes,l);
  973. if get(car pdes,'nvars)>m then m:=get(car pdes,'nvars)$
  974. >>;
  975. pdes:=cdr pdes
  976. >>;
  977. l:=reverse l;
  978. % find an equation with as many as possible variables for integration
  979. while m>=0 do <<
  980. l1:=l$
  981. while l1 do
  982. if (get(car l1,'nvars)=m) and
  983. (p:=integrate(car l1,genintflag,fullint)) then <<
  984. m:=-1$
  985. l1:=nil
  986. >> else l1:=cdr l1$
  987. m:=sub1 m
  988. >>$
  989. return p$
  990. end$
  991. endmodule$
  992. %********************************************************************
  993. module generalized_integration$
  994. %********************************************************************
  995. % Routines for generalized integration of pde's containing unknown
  996. % functions
  997. % Author: Andreas Brand
  998. % December 1991
  999. symbolic procedure gintorder(p,ftem,vl,x)$
  1000. % reorder equation p
  1001. begin scalar l,l1,q,m,b,c,q1,q2$
  1002. if pairp(p) and (car p='QUOTIENT) then <<
  1003. q:=caddr p$
  1004. p:=cadr p$
  1005. l1:=gintorder1(q,ftem,x,t)$
  1006. if DepOnAllVars(car l1,x,vl) then return nil;
  1007. q1:=car l1;
  1008. q2:=cadr l1;
  1009. >>$
  1010. if pairp(p) and (car p='PLUS) then p:=cdr p % list of summands
  1011. else p:=list p$
  1012. while p do
  1013. <<l1:=gintorder1(car p,ftem,x,nil)$
  1014. if DepOnAllVars(car l1,x,vl) then l:=p:=nil
  1015. else <<l:=termsort(l,l1)$p:=cdr p>> >>$
  1016. if l then
  1017. <<l:=for each a in l collect if cddr a then
  1018. <<b:=car a$
  1019. c:=cdr reval coeff1(cons('PLUS,cdr a),x,nil)$
  1020. m:=0$
  1021. while c and (car c=0) do <<c:=cdr c$m:=add1 m>>$
  1022. if m>0 then b:=list('TIMES,list('EXPT,x,m),b)$
  1023. cons(reval b,c)>>
  1024. else
  1025. cons(reval car a,cdr reval coeff1(cadr a,x,nil))$
  1026. if q then <<
  1027. l:=for each a in l collect
  1028. cons(car a,for each s in cdr a collect
  1029. reval list('QUOTIENT,s,q2))$
  1030. l:=for each a in l collect
  1031. cons(reval list('QUOTIENT,car a,q1),cdr a)
  1032. >>$
  1033. >>$
  1034. return l$
  1035. end$
  1036. symbolic procedure DepOnAllVars(c,x,vl)$
  1037. % tests for occurence of vars from vl in factors of c depending on x
  1038. begin scalar l$
  1039. if pairp c and (car c='TIMES) then c:=cdr c
  1040. else c:=list c$
  1041. while c and vl do
  1042. <<if not my_freeof(car c,x) then
  1043. for each v in vl do if not my_freeof(car c,v) then l:=cons(v,l)$
  1044. vl:=setdiff(vl,l)$
  1045. c:=cdr c
  1046. >>$
  1047. return (null vl)$
  1048. end$
  1049. symbolic procedure gintorder1(p,ftem,x,mode2)$
  1050. % reorder a term p
  1051. begin scalar l1,l2,sig$
  1052. % mode2 = nil then
  1053. % l2:list of factors of p not depending
  1054. % on x or beeing a power of x
  1055. % l1:all other factors
  1056. % mode2 = t then
  1057. % l2:list of factors of p not depending on x
  1058. % l1:all other factors
  1059. if pairp p and (car p='MINUS) then <<sig:=t$p:=cadr p>>$
  1060. if pairp p and (car p='TIMES) then p:=cdr p
  1061. else p:=list p$
  1062. for each a in p do
  1063. <<if my_freeof(a,x) and freeoflist(a,ftem) then l2:=cons(a,l2)
  1064. % freeoflist(a,ftem) to preserve linearity
  1065. else if mode2 then l1:=cons(a,l1)
  1066. else if a=x then l2:=cons(a,l2)
  1067. else if pairp a and (car a='EXPT) and (cadr a=x) and fixp caddr a
  1068. then l2:=cons(a,l2)
  1069. else l1:=cons(a,l1)>>$
  1070. if pairp l1 then
  1071. if cdr l1 then l1:=cons('TIMES,l1)
  1072. else l1:=car l1$
  1073. if pairp l2 then
  1074. if cdr l2 then l2:=cons('TIMES,l2)
  1075. else l2:=car l2$
  1076. if sig then if l2 then l2:=list('MINUS,l2)
  1077. else l2:=list('MINUS,1)$
  1078. return list(if l1 then l1 else 1,if l2 then l2 else 1)$
  1079. end$
  1080. symbolic procedure partint(p,ftem,vl,x,genint)$
  1081. begin scalar f,neg,l1,l2,n,k,l,h$
  1082. if tr_genint then <<
  1083. terpri()$
  1084. write "generalized integration of the unintegrated rest : "$
  1085. eqprint p
  1086. >>$
  1087. l:=gintorder(p,ftem,vl,x)$
  1088. % would too many new equations and functions be necessary?
  1089. if pairp(l) and (length(l)>genint) then return nil;
  1090. l:=for each s in l collect <<
  1091. h:=varslist(car s,ftem,vl)$
  1092. if h=nil then <<
  1093. list('TIMES,x,car s,cons('PLUS,cdr s))
  1094. >> else <<
  1095. f:=newfct(fname_,h,nfct_)$
  1096. nfct_:=add1 nfct_$
  1097. fnew_:=cons(f,fnew_)$
  1098. neg:=t$
  1099. n:=sub1 length cdr s$
  1100. k:=-1$
  1101. if (pairp car s) and (caar s='DF) then
  1102. <<h:=reval reval list('DIFFERENCE,cadar s,list('DF,f,x,add1 n))$
  1103. if not zerop h then l1:=cons(h,l1)$
  1104. l2:=cddar s>>
  1105. else
  1106. <<h:=signchange reval reval list('DIFFERENCE,car s,
  1107. list('DF,f,x,add1 n))$
  1108. if not zerop h then l1:=cons(h,l1)$
  1109. l2:=nil>>$
  1110. reval cons('PLUS, for each sk on cdr s collect
  1111. <<neg:=not neg$
  1112. k:=add1 k$
  1113. reval list('TIMES,if neg then -1 else 1,
  1114. append(list('DF,f,x,n-k),l2),
  1115. tailsum(sk,k,x) )
  1116. >>
  1117. )
  1118. >>
  1119. >>$
  1120. if l then l:=cons(reval cons('PLUS,l),l1)$
  1121. if tr_genint then
  1122. <<terpri()$
  1123. write "result (without constant or function of integration): "$
  1124. if l then <<
  1125. eqprint car l$
  1126. write "additional equations : "$
  1127. deprint cdr l
  1128. >> else write " nil "$
  1129. >>$
  1130. return l$
  1131. end$
  1132. symbolic procedure tailsum(sk,k,x)$
  1133. begin scalar j$
  1134. j:=-1$
  1135. return reval cons('PLUS,
  1136. for each a in sk collect
  1137. <<j:=j+1$
  1138. list('TIMES,a,prod(j+1,j+k),list('EXPT,x,j)) >> )
  1139. end$
  1140. symbolic procedure prod(m,n)$
  1141. if m>n then 1
  1142. else for i:=m:n product i$
  1143. endmodule$
  1144. %********************************************************************
  1145. module intfactor$
  1146. %********************************************************************
  1147. % Routines for finding integrating factors of PDEs
  1148. % Author: Thomas Wolf
  1149. % July 1994
  1150. % The following without factorization --> faster but less general
  1151. %symbolic procedure fctrs(p,vl,v)$
  1152. %begin scalar fl1,fl2,neg;
  1153. %
  1154. %write"p=",p;
  1155. %
  1156. % if car p='MINUS then <<neg:=t;p:=cdr p>>$
  1157. % return
  1158. % if not pairp p then if my_freeof(p,v) and (not freeoflist(p,vl)) then
  1159. % list(p,1,neg) else
  1160. % list(1,p,neg)
  1161. % else if car p='PLUS then list(1,p,neg)
  1162. % else
  1163. % if car p='TIMES then
  1164. % <<for each el in cdr p do if my_freeof(el,v) and (not freeoflist(p,vl)) then
  1165. % fl1:=cons(el,fl1) else
  1166. % fl2:=cons(el,fl2);
  1167. % if pairp fl1 then fl1:=cons('TIMES,fl1);
  1168. % if pairp fl2 then fl2:=cons('TIMES,fl2);
  1169. % if not fl1 then fl1:=1;
  1170. % if not fl2 then fl2:=1;
  1171. % list(fl1,fl2,neg)
  1172. % >> else if my_freeof(p,v) and (not freeoflist(p,vl)) then
  1173. % list(p,1,neg) else
  1174. % list(1,p,neg)
  1175. %end$ % of fctrs
  1176. %
  1177. symbolic procedure fctrs(p,indep,v)$
  1178. begin scalar fl1,fl2;
  1179. p:=cdr reval factorize p;
  1180. for each el in p do
  1181. if freeoflist(el,indep) and
  1182. ((v=nil) or (not my_freeof(el,v))) then fl1:=cons(el,fl1)
  1183. else fl2:=cons(el,fl2);
  1184. if null fl1 then fl1:=1;
  1185. if null fl2 then fl2:=1;
  1186. if pairp fl1 then if length fl1 = 1 then fl1:=car fl1
  1187. else fl1:=cons('TIMES,fl1);
  1188. if pairp fl2 then if length fl2 = 1 then fl2:=car fl2
  1189. else fl2:=cons('TIMES,fl2);
  1190. return list(fl1,fl2)
  1191. end$ % of fctrs
  1192. symbolic procedure extractfac(p,indep,v)$
  1193. % looks for factors of p dependent of v and independent of indep
  1194. % and returns a list of the numerator factors and a list of the
  1195. % denominator factors
  1196. begin scalar nu,de$
  1197. return
  1198. if (pairp p) and (car p='QUOTIENT) then
  1199. <<nu:=fctrs( cadr p,indep,v);
  1200. de:=fctrs(caddr p,indep,v);
  1201. list( reval if car de neq 1 then list('QUOTIENT, car nu, car de)
  1202. else car nu,
  1203. if cadr de neq 1 then list('QUOTIENT, cadr nu, cadr de)
  1204. else cadr nu
  1205. )
  1206. >> else fctrs(p,indep,v)
  1207. end$ % of extractfac
  1208. %----------------------------
  1209. symbolic procedure get_kernels(ex)$
  1210. % gets the list of all kernels in ex
  1211. begin scalar res,pri$
  1212. % pri:=t;
  1213. ex:=reval ex$
  1214. if pri then <<terpri()$write"ex=",ex>>;
  1215. if pairp ex then
  1216. if (car ex='QUOTIENT) or (car ex='PLUS) or (car ex='TIMES) then
  1217. for each s in cdr ex do res:=union(get_kernels s,res) else
  1218. if (car ex='MINUS) or
  1219. ((car ex='EXPT) and
  1220. % (numberp caddr ex)) then % not for e.g. (quotient,2,3)
  1221. (cadr ex neq 'E) and
  1222. (cadr ex neq 'e) and
  1223. (not fixp cadr ex) ) then res:=get_kernels cadr ex
  1224. else res:=list ex
  1225. else if idp ex then res:=list ex$
  1226. if pri then <<terpri()$write"res=",res>>;
  1227. return res$
  1228. end$
  1229. %------------------
  1230. symbolic procedure specialsol(p,vl,fl,x,indep,gk)$
  1231. % tries a power ansatz for the functions in fl in the kernels
  1232. % of p to make p to zero
  1233. % indep is a list of kernels, on which the special solution should
  1234. % not depend. Is useful, to reduce the search-space, e.g. when an
  1235. % integrating factor for a linear equation for, say f, is to be
  1236. % found then f itself can not turn up in the integrating factor fl
  1237. % gk are kernels which occur in p and possibly extra ones which
  1238. % e.g. are not longer in p because of factorizing p but which are
  1239. % likely to play a role, if nil then determined below
  1240. % x is a variable on which each factor in the special solution has
  1241. % to depend on.
  1242. begin
  1243. scalar e1,e2,n,nl,h,hh,ai,sublist,eqs,startval,pri,printold,pcopy;
  1244. %pri:=t;
  1245. p:=num p;
  1246. pcopy:=p;
  1247. if pri then <<
  1248. terpri()$write"The equation for the integrating factor:";
  1249. terpri()$eqprint p;
  1250. >>;
  1251. if null gk then gk:=get_kernels(p);
  1252. for each e1 in fl do <<
  1253. h:=nil; %---- h is the power ansatz
  1254. if pri then
  1255. for each e2 in gk do <<
  1256. terpri()$write"e2=",e2;
  1257. if my_freeof(e2,x) then write" freeof1";
  1258. if not freeoflist(e2,fl) then write" not freeoflist"$
  1259. if not freeoflist(e2,indep) then write" dependent on indep"
  1260. >>;
  1261. %----- nl is the list of constants to be found
  1262. for each e2 in gk do
  1263. if (not my_freeof(e2,x)) and % integ. fac. should depend on x
  1264. freeoflist(e2,fl) and % the ansatz for the functions to be
  1265. % solved should not include these functions
  1266. freeoflist(e2,indep) then <<
  1267. n:=gensym();nl:=cons(n,nl);
  1268. h:=cons(list('EXPT,e2,n),h);
  1269. >>;
  1270. if h then <<
  1271. if length h > 1 then h:=cons('TIMES,h)
  1272. else h:=car h;
  1273. %-- the list of substitutions for the special ansatz
  1274. sublist:=cons((e1 . h),sublist);
  1275. if pri then <<terpri()$write"Ansatz: ",e1," = ",h>>;
  1276. p:= reval num reval subst(h,e1,p);
  1277. if pri then <<terpri()$write"p=";eqprint p>>
  1278. >>
  1279. >>;
  1280. if null h then return nil;
  1281. %------- An numerical approach to solve for the constants
  1282. if nil then << % numerical approach
  1283. %--- Substituting all kernels in p by numbers
  1284. on rounded;
  1285. precision 20;
  1286. terpri()$terpri()$write"Before substituting numerical values:";
  1287. eqprint p;
  1288. terpri()$terpri()$write"Constants to be calculated: ";
  1289. for each n in nl do write n," ";
  1290. for each e1 in nl do <<
  1291. h:=p;
  1292. for each e2 in gk do
  1293. if freeoflist(e2,fl) then
  1294. if pairp e2 and ((car e2 = 'DF) or (car e2 = 'INT)) then <<
  1295. n:=list('QUOTIENT,1+random 30028,30029);
  1296. terpri();write"substitution done: ",e2," = ",n;
  1297. h:=subst(list('QUOTIENT,1+random 30028,30029),e2,h)
  1298. >>;
  1299. for each e2 in gk do
  1300. if freeoflist(e2,fl) then
  1301. if not(pairp e2 and ((car e2 = 'DF) or (car e2 = 'INT))) then <<
  1302. n:=list('QUOTIENT,1+random 30028,30029);
  1303. terpri();write"substitution done: ",e2," = ",n;
  1304. h:=subst(list('QUOTIENT,1+random 30028,30029),e2,h)
  1305. >>;
  1306. terpri()$terpri()$write"The equation after all substitutions: ";
  1307. terpri()$
  1308. eqprint h;
  1309. eqs:=cons(reval h,eqs);
  1310. startval:=cons(list('EQUAL,e1,1),startval)
  1311. >>;
  1312. if length eqs = 1 then eqs:=cdr eqs
  1313. else eqs:=cons('LIST,eqs);
  1314. if length startval = 1 then startval:=cdr startval
  1315. else startval:=cons('LIST,startval);
  1316. terpri()$write"start rdsolveeval!";terpri()$terpri()$
  1317. h:=rdsolveeval list(eqs,startval);
  1318. eqs:=nil;
  1319. off rounded;
  1320. >>;
  1321. %----- An analytical approach to solve for the constants
  1322. if null pri then <<printold:=print_;print_:=nil>>;
  1323. if p and not zerop p then % uebernommen aus SEPAR
  1324. if not (pairp p and (car p='QUOTIENT) and % " " "
  1325. intersection(argset smemberl(fl,cadr p),vl)) then
  1326. p:=separ2(p,fl,vl) else
  1327. p:=nil;
  1328. if null pri then print_:=printold;
  1329. if p then <<
  1330. % possibly investigating linear dependencies of different caar p
  1331. % solve(lasse x-abhaengige und nl-unabhaengige faktoren fallen von
  1332. % factorize df(reval list('QUOTIENT, caar p1, caar p2),x),nl).
  1333. while p do
  1334. if freeoflist(cdar p,nl) then <<eqs:=nil;p:=nil>>
  1335. % singular system --> no solution
  1336. else <<
  1337. eqs:=cons(cdar p,eqs);
  1338. p:=cdr p
  1339. >>;
  1340. >>;
  1341. if pri then <<terpri()$write"eqs1=",eqs>>;
  1342. if (null eqs) or (length eqs > maxalgsys_) then return nil
  1343. else <<
  1344. if pri then <<
  1345. terpri()$write"The algebraic system to solve for ",nl," is:";
  1346. if length eqs > 1 then deprint eqs
  1347. else eqprint car eqs
  1348. >>;
  1349. if length eqs > 1 then eqs:=cons('LIST,eqs)
  1350. else eqs:=car eqs;
  1351. if pri then <<terpri()$write"eqs2=",eqs;terpri();write"nl=",nl>>$
  1352. % for catching the error message `singular equations'
  1353. hh:=cons('LIST,nl);
  1354. eqs:=<<
  1355. ai:=!!arbint;
  1356. h:=errorset({'solveeval,mkquote{eqs, hh}},nil,nil)
  1357. where !*protfg=t;
  1358. erfg!*:=nil;
  1359. if errorp h then nil else cdar h % cdr for deleting 'LIST
  1360. >>;
  1361. if pri then <<terpri()$write"eqs3a=",eqs," ai=",ai," !!arbint=",
  1362. !!arbint;terpri()>>$
  1363. if not freeof(eqs,'ARBCOMPLEX) then <<
  1364. eqs:=reval car eqs;
  1365. for h:=(ai+1):!!arbint do
  1366. eqs:=subst(0,list('ARBCOMPLEX,h),eqs);
  1367. if pri then <<terpri()$write"eqs3b=",eqs;terpri()>>$
  1368. eqs:=<<
  1369. h:=errorset({'solveeval,mkquote{eqs, hh}},nil,nil)
  1370. where !*protfg=t;
  1371. erfg!*:=nil;
  1372. if errorp h then nil else cdar h % cdr for deleting 'LIST
  1373. >>;
  1374. >>;
  1375. if pri then <<terpri()$write"eqs3c=",eqs;terpri()>>$
  1376. %--- eqs is the list of solutions for the constant exponents of the
  1377. %--- integrating factor
  1378. if null eqs then return nil;
  1379. if length nl=1 then eqs:=list eqs;
  1380. if pri then <<write"nl=",nl," eqs4=",eqs;terpri()>>;
  1381. for each e1 in eqs do << % each e1 is a list of substitutions
  1382. if pri then <<terpri()$write"e2=",e1;terpri()>>$
  1383. if car e1='LIST then e1:=cdr e1;
  1384. if pri then <<terpri()$write"e3=",e1;terpri()>>$
  1385. for each e2 in e1 do <<
  1386. if pri then algebraic write"solution:",symbolic e2;
  1387. sublist:=subst(caddr e2,cadr e2,sublist)
  1388. >>;
  1389. if pri then <<terpri()$write"The sublist is:",sublist>>
  1390. >>;
  1391. >>;
  1392. if pri then <<terpri()$write"pcopy1=",pcopy;terpri()>>$
  1393. for each e1 in sublist do <<
  1394. pcopy:=subst(cdr e1,car e1,pcopy);
  1395. if pri then <<terpri()$write"e1=",e1;terpri();
  1396. write"pcopy2=",pcopy;terpri()>>$
  1397. >>$
  1398. if pri then <<terpri()$write"pcopy3=",reval pcopy;terpri()>>$
  1399. if pri then <<terpri()$write"pcopy4=",reval reval pcopy;terpri()>>$
  1400. if not zerop reval reval pcopy then return nil else
  1401. return for each e1 in sublist collect (car e1 . reval cdr e1)
  1402. end$ % of specialsol
  1403. %------------------
  1404. symbolic operator findintfac$
  1405. symbolic procedure findintfac(pl,ftem,vl,x,doneintvar,intfacdep,
  1406. factr,verbse)$
  1407. % - pl is a list of equations from which the *-part (inhomogeneous
  1408. % terms) have been dropped.
  1409. % - each equation of pl gets an integrating factor h
  1410. % - doneintvar is a list of variables, on which the integrating factor
  1411. % should not depend. The chances to find an integrating factor
  1412. % increase if the inhomogeneous part of pl is dropped and
  1413. % separately integrated with generalized integration later.
  1414. % - if factr is not nil then the equation(s) pl is(are) at first
  1415. % factorized, e.g. if integration(s) have already been done
  1416. % and there is a chance that the equation can factorize, thereby
  1417. % simplify and giving a higher chance for integrability.
  1418. begin
  1419. scalar h,newequ,tozero,fl,e1,pri,factr,exfactors,ftr,gk;
  1420. % exfactors is the list of factors extracted at the beginning
  1421. % pri:=t;
  1422. factr:=t; % whether tozero should be factorized
  1423. if pri then <<terpri()$write"START VON FINDINTFAC">>;
  1424. %--- Generation of the condition for the integrating factor(s) in fl
  1425. for each e1 in pl do <<
  1426. %--- extracting factors dependend on x and independent of
  1427. %--- doneintvar but only if integrations have already been done,
  1428. %--- i.e. (doneintvar neq nil)
  1429. gk:=union(gk,get_kernels(e1));
  1430. if factr then <<ftr:=extractfac(e1,append(doneintvar,ftem),x);
  1431. if not evalnumberp car ftr then
  1432. gk:=union(gk,list car ftr);
  1433. >>
  1434. else ftr:=list(1,nil);
  1435. exfactors:=cons(car ftr,exfactors);
  1436. if car ftr neq 1 then <<
  1437. e1:=cadr ftr;
  1438. if pri then <<terpri()$write"extracted factor:",eqprint car ftr>>;
  1439. >>;
  1440. %--- fl is to become the list of integrating factors h
  1441. h:=gensym();
  1442. depl!*:=cons(list(h,x),depl!*)$
  1443. depend h,x;
  1444. fl:=h . fl;
  1445. e1:=intpde(reval list('TIMES,h,e1),ftem,vl,x,t);
  1446. if e1 and car e1 then <<
  1447. newequ:=car e1 . newequ;
  1448. tozero:=cadr e1 . tozero;
  1449. if pri then <<
  1450. terpri()$write" the main part of integration:"$ eqprint(car e1);
  1451. terpri()$write"car e1=",car e1;
  1452. terpri()$write" the remainder of integration:"$ eqprint(cadr e1);
  1453. terpri()$write"cadr e1=",cadr e1;
  1454. >>
  1455. >>;
  1456. >>;
  1457. if null tozero then return nil;
  1458. %-------- newequ is the integral
  1459. newequ:=if length pl > 1 then cons('PLUS,newequ)
  1460. else car newequ;
  1461. %-------- tozero is the PDE for the integrating factor
  1462. tozero:=reval if length pl > 1 then cons('PLUS,tozero)
  1463. else car tozero;
  1464. if pairp tozero and (car tozero='QUOTIENT) then tozero:=cadr tozero$
  1465. if factr then <<
  1466. h:=cdr reval list('FACTORIZE,tozero)$
  1467. if pri then <<terpri()$write"The factors of tozero:",h>>;
  1468. tozero:=nil;
  1469. for each e1 in h do
  1470. if smemberl(fl,e1) then tozero:=cons(e1,tozero)$
  1471. tozero:= reval if length tozero > 1 then cons('TIMES,tozero)
  1472. else car tozero;
  1473. >>;
  1474. if nil and pri then <<write"tozero =";eqprint tozero >>;
  1475. h:=nil;
  1476. % actually only those f in ftem, in which pl is nonlinear, but also
  1477. % then only integrating factors with a leading derivative low enough
  1478. h:=specialsol(tozero,vl,fl,x,append(ftem,doneintvar),gk);
  1479. % h:=specialsol(tozero,vl,fl,x,doneintvar,gk);
  1480. if pri then <<write"h=",h;terpri()>>;
  1481. if h then <<
  1482. for each e1 in h do << % each e1 is one integrating factor determined
  1483. if pri then <<terpri()$write"e1=",e1;
  1484. terpri()$write"newequ=",newequ;terpri()>>;
  1485. newequ:=reval subst(cdr e1,car e1,newequ);
  1486. if pri then <<terpri()$write"newequ=",newequ>>;
  1487. >>
  1488. >> else if pri then write"no integrating factor";
  1489. %--- delete all dependencies of the functions in fl
  1490. %--- must come before the following update
  1491. for each e1 in fl do <<
  1492. depl!*:=delete(assoc(e1,depl!*),depl!*)$
  1493. depl!*:=delete(assoc(mkid(e1,'_),depl!*),depl!*)$
  1494. >>;
  1495. %--- update intfacdep
  1496. for each e1 in vl do
  1497. if (e1 neq x) and my_freeof(intfacdep,e1) and
  1498. ((not my_freeof(h,e1)) or (not my_freeof(exfactors,e1)))
  1499. then intfacdep:=cons(e1,intfacdep);
  1500. %--- returns nil if no integrating factor else a list of the
  1501. %--- factors and the integral
  1502. if h and print_ and verbse then <<
  1503. terpri()$write"The integrated equation:";
  1504. eqprint newequ;
  1505. terpri()$
  1506. if length pl = 1 then write"An integrating factor has been found:"
  1507. else write"Integrating factors have been found: "$
  1508. >>;
  1509. return if (null h) or (zerop newequ) then nil else
  1510. list(newequ,
  1511. for each e1 in h collect <<
  1512. ftr:=car exfactors;
  1513. exfactors:=cdr exfactors;
  1514. gk:=if ftr=1 then cdr e1
  1515. else reval list('QUOTIENT,cdr e1,ftr);
  1516. if print_ and verbse then mathprint gk;
  1517. gk
  1518. >>,
  1519. intfacdep)
  1520. end$
  1521. endmodule$
  1522. %********************************************************************
  1523. module odeintegration$
  1524. %********************************************************************
  1525. % Routines for integration of ode's containing unnown functions
  1526. % Author: Thomas Wolf
  1527. % August 1991
  1528. symbolic procedure integrateode(de,fold,xnew,ordr,ftem)$
  1529. % once equations are factorized before integration the % * lines
  1530. % can be droped or reduced
  1531. begin scalar newde,newnewde,l,l1,h,factrs,fc,changd,newcond,facnum$
  1532. if pairp de and (car de='QUOTIENT) then de:=cadr de$ % *
  1533. factrs:=cdr reval list('FACTORIZE,de); % *
  1534. facnum:=length factrs; % *
  1535. l:=for each fc in factrs collect % *
  1536. if not smember(fold,fc) then <<facnum:=facnum-1;fc>> % *
  1537. else % *
  1538. <<if facnum>1 then <<l1:=integrableode(fc,ftem); % *
  1539. if l1 then <<fold:=car l1; % *
  1540. xnew:=cadr l1; % *
  1541. ordr:=caddr l1 % *
  1542. >> % *
  1543. >> % *
  1544. else l1:=t;
  1545. h:= % the integrated equation
  1546. if not l1 then nil else % *
  1547. if not xnew then << % Integr. einer alg. Gl. fuer eine Abl.
  1548. newde:=cadr solveeval list(fc,fold)$
  1549. if not freeof(newde,'ROOT_OF) then nil
  1550. else <<
  1551. newde:=reval list('PLUS,cadr newde,list('MINUS,caddr newde))$
  1552. if (l:=integratepde(newde,ftem,nil,genint_,nil)) then
  1553. <<newcond:=append(newcond,cdr l);car l>>
  1554. %genflag=t,potflag=nil
  1555. else nil
  1556. >>
  1557. >> else % eine ode fuer ein f?
  1558. if not pairp fold then % i.e. not df(...,...), i.e. fold=f
  1559. odeconvert(fc,fold,xnew,ordr,ftem)
  1560. % --> ode fuer eine Abl. von f
  1561. else <<
  1562. newde:=odeconvert(fc,fold,xnew,ordr,ftem)$
  1563. if not newde then nil
  1564. else <<
  1565. newnewde:=cadr solveeval list(newde,fold)$
  1566. newnewde:=reval list('PLUS,cadr newnewde,list('MINUS,
  1567. caddr newnewde))$
  1568. ftem:=union(fnew_,ftem)$
  1569. newnewde:=integratede(newnewde,ftem,nil)$
  1570. if newnewde then <<newcond:=append(newcond,cdr newnewde);
  1571. car newnewde>>
  1572. else newde
  1573. >>
  1574. >>;
  1575. if h then <<changd:=t;h>> % factors to be collected % *
  1576. else fc % *
  1577. >>;
  1578. return if not changd then nil
  1579. else
  1580. cons(if length l > 1 then cons('TIMES,l) % *
  1581. else car l ,newcond) % *
  1582. end$ % of integrateode
  1583. symbolic procedure odecheck(ex,fint,ftem)$
  1584. % assumes an revaled expression ex
  1585. % Does wrong if car ex is a list!
  1586. begin scalar a,b,op,ex1$
  1587. %***** ex is a ftem-function *****
  1588. if ex=fint then % list(ex,0,0,..)
  1589. <<a:=list ex$
  1590. ex:=fctargs ex$
  1591. while ex do
  1592. <<a:=append(list(0,0),a)$
  1593. ex:=cdr ex>>$
  1594. % not checked if it is a function of an expression of x
  1595. op:=reverse a>>
  1596. else if pairp ex then
  1597. %***** car ex is 'df *****
  1598. if (car ex)='df then
  1599. <<a:=odecheck(cadr ex,fint,ftem)$
  1600. if not pairp a then op:=a
  1601. else % a is list(fctname,0,0,..,0,0)
  1602. <<op:=list(car a)$
  1603. a:=fctargs car a$ % a is list(variables), not checked
  1604. ex:=cddr ex$ % ex is list(derivatives)
  1605. while a do
  1606. <<ex1:=ex$
  1607. while ex1 and ((car a) neq (car ex1)) do ex1:=cdr ex1$
  1608. if null ex1 then op:=cons(0,cons(0,op))
  1609. else
  1610. <<if not cdr ex1 then b:=1 % b is number of deriv. of that var.
  1611. else
  1612. <<b:=cadr ex1$
  1613. if not numberp b then b:=1>>$
  1614. op:=cons(b,cons(b,op))>>$
  1615. a:=cdr a>>$
  1616. op:=reverse op>> >>
  1617. else
  1618. %***** car ex is a standard or other function *****
  1619. <<a:=car ex$ % for linearity check
  1620. ex:=cdr ex$
  1621. if a='INT then ex:=list reval car ex$
  1622. while (op neq '!_abb) and ex do
  1623. <<b:=odecheck(car ex,fint,ftem)$
  1624. if b then % function found
  1625. if b eq '!_abb then op:='!_abb % occures properly
  1626. else op:=odetest(op,b)$
  1627. ex:=cdr ex>> >>$
  1628. return op
  1629. end$
  1630. symbolic procedure integrableode(p,ftem)$
  1631. if delength p>(if odesolve_ then odesolve_ else 0) then
  1632. (if cont_ then
  1633. if yesp("expression to be integrated ? ") then
  1634. integrableode1(p,ftem))
  1635. else integrableode1(p,ftem)$
  1636. symbolic procedure integrableode1(p,ftem)$
  1637. begin scalar a,b,u,vl,le,uvar,
  1638. fint,fivar,% the function to be integrated and its variables
  1639. fold, % the new function of the ode
  1640. xnew, % the independ. variable of the ode
  1641. ordr1, % order of the ode
  1642. ordr2, % order of the derivative for which it is an ode
  1643. intlist$ % list of ode's
  1644. ftem:=smemberl(ftem,p)$
  1645. vl:=argset ftem$
  1646. % p muss genau eine Funktion aus ftem von allen Variablen enthalten.
  1647. % Die Integrationsvariable darf nicht Argument anderer in p enthaltener
  1648. % ftem-Funktionen sein.
  1649. a:=ftem$
  1650. b:=nil$
  1651. le:=length vl$
  1652. while a and vl do
  1653. <<u:=car a$
  1654. uvar:=fctargs u$
  1655. if (length uvar) = le then
  1656. if b then
  1657. <<vl:=nil$a:=list(nil)>>
  1658. else
  1659. <<b:=t$
  1660. fint:=u$
  1661. fivar:=uvar>>
  1662. else vl:=setdiff(vl,uvar)$
  1663. a:=cdr a>>$
  1664. if not b then vl:=nil$
  1665. le:=length p$
  1666. if ((1<le) and vl) then
  1667. <<a:=odecheck(p,fint,ftem)$
  1668. if not atom a then % The equation is an ode
  1669. <<ordr1:=0$
  1670. ordr2:=0$
  1671. xnew:=nil$
  1672. a:=cdr a$
  1673. b:=fivar$
  1674. while b do
  1675. <<if (car a) neq 0 then
  1676. <<fold:=cons(car b,fold)$
  1677. if (car a) > 1 then fold:=cons(car a,fold)>>$
  1678. ordr2:=ordr2+car a$
  1679. if (car a) neq (cadr a) then
  1680. <<xnew:=car b$
  1681. if not member(xnew,vl) then
  1682. <<b:=list(nil)$vl:=nil>>$
  1683. ordr1:=(cadr a) - (car a)>>$
  1684. b:=cdr b$
  1685. a:=cddr a>>$
  1686. fold:=reverse fold$
  1687. %fold is the list of diff.variables + number of diff.
  1688. if fold then fold:=cons('df,cons(fint,fold))
  1689. else fold:=fint$
  1690. if vl and ((ordr1 neq 0) or (ordr2 neq 0)) then
  1691. intlist:=list(fold,xnew,ordr1,ordr2)
  1692. >> % of variable found
  1693. >>$ % of if
  1694. return intlist
  1695. end$ % of integrableode1
  1696. symbolic procedure odetest(op,b)$
  1697. if not op then b
  1698. else % op=nil --> first function found
  1699. if (car op) neq (car b) then '!_abb else % f occurs in differ. fct.s
  1700. begin scalar dif,a$
  1701. dif:=nil$ % dif=t --> different derivatives
  1702. a:=list(car op)$ % in one variable already found
  1703. op:=cdr op$
  1704. b:=cdr b$
  1705. while op do
  1706. <<a:=cons(max(cadr op,cadr b),cons(min(car op,car b),a))$
  1707. if (car a) neq ( cadr a) then
  1708. if dif then
  1709. <<a:='!_abb$
  1710. op:=list(1,1)>>
  1711. else dif:=t$
  1712. op:=cddr op$
  1713. b:=cddr b>>$
  1714. if not atom a then a:=reverse a$
  1715. return a % i.e. '!_abb or (fctname,min x1-der.,max x1-der.,...)
  1716. end$
  1717. symbolic procedure odeconvert(de,ford,xnew,ordr,ftem)$
  1718. begin scalar j,ford_,newco,oldde,newde,newvl,null_,ruli,zd$
  1719. % trig1,trig2,trig3,trig4,trig5,trig6$
  1720. ford_:=gensym()$
  1721. depl!*:=delete(assoc(ford_,depl!*),depl!*)$
  1722. depend1(ford_,xnew,t)$
  1723. oldde:=reval subst(ford_,reval ford,de)$
  1724. if pairp ford then % i.e. (car ford) eq 'DF then
  1725. << for j:=1:ordr do
  1726. oldde:= subst( reval list('DF,ford_,xnew,j),
  1727. reval list('DF,ford,xnew,j), oldde)>>$
  1728. algebraic !!arbconst:=0$
  1729. newde:=algebraic first
  1730. odesolve(symbolic oldde,symbolic ford_,symbolic xnew)$
  1731. ruli:= start_let_rules()$
  1732. newde:=reval newde;
  1733. % Instead of the following test one should return several cases
  1734. zd:=zero_den(newde,cons(ford_,ftem),union(list xnew,argset ftem));
  1735. % if safeint_ and zero_den(newde,ftem,argset ftem) then newde:=nil;
  1736. if freeint_ and null freeof(newde,'INT) then newde:=nil;
  1737. if newde and (cadr newde neq oldde) then << % solution found
  1738. % Test der Loesung klappt nur, wenn Loesung explizit gegeben
  1739. if cadr newde neq ford_ then <<
  1740. if print_ then
  1741. <<write "Solution of the ode is not explicitly given."$
  1742. algebraic write "Equation is: ",algebraic symbolic oldde$
  1743. algebraic write "Solution is: ",algebraic symbolic newde
  1744. >>;
  1745. if poly_only then % The solution must be rational in the
  1746. % function and constants of integration
  1747. if not rationalp(newde,ford_) then newde:=nil else <<
  1748. j:=1;
  1749. while (j leq ordr) and
  1750. rationalp(subst(ford_,list('arbconst,j),newde),ford_) do j:=j+1;
  1751. if j leq ordr then newde:=nil
  1752. >>;
  1753. if newde then
  1754. if (caadr newde = 'QUOTIENT) and (zerop caddr newde) then
  1755. newde:={'EQUAL,cadadr newde,0} else
  1756. if (caaddr newde = 'QUOTIENT) and (zerop cadr newde) then
  1757. newde:={'EQUAL,0,cadr caddr newde}
  1758. >> else <<
  1759. null_:=reval reval aeval subst(caddr newde, ford_, oldde)$
  1760. % reval reval because of a REDUCE bug for special data,
  1761. % to be dropped as soon as possible
  1762. if (null_ neq 0) then <<
  1763. % newde:=nil$
  1764. if print_ then <<
  1765. write "odesolve solves : "$
  1766. deprint list oldde$
  1767. write "to"$
  1768. deprint list newde$
  1769. Write "which inserted in the equation yields"$
  1770. deprint list null_$
  1771. >>
  1772. >>
  1773. >>
  1774. >>$
  1775. if newde then
  1776. <<newde:=list('PLUS,cadr newde,list('MINUS,caddr newde))$
  1777. if zerop reval list('PLUS,newde,list('MINUS,oldde)) then newde:=nil$
  1778. if newde and (zd neq nil) then
  1779. newde:=cons('TIMES,append(zd,list newde))$
  1780. >>$
  1781. depl!*:=delete(assoc(ford_,depl!*),depl!*)$
  1782. stop_let_rules(ruli)$
  1783. return
  1784. if null newde then nil
  1785. else
  1786. <<newde:=subst(ford,ford_,newde)$
  1787. newvl:=delete(xnew,if (pairp ford and (car ford='DF))
  1788. then fctargs cadr ford
  1789. else fctargs ford)$
  1790. % if pairp ford then newvl:=delete(xnew,cdr assoc(cadr ford,depl!*))
  1791. % else newvl:=delete(xnew,cdr assoc(ford,depl!*))$
  1792. for j:=1:ordr do <<
  1793. newco:=newfct(fname_,newvl,nfct_)$
  1794. nfct_:=add1 nfct_$
  1795. fnew_:=cons(newco,fnew_)$
  1796. newde:=subst(newco,list('arbconst,j),newde)
  1797. % newde:=subst(newco, prepf !*kk2f list('arbconst,j),newde)
  1798. % newde:=reval subst(newco,list('arbconst,j),newde)
  1799. % newde:=reval subst(newco, prepf !*kk2f list('arbconst,j),newde)
  1800. >>$
  1801. newde>>
  1802. end$
  1803. endmodule$
  1804. end$