edspde.red 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. module edspde;
  2. % PDE interface to EDS
  3. % Author: David Hartley
  4. fluid '(xvars!* kord!* depl!* dependencies);
  5. global '(indxl!*);
  6. put('pde2eds,'rtypefn,'quoteeds);
  7. put('pde2eds,'edsfn,'pde2eds);
  8. flag('(pde2eds),'nospread);
  9. symbolic procedure pde2eds u;
  10. % u:{pde:list of equations|expressions, [dep,ind:list of variables]}
  11. % -> pde2eds:eds
  12. % Assumes all non-kernel variables are indexed 0-forms.
  13. begin scalar pde,dep,ind,vars,fns,s,map;
  14. % Analyse PDE and convert to jet notation
  15. pde := pde2jet u; dep := cadr pde; ind := caddr pde;
  16. fns := cadddr pde; pde := getrlist car pde;
  17. vars := append(ind,foreach p in dep collect car p);
  18. % Save dependencies in shared variable "dependencies"
  19. dependencies := makelist purge
  20. foreach k in append(fns,vars) join
  21. if k := atsoc(lid k,depl!*) then {makelist k};
  22. % All variables must be dependency-free, and all functions have
  23. % fdomains. Functions without dependencies must depend on all
  24. % independent variables.
  25. foreach k in vars do
  26. << k := lid k; % get leading id
  27. foreach x in atsoc(k,depl!*) do depend1(k,x,nil);
  28. remflag({k},'impfun); >>;
  29. foreach k in fns do
  30. << k := lid k; % get leading id
  31. foreach x in setdiff(atsoc(k,depl!*),ind) do depend1(k,x,nil);
  32. if null atsoc(k,depl!*) then foreach x in ind do depend1(k,x,t);
  33. flag({k},'impfun); >>;
  34. % Construct contact system
  35. vars := {};
  36. foreach p in dep do
  37. if s := assoc(cdr p,vars) then cdr s := car p . cdr s
  38. else vars := (cdr p . {car p}) . vars;
  39. s := partialcontact(makelist foreach l in vars collect
  40. makelist l,makelist ind);
  41. % Decide what to pullback or augment
  42. map := makelist foreach x in pde join
  43. if eqexpr x and kernp simp!* cadr x then {x};
  44. pde := makelist foreach x in setdiff(pde,map) collect !*eqn2a x;
  45. % Finished
  46. if pde then s := edscall augmenteds(s,pde);
  47. if map then s := edscall pullbackeds(s,map);
  48. return s;
  49. end;
  50. put('partial_contact,'rtypefn,'quoteeds);
  51. put('partial_contact,'edsfn,'partialcontact);
  52. symbolic procedure partialcontact(vars,ind);
  53. % vars:rlist of (degree . rlist of kernel), ind:rlist of kernel
  54. % -> partialcontact:eds
  55. begin scalar s,jet,ord,sys;
  56. vars := foreach l in getrlist vars collect getrlist l;
  57. vars := sort(vars,function(lambda(x,y); car x > car y));
  58. ind := !*a2cfrm{makelist getrlist ind};
  59. s := mkeds{{},foreach f in cfrm_cob ind collect !*k2pf f,ind,nil};
  60. puteds(s,'sqvar,!*sqvar!*);
  61. foreach f in {'solved,'reduced,'quasilinear,'pfaffian,'involutive} do
  62. flagtrueeds(s,f);
  63. while vars do
  64. << jet := !*a2cfrm{makelist cdar vars};
  65. eds_cfrm s := cfrmprod2(eds_cfrm s,jet);
  66. puteds(s,'jet0,append(geteds(s,'jet0),cdar vars));
  67. ord := if cdr vars then caar vars - caadr vars else caar vars;
  68. for i:=1:ord do % gbsys doesn't produce redundant mixed partials
  69. << sys := eds_sys s;
  70. s := edscall gbsys s;
  71. eds_sys s := append(sys,eds_sys s) >>;
  72. vars := cdr vars >>;
  73. return s;
  74. end;
  75. put('pde2jet,'rtypefn,'quotelist);
  76. put('pde2jet,'listfn,'pde2jeteval);
  77. symbolic procedure pde2jeteval(u,v);
  78. reval1(car pde2jet revlis u,v);
  79. symbolic procedure pde2jet u;
  80. % u:{pde:list of equations|expressions, [dep,ind:list of variables]}
  81. % -> pde2jet:{pde:rlist of prefix, dep:list of kernel . int,
  82. % ind:list of kernel, fns:list of kernel}
  83. begin scalar dep1,ind1,drv,ind,dep,fns,idxs,rlb,!*evallhseqp;
  84. if length u neq 1 and length u neq 3 then
  85. rerror(eds,000,"Wrong number of arguments to pde2jet");
  86. if length u > 1 then
  87. << dep1 := foreach v in getrlist cadr u collect !*a2k v;
  88. ind1 := foreach v in getrlist caddr u collect !*a2k v >>;
  89. on evallhseqp;
  90. % Collect all derivatives and possible dependent variables
  91. foreach x in getrlist car u do drv := union(edsdfkernels x,drv);
  92. edsdebug("Derivatives and functions found",drv,'cob);
  93. % Scan to distinguish dependent and independent variables and get
  94. % orders
  95. ind := edspdescan drv; dep := car ind; ind := cadr ind;
  96. % If there are explicit variable lists given, pick out functions not
  97. % in dependent variables, add any dependent variable which did not
  98. % occur, and likewise for independent variables
  99. if length u > 1 then
  100. << if not subsetp(ind,ind1) then
  101. rerror(eds,000,
  102. "Less independent variables given than occur in PDE");
  103. ind := ind1;
  104. foreach k in ind do dep := delasc(k,dep);
  105. fns := setdiff(foreach p in dep collect car p,dep1);
  106. foreach k in fns do dep := delasc(k,dep);
  107. foreach k in dep1 do if not atsoc(k,dep) then
  108. dep := (k . 0) . dep; >>;
  109. % Sort variables
  110. dep := sort(dep,function ordopcar);
  111. ind := sort(ind,function ordop);
  112. fns := sort(fns,function ordop);
  113. edsdebug("Dependent variables and orders",
  114. makelist foreach p in dep
  115. collect {'equal,car p,cdr p},'prefix);
  116. edsdebug("Independent variables",ind,'cob);
  117. edsdebug("Other functions",fns,'cob);
  118. % All variables and functions must be 0-forms.
  119. foreach k in append(fns,ind) do if not exformp k then mkform!*(k,0);
  120. foreach k in dep do if not exformp car k then mkform!*(car k,0);
  121. % All dependent variables and functions with dependencies must be
  122. % impfuns
  123. %% flag(foreach k in fns join if atsoc(k,depl!*) then {k},'impfun);
  124. %% flag(foreach p in dep join if atsoc(car p,depl!*) then
  125. %% {car p},'impfun);
  126. % Get indices and fix index names (cf. gbsys)
  127. idxs := uniqids ind;
  128. if not subsetp(idxs,indxl!*) then % indexrange is an rlist
  129. apply1('indexrange,{{'equal,gensym(),makelist idxs}});
  130. idxs := pair(ind,idxs);
  131. % Construct relabelling list
  132. foreach k in drv do
  133. if eqcar(k,'df) or eqcar(k,'partdf) then
  134. if cadr k memq fns then
  135. rlb := {'equal,k,!*df2partdf k} . rlb
  136. else
  137. rlb := {'equal,k,!*df2jet(k,idxs)} . rlb;
  138. edsdebug("Relabelling list",makelist rlb,'prefix);
  139. return {subeval{makelist rlb,car u},dep,ind,fns};
  140. end;
  141. symbolic procedure edspdescan u;
  142. % u:list of kernel-> edspdescan:{list of kernel . int,list of kernel}
  143. % Look for dependent and independent variables and order of
  144. % differentials in u. All variables which are not differentiated wrt
  145. % are considered dependent. All non-indexed variables are broken up
  146. % and the arguments are scanned instead.
  147. begin scalar dep,ind,k,p;
  148. while u do
  149. << k := car u; u := cdr u;
  150. if eqcar(k,'partdf) or eqcar(k,'df) then
  151. << k := cadr k . edsdfexpand cddr k;
  152. ind := union(cdr k,ind);
  153. if (p := atsoc(car k,dep)) then
  154. cdr p := max(cdr p,length cdr k)
  155. else
  156. dep := (car k . length cdr k) . dep >>
  157. else if not atsoc(k,dep) then
  158. if atom k or (xvarp k where xvars!* = t) then
  159. dep := (k . 0) . dep
  160. else
  161. foreach v in cdr k do u := union(edsdfkernels v,u) >>;
  162. foreach k in ind do dep := delasc(k,dep);
  163. return {dep,ind};
  164. end;
  165. symbolic procedure edsdfkernels x;
  166. % x:prefix -> edsdfkernels:list of kernel
  167. % Returns all kernels in x which could be differentiable
  168. if eqexpr x then
  169. union(edsdfkernels cadr x,edsdfkernels caddr x)
  170. else
  171. << x := simp!* x;
  172. foreach k in union(kernels numr x,kernels denr x) join
  173. if eqcar(k,'df) or eqcar(k,'partdf) or
  174. assoc(k,depl!*) or exformp k then {k} >>;
  175. symbolic procedure !*df2jet(u,idxs);
  176. % u:df or partdf kernel, idxs:alist of kernel . id -> !*df2jet:kernel
  177. begin scalar v,ixl;
  178. u := cdr u;
  179. if atom(v := car u) then v := {v};
  180. ixl := sublis(idxs,edsdfexpand cdr u);
  181. ixl := foreach j in sort(ixl,'indtordp) collect lowerind j;
  182. u := car fkern append(v,ixl);
  183. return mkform!*(u,0);
  184. end;
  185. symbolic procedure !*df2partdf u;
  186. % u:df kernel -> !*df2partdf:kernel
  187. car fkern('partdf . cadr u . edsdfexpand cddr u);
  188. symbolic procedure edsdfexpand u;
  189. % u:list of (id|posint) -> edsdfexpand:list of id
  190. % take list of derivatives used by df and partdf operators and
  191. % expand any repeat counts to explicitly repeat derivatives
  192. if null u then nil
  193. else if cdr u and fixp cadr u then
  194. nconc(nlist(car u,cadr u),edsdfexpand cddr u)
  195. else
  196. car u . edsdfexpand cdr u;
  197. symbolic operator mkdepend;
  198. symbolic procedure mkdepend u;
  199. % u:rlist of rlists -> nil
  200. foreach v in getrlist u do
  201. if v := getrlist v then
  202. << depl!* := v . delasc(car v,depl!*);
  203. if exformp car v or flagp(car v,'indexvar) then
  204. flag({car v},'impfun) >>;
  205. endmodule;
  206. end;