123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- module approx;
- % Author: R. Liska$
- % Version REDUCE 3.6 05/1991$
- fluid '(!*prapprox)$
- switch prapprox$
- !*prapprox:=nil$
- global '(cursym!* coords!* icoords!* functions!* hipow!* lowpow!*)$
- % Implicitely given indices
- icoords!*:='(i j k l m n i1 j1 k1 l1 m1 n1)$
- algebraic$
- procedure fact(n)$
- if n=0 then 1
- else n*fact(n-1)$
- procedure taylor(fce,var,step,ord)$
- if step=0 or ord=0 then fce
- else fce+for j:=1:ord sum step**j/fact(j)*df(fce,var,j)$
- symbolic$
- procedure maxorder u$
- begin
- scalar movar,var$
- a:movar:=car u$
- if not eqexpr movar then return errpri2(movar,'hold)$
- movar:=cdr movar$
- var:=car movar$
- movar:=reval cadr movar$
- if not atom var or not(var memq coords!*) then return msgpri(
- " Parameter ",var," must be coordinate",nil,'hold)
- else if not fixp movar then return msgpri(
- " Parameter ", movar," must be integer",nil,'hold)
- else put(var,'maxorder,movar)$
- u:=cdr u$
- if u then go to a$
- return nil
- end$
- put('maxorder,'stat,'rlis)$
- procedure center u$
- begin
- scalar movar,var$
- a:movar:=car u$
- if not eqexpr movar then return errpri2(movar,'hold)$
- movar:=cdr movar$
- var:=car movar$
- movar:=reval cadr movar$
- if not atom var or not(var memq coords!*) then return msgpri(
- " Parameter ",var," must be coordinate",nil,'hold)
- else if not(fixp movar or (eqcar(movar,'quotient) and
- (fixp cadr movar or
- (eqcar(cadr movar,'minus) and fixp cadadr movar))
- and fixp caddr movar)) then return msgpri(
- " Parameter ", movar," must be integer or rational number",nil,
- 'hold)
- else put(var,'center,movar)$
- u:=cdr u$
- if u then go to a$
- return nil
- end$
- put('center,'stat,'rlis)$
- procedure functions u$
- <<functions!* := u$
- for each a in u do put(a,'simpfn,'simpiden) >>$
- put('functions,'stat,'rlis)$
- procedure simptaylor u$
- begin
- scalar ind,var,movar,step,fce,ifce$
- fce:=car u$
- if null cdr u then return simp fce$
- ifce:=cadr u$
- if cddr u then fce:= fce . cddr u$
- ind:=mvar numr simp ifce$
- var:=tcar get(ind,'coord)$
- step:=reval list('difference,
- ifce,
- list('plus,
- if (movar:=get(var,'center)) then movar
- else 0,
- ind))$
- step:=list('times,
- step,
- get(var,'gridstep))$
- movar:=if (movar:=get(var,'maxorder)) then movar
- else 3$
- return simp list('taylor,
- fce,
- var,
- step,
- movar)
- end$
- algebraic$
- procedure approx difsch$
- begin
- scalar ldifsch,rdifsch,nrcoor,coors,rest,ldifeq,rdifeq,alglist!*$
- symbolic
- <<for each a in functions!* do
- <<put(a,'simpfn,'simptaylor)$
- eval list('depend,mkquote (a . coords!*)) >>$
- flag(functions!*,'full)$
- for each a in coords!* do put(a,'gridstep, intern compress append
- (explode 'h,explode a))$
- nrcoor:=length coords!* - 1$
- eval list('array,
- mkquote list('steps . add1lis list(nrcoor)))$
- coors:=coords!*$
- for j:=0:nrcoor do
- <<setel(list('steps,j),aeval get(car coors,'gridstep))$
- coors:=cdr coors >> >>$
- ldifsch:=lhs difsch$
- rdifsch:=rhs difsch$
- ldifeq:=ldifsch$
- rdifeq:=rdifsch$
- ldifeq:=substeps(ldifeq)$
- rdifeq:=substeps(rdifeq)$
- rest:=ldifsch-ldifeq-rdifsch+rdifeq$
- for j:=0:nrcoor do
- steps(j):=steps(j)**minorder(rest,steps(j))$
- write " Difference scheme approximates differential equation ",
- ldifeq=rdifeq$
- write " with orders of approximation:"$
- on div$
- for j:=0:nrcoor do write steps(j)$
- off div$
- symbolic if !*prapprox
- then algebraic write " Rest of approximation : ",rest$
- symbolic
- <<for each a in functions!* do
- <<put(a,'simpfn,'simpiden)$
- eval list('nodepend,mkquote (a . coords!*)) >>$
- remflag(functions!*,'full)>>$
- clear steps
- end$
- procedure substeps u$
- begin
- scalar step,nu,du$
- nu:=num u$
- du:=den u$
- symbolic for each a in coords!* do
- <<step:=get(a,'gridstep)$
- flag(list step,'used!*)$
- put(step,'avalue,'(scalar 0)) >>$
- symbolic rmsubs()$
- nu:=nu$
- du:=du$
- symbolic for each a in coords!* do
- <<step:=get(a,'gridstep)$
- remflag(list step,'used!*)$
- remprop(step,'avalue) >>$
- symbolic rmsubs()$
- if du=0 then <<write
- " Reformulate difference scheme, grid steps remain in denominators"$
- u:=0 >>
- else u:=nu/du$
- return u
- end$
- procedure minorder(pol,var)$
- begin
- scalar lcofs,mord$
- coeff(den pol,var)$
- mord:=-hipow!*$
- lcofs := rest coeff(num pol,var)$
- if not(mord=0) then return (mord+lowpow!*)$
- mord:=1$
- a:if lcofs={} then return 0
- else if first lcofs=0 then lcofs:=rest lcofs
- else return mord$
- mord:=mord+1$
- go to a
- end$
- endmodule;
- end;
|