12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919 |
- %*********************************************************************
- module integration$
- %*********************************************************************
- % Routines for integration of pde's
- % Author: Thomas Wolf, Andreas Brand
- % 1993 1995
- %
- % $Id: crint.red,v 1.13 1998/06/25 18:21:25 tw Exp tw $
- %
- symbolic procedure ldlist(p,f,vl)$
- % provides a reverse list of leading derivatives of f in p, vl is list
- % of variables
- begin scalar a$
- if not atom p then
- if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,'QUOTIENT,'DF,'EQUAL))
- then <<
- if (car p='PLUS) or (car p='TIMES) or
- (car p='QUOTIENT) or (car p='EQUAL) then
- <<p:=cdr p$
- while p do
- <<a:=diffincl(a,ldlist(car p,f,vl))$
- p:=cdr p>>
- >> else
- if car p='MINUS then a:=ldlist(cadr p,f,vl) else
- if car p='EXPT then % if numberp caddr p then
- a:=ldlist(cadr p,f,vl) else % fuehrende Abl. aus der Basis
- % else a:=nil
- if car p='DF then if cadr p=f then
- <<p:=cddr p;
- while vl do
- <<a:=cons(dfdeg(p,car vl),a);
- vl:=cdr vl>>;
- a:=list a
- >>
- >>$
- return a
- end$
- symbolic procedure diffincl(a,b)$
- % a,b are lists of leading derivatives which are to be united
- begin
- scalar p;
- while a and b do
- <<a:=ddroplow(a,car b);
- if car a then p:=cons(car a,p);
- a:=cdr a;
- b:=cdr b>>;
- return
- if null a then if p then nconc(p,b)
- else b
- else if p then a:=nconc(p,a)
- else a
- end$
- symbolic procedure ddroplow(a,cb)$
- % loescht Elemente von a, von denen cb eine Ableitung ist, loescht cb,
- % wenn ein Element von a eine Ableitung von cb ist
- begin
- scalar h;
- return
- if null a then list(cb)
- else
- <<h:=compdiffer(car a,cb);
- if numberp(h) then if h>0 then cons(nil,a) % car a=df(cb,..
- else ddroplow(cdr a,cb) % cb=df(car a,..
- else <<h:=ddroplow(cdr a,cb); % neither
- cons(car h,cons(car a,cdr h))>>
- >>
- end$
- symbolic procedure compdiffer(p,q)$
- % finds whether p is a derivative of q or q of p or neither
- begin
- scalar p!>q,q!>p;
- while p and ((null p!>q) or (null q!>p)) do
- <<if car p>car q then p!>q:=t else % compare orders of derivatives
- if car p<car q then q!>p:=t;
- p:=cdr p;q:=cdr q
- >>;
- return
- if q!>p then if p!>q then nil % neither
- else 0 % q is derivative of p
- else if p!>q then 2 % p is derivative of q
- else 1 % p equal q
- end$
- symbolic procedure ldintersec(a)$
- % determines the intersection of derivatives in the list a
- begin
- scalar b;
- return
- if null a then nil else
- <<b:=car a;a:=cdr a;
- while a do
- <<b:=isec(b,car a)$
- a:=cdr a
- >>;
- b
- >>
- end$
- symbolic procedure isec(ca,b)$
- % determines the minimum derivatives between ca and b
- begin
- scalar newb;
- while ca do
- <<newb:=cons(if car b<car ca then car b else car ca, newb);
- ca:=cdr ca;b:=cdr b
- >>;
- return reverse newb
- end$
- symbolic procedure disjun(a,b)$
- <<while a do
- if (car a neq 0) and (car b neq 0) then a:=nil
- else <<a:=cdr a;b:=cdr b>>;
- if b then nil else t
- >>$
- symbolic procedure ddrophigh(a,cb)$
- % loescht Elemente von a, die Ableitung von cb sind,
- % loescht cb, wenn cb Ableitung eines Elements von a ist oder =a ist,
- % haengt cb ansonsten an
- begin
- scalar h;
- return
- if null a then list(cb)
- else
- <<h:=compdiffer(car a,cb);
- if numberp(h) then if h<2 then a % cb is deriv or = car a
- else ddrophigh(cdr a,cb) % car a=df(cb,..
- else cons(car a,ddrophigh(cdr a,cb)) % neither
- >>
- end$
- symbolic procedure elibar(l1,l2,lds)$
- begin
- scalar found1,found2,h;
- % found1=t if an LD=l1 is found, found2=t if contradiction found
- while lds and (not found2) do
- <<if car lds=l1 then found1:=t else
- <<h:=compdiffer(l2,car lds);
- if (null h) or (h eq 2) then found2:=t
- >>;
- lds:=cdr lds
- >>;
- return found1 and (not found2)
- end$
- symbolic procedure intminderiv(p,ftem,vlrev,maxvanz,nfsub)$
- % yields a list {nv1,nv2, ... } such that nvi is the minimum
- % of the highest derivatives w.r.t. vi of all the leading derivatives
- % of all functions of ftem which are functions of all maxvanz variables.
- % Only those are kept for which nvi>0.
- % further a list ((f1 ld's of f1) (f2 ld's of f2)...),
- begin scalar l,a,listoflds$
- while ftem do
- <<if (maxvanz=(fctlength car ftem)) or (nfsub=0) then
- <<l:=ldlist(p,car ftem,vlrev);
- listoflds:=cons(cons(car ftem,l),listoflds)$
- a:=if a then ldintersec(cons(a,l))
- else ldintersec(l)
- >>$
- ftem:=cdr ftem
- >>$
- return list(a,listoflds)
- end$
- symbolic procedure potintegrable(listoflds)$
- begin
- scalar h,l1,l2,f,n,lds,f1,f2$
- if tr_genint then write "Does a potential exist?"$
- %------- Determining 2 minimal sets of integration variables
- % There must be two disjunct LDs such that all others are in their
- % ideal. This is necessary if we want to eliminate 2 functions.
- h:=listoflds;
- l1:=nil;
- while h do
- <<l2:=cdar h; % the list of LDs for the function caar h
- while l2 do
- <<l1:=ddrophigh(l1,car l2)$
- l2:=cdr l2>>;
- h:=cdr h
- >>;
- return
- if length l1 neq 2 then nil else
- if not disjun(car l1,cadr l1) then nil else
- % if there would be an overlap between l1 and l2 then it would have
- % to be integrated for elimination but it cannot --> no overlap
- % possible
- <<% selecting interesting functions for which one LD is = l1 and all
- % others are derivatives of l2 or equal l2 and vice versa. Two
- % necessary (one with an LD=l1 and one with an LD=l2) from which at
- % least one function (f) has no further LD.
- % Exception: 2 functions with each 2 LDs equal to (l1,l2) (these
- % functions are counted by n)
- l2:=cadr l1;l1:=car l1;
- f:=nil;f1:=nil;f2:=nil;n:=0;
- h:=listoflds;
- while h and ((not f1) or (not f2) or ((not f) and (n neq 2))) do
- <<lds:=cdar h;
- if (not f1) or (not f) then
- if elibar(l1,l2,lds) then
- <<f1:=cons(caar h,f1);
- if length lds eq 1 then f:=caar h else
- if length lds eq 2 then
- if (car lds = l2) or (cadr lds = l2) then n:=n+1
- >>;
- if (not f2) or (not f) then
- if elibar(l2,l1,lds) then
- <<f2:=cons(caar h,f2);
- if length lds eq 1 then f:=caar h
- >>;
- h:=cdr h
- >>;
- if f1 and ((n>1) or (f2 and f)) then list(l1,l2)
- else nil
- >>
- end$ % of potintegrable
- symbolic procedure vlofintlist(vl,intlist)$
- % provides a list of elements of vl for which the corresponding
- % elements of intlist are non-zero
- begin scalar a;
- while intlist do
- <<if (car intlist) and (not zerop car intlist) then a:=cons(car vl,a);
- vl:=cdr vl;
- intlist:=cdr intlist
- >>;
- return a
- end$
- symbolic procedure vlofintfaclist(vl,intfaclist)$
- % determining the list of all variables of vl in intfaclist
- begin scalar e1,a;
- for each e1 in vl do
- if not my_freeof(intfaclist,e1) then a:=cons(e1,a);
- return a
- end$
- symbolic procedure multipleint(intvar,ftem,q,vari,vl,genflag,
- potflag,partial,doneintvar)$
- % multiple integration of q wrt. variables in vl, max. number of
- % integrations specified by intvar
- % integrating factors must not depend on doneintvar, doneintvar is
- % a list of integration variables so far
- % partial=t then as much as possible of an expression is integrated
- % even if there is a remainder
- begin
- scalar pri,vlcop,v,nmax,geni,intlist,iflag,n,nges,newcond,
- intfaclist,ph,pih,qh,qih,intfacdepnew,intfacdep$
- % intfacdep is a list of variables on which factors of integration
- % depend so far, other than the integration variable in their
- % integration --> no integration wrt. these variables by potint
- % because there the diff. operators wrt. to different variables
- % need not commute because the integrations are not done
- % pri:=t$
- if (not vari) and (zerop q) then return nil;
- nges:=0;
- vlcop:=vl;
- pih:=t;
- % Splitting of the equation into the homogeneous and inhomogeneous
- % part which is of advantage for finding integrating factors
- q:=splitinhom(q,ftem,vl)$
- qh:=car q; qih:=cdr q; q:=nil;
- while (vari or vlcop) and (pih or (not potflag)) do
- %------- if for potflag=t one variable can not be integrated the
- %------- maximal number of times (nmax) then immediate stop because
- %------- then no elimination of two functions will be possible
- << %-- The next integration variable: x, no of integrations: nmax
- if vari then <<v:=vari;nmax:=1>>
- else <<v:=car vlcop; vlcop:=cdr vlcop;
- nmax:=car intvar; intvar:=cdr intvar>>;
- if zerop nmax then intlist:=cons(nil,intlist)
- else
- <<if pri then write"anf: intvar=",intvar," vari=",vari," q=",q$
- if vari and (not member(v,vl)) then
- <<qh :=reval list('INT,qh ,v)$
- if freeof(qh,'INT) then <<
- qih:=reval list('INT,qih,v)$
- iflag:=if freeint_ and
- (null freeof(qih,'INT)) then nil
- else <<
- intlist:=cons(list(1),intlist)$
- 'success>>$
- if pri then <<write"232323 qh=",qh;terpri();
- write"qih=",qih;terpri()>>
- >>
- >> else
- <<n:=0$
- if pri then write"333"$
- intfaclist:=nil; %-- the list of integr. factors in v-integr.
- if potflag or my_freeof(intfacdep,v) then
- % otherwise v-integration not allowed because one integrating
- % factor already depends on v
- % for potflag=t this `commutativity'-demand plays no role
- repeat << %--- max nmax integrations of qh and qih wrt. v
- if pri then <<write"444 vor intpde:"$eqprint q$terpri()$
- write"potflag=",potflag," v=",v,
- " ftem=",ftem>>$
- % At first trying a direct integration of the homog. part qh
- ph:=intpde(qh,ftem,vl,v,partial)$ % faster if potflag=nil
- if pri then <<write"nach intpde(qh):"$deprint ph>>$
- %------ At first the integration of the homogeneous part
- intfacdepnew:=intfacdep;
- if ph and (partial or (zerop cadr ph)) then <<
- %---- For the homogen. part cadr ph must be zero
- intfaclist:=cons(1,intfaclist);
- ph:=car ph;
- if pri then <<write"565656 ph=",ph;terpri()>>;
- >> else
- if vari then ph:=nil
- else
- if facint_ then <<
- ph:=findintfac(list(qh),ftem,vl,v,doneintvar,intfacdep,
- not zerop n,not potflag);
- % factorize before ivestig., no report of int. factors
- if ph then << %--- Complete integr. of qh was possible
- if print_ then write"of the homogeneous part"$terpri()$
- %--- update the list of variables on which all integr.
- %--- factors depend apart from the integration variable
- intfacdepnew:=caddr ph;
- %--- extend the list of integrating factors, cadr ph
- %--- is a list of integr. factors, here only one
- intfaclist:=cons(caadr ph,intfaclist);
- %--- multiply the inhomogeneous part with integ. factor
- qih:=reval reval reval list('TIMES,car intfaclist,qih);
- if pri then <<write"454545 qih=",qih;terpri()>>;
- ph:=car ph % the integral of qh
- >>
- >>;
- %------ Now the integration of the inhomogeneous part
- if not ph then pih:=nil %--- no integration possible
- else <<
- if zerop qih then pih:=list(0,0) else
- pih:=intpde(qih,ftem,vl,v,partial)$
- if null pih then
- write"error2: inhom. expr. can not be integrated"$
- if pri then <<write"nach intpde(qih):",pih$terpri()$
- write"genflag=",genflag$terpri()>>$
- if pih then
- if zerop cadr pih then
- <<qih:=car pih$n:=add1 n$iflag:='success$
- if pri then write" success "$
- >>
- else if not genflag then pih:=nil
- else
- <<if pri then write"555"$
- geni:=partint(cadr pih,smemberl(ftem,cadr pih),
- vl,v,genflag)$
- if geni then
- <<qih:=reval list('PLUS,car pih,car geni)$
- n:=add1 n$
- ftem:=union(fnew_,ftem)$
- newcond:=append(cdr geni,newcond)$ % additional de's
- if pri then
- <<terpri()$write"nach gen newcond:",newcond>>$
- iflag:='genint
- >> else
- if partial then qih:=car pih
- else pih:=nil
- >>;
- if pih then <<
- if pri then write"AAA"$
- qh:=ph;
- if (not potflag) and (n neq 1) then
- intfacdep:=intfacdepnew
- %-The first integr. factor of all v-integrations does not
- % depend on any earlier integration variables and can
- % therefore be taken out of all integrals --> no incease
- % of intfacdep for n=1.
- %-For potential integration the integration variables and
- % extra-dependencies-variables of integr. factors need not
- % be disjunct therefore the intfacdep-update only for
- % not-potflag
- >> else <<
- if pri then write"BBB"$
- % inhomogeneous part can not be integrated therefore
- % reversing the succesful integration of the hom. part
- if car intfaclist neq 1 then
- qih:=reval list('QUOTIENT,qih,car intfaclist);
- intfaclist:=cdr intfaclist
- >>;
- >>; %-- end of the integration of the inhomog. part
- if pri then write"n=",n," nmax=",nmax," not pih=",not pih$
- >> until (n=nmax) or (not pih)$ %---- end of v-integration
- %------- variables of done integrations are collected for
- %------- determining integrating factors in later integr.
- if not zerop n then doneintvar:=cons(v,doneintvar)$
- nges:=nges+n;
- intlist:=cons(intfaclist,intlist)
- >>$ % of not ( vari and (not member(v,vl)))
- if vari then <<vari:=nil;vlcop:=nil>>;
- if pri then write"ende: intvar=",intvar," vari=",vari,
- " qh=",qh," qih=",qih$
- >> % of (nmax neq zero)
- >>$ % of ( while (vari or vlcop) and (pih or (not potflag)) )
- % intlist and its elements intfaclist are in the inverse order
- % to vl and the sequence of integrations done
- q:=reval list('PLUS,qh,qih)$ %--- adding homog. and inhomog. part
- if pri then <<terpri()$write"\\\ newcond:"$deprint newcond;
- write"multiple result:",if null iflag then nil
- else list(q,intlist,newcond,nges)
- >>;
- return if null iflag then nil
- else list(q,intlist,newcond,nges)
- end$ % of multipleint
- symbolic procedure uplistoflds(intlist,listoflds)$
- begin
- scalar f,h1,h2,h3,h4,lds,itl;
- while listoflds do
- <<f:=caar listoflds;
- lds:=cdar listoflds;
- listoflds:=cdr listoflds;
- h2:=nil; % h2 becomes the new list of lds of f
- while lds do
- <<h3:=car lds; lds:=cdr lds;
- itl:=intlist;
- h4:=nil; % h4 becomes one new ld of f
- while h3 do
- <<h4:=cons(car h3 - if null car itl then 0
- else length car itl, h4);
- h3:=cdr h3;itl:=cdr itl
- >>;
- h2:=cons(reverse h4,h2)
- >>;
- h1:=cons(cons(f,h2),h1)
- >>;
- return h1 % updated listoflds
- end$ % of uplistoflds
- symbolic procedure addintco(q, ftem, ifac, vl, vari)$
- begin scalar v,f,l,vl1;
- % multi.ing factors to the constants/functions of integration
- if zerop q then l:=1
- else
- <<ftem:=fctsort ftem$
- while ftem do
- if fctlength car ftem<length vl then ftem:=nil
- else if fctlinear(q,f) then
- <<f:=car ftem$ ftem:=nil>> else
- ftem:=cdr ftem$
- if f then
- <<l:=lderiv(q,f,fctargs f)$
- l:=reval coeffn(q,reval car l,cdr l)
- >> else l:=1
- >>;
- % the constants and functions of integration
- if vari then q:=list('PLUS,q,intconst(l,vl,vari,list(1)))
- else
- <<vl1:=vl;
- while vl1 do
- <<v:=car vl1; vl1:=cdr vl1;
- if car ifac then
- q:=list('PLUS,q,intconst(l,vl,v,car ifac))$
- % l..product of factors in the coefficient of the function to be
- % eliminated, car ifac .. list of integrating factors
- ifac:=cdr ifac;
- >>
- >>$
- return reval q
- end$ % of addintco
- symbolic procedure integratepde(p,ftem,vari,genflag,potflag)$
- % Generalized integration of the expression p
- % if not genflag then "normal integration"
- % Equation p must not be directly separable, otherwise the depen-
- % dencies of functions of integration on their variables is wrong,
- % i.e. no dependence on explicit variables
- % ftem are all functions from the `global' ftem which occur in p, i.e.
- % ftem:=smemberl(ftem,p)$
- % if vari=nil then integration w.r.t. all possible variables within
- % the equation
- % else only w.r.t. vari one time
- begin
- scalar vl,vlrev,v,intlist,
- ili1a,ili2a,maxvanz,fsub,h,hh,nfsub,iflag,newcond,
- n1,n2,pot1,pot2,p1,p2,listoflds,secnd,ifac0,
- ifac1a,ifac1b,ifac2a,ifac2b,cop,v1a,v2a,pri$
- % pri:=t;
- if pri then <<terpri()$write"Start Integratepde">>$
- vl:=argset ftem$
- vlrev:=reverse vl;
- if vari then <<potflag:=nil;
- if zerop p then iflag:='success>>
- else
- <<%------- determining fsub=list of functions of all variables
- maxvanz:=length vl$
- fsub:=nil;
- h:=ftem;
- while h do
- <<if fctlength car h=maxvanz then
- fsub:=cons(car h,fsub)$
- h:=cdr h
- >>$
- nfsub:=length fsub$ % must be >1 for potential-integration
- h:=intminderiv(p,ftem,vlrev,maxvanz,nfsub)$ % fsub is also for below
- intlist:=car h$
- %-- list of necessary integrations of the whole equation to solve
- %-- for a function of all variables
- listoflds:=cadr h$ %-- list of leading derivatives
- >>$
- if pri then <<terpri()$
- write"complete integrations:",intlist," for:",vl>>;
- %-- n1 is the number of integrations which must be done to try
- %-- potential integration which must enable to eliminate 2 functions
- %-- n2 is the number of integrations actually done
- n1:=for each h in intlist sum h;
- if (not vari) and (zerop n1) then
- <<n2:=0;
- if potflag then % else not necessary
- for h:=1:(length vl) do ifac0:=cons(nil,ifac0)
- >> else
- <<if tr_genint then
- <<terpri()$write "integration of the expression : "$
- eqprint p>>$
- if pri then
- <<terpri()$write"at first all multiple complete integration">>;
- %-- At first if possible n2 integrations of the whole equation
- h:=multipleint(intlist,ftem,p,vari,vl,genflag,nil,nil,nil)$
- % potflag=nil, partial=nil, doneintvar=nil
- if h then
- <<p:=car h;
- ifac0:=cadr h; % ifac0 is the list of lists of integr. factors
- newcond:=caddr h;
- n2:=cadddr h; % number of done integrations
- % doneintvar & intfacdep for the two halfs of integrations
- % from the two parts of ifac0
- h:=nil;
- iflag:='success;
- >> else n2:=0;
- ftem:=union(fnew_,ftem)$
- >>;
- %------------ Existence of a potential ?
- if (n1=n2) and potflag and (nfsub>1) then
- %---- at least 2 functions to solve for
- <<if not zerop n2 then %---- update listoflds
- listoflds:=uplistoflds(reverse ifac0,listoflds)$
- if pri then <<terpri()$write"uplistoflds:",listoflds>>$
- if h:=potintegrable(listoflds) then
- <<ili1a:=car h; ili2a:=cadr h;
- % The necess. differentiations of the potential
- if pri then
- <<terpri()$write"potintegrable:",ili1a," ",ili2a>>$
- if pri then <<write"+++ intlist=",intlist,
- " ili1a=",ili1a,
- " ili2a=",ili2a>>$
- %-- distributing the integrating factors of ifac0 among
- %-- the two lists ifac1b and ifac2b which are so far nil
- %-- such that (ifac1b and ili1a are disjunct) and
- %-- (ifac2b and ili2a are disjunct)
- v1a:=vlofintlist(vl,ili1a);
- v2a:=vlofintlist(vl,ili2a);
- hh:=t;
- cop:=reverse ifac0;
- ifac1a:=ili1a;ifac2a:=ili2a;
- while hh and cop do <<
- % cop is a list of lists of integr. factors
- if car cop then h:=vlofintfaclist(vl,cdar cop)
- else h:=nil;
- if freeoflist(h,v2a) and (car ifac2a=0) then <<
- ifac1b:=cons( nil, ifac1b);
- ifac2b:=cons( reverse car cop, ifac2b)
- >> else
- if freeoflist(h,v1a) and (car ifac1a=0) then <<
- ifac2b:=cons( nil, ifac2b);
- ifac1b:=cons( reverse car cop, ifac1b)
- >> else
- if car cop then hh:=nil;
- ifac1a:=cdr ifac1a;
- ifac2a:=cdr ifac2a;
- cop:=cdr cop;
- >>;
- % the elements of ifac1b,ifac2b are in reverse order to
- % ifac1a,ifac2a and are in the same order as vl, also
- % the elements in the infac-lists are in inverse order,
- % i.e. in the order the integrations have been done
- if pri then <<terpri()$
- write "ifac1a=",ifac1a," ifac1b=",ifac1b,
- " ifac2a=",ifac2a," ifac2b=",ifac2b >>$
- %-- lists of integrations to be done to both parts
- if hh then
- repeat % possibly a second try with part2 integrated first
- <<n1:=for each n1 in ili1a sum n1;
- % n1 .. number of remaining integrations of the first half
- p1:=multipleint(ili1a,ftem,p,nil,vl,genflag,t,t,
- % potflag=t, partial=t
- union(vlofintlist(vl,ili2a),
- vlofintlist(vl,ifac1b)))$
- % that the variables of integration are not in ifac1b
- % was already checked. Only restriction: the integrating
- % factors must not depend on the last argument.
- ftem:=union(fnew_,ftem)$
- if p1 then <<
- ifac1a:=cadr p1;
- % ifac1a is now the list of integrating factors
- if newcond then newcond:=nconc(newcond,caddr p1)
- else newcond:=caddr p1;
- if pri then <<terpri()$write"mul2: newcond=",newcond>>$
- n2:=cadddr p1;
- p1:=car p1
- >>;
- if p1 and (n1=n2) then
- %--- if the first half has been integrated suff. often
- <<%--- integrating the second half sufficiently often
- n1:=for each n1 in ili2a sum n1;
- % calculation of the 2. part which is not contained in p1
- p2:=p1;
- cop:=ifac1a; hh:=vlrev; % because ifac1a is reversed
- while cop do <<
- h:=car cop;cop:=cdr cop;
- v:=car hh;hh:=cdr hh;
- % h is the list of integrating factors of the v-integr.
- while h do <<
- p2:=reval list('QUOTIENT,list('DF,p2,v),car h);
- h:=cdr h
- >>
- >>;
- p2:=reval reval list('PLUS,p,list('MINUS,p2));
- p2:=multipleint(ili2a,ftem,p2,nil,vl,genflag,t,nil,
- % potflag=t, partial=nil
- union(vlofintlist(vl,ili1a),
- vlofintlist(vl,ifac2b)))$
- ftem:=union(fnew_,ftem)$
- if p2 then <<
- ifac2a:=cadr p2;
- % ifac2a is now list of integrating factors
- if newcond then newcond:=nconc(newcond,caddr p2)
- else newcond:=caddr p2;
- if pri then <<terpri()$write"mul3: newcond=",newcond>>$
- n2:=cadddr p2;
- p2:=car p2
- >>;
- if p2 and (n1=n2) then
- % if the second half has been integrated sufficiently often
- <<% can both halfes be solved for different functions
- % i.e. are they algebraic and linear in different functions?
- pot1:=nil;
- pot2:=nil;
- for each h in fsub do <<
- if ld_deriv_search(p1,h,vl) = (nil . 1) then
- pot1:=cons(h,pot1);
- if ld_deriv_search(p2,h,vl) = (nil . 1) then
- pot2:=cons(h,pot2);
- >>$
- if (null not_included(pot1,pot2)) or
- (null not_included(pot2,pot1)) then p2:=nil
- >>$
- if p2 and (n1=n2) then
- <<iflag:='potint;
- % ifac1b,ifac2b are in reverse order to ifac1a,ifac2a!
- pot1:=newfct(fname_,vl,nfct_)$ % the new potential fct.
- pot2:=pot1;
- nfct_:=add1 nfct_$
- fnew_:=cons(pot1,fnew_);
- v:=vlrev;
- while v do
- <<cop:=car ifac1a; ifac1a:=cdr ifac1a;
- while cop do <<
- pot1:=reval list('QUOTIENT,list('DF,pot1,car v),car cop);
- cop:=cdr cop
- >>;
- cop:=car ifac2a; ifac2a:=cdr ifac2a;
- while cop do <<
- pot2:=reval list('QUOTIENT,list('DF,pot2,car v),car cop);
- cop:=cdr cop
- >>;
- v:=cdr v;
- >>;
- p:=addintco(list('PLUS,p1,reval pot2),
- ftem,ifac1b,vlrev,nil)$
- newcond:=cons(addintco(list('PLUS,p2,
- list('MINUS,reval pot1)),
- ftem,ifac2b,vlrev,nil),
- newcond) % vari=nil
- >>
- ;if pri then write":::"$
- >>;
- secnd:=not secnd;
- % retry in different order of integration, p is still the same
- if (iflag neq 'potint) and secnd then
- <<cop:=ili1a;ili1a:=ili2a;ili2a:=cop>>
- >> until (iflag eq 'potint) or (not secnd)
- >>;
- >>$
- %--------- returning the result
- return if not iflag then nil
- else
- <<if iflag neq 'potint then % constants of integration
- p:=addintco(p, ftem, % the completely reversed ifac0
- <<h:=nil;
- while ifac0 do <<h:=cons(reverse car ifac0,h);ifac0:=cdr ifac0>>;
- h
- >>, vl, vari)$
- if pri then
- <<terpri()$write"ENDE INTEGRATEPDE"$deprint(cons(p,newcond))>>$
- cons(p,newcond)
- >>
- end$ % of integratepde
- symbolic procedure intpde(p,ftem,vl,x,potint)$
- % integration of an polynomial expr. p w.r.t. x
- begin scalar f,ft,l,l1,l2,vl,k,s,a,iflag,flag$
- ft:=ftem$
- vl:=cons(x,delete(x,vl))$
- while ftem and not flag do
- <<f:=car ftem$ % integrating all terms including car ftem
- if member(x,fctargs f) then
- <<l1:=l:=lderiv(p,f,vl)$
- while not (flag or (iflag:=intlintest(l,x))) do
- <<k:=reval coeffn(p,car l,cdr l)$
- if intcoefftest(car lderiv(k,f,vl),car l,vl) then
- <<a:=decderiv(car l,x)$
- k:=reval list('INT,subst('v_a_r_,a,k),'v_a_r_)$
- k:=reval subst(a,'v_a_r_,k)$
- s:=cons(k,s)$
- p:=reval aeval list('DIFFERENCE,p,list('DF,k,x))$
- if (l:=lderiv(p,f,vl))=l1 then flag:='neverending
- else l1:=l
- >> else
- flag:='coeffld
- >>$
- % iflag='nofct is the so far integrable case
- % the non-integrable cases are: flag neq nil,
- % (iflag neq nil) and (iflag neq 'nofct), an exception to the
- % second case is potint where non-integrable rests are allowed
- if iflag='nofct then ftem:=smemberl(ftem,p)
- else if potint or (fctlength f<length vl) then
- <<ftem:=cdr ftem$flag:=nil>> else
- flag:=(iflag or flag)
- >> else
- ftem:=cdr ftem
- >>$
- return
- if not flag then
- <<l:=explicitpart(p,ft,x)$
- l1:=list('INT,l,x)$
- s:=reval aeval cons('PLUS,cons(l1,s))$
- if freeint_ and
- (null freeof(s,'INT)) then nil
- else <<
- k:=start_let_rules()$
- l2 := reval {'DF,l1,x} where !*precise=nil;
- if 0 neq (reval {'DIFFERENCE,l,l2} where !*precise=nil) then <<
- write"REDUCE integrator error:"$terpri()$
- algebraic write "int(",l,",",x,") neq ",l1;terpri()$
- write"Result ignored.";terpri()$
- stop_let_rules(k)$
- nil
- >> else <<
- p:=reval reval aeval list('DIFFERENCE,p,l2)$
- stop_let_rules(k)$
- if poly_only then if ratexp(s,ft) then list(s,p)
- else nil
- else list(s,p)
- >>
- >>
- >> else nil$
- end$ % of intpde
- symbolic procedure explicitpart(p,ft,x)$
- % part of a sum p which only explicitly depends on a variable x
- begin scalar l$
- if not member(x,argset smemberl(ft,p)) then l:=p
- else if pairp p then
- <<if car p='MINUS then
- l:=reval list('MINUS,explicitpart(cadr p,ft,x))$
- if (car p='QUOTIENT) and not member(x,argset smemberl(ft,caddr p))
- then
- l:=reval list('QUOTIENT,explicitpart(cadr p,ft,x),caddr p)$
- if car p='PLUS then
- <<for each a in cdr p do
- if not member(x,argset smemberl(ft,a)) then l:=cons(a,l)$
- if pairp l then l:=reval cons('PLUS,l)>> >>$
- if not l then l:=0$
- return l$
- end$
- symbolic procedure intconst(co,vl,x,ifalist)$
- % The factors in ifalist must be in the order of integrations done
- if null ifalist then 0 else
- begin scalar l,l2,f,coli,cotmp$
- while ifalist do <<
- cotmp:=coli;
- coli:=nil;
- while cotmp do <<
- coli:=cons(list('INT,list('TIMES,car ifalist,car cotmp),x),coli);
- cotmp:=cdr cotmp
- >>;
- coli:=cons(1,coli);
- ifalist:=cdr ifalist
- >>;
- while coli do
- <<f:=newfct(fname_,delete(x,vl),nfct_)$
- nfct_:=add1 nfct_$
- fnew_:=cons(f,fnew_)$
- l:=cons(list('TIMES,f,car coli),l)$
- coli:=cdr coli
- >>$
- if length l>1 then l:=cons('PLUS,l)
- else if pairp l then l:=car l
- else l:=0$
- if co and co neq 1 then
- if pairp co then
- <<if car co='TIMES then co:=cdr co
- else co:=list co$
- while co do <<if my_freeof(car co,x) then l2:=cons(car co,l2)$
- co:=cdr co>>
- >>
- else if co neq x then l2:=list co$
- return reval if l2 then cons('TIMES,cons(l,l2))
- else l
- end$
- symbolic procedure intcoefftest(l,l1,vl)$
- begin scalar s$
- return if not pairp l then t
- else if car l='DF then
- <<s:=decderiv(l1,car vl)$
- if pairp s and pairp cdr s then s:=cddr s
- else s:=nil$
- if diffrelp(cons(cddr l,1),cons(s,1),vl) then t
- else nil>>
- else t$
- end$
- symbolic procedure fctlinear(p,f)$
- <<p:=ldiffp(p,f)$
- (null car p) and (cdr p=1)>>$
- symbolic procedure intlintest(l,x)$
- % Test,ob in einem Paar (fuehrende Ableitung.Potenz)
- % eine x-Ableitung linear auftritt
- if not car l then
- if zerop cdr l then 'nofct
- else 'nonlin
- else % Fkt. tritt auf
- if (car l) and (cdr l=1) then % fuehr. Abl. tritt linear auf
- if pairp car l then % Abl. der Fkt. tritt auf
- if caar l='DF then
- if member(x,cddar l) then nil
- % x-Abl. tritt auf
- else if member(x,fctargs cadar l) then 'noxdrv
- else 'noxdep
- else 'nodrv
- else 'nodrv
- else 'nonlin$
- symbolic procedure decderiv(l,x)$
- % in Diff.ausdr. l wird Ordn. d. Abl. nach x um 1 gesenkt
- begin scalar l1$
- return if l then if car l='DF then
- <<l1:=decderiv1(cddr l,x)$
- if l1 then cons('DF,cons(cadr l,l1))
- else cadr l>>
- else l
- else nil$
- end$
- symbolic procedure decderiv1(l,x)$
- if null l then nil
- else
- if car l=x then
- if cdr l then
- if numberp cadr l then
- if cadr l>2 then cons(car l,cons(sub1 cadr l,cddr l))
- else cons(car l,cddr l)
- else cdr l
- else nil
- else cons(car l,decderiv1(cdr l,x))$
- symbolic procedure integratede(q,ftem,genflag)$
- % Integration of a de
- % result: newde if successfull, nil otherwise
- begin scalar l,l1,l2,fl$
- ftem:=smemberl(ftem,q)$
- again:
- if l1:=integrableode(q,ftem) then % looking for an integrable ode
- if l1:=integrateode(q,car l1,cadr l1,caddr l1,ftem) then
- % trying to integrate it
- <<l:=append(cdr l1,l);
- q:=simplifypde(car l1,ftem,nil)$
- ftem:=smemberl(union(fnew_,ftem),q)$
- fl:=t
- >>$
- if l1:=integratepde(q,ftem,nil,genflag,potint_) then
- % trying to integrate a pde
- <<q:=car l1$
- for each a in cdr l1 do
- <<ftem:=union(fnew_,ftem)$
- if (l2:=integratede(a,ftem,nil)) then l:=append(l2,l)
- else l:=cons(a,l)
- >>$
- fl:=t$
- if null genflag then l1:=nil$
- ftem:=smemberl(union(fnew_,ftem),q);
- goto again
- >>$
- if fl then
- <<l:=cons(q,l)$
- l:=for each a in l collect reval aeval a$
- l:=for each a in l collect
- if pairp a and (car a='QUOTIENT) then cadr a
- else a>>$
- return l$
- end$
- symbolic procedure intflagtest(q,fullint)$
- if flagp(q,'to_int) then
- if fullint then
- if get(q,'full_int) then t else
- if get(q,'starde) then nil else
- begin scalar fl,vl,dl,l,n,mi$
- n:=get(q,'nvars)$
- for each f in get(q,'rational) do % only rational fcts
- if fctlength f=n then fl:=cons(f,fl)$
- if null fl then return nil$
- vl:=get(q,'vars)$
- dl:=get(q,'derivs)$
- for each d in dl do
- if member(caar d,fl) then
- put(caar d,'maxderivs,maxderivs(get(caar d,'maxderivs),cdar d,vl))$
- dl:=fl$
- while vl do
- <<mi:=car get(car fl,'maxderivs)$
- l:=list car fl$
- put(car fl,'maxderivs,cdr get(car fl,'maxderivs))$
- for each f in cdr fl do
- <<if (n:=car get(f,'maxderivs))=mi then l:=cons(f,l)
- else if n<mi then
- <<l:=list f$
- mi:=n>>$
- put(f,'maxderivs,cdr get(f,'maxderivs))
- >>$
- dl:=intersection(l,dl)$
- if dl then vl:=cdr vl
- else vl:=nil>>$
- for each f in fl do remprop(f,'maxderivs)$
- return dl
- end
- else t$
- symbolic procedure integrate(q,genintflag,fullint)$
- % integrate pde q; if genintflag is not nil then indirect
- % integration is allowed
- % if fullint is not nil then only full integration is allowed
- % Es wird noch nicht ausgenutzt:
- % 1) Fcts, die rational auftreten
- % 2) starde
- begin scalar l$
- if intflagtest(q,fullint) then
- <<if (l:=integratede(get(q,'val),get(q,'fcts),genintflag)) then
- <<ftem_:=reverse ftem_$
- for each f in reverse fnew_ do
- ftem_:=fctinsert(f,ftem_)$
- ftem_:=reverse ftem_$
- fnew_:=nil$
- flag1(q,'to_eval)$
- update(q,car l,ftem_,get(q,'vars),t,list(0))$
- l:=cons(q,mkeqlist(cdr l,ftem_,get(q,'vars),
- allflags_,t,get(q,'orderings)))$
- remflag1(q,'to_int)$
- if print_ then
- <<terpri()$
- if cdr l
- then write "Indirect integration of ",q," yields ",l
- else write "Integration of ",q>>$
- >>$
- remflag1(q,'to_int)>>$
- return l$
- end$
- symbolic procedure quick_integrate_one_pde(pdes)$
- begin scalar m,q,p$
- % find the lowest order derivative wrt. only one variable
- while pdes and
- (get(car pdes,'length) = 1) do << % only 1 term
- q:=caar get(car pdes,'derivs)$
- if ( length q = 2 ) or
- ((length q = 3) and
- (fixp caddr q) and
- ((null p) or
- (caddr q<m) ) ) then
- <<p:=car pdes;
- m:=if (length q = 2) then 1
- else caddr q>>;
- pdes:=cdr pdes
- >>$
- if p then p:=integrate(p,nil,t)$
- return p
- end$
- symbolic procedure integrate_one_pde(pdes,genintflag,fullint)$
- % trying to integrate one pde
- begin scalar l,l1,m,p$
- % at first selecting all eligible de's
- m:=-1$
- while pdes do <<
- if flagp(car pdes,'to_int) and not(get(car pdes,'starde)) then <<
- l:=cons(car pdes,l);
- if get(car pdes,'nvars)>m then m:=get(car pdes,'nvars)$
- >>;
- pdes:=cdr pdes
- >>;
- l:=reverse l;
- % find an equation with as many as possible variables for integration
- while m>=0 do <<
- l1:=l$
- while l1 do
- if (get(car l1,'nvars)=m) and
- (p:=integrate(car l1,genintflag,fullint)) then <<
- m:=-1$
- l1:=nil
- >> else l1:=cdr l1$
- m:=sub1 m
- >>$
- return p$
- end$
- endmodule$
- %********************************************************************
- module generalized_integration$
- %********************************************************************
- % Routines for generalized integration of pde's containing unknown
- % functions
- % Author: Andreas Brand
- % December 1991
- symbolic procedure gintorder(p,ftem,vl,x)$
- % reorder equation p
- begin scalar l,l1,q,m,b,c,q1,q2$
- if pairp(p) and (car p='QUOTIENT) then <<
- q:=caddr p$
- p:=cadr p$
- l1:=gintorder1(q,ftem,x,t)$
- if DepOnAllVars(car l1,x,vl) then return nil;
- q1:=car l1;
- q2:=cadr l1;
- >>$
- if pairp(p) and (car p='PLUS) then p:=cdr p % list of summands
- else p:=list p$
- while p do
- <<l1:=gintorder1(car p,ftem,x,nil)$
- if DepOnAllVars(car l1,x,vl) then l:=p:=nil
- else <<l:=termsort(l,l1)$p:=cdr p>> >>$
- if l then
- <<l:=for each a in l collect if cddr a then
- <<b:=car a$
- c:=cdr reval coeff1(cons('PLUS,cdr a),x,nil)$
- m:=0$
- while c and (car c=0) do <<c:=cdr c$m:=add1 m>>$
- if m>0 then b:=list('TIMES,list('EXPT,x,m),b)$
- cons(reval b,c)>>
- else
- cons(reval car a,cdr reval coeff1(cadr a,x,nil))$
- if q then <<
- l:=for each a in l collect
- cons(car a,for each s in cdr a collect
- reval list('QUOTIENT,s,q2))$
- l:=for each a in l collect
- cons(reval list('QUOTIENT,car a,q1),cdr a)
- >>$
- >>$
- return l$
- end$
- symbolic procedure DepOnAllVars(c,x,vl)$
- % tests for occurence of vars from vl in factors of c depending on x
- begin scalar l$
- if pairp c and (car c='TIMES) then c:=cdr c
- else c:=list c$
- while c and vl do
- <<if not my_freeof(car c,x) then
- for each v in vl do if not my_freeof(car c,v) then l:=cons(v,l)$
- vl:=setdiff(vl,l)$
- c:=cdr c
- >>$
- return (null vl)$
- end$
- symbolic procedure gintorder1(p,ftem,x,mode2)$
- % reorder a term p
- begin scalar l1,l2,sig$
- % mode2 = nil then
- % l2:list of factors of p not depending
- % on x or beeing a power of x
- % l1:all other factors
- % mode2 = t then
- % l2:list of factors of p not depending on x
- % l1:all other factors
- if pairp p and (car p='MINUS) then <<sig:=t$p:=cadr p>>$
- if pairp p and (car p='TIMES) then p:=cdr p
- else p:=list p$
- for each a in p do
- <<if my_freeof(a,x) and freeoflist(a,ftem) then l2:=cons(a,l2)
- % freeoflist(a,ftem) to preserve linearity
- else if mode2 then l1:=cons(a,l1)
- else if a=x then l2:=cons(a,l2)
- else if pairp a and (car a='EXPT) and (cadr a=x) and fixp caddr a
- then l2:=cons(a,l2)
- else l1:=cons(a,l1)>>$
- if pairp l1 then
- if cdr l1 then l1:=cons('TIMES,l1)
- else l1:=car l1$
- if pairp l2 then
- if cdr l2 then l2:=cons('TIMES,l2)
- else l2:=car l2$
- if sig then if l2 then l2:=list('MINUS,l2)
- else l2:=list('MINUS,1)$
- return list(if l1 then l1 else 1,if l2 then l2 else 1)$
- end$
- symbolic procedure partint(p,ftem,vl,x,genint)$
- begin scalar f,neg,l1,l2,n,k,l,h$
- if tr_genint then <<
- terpri()$
- write "generalized integration of the unintegrated rest : "$
- eqprint p
- >>$
- l:=gintorder(p,ftem,vl,x)$
- % would too many new equations and functions be necessary?
- if pairp(l) and (length(l)>genint) then return nil;
- l:=for each s in l collect <<
- h:=varslist(car s,ftem,vl)$
- if h=nil then <<
- list('TIMES,x,car s,cons('PLUS,cdr s))
- >> else <<
- f:=newfct(fname_,h,nfct_)$
- nfct_:=add1 nfct_$
- fnew_:=cons(f,fnew_)$
- neg:=t$
- n:=sub1 length cdr s$
- k:=-1$
- if (pairp car s) and (caar s='DF) then
- <<h:=reval reval list('DIFFERENCE,cadar s,list('DF,f,x,add1 n))$
- if not zerop h then l1:=cons(h,l1)$
- l2:=cddar s>>
- else
- <<h:=signchange reval reval list('DIFFERENCE,car s,
- list('DF,f,x,add1 n))$
- if not zerop h then l1:=cons(h,l1)$
- l2:=nil>>$
- reval cons('PLUS, for each sk on cdr s collect
- <<neg:=not neg$
- k:=add1 k$
- reval list('TIMES,if neg then -1 else 1,
- append(list('DF,f,x,n-k),l2),
- tailsum(sk,k,x) )
- >>
- )
- >>
- >>$
- if l then l:=cons(reval cons('PLUS,l),l1)$
- if tr_genint then
- <<terpri()$
- write "result (without constant or function of integration): "$
- if l then <<
- eqprint car l$
- write "additional equations : "$
- deprint cdr l
- >> else write " nil "$
- >>$
- return l$
- end$
- symbolic procedure tailsum(sk,k,x)$
- begin scalar j$
- j:=-1$
- return reval cons('PLUS,
- for each a in sk collect
- <<j:=j+1$
- list('TIMES,a,prod(j+1,j+k),list('EXPT,x,j)) >> )
- end$
- symbolic procedure prod(m,n)$
- if m>n then 1
- else for i:=m:n product i$
- endmodule$
- %********************************************************************
- module intfactor$
- %********************************************************************
- % Routines for finding integrating factors of PDEs
- % Author: Thomas Wolf
- % July 1994
- % The following without factorization --> faster but less general
- %symbolic procedure fctrs(p,vl,v)$
- %begin scalar fl1,fl2,neg;
- %
- %write"p=",p;
- %
- % if car p='MINUS then <<neg:=t;p:=cdr p>>$
- % return
- % if not pairp p then if my_freeof(p,v) and (not freeoflist(p,vl)) then
- % list(p,1,neg) else
- % list(1,p,neg)
- % else if car p='PLUS then list(1,p,neg)
- % else
- % if car p='TIMES then
- % <<for each el in cdr p do if my_freeof(el,v) and (not freeoflist(p,vl)) then
- % fl1:=cons(el,fl1) else
- % fl2:=cons(el,fl2);
- % if pairp fl1 then fl1:=cons('TIMES,fl1);
- % if pairp fl2 then fl2:=cons('TIMES,fl2);
- % if not fl1 then fl1:=1;
- % if not fl2 then fl2:=1;
- % list(fl1,fl2,neg)
- % >> else if my_freeof(p,v) and (not freeoflist(p,vl)) then
- % list(p,1,neg) else
- % list(1,p,neg)
- %end$ % of fctrs
- %
- symbolic procedure fctrs(p,indep,v)$
- begin scalar fl1,fl2;
- p:=cdr reval factorize p;
- for each el in p do
- if freeoflist(el,indep) and
- ((v=nil) or (not my_freeof(el,v))) then fl1:=cons(el,fl1)
- else fl2:=cons(el,fl2);
- if null fl1 then fl1:=1;
- if null fl2 then fl2:=1;
- if pairp fl1 then if length fl1 = 1 then fl1:=car fl1
- else fl1:=cons('TIMES,fl1);
- if pairp fl2 then if length fl2 = 1 then fl2:=car fl2
- else fl2:=cons('TIMES,fl2);
- return list(fl1,fl2)
- end$ % of fctrs
- symbolic procedure extractfac(p,indep,v)$
- % looks for factors of p dependent of v and independent of indep
- % and returns a list of the numerator factors and a list of the
- % denominator factors
- begin scalar nu,de$
- return
- if (pairp p) and (car p='QUOTIENT) then
- <<nu:=fctrs( cadr p,indep,v);
- de:=fctrs(caddr p,indep,v);
- list( reval if car de neq 1 then list('QUOTIENT, car nu, car de)
- else car nu,
- if cadr de neq 1 then list('QUOTIENT, cadr nu, cadr de)
- else cadr nu
- )
- >> else fctrs(p,indep,v)
- end$ % of extractfac
- %----------------------------
- symbolic procedure get_kernels(ex)$
- % gets the list of all kernels in ex
- begin scalar res,pri$
- % pri:=t;
- ex:=reval ex$
- if pri then <<terpri()$write"ex=",ex>>;
- if pairp ex then
- if (car ex='QUOTIENT) or (car ex='PLUS) or (car ex='TIMES) then
- for each s in cdr ex do res:=union(get_kernels s,res) else
- if (car ex='MINUS) or
- ((car ex='EXPT) and
- % (numberp caddr ex)) then % not for e.g. (quotient,2,3)
- (cadr ex neq 'E) and
- (cadr ex neq 'e) and
- (not fixp cadr ex) ) then res:=get_kernels cadr ex
- else res:=list ex
- else if idp ex then res:=list ex$
- if pri then <<terpri()$write"res=",res>>;
- return res$
- end$
- %------------------
- symbolic procedure specialsol(p,vl,fl,x,indep,gk)$
- % tries a power ansatz for the functions in fl in the kernels
- % of p to make p to zero
- % indep is a list of kernels, on which the special solution should
- % not depend. Is useful, to reduce the search-space, e.g. when an
- % integrating factor for a linear equation for, say f, is to be
- % found then f itself can not turn up in the integrating factor fl
- % gk are kernels which occur in p and possibly extra ones which
- % e.g. are not longer in p because of factorizing p but which are
- % likely to play a role, if nil then determined below
- % x is a variable on which each factor in the special solution has
- % to depend on.
- begin
- scalar e1,e2,n,nl,h,hh,ai,sublist,eqs,startval,pri,printold,pcopy;
- %pri:=t;
- p:=num p;
- pcopy:=p;
- if pri then <<
- terpri()$write"The equation for the integrating factor:";
- terpri()$eqprint p;
- >>;
- if null gk then gk:=get_kernels(p);
- for each e1 in fl do <<
- h:=nil; %---- h is the power ansatz
- if pri then
- for each e2 in gk do <<
- terpri()$write"e2=",e2;
- if my_freeof(e2,x) then write" freeof1";
- if not freeoflist(e2,fl) then write" not freeoflist"$
- if not freeoflist(e2,indep) then write" dependent on indep"
- >>;
- %----- nl is the list of constants to be found
- for each e2 in gk do
- if (not my_freeof(e2,x)) and % integ. fac. should depend on x
- freeoflist(e2,fl) and % the ansatz for the functions to be
- % solved should not include these functions
- freeoflist(e2,indep) then <<
- n:=gensym();nl:=cons(n,nl);
- h:=cons(list('EXPT,e2,n),h);
- >>;
- if h then <<
- if length h > 1 then h:=cons('TIMES,h)
- else h:=car h;
- %-- the list of substitutions for the special ansatz
- sublist:=cons((e1 . h),sublist);
- if pri then <<terpri()$write"Ansatz: ",e1," = ",h>>;
- p:= reval num reval subst(h,e1,p);
- if pri then <<terpri()$write"p=";eqprint p>>
- >>
- >>;
- if null h then return nil;
- %------- An numerical approach to solve for the constants
- if nil then << % numerical approach
- %--- Substituting all kernels in p by numbers
- on rounded;
- precision 20;
- terpri()$terpri()$write"Before substituting numerical values:";
- eqprint p;
- terpri()$terpri()$write"Constants to be calculated: ";
- for each n in nl do write n," ";
- for each e1 in nl do <<
- h:=p;
- for each e2 in gk do
- if freeoflist(e2,fl) then
- if pairp e2 and ((car e2 = 'DF) or (car e2 = 'INT)) then <<
- n:=list('QUOTIENT,1+random 30028,30029);
- terpri();write"substitution done: ",e2," = ",n;
- h:=subst(list('QUOTIENT,1+random 30028,30029),e2,h)
- >>;
- for each e2 in gk do
- if freeoflist(e2,fl) then
- if not(pairp e2 and ((car e2 = 'DF) or (car e2 = 'INT))) then <<
- n:=list('QUOTIENT,1+random 30028,30029);
- terpri();write"substitution done: ",e2," = ",n;
- h:=subst(list('QUOTIENT,1+random 30028,30029),e2,h)
- >>;
- terpri()$terpri()$write"The equation after all substitutions: ";
- terpri()$
- eqprint h;
- eqs:=cons(reval h,eqs);
- startval:=cons(list('EQUAL,e1,1),startval)
- >>;
- if length eqs = 1 then eqs:=cdr eqs
- else eqs:=cons('LIST,eqs);
- if length startval = 1 then startval:=cdr startval
- else startval:=cons('LIST,startval);
- terpri()$write"start rdsolveeval!";terpri()$terpri()$
- h:=rdsolveeval list(eqs,startval);
- eqs:=nil;
- off rounded;
- >>;
- %----- An analytical approach to solve for the constants
- if null pri then <<printold:=print_;print_:=nil>>;
- if p and not zerop p then % uebernommen aus SEPAR
- if not (pairp p and (car p='QUOTIENT) and % " " "
- intersection(argset smemberl(fl,cadr p),vl)) then
- p:=separ2(p,fl,vl) else
- p:=nil;
- if null pri then print_:=printold;
- if p then <<
- % possibly investigating linear dependencies of different caar p
- % solve(lasse x-abhaengige und nl-unabhaengige faktoren fallen von
- % factorize df(reval list('QUOTIENT, caar p1, caar p2),x),nl).
- while p do
- if freeoflist(cdar p,nl) then <<eqs:=nil;p:=nil>>
- % singular system --> no solution
- else <<
- eqs:=cons(cdar p,eqs);
- p:=cdr p
- >>;
- >>;
- if pri then <<terpri()$write"eqs1=",eqs>>;
- if (null eqs) or (length eqs > maxalgsys_) then return nil
- else <<
- if pri then <<
- terpri()$write"The algebraic system to solve for ",nl," is:";
- if length eqs > 1 then deprint eqs
- else eqprint car eqs
- >>;
- if length eqs > 1 then eqs:=cons('LIST,eqs)
- else eqs:=car eqs;
- if pri then <<terpri()$write"eqs2=",eqs;terpri();write"nl=",nl>>$
- % for catching the error message `singular equations'
- hh:=cons('LIST,nl);
- eqs:=<<
- ai:=!!arbint;
- h:=errorset({'solveeval,mkquote{eqs, hh}},nil,nil)
- where !*protfg=t;
- erfg!*:=nil;
- if errorp h then nil else cdar h % cdr for deleting 'LIST
- >>;
- if pri then <<terpri()$write"eqs3a=",eqs," ai=",ai," !!arbint=",
- !!arbint;terpri()>>$
- if not freeof(eqs,'ARBCOMPLEX) then <<
- eqs:=reval car eqs;
- for h:=(ai+1):!!arbint do
- eqs:=subst(0,list('ARBCOMPLEX,h),eqs);
- if pri then <<terpri()$write"eqs3b=",eqs;terpri()>>$
- eqs:=<<
- h:=errorset({'solveeval,mkquote{eqs, hh}},nil,nil)
- where !*protfg=t;
- erfg!*:=nil;
- if errorp h then nil else cdar h % cdr for deleting 'LIST
- >>;
- >>;
- if pri then <<terpri()$write"eqs3c=",eqs;terpri()>>$
- %--- eqs is the list of solutions for the constant exponents of the
- %--- integrating factor
- if null eqs then return nil;
- if length nl=1 then eqs:=list eqs;
- if pri then <<write"nl=",nl," eqs4=",eqs;terpri()>>;
- for each e1 in eqs do << % each e1 is a list of substitutions
- if pri then <<terpri()$write"e2=",e1;terpri()>>$
- if car e1='LIST then e1:=cdr e1;
- if pri then <<terpri()$write"e3=",e1;terpri()>>$
- for each e2 in e1 do <<
- if pri then algebraic write"solution:",symbolic e2;
- sublist:=subst(caddr e2,cadr e2,sublist)
- >>;
- if pri then <<terpri()$write"The sublist is:",sublist>>
- >>;
- >>;
- if pri then <<terpri()$write"pcopy1=",pcopy;terpri()>>$
- for each e1 in sublist do <<
- pcopy:=subst(cdr e1,car e1,pcopy);
- if pri then <<terpri()$write"e1=",e1;terpri();
- write"pcopy2=",pcopy;terpri()>>$
- >>$
- if pri then <<terpri()$write"pcopy3=",reval pcopy;terpri()>>$
- if pri then <<terpri()$write"pcopy4=",reval reval pcopy;terpri()>>$
- if not zerop reval reval pcopy then return nil else
- return for each e1 in sublist collect (car e1 . reval cdr e1)
- end$ % of specialsol
- %------------------
- symbolic operator findintfac$
- symbolic procedure findintfac(pl,ftem,vl,x,doneintvar,intfacdep,
- factr,verbse)$
- % - pl is a list of equations from which the *-part (inhomogeneous
- % terms) have been dropped.
- % - each equation of pl gets an integrating factor h
- % - doneintvar is a list of variables, on which the integrating factor
- % should not depend. The chances to find an integrating factor
- % increase if the inhomogeneous part of pl is dropped and
- % separately integrated with generalized integration later.
- % - if factr is not nil then the equation(s) pl is(are) at first
- % factorized, e.g. if integration(s) have already been done
- % and there is a chance that the equation can factorize, thereby
- % simplify and giving a higher chance for integrability.
- begin
- scalar h,newequ,tozero,fl,e1,pri,factr,exfactors,ftr,gk;
- % exfactors is the list of factors extracted at the beginning
- % pri:=t;
- factr:=t; % whether tozero should be factorized
- if pri then <<terpri()$write"START VON FINDINTFAC">>;
- %--- Generation of the condition for the integrating factor(s) in fl
- for each e1 in pl do <<
- %--- extracting factors dependend on x and independent of
- %--- doneintvar but only if integrations have already been done,
- %--- i.e. (doneintvar neq nil)
- gk:=union(gk,get_kernels(e1));
- if factr then <<ftr:=extractfac(e1,append(doneintvar,ftem),x);
- if not evalnumberp car ftr then
- gk:=union(gk,list car ftr);
- >>
- else ftr:=list(1,nil);
- exfactors:=cons(car ftr,exfactors);
- if car ftr neq 1 then <<
- e1:=cadr ftr;
- if pri then <<terpri()$write"extracted factor:",eqprint car ftr>>;
- >>;
- %--- fl is to become the list of integrating factors h
- h:=gensym();
- depl!*:=cons(list(h,x),depl!*)$
- depend h,x;
- fl:=h . fl;
- e1:=intpde(reval list('TIMES,h,e1),ftem,vl,x,t);
- if e1 and car e1 then <<
- newequ:=car e1 . newequ;
- tozero:=cadr e1 . tozero;
- if pri then <<
- terpri()$write" the main part of integration:"$ eqprint(car e1);
- terpri()$write"car e1=",car e1;
- terpri()$write" the remainder of integration:"$ eqprint(cadr e1);
- terpri()$write"cadr e1=",cadr e1;
- >>
- >>;
- >>;
- if null tozero then return nil;
- %-------- newequ is the integral
- newequ:=if length pl > 1 then cons('PLUS,newequ)
- else car newequ;
- %-------- tozero is the PDE for the integrating factor
- tozero:=reval if length pl > 1 then cons('PLUS,tozero)
- else car tozero;
- if pairp tozero and (car tozero='QUOTIENT) then tozero:=cadr tozero$
- if factr then <<
- h:=cdr reval list('FACTORIZE,tozero)$
- if pri then <<terpri()$write"The factors of tozero:",h>>;
- tozero:=nil;
- for each e1 in h do
- if smemberl(fl,e1) then tozero:=cons(e1,tozero)$
- tozero:= reval if length tozero > 1 then cons('TIMES,tozero)
- else car tozero;
- >>;
- if nil and pri then <<write"tozero =";eqprint tozero >>;
- h:=nil;
- % actually only those f in ftem, in which pl is nonlinear, but also
- % then only integrating factors with a leading derivative low enough
- h:=specialsol(tozero,vl,fl,x,append(ftem,doneintvar),gk);
- % h:=specialsol(tozero,vl,fl,x,doneintvar,gk);
- if pri then <<write"h=",h;terpri()>>;
- if h then <<
- for each e1 in h do << % each e1 is one integrating factor determined
- if pri then <<terpri()$write"e1=",e1;
- terpri()$write"newequ=",newequ;terpri()>>;
- newequ:=reval subst(cdr e1,car e1,newequ);
- if pri then <<terpri()$write"newequ=",newequ>>;
- >>
- >> else if pri then write"no integrating factor";
- %--- delete all dependencies of the functions in fl
- %--- must come before the following update
- for each e1 in fl do <<
- depl!*:=delete(assoc(e1,depl!*),depl!*)$
- depl!*:=delete(assoc(mkid(e1,'_),depl!*),depl!*)$
- >>;
- %--- update intfacdep
- for each e1 in vl do
- if (e1 neq x) and my_freeof(intfacdep,e1) and
- ((not my_freeof(h,e1)) or (not my_freeof(exfactors,e1)))
- then intfacdep:=cons(e1,intfacdep);
- %--- returns nil if no integrating factor else a list of the
- %--- factors and the integral
- if h and print_ and verbse then <<
- terpri()$write"The integrated equation:";
- eqprint newequ;
- terpri()$
- if length pl = 1 then write"An integrating factor has been found:"
- else write"Integrating factors have been found: "$
- >>;
- return if (null h) or (zerop newequ) then nil else
- list(newequ,
- for each e1 in h collect <<
- ftr:=car exfactors;
- exfactors:=cdr exfactors;
- gk:=if ftr=1 then cdr e1
- else reval list('QUOTIENT,cdr e1,ftr);
- if print_ and verbse then mathprint gk;
- gk
- >>,
- intfacdep)
- end$
- endmodule$
- %********************************************************************
- module odeintegration$
- %********************************************************************
- % Routines for integration of ode's containing unnown functions
- % Author: Thomas Wolf
- % August 1991
- symbolic procedure integrateode(de,fold,xnew,ordr,ftem)$
- % once equations are factorized before integration the % * lines
- % can be droped or reduced
- begin scalar newde,newnewde,l,l1,h,factrs,fc,changd,newcond,facnum$
- if pairp de and (car de='QUOTIENT) then de:=cadr de$ % *
- factrs:=cdr reval list('FACTORIZE,de); % *
- facnum:=length factrs; % *
- l:=for each fc in factrs collect % *
- if not smember(fold,fc) then <<facnum:=facnum-1;fc>> % *
- else % *
- <<if facnum>1 then <<l1:=integrableode(fc,ftem); % *
- if l1 then <<fold:=car l1; % *
- xnew:=cadr l1; % *
- ordr:=caddr l1 % *
- >> % *
- >> % *
- else l1:=t;
- h:= % the integrated equation
- if not l1 then nil else % *
- if not xnew then << % Integr. einer alg. Gl. fuer eine Abl.
- newde:=cadr solveeval list(fc,fold)$
- if not freeof(newde,'ROOT_OF) then nil
- else <<
- newde:=reval list('PLUS,cadr newde,list('MINUS,caddr newde))$
- if (l:=integratepde(newde,ftem,nil,genint_,nil)) then
- <<newcond:=append(newcond,cdr l);car l>>
- %genflag=t,potflag=nil
- else nil
- >>
- >> else % eine ode fuer ein f?
- if not pairp fold then % i.e. not df(...,...), i.e. fold=f
- odeconvert(fc,fold,xnew,ordr,ftem)
- % --> ode fuer eine Abl. von f
- else <<
- newde:=odeconvert(fc,fold,xnew,ordr,ftem)$
- if not newde then nil
- else <<
- newnewde:=cadr solveeval list(newde,fold)$
- newnewde:=reval list('PLUS,cadr newnewde,list('MINUS,
- caddr newnewde))$
- ftem:=union(fnew_,ftem)$
- newnewde:=integratede(newnewde,ftem,nil)$
- if newnewde then <<newcond:=append(newcond,cdr newnewde);
- car newnewde>>
- else newde
- >>
- >>;
- if h then <<changd:=t;h>> % factors to be collected % *
- else fc % *
- >>;
- return if not changd then nil
- else
- cons(if length l > 1 then cons('TIMES,l) % *
- else car l ,newcond) % *
- end$ % of integrateode
- symbolic procedure odecheck(ex,fint,ftem)$
- % assumes an revaled expression ex
- % Does wrong if car ex is a list!
- begin scalar a,b,op,ex1$
- %***** ex is a ftem-function *****
- if ex=fint then % list(ex,0,0,..)
- <<a:=list ex$
- ex:=fctargs ex$
- while ex do
- <<a:=append(list(0,0),a)$
- ex:=cdr ex>>$
- % not checked if it is a function of an expression of x
- op:=reverse a>>
- else if pairp ex then
- %***** car ex is 'df *****
- if (car ex)='df then
- <<a:=odecheck(cadr ex,fint,ftem)$
- if not pairp a then op:=a
- else % a is list(fctname,0,0,..,0,0)
- <<op:=list(car a)$
- a:=fctargs car a$ % a is list(variables), not checked
- ex:=cddr ex$ % ex is list(derivatives)
- while a do
- <<ex1:=ex$
- while ex1 and ((car a) neq (car ex1)) do ex1:=cdr ex1$
- if null ex1 then op:=cons(0,cons(0,op))
- else
- <<if not cdr ex1 then b:=1 % b is number of deriv. of that var.
- else
- <<b:=cadr ex1$
- if not numberp b then b:=1>>$
- op:=cons(b,cons(b,op))>>$
- a:=cdr a>>$
- op:=reverse op>> >>
- else
- %***** car ex is a standard or other function *****
- <<a:=car ex$ % for linearity check
- ex:=cdr ex$
- if a='INT then ex:=list reval car ex$
- while (op neq '!_abb) and ex do
- <<b:=odecheck(car ex,fint,ftem)$
- if b then % function found
- if b eq '!_abb then op:='!_abb % occures properly
- else op:=odetest(op,b)$
- ex:=cdr ex>> >>$
- return op
- end$
- symbolic procedure integrableode(p,ftem)$
- if delength p>(if odesolve_ then odesolve_ else 0) then
- (if cont_ then
- if yesp("expression to be integrated ? ") then
- integrableode1(p,ftem))
- else integrableode1(p,ftem)$
- symbolic procedure integrableode1(p,ftem)$
- begin scalar a,b,u,vl,le,uvar,
- fint,fivar,% the function to be integrated and its variables
- fold, % the new function of the ode
- xnew, % the independ. variable of the ode
- ordr1, % order of the ode
- ordr2, % order of the derivative for which it is an ode
- intlist$ % list of ode's
- ftem:=smemberl(ftem,p)$
- vl:=argset ftem$
- % p muss genau eine Funktion aus ftem von allen Variablen enthalten.
- % Die Integrationsvariable darf nicht Argument anderer in p enthaltener
- % ftem-Funktionen sein.
- a:=ftem$
- b:=nil$
- le:=length vl$
- while a and vl do
- <<u:=car a$
- uvar:=fctargs u$
- if (length uvar) = le then
- if b then
- <<vl:=nil$a:=list(nil)>>
- else
- <<b:=t$
- fint:=u$
- fivar:=uvar>>
- else vl:=setdiff(vl,uvar)$
- a:=cdr a>>$
- if not b then vl:=nil$
- le:=length p$
- if ((1<le) and vl) then
- <<a:=odecheck(p,fint,ftem)$
- if not atom a then % The equation is an ode
- <<ordr1:=0$
- ordr2:=0$
- xnew:=nil$
- a:=cdr a$
- b:=fivar$
- while b do
- <<if (car a) neq 0 then
- <<fold:=cons(car b,fold)$
- if (car a) > 1 then fold:=cons(car a,fold)>>$
- ordr2:=ordr2+car a$
- if (car a) neq (cadr a) then
- <<xnew:=car b$
- if not member(xnew,vl) then
- <<b:=list(nil)$vl:=nil>>$
- ordr1:=(cadr a) - (car a)>>$
- b:=cdr b$
- a:=cddr a>>$
- fold:=reverse fold$
- %fold is the list of diff.variables + number of diff.
- if fold then fold:=cons('df,cons(fint,fold))
- else fold:=fint$
- if vl and ((ordr1 neq 0) or (ordr2 neq 0)) then
- intlist:=list(fold,xnew,ordr1,ordr2)
- >> % of variable found
- >>$ % of if
- return intlist
- end$ % of integrableode1
- symbolic procedure odetest(op,b)$
- if not op then b
- else % op=nil --> first function found
- if (car op) neq (car b) then '!_abb else % f occurs in differ. fct.s
- begin scalar dif,a$
- dif:=nil$ % dif=t --> different derivatives
- a:=list(car op)$ % in one variable already found
- op:=cdr op$
- b:=cdr b$
- while op do
- <<a:=cons(max(cadr op,cadr b),cons(min(car op,car b),a))$
- if (car a) neq ( cadr a) then
- if dif then
- <<a:='!_abb$
- op:=list(1,1)>>
- else dif:=t$
- op:=cddr op$
- b:=cddr b>>$
- if not atom a then a:=reverse a$
- return a % i.e. '!_abb or (fctname,min x1-der.,max x1-der.,...)
- end$
- symbolic procedure odeconvert(de,ford,xnew,ordr,ftem)$
- begin scalar j,ford_,newco,oldde,newde,newvl,null_,ruli,zd$
- % trig1,trig2,trig3,trig4,trig5,trig6$
- ford_:=gensym()$
- depl!*:=delete(assoc(ford_,depl!*),depl!*)$
- depend1(ford_,xnew,t)$
- oldde:=reval subst(ford_,reval ford,de)$
- if pairp ford then % i.e. (car ford) eq 'DF then
- << for j:=1:ordr do
- oldde:= subst( reval list('DF,ford_,xnew,j),
- reval list('DF,ford,xnew,j), oldde)>>$
- algebraic !!arbconst:=0$
- newde:=algebraic first
- odesolve(symbolic oldde,symbolic ford_,symbolic xnew)$
- ruli:= start_let_rules()$
- newde:=reval newde;
- % Instead of the following test one should return several cases
- zd:=zero_den(newde,cons(ford_,ftem),union(list xnew,argset ftem));
- % if safeint_ and zero_den(newde,ftem,argset ftem) then newde:=nil;
- if freeint_ and null freeof(newde,'INT) then newde:=nil;
- if newde and (cadr newde neq oldde) then << % solution found
- % Test der Loesung klappt nur, wenn Loesung explizit gegeben
- if cadr newde neq ford_ then <<
- if print_ then
- <<write "Solution of the ode is not explicitly given."$
- algebraic write "Equation is: ",algebraic symbolic oldde$
- algebraic write "Solution is: ",algebraic symbolic newde
- >>;
- if poly_only then % The solution must be rational in the
- % function and constants of integration
- if not rationalp(newde,ford_) then newde:=nil else <<
- j:=1;
- while (j leq ordr) and
- rationalp(subst(ford_,list('arbconst,j),newde),ford_) do j:=j+1;
- if j leq ordr then newde:=nil
- >>;
- if newde then
- if (caadr newde = 'QUOTIENT) and (zerop caddr newde) then
- newde:={'EQUAL,cadadr newde,0} else
- if (caaddr newde = 'QUOTIENT) and (zerop cadr newde) then
- newde:={'EQUAL,0,cadr caddr newde}
- >> else <<
- null_:=reval reval aeval subst(caddr newde, ford_, oldde)$
- % reval reval because of a REDUCE bug for special data,
- % to be dropped as soon as possible
- if (null_ neq 0) then <<
- % newde:=nil$
- if print_ then <<
- write "odesolve solves : "$
- deprint list oldde$
- write "to"$
- deprint list newde$
- Write "which inserted in the equation yields"$
- deprint list null_$
- >>
- >>
- >>
- >>$
- if newde then
- <<newde:=list('PLUS,cadr newde,list('MINUS,caddr newde))$
- if zerop reval list('PLUS,newde,list('MINUS,oldde)) then newde:=nil$
- if newde and (zd neq nil) then
- newde:=cons('TIMES,append(zd,list newde))$
- >>$
- depl!*:=delete(assoc(ford_,depl!*),depl!*)$
- stop_let_rules(ruli)$
- return
- if null newde then nil
- else
- <<newde:=subst(ford,ford_,newde)$
- newvl:=delete(xnew,if (pairp ford and (car ford='DF))
- then fctargs cadr ford
- else fctargs ford)$
- % if pairp ford then newvl:=delete(xnew,cdr assoc(cadr ford,depl!*))
- % else newvl:=delete(xnew,cdr assoc(ford,depl!*))$
- for j:=1:ordr do <<
- newco:=newfct(fname_,newvl,nfct_)$
- nfct_:=add1 nfct_$
- fnew_:=cons(newco,fnew_)$
- newde:=subst(newco,list('arbconst,j),newde)
- % newde:=subst(newco, prepf !*kk2f list('arbconst,j),newde)
- % newde:=reval subst(newco,list('arbconst,j),newde)
- % newde:=reval subst(newco, prepf !*kk2f list('arbconst,j),newde)
- >>$
- newde>>
- end$
- endmodule$
- end$
|