approx.red 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. module approx;
  2. % Author: R. Liska$
  3. % Version REDUCE 3.6 05/1991$
  4. fluid '(!*prapprox)$
  5. switch prapprox$
  6. !*prapprox:=nil$
  7. global '(cursym!* coords!* icoords!* functions!* hipow!* lowpow!*)$
  8. % Implicitely given indices
  9. icoords!*:='(i j k l m n i1 j1 k1 l1 m1 n1)$
  10. algebraic$
  11. procedure fact(n)$
  12. if n=0 then 1
  13. else n*fact(n-1)$
  14. procedure taylor(fce,var,step,ord)$
  15. if step=0 or ord=0 then fce
  16. else fce+for j:=1:ord sum step**j/fact(j)*df(fce,var,j)$
  17. symbolic$
  18. procedure maxorder u$
  19. begin
  20. scalar movar,var$
  21. a:movar:=car u$
  22. if not eqexpr movar then return errpri2(movar,'hold)$
  23. movar:=cdr movar$
  24. var:=car movar$
  25. movar:=reval cadr movar$
  26. if not atom var or not(var memq coords!*) then return msgpri(
  27. " Parameter ",var," must be coordinate",nil,'hold)
  28. else if not fixp movar then return msgpri(
  29. " Parameter ", movar," must be integer",nil,'hold)
  30. else put(var,'maxorder,movar)$
  31. u:=cdr u$
  32. if u then go to a$
  33. return nil
  34. end$
  35. put('maxorder,'stat,'rlis)$
  36. procedure center u$
  37. begin
  38. scalar movar,var$
  39. a:movar:=car u$
  40. if not eqexpr movar then return errpri2(movar,'hold)$
  41. movar:=cdr movar$
  42. var:=car movar$
  43. movar:=reval cadr movar$
  44. if not atom var or not(var memq coords!*) then return msgpri(
  45. " Parameter ",var," must be coordinate",nil,'hold)
  46. else if not(fixp movar or (eqcar(movar,'quotient) and
  47. (fixp cadr movar or
  48. (eqcar(cadr movar,'minus) and fixp cadadr movar))
  49. and fixp caddr movar)) then return msgpri(
  50. " Parameter ", movar," must be integer or rational number",nil,
  51. 'hold)
  52. else put(var,'center,movar)$
  53. u:=cdr u$
  54. if u then go to a$
  55. return nil
  56. end$
  57. put('center,'stat,'rlis)$
  58. procedure functions u$
  59. <<functions!* := u$
  60. for each a in u do put(a,'simpfn,'simpiden) >>$
  61. put('functions,'stat,'rlis)$
  62. procedure simptaylor u$
  63. begin
  64. scalar ind,var,movar,step,fce,ifce$
  65. fce:=car u$
  66. if null cdr u then return simp fce$
  67. ifce:=cadr u$
  68. if cddr u then fce:= fce . cddr u$
  69. ind:=mvar numr simp ifce$
  70. var:=tcar get(ind,'coord)$
  71. step:=reval list('difference,
  72. ifce,
  73. list('plus,
  74. if (movar:=get(var,'center)) then movar
  75. else 0,
  76. ind))$
  77. step:=list('times,
  78. step,
  79. get(var,'gridstep))$
  80. movar:=if (movar:=get(var,'maxorder)) then movar
  81. else 3$
  82. return simp list('taylor,
  83. fce,
  84. var,
  85. step,
  86. movar)
  87. end$
  88. algebraic$
  89. procedure approx difsch$
  90. begin
  91. scalar ldifsch,rdifsch,nrcoor,coors,rest,ldifeq,rdifeq,alglist!*$
  92. symbolic
  93. <<for each a in functions!* do
  94. <<put(a,'simpfn,'simptaylor)$
  95. eval list('depend,mkquote (a . coords!*)) >>$
  96. flag(functions!*,'full)$
  97. for each a in coords!* do put(a,'gridstep, intern compress append
  98. (explode 'h,explode a))$
  99. nrcoor:=length coords!* - 1$
  100. eval list('array,
  101. mkquote list('steps . add1lis list(nrcoor)))$
  102. coors:=coords!*$
  103. for j:=0:nrcoor do
  104. <<setel(list('steps,j),aeval get(car coors,'gridstep))$
  105. coors:=cdr coors >> >>$
  106. ldifsch:=lhs difsch$
  107. rdifsch:=rhs difsch$
  108. ldifeq:=ldifsch$
  109. rdifeq:=rdifsch$
  110. ldifeq:=substeps(ldifeq)$
  111. rdifeq:=substeps(rdifeq)$
  112. rest:=ldifsch-ldifeq-rdifsch+rdifeq$
  113. for j:=0:nrcoor do
  114. steps(j):=steps(j)**minorder(rest,steps(j))$
  115. write " Difference scheme approximates differential equation ",
  116. ldifeq=rdifeq$
  117. write " with orders of approximation:"$
  118. on div$
  119. for j:=0:nrcoor do write steps(j)$
  120. off div$
  121. symbolic if !*prapprox
  122. then algebraic write " Rest of approximation : ",rest$
  123. symbolic
  124. <<for each a in functions!* do
  125. <<put(a,'simpfn,'simpiden)$
  126. eval list('nodepend,mkquote (a . coords!*)) >>$
  127. remflag(functions!*,'full)>>$
  128. clear steps
  129. end$
  130. procedure substeps u$
  131. begin
  132. scalar step,nu,du$
  133. nu:=num u$
  134. du:=den u$
  135. symbolic for each a in coords!* do
  136. <<step:=get(a,'gridstep)$
  137. flag(list step,'used!*)$
  138. put(step,'avalue,'(scalar 0)) >>$
  139. symbolic rmsubs()$
  140. nu:=nu$
  141. du:=du$
  142. symbolic for each a in coords!* do
  143. <<step:=get(a,'gridstep)$
  144. remflag(list step,'used!*)$
  145. remprop(step,'avalue) >>$
  146. symbolic rmsubs()$
  147. if du=0 then <<write
  148. " Reformulate difference scheme, grid steps remain in denominators"$
  149. u:=0 >>
  150. else u:=nu/du$
  151. return u
  152. end$
  153. procedure minorder(pol,var)$
  154. begin
  155. scalar lcofs,mord$
  156. coeff(den pol,var)$
  157. mord:=-hipow!*$
  158. lcofs := rest coeff(num pol,var)$
  159. if not(mord=0) then return (mord+lowpow!*)$
  160. mord:=1$
  161. a:if lcofs={} then return 0
  162. else if first lcofs=0 then lcofs:=rest lcofs
  163. else return mord$
  164. mord:=mord+1$
  165. go to a
  166. end$
  167. endmodule;
  168. end;