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