3 odes package for solving ordinary diferential equations
5 Copyright (C) A.Domarkas 2013
6 odes package is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License,
11 Examples see in odes-doc.pdf
18 odecv(tr,eq,y,x):=block([_n,_t,tr1,itr,eq1,r,solvetrigwarn],
19 solvetrigwarn:false,_n:derivdegree(eq,y,x),
21 _t:last(listofvars(rhs(tr1))),
22 itr:(solve(tr,_t))[1],
25 makelist(diff(itr,x,k),k,1,_n),
29 remove([y,_t],dependency),
36 dchange(tr,eq,fun,var,nfun,nvar):=block(local(T,keit),
38 if k = 0 then f[2] elseif k = 1
39 then ratsimp(diff(f[2],t,1)/diff(f[1],t,1))
40 else ratsimp(diff(diffpf(f,t,k-1),t,1)/diff(f[1],t,1))),
41 T:makelist('diff(fun,var,k)=
42 diffpf([rhs(tr),nfun],nvar,k),k,0,derivdegree(eq,fun,var)),
43 keit:append(reverse(T),[tr]),
50 odeC(eq,r,x):=block([derivsubst,_u,tr,itr,L],
51 depends(_u,x),assume(_u>0),
54 tr:_u=r, itr:solve(tr,last(L))[1],
56 ev(%%, nouns), expand(%%),
65 solvet(eq,x):=block([spr,k,maperror,mapprint],
66 maperror:false,mapprint:false,
69 if freeof(sin,%%) then return(sort(%%))
70 else makelist(x=map(polarform,rhs(spr[k])),k,1,length(spr)),
79 ode1_ic(eq,y,x,_ic):=block([sol,gsol, spr,ats,p],
82 if %%=false then return(false),
88 gsol:rootscontract(%%),
89 subst([x=_ic[1],y=_ic[2]],trigsimp(gsol)),
92 sol:ratsimp(logcontract(%%)),
94 if not freeof(y,map(rhs,%%)) then return(sol),
95 if length(spr)=1 and freeof(y,rhs(spr[1])) then return(spr[1]),
96 sublist(spr,lambda([e],is(radcan(subst([x=_ic[1], y=_ic[2]],e))))),
99 if not freeof(%e,%%) then
101 if not freeof(%i,%%) then
102 ats:rootscontract(subst(%i=sqrt(-1),%%))
111 ode2_ic(eq,y,x,_ic):=block([p,sol,ats,spr],
117 solve(eq,'diff(y,x,2)),
119 if listofvars(%%)=[y] and listp(sol) then
121 subst('diff(y,x,2)=p*'diff(p,y),eq),
122 ode1_ic(%%,p,y,[_ic[2],_ic[3]]),
123 subst(p='diff(y,x),%%),
124 ats:ode1_ic(%%,y,x,[_ic[1],_ic[2]])
128 ic2(sol, x=_ic[1], y=_ic[2],'diff(y,x)=_ic[3]),
129 ats:lhs(%%)=map(factor,rhs(%%)),
135 sublist(spr,lambda([e],
136 _ic[2]=ratsimp(ev(rhs(e),x=_ic[1])) and
137 _ic[3]=ratsimp(at(diff(rhs(e),x),x=_ic[1])))),
150 ode_ic(eq,y,x,_ic):=block([],
151 if derivdegree(eq,y,x)=1 then ode1_ic(eq,y,x,_ic)
152 elseif derivdegree(eq,y,x)=2 then ode2_ic(eq,y,x,_ic)
153 else error("equation must be the first or second order"),
161 P_iter(eq,x,y,x0,y0,n):=block([f,t],
162 solve(eq,'diff(y,x,1))[1],
163 define(f(x,y),rhs(%%)),
166 subst(x=t,f(t,P_iter(eq,x,y,x0,y0,n-1))),
167 y0+expand(integrate(%%,t,x0,x))))$
173 ode1taylor(eq,x0,y0,n):=block([spr,nezin],
174 atvalue(y(x),x=x0,y0),
175 spr:taylor(y(x),x,x0,n),
176 nezin:at(makelist(diff(y(x),x,k),k,1,n),x=x0),
177 makelist(diff(eq,x,k),k,0,n-1),
178 at(%%,x=x0),solve(%%,nezin),
179 ratexpand(ev(spr,first(%%))),
187 ode2taylor(eq,x0,y0,y1,n):=block([spr,nezin],
188 atvalue(y(x),x=x0,y0),
189 atvalue(diff(y(x),x),x=x0,y1),
190 spr:taylor(y(x),x,x0,n),
191 nezin:at(makelist(diff(y(x),x,k),k,2,n),x=x0),
192 makelist(diff(eq,x,k),k,0,n-2),
193 at(%%,x=x0),solve(%%,nezin),
194 ratexpand(ev(spr,first(%%))),
202 ode1exact(eq):=block([P,Q,F],
203 P:coeff(expand(lhs(eq)-rhs(eq)),dx),
204 Q:coeff(expand(lhs(eq)-rhs(eq)),dy),
205 if trigsimp(trigexpand(diff(P,y)-diff(Q,x)))=0 then
206 (F:integrate(P,x)+g(y),diff(F,y)=Q,
208 subst([%%,%c=0],F)=C,
218 intfactor1(eq,omega):=block([P,Q,d,t,ans],
219 P:coeff(expand(lhs(eq)-rhs(eq)),dx),
220 Q:coeff(expand(lhs(eq)-rhs(eq)),dy),
221 (diff(P,y)-diff(Q,x))/(Q*diff(omega,x)-P*diff(omega,y)),
222 ratsimp(ev(%%,diff)),
224 ratsubst(t,omega,%%),
225 d:map(radcan,expand(%%)),
226 if listofvars(%%)=[t] or listofvars(%%)=[] then (
228 ans:subst(t=omega,%%))
230 if freeof(integrate, ans) then return(ans)
238 odeL(eq,y,x):=block([n,_yp,gamma_expand,i,_Y,_C],
241 n:derivdegree(eq,y,x),
243 _C:makelist(concat(C,i),i,1,n),
250 odeL_ic(eq,y,x,ic):=block(odeL(eq,y,x), icn(%%,y,x,ic))$
252 icn(sol,y,x,ic):=block([_spr,n],
255 makelist(at(diff(_spr,x,k),x=ic[1])=ic[k+2],k,0,n-1),
256 solve(%%,_C:makelist(concat(C,i),i,1,n)),
264 fs(eq,y,x):=block([_f,n,j,cr,_k,ce],
265 _f(r):=block([a,b,i],
266 a:radcan(realpart(r[1])),
267 b:radcan(imagpart(r[1])),
269 return(makelist(x^(i-1)*exp(a*x),i,1,r[2]))
271 join(makelist(x^(i-1)*exp(a*x)*cos(b*x),i,1,r[2]),
272 makelist(x^(i-1)*exp(a*x)*sin(b*x),i,1,r[2]))),
273 n:derivdegree(eq,y,x),
274 makelist('diff(y,x,j)=_k^j,j,0,n),
276 ce:subst(%%,lhs(eq))=0,
280 makelist([%%[j],multiplicities[j]],j,1,length(%%)),
281 cr:sublist(%%,lambda([e],is(radcan(imagpart(e[1]))>=0))),
291 partsolL_UC(eq,y,x):=block([spr,u],
292 if rhs(eq)=0 then return(0),
294 rhs(desolve([%%],[u(x)])),
296 sublist(%%,lambda([e],freeof(u,ilt,e))),
298 if not atom(spr) and op(spr)="+" then
300 sublist(%%,lambda([e],ode_check(lhs(eq),y=e)#0) ),
301 apply("+",%%),return(ratsimp(%%)))
306 partsolL_VP(eq,y,x):=block([W,Wi,_n,_dp],
307 if rhs(eq)=0 then return(0),
312 makelist(0,i,1,_n-1),
314 Wi:radcan(trigsimp(invert(W))),
326 partsol(eq,y,x):=block([s,eq1],
327 eq1:subst(y=y(x),eq),
328 if freeof(laplace,laplace(rhs(eq),x,s))
329 and freeof(log,tan,atan,sec,csc,rhs(eq))
330 then partsolL_UC(eq,y,x)
331 else partsolL_VP(eq,y,x)
338 odeM(A,F,t):=block([W,gamma_expand,n,Ya],
342 W.integrate(trigsimp(invert(W).F),t),
345 W.transpose(makelist(concat(C,i),i,1,n))+Ya)$
351 odeM_ic(A,B,t,t0,Y0):=block([bspr],
354 list_matrix_entries(%%),
355 solve(%%,makelist(concat(C,i),i,1,length(Y0))),
364 matrix_exp(A,r):=block([n,B,s,t,Lap,f],
366 B:invert(s*ident(n)-A),
367 Lap(f):=ilt(f, s, t),
375 odelinsys(A,F,t,t0,Y0):=block([s,g,expA],
378 mat_function(exp,A*t),ratsimp(%%),
380 Aexp(t-t0).Y0+integrate(Aexp(t-s).g(s),s,t0,t),
388 wronskian(functlist,var):=block([end],end:length(functlist)-1,functlist:[
389 functlist],thru end do functlist:
390 endcons(map(lambda([x],diff(x,var)),last(functlist)),functlist),
391 apply('matrix,functlist))$
397 itr2can(eq,y,x):=block(coeff(lhs(eq),'diff(y,x))/coeff(lhs(eq),'diff(y,x,2)),
398 t=radcan(integrate(exp(-integrate(%%,x)),x)))$
400 rootssimp(x):=block([maperror,mapprint],
403 map(polarform,x),rectform(%%),trigsimp(%%))$
406 [f,x,sol,spr,spr1,solvetrigwarn,algebraic],
409 if freeof(%pi,r) then return(r),
411 if part(r,0)="-" then f:part(r,1,0),
413 sol:solve(x=r,%pi)[1],
419 if (length(spr)<=2 or not freeof(%i,%%)) then return(r),
420 spr1:sublist(spr,lambda([e],is(abs(rhs(e)-r)<ratepsilon))),
421 if %%=[] then return(r),