:

Delay differential equations - Maple is a leader

Maple's dsolve numeric can solve delay ODEs and DAEs as of Maple 18. However, if I am not wrong, it cannot solve delay equations with a time dependent history. In this post I show two examples.

Example 1:

y1(t) and y2(t) with time dependent history. Use of piecewise helps this problem to be solved efficiently. Hopefully Maple will add history soon in its capability.

Example 2:

This is a very a complicated stiff problem from immunology. As of now, I believe only Maple can solve this (other than RADAR5 from Prof. Hairer). Details and plots are posted in the attached code.

Let me know if any one has a delay problem that needs to be solved. I have tested many delay problems in Maple (they work fine). The attached examples required addtional tweaking, hence the post.

I want to take this opportunity to congratulate and thank Maple's dsolve numeric/delay solvers for their fantastic job. Maple is world leader not because of example1, but because of its ability to solve example 2.

 > restart;

This code is written by Dayaram Sonawane and Venkat R. Subramnian, University of Washington. You will need Maple 18 or later for this. For those who are wanting to solve these problems in earlier versions, I can help them by offering a procedure based approach (less efficient).

Example1 The first example solved is a state dependent delay problem (http://www.mathworks.com/help/matlab/math/state-dependent-delay-problem.html).

 > eq1:= diff(y1(t),t)=y2(t);
 (1)
 > eq2:=diff(y2(t),t)=-y2(exp(1-y2(t)))*y2(t)^2*exp(1-y2(t));
 (2)

Both y1(t) and y2(t) have time dependent history (y1(t)=log(t) and y2(t)=1/t, t<-0.1). If I am not mistaken one cannot solve this directly using Maple's dsolve numeric command. However, a simple trick can be used to redefine the equations for y1(t) and y2(t) as below

 > eq3:=diff(y1(t),t)=piecewise(t<=0.1,1/t,y2(t));
 (3)
 > eq4:=diff(y2(t),t)=piecewise(t<=0.1,-1/t^2,-y2(exp(1-y2(t)))*y2(t)^2*exp(1-y2(t)));
 (4)

The problem is solved from a small number close to t = 0 (1e-4) to make Maple's dsolve numeric remember the history till t = 0.1

 > epsilon:=1e-4;
 (5)
 > sol:=dsolve({eq3,eq4,y1(epsilon)=log(epsilon),y2(epsilon)=1/epsilon},type=numeric,delaymax=5):
 > with(plots):
 > odeplot(sol,[t,y1(t)],0.1..5,thickness=3,axes=boxed);
 > odeplot(sol,[t,y2(t)],0.1..5,thickness=3,axes=boxed);
 > sol(5.0);log(5.0);1/5.0;
 (6)

Tweaking the tolerances and epsilon will get the solution even more closer to the expected answers.

 >
 >

Example 2

The next problem discussed is very stiff, complicated and as of today, according Professor Hairer (one of the world's leading authority in numerical solutions of ODEs, DAEs), cannot be solved by any other code other than his RADAR (5th order implicit Runge Kutta modified for delay equations, Guglielmi N. and Hairer E. (2001) Implementing Radau IIa methods for stiff delay differential equations. Computing 67:1-12). This problem requires very stringent tolerances. For more information read, http://www.scholarpedia.org/article/Stiff_delay_equations. I can safely say that Maple can boast that it can solve this delay differential equation by using a switch function (instead of Heaviside/picecewise function). Code is attached below and results are compared with the output from RADAR code.  Note that dsolve/numeric is probably taking more time steps compared to RADAR, but the fact that Maple's dsolve numeric solved this model (which cannot be solved in Mathematica or MATLAB[needs confirmation for MATLAB]) should make Maple's code writers proud. It is very likely that we will be trying to submit an educational/research article on this topic/example soon to a journal. For some weird reasons, stiff=true gives slightly inaccurate results.

 > restart:
 >
 (7)
 (8)
 > eq[1]:=diff(y[1](t),t)=-r*y[1](t)*y[2](t)-s*y[1](t)*y[4](t);
 (9)
 > eq[2]:=diff(y[2](t),t)=-r*y[1](t)*y[2](t)+alpha*r*y[1](y[5](t))*y[2](y[5](t))*H1;#Heaviside(t-35);
 (10)
 > eq[3]:=diff(y[3](t),t)=r*y[1](t)*y[2](t);
 (11)
 > eq[4]:=diff(y[4](t),t)=-s*y[1](t)*y[4](t)-gamma1*y[4](t)+beta*r*y[1](y[6](t))*y[2](y[6](t))*H2;#Heaviside(t-197);
 (12)
 > eq[5]:=diff(y[5](t),t)=H1*(y[1](t)*y[2](t)+y[3](t))/(y[1](y[5](t))*y[2](y[5](t))+y[3](y[5](t)));#eq[7]:=y[7](t)=HH(t);
 (13)
 > eq[6]:=diff(y[6](t),t)=H2*(10.^(-12)*0+y[2](t)+y[3](t))/(10.^(-12)*0+y[2](y[6](t))+y[3](y[6](t)));
 (14)
 > H1:=1/2+1/2*tanh(100*(t-35));H2:=1/2+1/2*tanh(100*(t-197));
 (15)
 > alpha:=1.8;beta:=20.;gamma1:=0.002;r:=5.*10^4;s:=10.^5;
 (16)
 > seq(eq[i],i=1..6);
 (17)
 > ics:=y[1](0)=5.*10^(-6),y[2](0)=10.^(-15),y[3](0)=0,y[4](0)=0,y[5](0)=1e-40,y[6](0)=1e-20;
 (18)
 > #infolevel[all]:=10;
 > sol:=dsolve({seq(eq[i],i=1..6),ics},type=numeric,delaymax=300,initstep=1e-6,abserr=[1e-21,1e-21,1e-21,1e-21,1e-9,1e-9],[y[1](t),y[2](t),y[3](t),y[4](t),y[5](t),y[6](t)],relerr=1e-9,maxstep=10,optimize=false,compile=true,maxfun=0):

note that compile = true was used for efficiency

 > t11:=time():sol(300);time()-t11;
 (19)
 > with(plots):
 (20)
 (21)

Values at t = 300 match with expected results.

 > p[1]:=odeplot(sol,[t,log(y[1](t))/log(10)],0..300,axes=boxed,thickness=3):
 > display({pr[1],p[1]});
 > p[2]:=odeplot(sol,[t,log(y[2](t))/log(10)],0..300,axes=boxed,thickness=3,numpoints=1000):
 > display({pr[2],p[2]});
 >
 > p[3]:=odeplot(sol,[t,log(y[3](t))/log(10)],0..300,axes=boxed,thickness=3):
 > display({pr[3],p[3]});
 > p[4]:=odeplot(sol,[t,log(y[4](t))/log(10)],197..300,axes=boxed,thickness=3,view=[197..300,-9..-5]):
 > display({pr[4],p[4]});