1%******************************************************************** 2module underdetde$ 3%******************************************************************** 4% Routines for the solution of underdetermined ODEs and PDEs 5% Author: Thomas Wolf 6% August 1998, since February 1999 7 8% BSDlicense: ***************************************************************** 9% * 10% Redistribution and use in source and binary forms, with or without * 11% modification, are permitted provided that the following conditions are met: * 12% * 13% * Redistributions of source code must retain the relevant copyright * 14% notice, this list of conditions and the following disclaimer. * 15% * Redistributions in binary form must reproduce the above copyright * 16% notice, this list of conditions and the following disclaimer in the * 17% documentation and/or other materials provided with the distribution. * 18% * 19% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * 20% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * 21% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 22% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE * 23% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 24% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * 25% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 26% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * 27% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 28% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 29% POSSIBILITY OF SUCH DAMAGE. * 30%****************************************************************************** 31 32symbolic procedure undetalg(arglist)$ 33% parametric solution of single underdetermined algebraic equations 34% checking whether there is one equation with 2 functions with at least 35% 2 terms of degree at least 2 but with as low as possible max degree 36% of any function. 37begin scalar pdes,forg,l,l1,p,h,f1,f2,f3,f4,f5$ 38 pdes:=car arglist$ 39 forg:=cadr arglist$ 40 if expert_mode then <<l1:=selectpdes(pdes,1);flag(l1,'to_under)>> 41 else l1:=cadddr arglist$ 42 43 % We have different tests and procedures to apply, each relying on the 44 % equation being rather special. We therefore just check each equation one 45 % by one, concerning all tests not searching for the most promising equation 46 % for one method before trying the other method. The purpose is to be able to 47 % to have only one flag 'to_under which includes all these tests. 48 49 while l1 and null l do 50 if null flagp(car l1,'to_under) and 51 (get(car l1,'nvars)=0) then l1:=cdr l1 52 else << 53 p:=car l1; l1:=cdr l1; 54 remflag1(p,'to_under)$ 55 56 % Currently both methods require that the equation is a polynomial 57 % in 2 unknowns with more than one term 58 h:=get(p,'fcts); 59 if (get(p,'terms)>1) and 60 (null get(p,'nonrational)) and 61 cdr h and 62 null cddr h then << % polynomial in exactly 2 unknowns else done 63 f1:=car h; 64 f2:=cadr h; 65 f3:=nil; f4:=nil; f5:=nil; 66 67 % Currently for both methods the equation needs to be at least 68 % quadratic for each unknown 69 70 h:=get(p,'derivs); 71 while h do << 72 if cdar h > 1 then f3:=union(list caaar h,f3); 73 if cdar h = 2 then f4:=union(list caaar h,f4) else 74 if cdar h > 2 then f5:=union(list caaar h,f5); 75 h:=cdr h 76 >>; 77 78 % 1. Test whether the equation is a polynomial in one variable 79 % which itself is a polynomial in more than one variable. 80 81 if member(f1,f3) and member(f2,f3) then l:=tryalg1(p,pdes); 82 83 % 2. Test whether the equation is itself quadratic and quadratic 84 % in each unknown to compute a complete parametric solution. 85 86 if null l and null f5 and 87 member(f1,f4) and member(f2,f4) then l:=tryalg2(p,pdes) 88 >> 89 >>; 90 if null l then return nil; 91 92 if print_ then << 93 write"Parametric solution of the 'underdetermined' algebraic equation ",p$ 94 terpri(); 95 write"giving the new algebraic equation(s) "$ 96 listprint l; 97 terpri() 98 >>$ 99 for each h in l do << 100 pdes:=eqinsert(h,pdes)$ 101 if member(h,pdes) then 102 to_do_list:=cons(list('subst_level_4,list h),to_do_list)$ 103 >>$ 104 105 return list(pdes,forg) 106end$ 107 108 109symbolic procedure tryalg1(p,pdes)$ 110begin scalar f1,f2,f1d,f2d,d1,d2,gd,phi,newf,q$ 111 112 f2:=get(p,'fcts); 113 f1:=car f2; f1d:=mvar car mksq(f1,1); 114 f2:=cadr f2; f2d:=mvar car mksq(f2,1); 115 116 d1:=diffsq(get(p,'sqval),f1d); 117 d2:=diffsq(get(p,'sqval),f2d); 118 119 gd:=err_catch_gcd({'!*sq,d1,t},{'!*sq,d2,t}); 120 121 return 122 if freeof(gd,f1) or freeof(gd,f2) then nil 123 else << 124 d1:=quotsq(d1,cadr gd); 125 d2:=quotsq(d2,cadr gd); 126 127 if not sqzerop subtrsq(diffsq(d1,f2d),diffsq(d2,f1d)) then nil 128 else << 129 phi:=simp reval list('int,prepsq d1,f1)$ 130 phi:=addsq(phi,simp reval list('int,prepsq subtrsq(d2,diffsq(phi,f2d)),f2)); 131 newf:=newfct(fname_,nil,nfct_)$ 132 nfct_:=add1 nfct_; 133 ftem_:=fctinsert(newf,ftem_)$ 134 q:=mkeqSQ(subtrsq(simp newf,phi),nil,nil,{newf,f1,f2},nil,allflags_,nil, 135 list(0),nil,pdes); 136 put(q,'not_to_eval,{newf})$ 137 {q} 138 >> 139 >> 140end$ 141 142 143symbolic procedure tryalg2(p,pdes)$ 144begin scalar h,f1,f2,f3,s,k,l,d,q$ 145 146 h:=get(p,'fcts); 147 f1:=car h; 148 f2:=cadr h; 149 150 % Is the whole equation only 2nd degree? 151 s:=gensym()$ 152 k:=setkorder {s}$ 153 h:=simp!* {'!*sq,subsq(get(p,'sqval), 154 {(f1 . {'times,f1,s}), 155 (f2 . {'times,f2,s}) }),nil}$ 156 setkorder k$ 157 158 return 159 if (mvar numr h neq s) or 160 (ldeg numr h neq 2) then nil 161 else << % the equation is of 2nd degree 162 h:=mksq(lc numr h,1); % the sum of the quadratic terms 163 d:=solveeval list({'!*sq,h,t},f1); 164 165 if not freeof(d,'abs) then << 166 algebraic (let abs_); 167 d:=algebraic lisp d; 168 algebraic(clearrules abs_); 169 >>$ 170 171 l:=nil; 172 if d and (car d='list) then for each h in cdr d do << 173 % i.e. for each of the two equalities f1=.., f1=.. 174 175 f3:=newfct(fname_,get(p,'vars),nfct_)$ 176 nfct_:=add1 nfct_$ 177 ftem_:=fctinsert(f3,ftem_)$ 178 179 % currently h={'equal,f1,rhs} 180 q:=mkeqSQ(addsq(simp f3,subtrsq(simp cadr h,simp caddr h)),nil,nil, 181 {f1,f2,f3},get(p,'vars),allflags_,t,list(0),nil,pdes)$ 182 put(q,'not_to_eval,{f3})$ 183 l:=cons(q,l) 184 >>; 185 186 l 187 >> 188end$ 189 190 191symbolic procedure undetlinode(arglist)$ 192% parametric solution of underdetermined ODEs 193begin scalar l,l1,p,pdes,forg,s$ 194 pdes:=car arglist$ 195 forg:=cadr arglist$ 196 if expert_mode then <<l1:=selectpdes(pdes,1);flag(l1,'to_under)>> 197 else l1:=cadddr arglist$ 198 while l1 do 199 if null (p:=get_ulode(l1)) then l1:=nil 200 else << 201 l:=underode(p,pdes)$ 202 p:=car p$ 203 if null l then <<remflag1(p,'to_under);l1:=delete(p,l1)>> 204 else << 205 if print_ then << 206 write"Parametric solution of the underdetermined ODE ",p$ 207 terpri(); 208 write"giving the new ODEs "$ 209 s:=l; 210 while s do << 211 write car s; 212 s:=cdr s; 213 if s then write "," 214 >>$ 215 terpri() 216 >>$ 217 pdes:=drop_pde(p,pdes,nil)$ 218 for each s in l do pdes:=eqinsert(s,pdes)$ 219 l:=list(pdes,forg)$ 220 l1:=nil; 221 >> 222 >>$ 223 return l$ 224end$ 225 226symbolic procedure undetlinpde(arglist)$ 227% parametric solution of underdetermined PDEs 228begin scalar l,l1,p,pdes,forg$ 229 pdes:=car arglist$ 230 forg:=cadr arglist$ 231 if expert_mode then <<l1:=selectpdes(pdes,1);flag(l1,'to_under)>> 232 else l1:=cadddr arglist$ 233 while l1 do 234 if null (p:=get_ulpde(l1)) then l1:=nil 235 else << 236 l:=underpde(p,pdes)$ % l has to be the list of new pdes 237 p:=car p$ 238 if null l then <<remflag1(p,'to_under);l1:=delete(p,l1)>> 239 else << 240 pdes:=drop_pde(p,pdes,nil)$ 241 for each s in l do pdes:=eqinsert(s,pdes)$ 242 l:=list(pdes,forg)$ 243 l1:=nil; 244 >> 245 >>$ 246 return l$ 247end$ 248 249%symbolic procedure get_udalg(pdes)$ 250%% It looks for an algebraic equation (no independent variables) with as 251%% low as possible maximum degree of any variable but at least 252%begin scalar h,best_udalg; 253% for each p in pdes do 254% if flagp(p,'to_under) and (get(p,'nvars)=0) then 255% if null (h:=udalgp(p)) then remflag1(p,'to_under) 256% else 257% if ((null best_udalg) or (car h < car best_udalg)) then best_udalg:=h; 258% return if best_udalg then cdr best_udalg % return the name of the equation 259% else nil 260%end$ 261 262symbolic procedure get_ulode(pdes)$ 263begin scalar h,best_ulode; 264 for each p in pdes do 265 if flagp(p,'to_under) % and (get(p,'nvars)=1) 266 then 267 if null (h:=ulodep(p)) then remflag1(p,'to_under) 268 else 269 if ((null best_ulode) or (car h < car best_ulode)) then best_ulode:=h; 270 return if best_ulode then cdr best_ulode 271 else nil 272end$ 273 274symbolic procedure get_ulpde(pdes)$ 275begin scalar h,best_ulpde; 276 for each p in pdes do 277 if flagp(p,'to_under) and (get(p,'nvars)>1) then 278 if null (h:=ulpdep(p)) then remflag1(p,'to_under) 279 else 280 if ((null best_ulpde) or (car h < car best_ulpde)) then best_ulpde:=h; 281 return if best_ulpde then cdr best_ulpde 282 else nil 283end$ 284 285symbolic procedure udalgp(p)$ 286if (get(p,'terms)<2) or 287 get(p,'nonrational) or 288 ((length get(p,'fcts)) neq 2) then nil else 289begin scalar mxdeg,dfs$ 290 mxdeg:=0$ 291 dfs:=get(p,'derivs)$ 292 while dfs do << 293 if cdar dfs>mxdeg then mxdeg:=cdar dfs; 294 dfs:=cdr dfs 295 >>; 296 return if mxdeg<2 then nil 297 else (mxdeg . p) 298end$ 299 300symbolic procedure ulodep(p)$ 301begin 302 scalar tr_ulode,drvs,ulode,allvarf,minord,dv,f,x,h,found,minordf,totalorder$ 303 % minord and minordf are currently not needed later on 304 305% tr_ulode:=t; 306 307 % Is it an underdetermined linear ODE for the allvarfcts? 308 drvs:=get(p,'derivs)$ 309 ulode:=t$ 310 allvarf:=get(p,'allvarfcts); 311 if tr_ulode then << 312 write"allvarf=",allvarf$ 313 terpri()$ 314 >>$ 315 316 minord:=1000; 317 if not (allvarf and cdr allvarf) then ulode:=nil 318 else % at least two allvar-fcts 319 while ulode and drvs do << 320 dv:=caar drvs; 321 f:=car dv$ 322 if tr_ulode then << 323 write"car drvs=",car drvs," dv=",dv," f=",f, 324 " member(f,allvarf)=",member(f,allvarf)$ 325 terpri()$ 326 >>$ 327 if member(f,allvarf) then 328 if (cdar drvs neq 1) or % not linear 329 % x is already determined and it is not x: 330 (cdr dv and ((x and (x neq cadr dv) ) or 331 % there are other differentiation variables: 332 ((cddr dv) and ((not fixp caddr dv) or 333 cdddr dv )) ) 334 ) then << % no ODE: 335 ulode:=nil; 336 if tr_ulode then << 337 write"new ulode=",ulode$ 338 terpri()$ 339 >>$ 340 >> else % can be an ODE 341 if null cdr dv then % f has no derivatives 342 if not member(f,found) then ulode:=nil % no ODE --> substitition 343 else % f has already been found with a 344 % consequently higher x-derivative 345 else % this is an x-derivative of f 346 if null x then << % x had not yet been determined 347 if tr_ulode then << 348 write"null x"$ 349 terpri()$ 350 >>$ 351 found:=cons(f,found)$ 352 x:=cadr dv; 353 minordf:=car dv; 354 if null cddr dv then minord:=1 355 else minord:=caddr dv; 356 totalorder:=minord 357 >> else % x has already been determined 358 if not member(f,found) then << % only leading derivatives matter 359 found:=cons(f,found)$ % and the first deriv. of f is leading 360 if null cddr dv then h:=1 361 else h:=caddr dv; 362 totalorder:=totalorder+h; 363 if h<minord then << 364 minord:=h; 365 minordf:=car dv 366 >> 367 >> else 368 else % not member(f,allvarf) 369 if null x or % then there are only derivatives 370 % of non-allvarfcts left 371 member(x,fctargs f) then ulode:=nil; % no x-dependent non-allvarfcts 372 if tr_ulode then << 373 write"found=",found," minord=",minord," minordf=",minordf$ 374 terpri()$ 375 >>$ 376 377 drvs:=cdr drvs; 378 >>$ 379 if ulode and null get(p,'linear_) and null lin_check_SQ(get(p,'sqval),get(p,'allvarfcts)) 380 then ulode:=nil$ 381 382 if tr_ulode then << 383 write"ulode=",ulode$ 384 terpri()$ 385 >>$ 386 return if ulode then {totalorder,p,x,minord,minordf} 387 else nil 388end$ % of ulodep 389 390symbolic procedure ulpdep_(p)$ 391begin 392 scalar tr_ulpde,drvs,drv,ulpde,allvarf,allvarfcop, 393 vld,vl,v,pdo,fn,f,no_of_drvs,no_of_tms,ordr,maxordr,parti$ 394%tr_ulpde:=t; 395 396 % Is it an underdetermined linear PDE for the allvarfcts? 397 drvs:=get(p,'derivs)$ 398 ulpde:=t$ 399 allvarf:=get(p,'allvarfcts); 400 if tr_ulpde then << 401 write"allvarf=",allvarf$ 402 terpri()$ 403 >>$ 404 405 if not (allvarf and cdr allvarf) then ulpde:=nil 406 else << % at least two allvar-fcts 407 allvarfcop:=allvarf$ 408 no_of_tms:=0; % total number of terms of all diff operators 409 vl:=get(p,'vars)$ 410 411 while ulpde and allvarfcop do << 412 % extracting the differential operator for car allvarfcop 413 pdo:=get(p,'sqval); 414 415 fn:=car allvarfcop; allvarfcop:=cdr allvarfcop; 416 for each f in allvarf do 417 if f neq fn then pdo:=subsq(pdo,{(f . 0)}); 418 419 % Is pdo linear in fn? 420 if not lin_check_SQ(pdo,{fn}) then << 421 if tr_ulpde then <<write"not linear in ",f$terpri()>>$ 422 ulpde:=nil 423 >> else << 424 % add up the number of terms 425 no_of_tms:=no_of_tms + no_of_tm_sf numr pdo$ 426 427 % What are all variables in pdo? This is needed to test later 428 % whether they are disjunct from all variables from another 429 % diff. operator 430 vld:=nil; 431 for each v in vl do if not freeof(pdo,v) then vld:=cons(v,vld); 432 433 % What is the number of derivatives of fn? 434 % What order is the highest derivative of fn? 435 no_of_drvs:=0; 436 for each drv in drvs do 437 if fn=caar drv then << 438 ordr:=absodeg(cdar drv); 439 if (no_of_drvs=0) or (ordr>maxordr) then maxordr:=ordr; 440 no_of_drvs:=add1 no_of_drvs; 441 >>; 442 443 % collect the differential operators with properties in parti 444 parti:=cons({pdo,fn,vld,no_of_drvs,maxordr},parti); 445 % commutativity of differential operators 446 >> 447 >>; 448 if no_of_tms neq get(p,'terms) then << 449 if tr_ulpde then << 450 write"not a lin. homog. PDE"$terpri() 451 >>$ 452 ulpde:=nil; % not a lin. homog. PDE 453 >>$ 454 if tr_ulpde then << 455 write"parti="$ 456 prettyprint parti$ 457 >>$ 458 >>$ 459 return if null ulpde then nil 460 else parti 461end$ 462 463 464symbolic procedure ulpdep(p)$ 465begin 466 scalar tr_ulpde,drvs,drv,ulpde,parti,pde, 467 difop1,difop2,commu,disjn,totalcost$ 468%tr_ulpde:=t; 469 % Is it an underdetermined linear PDE for the allvarfcts? 470 drvs:=get(p,'derivs)$ 471 ulpde:=ulpdep_(p)$ 472 if ulpde then << 473 parti:=ulpde$ ulpde:=t$ 474 % Find a differential operator pde in parti 475 pde:=nil; 476 for each difop1 in parti do << 477 commu:=t; 478 % which does commute with all other diff. operators 479 for each difop2 in parti do 480 if (cadr difop1 neq cadr difop2) and 481 not sqzerop 482 subtrsq( subsq(car difop2,{(cadr difop2 . {'!*sq,car difop1,t})}), 483 subsq(subsq(car difop1,{(cadr difop1 . {'!*sq,car difop2,t})}), 484 {(cadr difop2 . cadr difop1)} 485 )) % if car()<>nil then ()<>0 486 then << 487 commu:=nil; 488 if tr_ulpde then << 489 write"no commutation of:"$terpri()$ 490 prettyprint difop1$ 491 write"and "$terpri()$ 492 prettyprint difop2 493 >> 494 >>$ 495 % and is variable-disjunct with at least one other diff. operator 496 if commu then << 497 disjn:=nil; 498 for each difop2 in parti do 499 if (cadr difop1 neq cadr difop2) and 500 freeoflist(caddr difop1,caddr difop2) then disjn:=t; 501 if disjn then 502 if null pde then pde:=difop1 else 503 if ( car cddddr difop1) < (car cddddr pde) or % minimal maxord 504 (((car cddddr difop1) = (car cddddr pde)) and % minimal number of terms 505 ((cadddr difop1) < (cadddr pde)) ) then pde:=difop1 506 >> 507 >>; 508 if null pde then ulpde:=nil 509 >>; 510 511 if tr_ulpde then << 512 write"ulpde=",ulpde$ 513 terpri()$ 514 >>$ 515 % as a first try we take as cost for the PDE p the sum of all orders 516 % of all derivatives of all functions in p 517 totalcost:=0; 518 for each drv in drvs do totalcost:=totalcost+absodeg(cdar drv); 519 520 return if ulpde then {totalcost,p,pde,parti} 521 else nil 522end$ % of ulpdep 523 524symbolic procedure min_ord_f(ode,allvarf,vl)$ 525begin scalar minord,minordf,newallvarf,f,h,tr_ulode$ 526% tr_ulode:=t; 527 % does any function not occur anymore? 528 % Which function does occur with lowest derivative: minord, minordf? 529 minord:=1000; 530 minordf:=nil; 531 newallvarf:=nil; 532 for each f in allvarf do << 533 h:=ld_deriv_search(ode,f,vl)$ 534 if tr_ulode then << 535 write"ld_deriv_search(",f,")=",h$ 536 terpri()$ 537 >>$ 538 if not zerop cdr h then << % otherwise f does not occur anymore in ode 539 newallvarf:=cons(f,newallvarf)$ 540 h:=car h$ 541 h:=if null h then 0 else 542 if null cdr h then 1 else cadr h$ % asuming that car h = x 543 if h<minord then <<minord:=h;minordf:=f>> 544 >> 545 >>$ 546 return {minord,minordf,newallvarf} 547end$ 548 549symbolic procedure underode(pchar,pdes)$ 550% pchar has the form {p,x,minord,minordf} 551begin 552 scalar tr_ulode,p,x,allvarf,orgallvarf,ode,vl,%noallvarf, 553 minord,minordf,adj,f,h,newf,sol,sublist,rtnlist, 554 freeint_bak,freeabs_bak$ 555 556% tr_ulode:=t; 557 558 p :=car pchar; 559 x :=cadr pchar; 560 minord :=caddr pchar; 561 minordf:=cadddr pchar; 562 563 allvarf:=get(p,'allvarfcts); 564 orgallvarf:=allvarf; 565 freeint_bak:=freeint_; freeint_:=nil; % to avoid intpde()=>nil 566 freeabs_bak:=freeabs_; freeabs_:=nil; % " 567 568%ode:=get(p,'val); 569 cp_sq2p_val(p)$ 570 ode:=get(p,'pval); 571 %noallvarf:=length(allvarf); 572 vl:=get(p,'vars); 573 while (minord>0) and 574 % (length(allvarf)=noallvarf) 575 (length(allvarf) > 1) 576 do << 577 if tr_ulode then << 578 write "x=",x," minord=",minord," minordf=",minordf, 579 " allvarf=", allvarf$ 580 terpri()$ 581 >>$ 582 repeat << 583 adj:=intpde(ode,allvarf,vl,x,t); 584 if tr_ulode then << 585 write"car adj = new_function = "$mathprint car adj$ 586 write"cadr adj = - df(new_function,",x,")="$mathprint cadr adj$ % #?# 587 terpri()$ 588 >>$ 589 590 h:=nil; 591 for each f in allvarf do if not freeof(cadr adj,f) then h:=cons(f,h); 592 if null h then % exact ode --> should do better then what is done now 593 ode:=reval {'times,x,ode}; 594 >> until h; 595 596 minordf:=cadr min_ord_f(ode,h,vl)$ 597 598 % a new function (potential) is needed: 599 newf:=newfct(fname_,vl,nfct_)$ 600 nfct_:=add1 nfct_; 601 602 if tr_ulode then << 603 algebraic write"eqn=",{'list,{'plus,{'df,newf,x},lisp cadr adj}}$ 604 algebraic write"var=",{'list,minordf } 605 >>$ 606 sol:=cadr solveeval list({'list,{'plus,{'df,newf,x},cadr adj}}, 607 {'list,minordf } ); 608 allvarf:=delete(minordf,allvarf)$ 609 allvarf:=cons(newf,allvarf)$ 610 % assuming that there is exacly one solution to the lin. alg. equation 611 if tr_ulode then << 612 terpri()$ 613 write"sol=",sol$ 614 terpri()$ 615 >>$ 616 sublist:=cons(sol,sublist)$ 617 ode:=reval num reval 618 {'plus,newf,{'minus,subst(caddr sol,cadr sol,car adj)}}$ 619 if tr_ulode then algebraic(write"ode=",ode)$ 620 621 h:=min_ord_f(ode,allvarf,vl)$ 622 minord:=car h; minordf:=cadr h; allvarf:=caddr h; 623 624 if minord=0 then 625 sublist:=cons(cadr solveeval list({'list,ode},{'list,minordf}),sublist)$ 626 627 if tr_ulode then << 628 write"allvarf=",allvarf," minord=",minord," minordf=",minordf$ 629 terpri()$ 630 >>$ 631 632 >>$ 633 634 if (minord neq 0) and (not zerop ode) then rtnlist:=list ode; 635 ode:=nil; 636 if tr_ulode then <<write"rtnlist=", rtnlist;terpri()>>$ 637 if tr_ulode then algebraic(write"sublist=",cons('list,sublist)); 638 while sublist do << 639 if member(cadar sublist,orgallvarf) then 640 rtnlist:=cons(reval num reval {'plus,cadar sublist, 641 {'minus,caddar sublist}},rtnlist)$ 642 sublist:=cdr reval cons('list, 643 subst(caddar sublist,cadar sublist,cdr sublist))$ 644 if tr_ulode then algebraic(write"sublist=",cons('list,sublist)) 645 >>$ 646 647 allvarf:=smemberl(allvarf,rtnlist)$ 648 if tr_ulode then << 649 write"allvarf=",allvarf$ 650 terpri()$ 651 >>$ 652 for each h in allvarf do << 653 ftem_:=fctinsert(h,ftem_)$ 654 flin_:=sort_according_to(cons(h,flin_),ftem_) 655 >>$ 656 if tr_ulode then algebraic(write"rtnlist=",cons('list,rtnlist)); 657 h:=for each h in rtnlist collect 658 mkeqSQ(nil,nil,h,union(get(p,'fcts),allvarf),vl,allflags_,t, 659 list(0),nil,pdes)$ 660 if print_ then terpri()$ 661 freeint_:=freeint_bak; 662 freeabs_:=freeabs_bak; 663 return h 664end$ 665 666symbolic procedure underpde(pchar,pdes)$ 667% pchar has the form {p,difop,parti} where p is the name of the equation, 668% difop is the main differential operator in p and parti is a partition 669% of p, i.e. the list of all differential operators. Each differential 670% operator has the form 671% {pde,fn,vld,no_of_drvs,maxordr} 672% where pde are all terms in p with fn, vld is a list of all variables 673% in pde, no_of_dervs is the number of different derivatives of fn, 674% maxord is the maximal order of derivatives of fn (order of pde) 675 676begin 677 scalar tr_ulpde,ldo,parti,fn,lcond,difop,h,fl,eqlist,vl$ 678% has to return list of new pde just like in underode 679% tr_ulpde:=t; 680 ldo:=cadr pchar; 681 parti:=caddr pchar$ 682 vl:=get(car pchar,'vars)$ 683 fn:=cadr ldo$ 684 lcond:={fn}$ 685 if tr_ulpde then << 686 write"ldo="$prettyprint parti$ 687 write"parti="$prettyprint parti 688 >>$ 689 for each difop in parti do 690 if cadr difop neq fn then << 691 h:=newfct(fname_,vl,nfct_)$ 692 nfct_:=add1 nfct_$ 693 if print_ then terpri()$ 694 fl:=cons(h,fl)$ 695 eqlist:=cons(cons({cadr difop,h}, 696 reval {'difference,cadr difop,subst(h,fn,prepsq car ldo)}), 697 eqlist)$ 698 lcond:=cons(subst(h,cadr difop,prepsq car difop),lcond) 699 >>$ 700 eqlist:=cons(cons(append(get(car pchar,'fcts),fl), 701 cons('plus,lcond)),eqlist)$ 702 if tr_ulpde then << 703 write"eqlist="$prettyprint eqlist$ 704 >>$ 705 706 for each h in fl do << 707 ftem_:=fctinsert(h,ftem_)$ 708 flin_:=sort_according_to(cons(h,flin_),ftem_) 709 >>$ 710 h:=for each h in eqlist collect 711 mkeqSQ(nil,nil,cdr h,car h,get(car pchar,'vars),allflags_, 712 t,list(0),nil,pdes)$ 713 if print_ then terpri()$ 714 return h 715end$ 716 717endmodule$ 718 719end$ 720 721tr undetalg 722tr tryalg1 723tr tryalg2 724tr undetlinode 725tr undetlinpde 726tr get_udalg 727tr get_ulode 728tr get_ulpde 729tr udalgp 730tr ulodep 731tr ulpdep_ 732tr ulpdep 733tr min_ord_f 734tr underode 735tr underpde 736