Euler's method for 2D systems

October 7, 1998

Here is how use Maple to perform Euler's method for a 2D system.
It's a straightfoward extension of the 1D version.

We'll apply it to the Van der Pol initial value problem:

diff(x(t), t) = y

diff(y(t), t) = -x+(1-x^2)*y

x(0) = 1

y(0) = 1

> dt:=0.50:
n:=ceil(4.0/dt):  

t:=0.0:  

x:=1.0:  

y:=1.0:  

txdata[0] := [t,x]:  

tydata[0] := [t,y]:  

xydata[0] := [x,y]:

txydata[0] := [t,x,y]:  

for i from 1 to n do     

  mk := y:     

  nk := -x + (1-x^2)*y:     

  x := x + dt*mk:     

  y := y + dt*nk:     

  t := t + dt:     

  txdata[i] := [t,x]:   

  tydata[i] := [t,y]:  

  xydata[i] := [x,y]:  

  txydata[i] := [t,x,y]:

od:  

t:='t': x:='x': y:='y':                      # (clean-up)

txdatalist := [ seq( txdata[i], i=0..n ) ]:  

tydatalist := [ seq( tydata[i], i=0..n ) ]:  

xydatalist := [ seq( xydata[i], i=0..n ) ]:

txydatalist := [ seq( txydata[i], i=0..n ) ]:

txymatrix := convert(txydatalist,matrix);

txymatrix := matrix([[0, 1.0, 1.0], [.50, 1.500, .500], [1.00, 1.75000, -.562500000], [1.50, 1.468750000, -.8574218750], [2.00, 1.040039063, -1.095681190], [2.50, .4921984680, -1.570952415], [3.00, -....

Here is a way to plot the x and y functions.

> plot( {txdatalist,tydatalist},
`t`=0..4, `x and y`=-3.5..1.8);

[Plot]

Here is how to get a phase plane plot.

> plot( xydatalist );

[Plot]

> with(DEtools):
with(plots):

Here the phase plane plot is combined with the slope field plot.

> fieldplot := dfieldplot([D(x)(t)=y(t),D(y)(t)=-x(t)+(1-x(t)^2)*y(t)],
[x(t),y(t)],t=0..10,x=-3..3,y=-5..5):

eulerplot := plot( xydatalist,color=blue):

display([fieldplot,eulerplot]);

[Plot]

> dt:=0.05:
n:=ceil(4.0/dt):  

t:=0.0:  

x:=1.0:  

y:=1.0:  

txdata[0] := [t,x]:  

tydata[0] := [t,y]:  

xydata[0] := [x,y]:

txydata[0] := [t,x,y]:  

for i from 1 to n do     

  mk := y:     

  nk := -x + (1-x^2)*y:     

  x := x + dt*mk:     

  y := y + dt*nk:     

  t := t + dt:     

  txdata[i] := [t,x]:   

  tydata[i] := [t,y]:  

  xydata[i] := [x,y]:  

  txydata[i] := [t,x,y]:

od:  

t:='t': x:='x': y:='y':                      # (clean-up)

txdatalist2 := [ seq( txdata[i], i=0..n ) ]:  

tydatalist2 := [ seq( tydata[i], i=0..n ) ]:  

xydatalist2 := [ seq( xydata[i], i=0..n ) ]:

txydatalist2 := [ seq( txydata[i], i=0..n ) ]:

txymatrix2 := convert(txydatalist2,matrix);

txymatrix2 := matrix([[0, 1.0, 1.0], [0.5e-1, 1.050, .950], [.10, 1.09750, .8926312500], [.15, 1.142131563, .8286288165], [.20, 1.183563004, .7589078352], [.25, 1.221508396, .6845203606], [.30, 1.2557...

> eulerplot2 := plot( xydatalist2,color=green):
display([fieldplot,eulerplot,eulerplot2]);

[Plot]

> dt:=0.005:
n:=ceil(4.0/dt):  

t:=0.0:  

x:=1.0:  

y:=1.0:  

txdata[0] := [t,x]:  

tydata[0] := [t,y]:  

xydata[0] := [x,y]:

txydata[0] := [t,x,y]:  

for i from 1 to n do     

  mk := y:     

  nk := -x + (1-x^2)*y:     

  x := x + dt*mk:     

  y := y + dt*nk:     

  t := t + dt:     

  txdata[i] := [t,x]:   

  tydata[i] := [t,y]:  

  xydata[i] := [x,y]:  

  txydata[i] := [t,x,y]:

od:  

t:='t': x:='x': y:='y':                      # (clean-up)

txdatalist3 := [ seq( txdata[i], i=0..n ) ]:  

tydatalist3 := [ seq( tydata[i], i=0..n ) ]:  

xydatalist3 := [ seq( xydata[i], i=0..n ) ]:

txydatalist3 := [ seq( txydata[i], i=0..n ) ]:

txymatrix3 := convert(txydatalist3,matrix):

eulerplot3 := plot( xydatalist3,color=black):

display([fieldplot,eulerplot,eulerplot2,eulerplot3]);

[Plot]

Below we list the endpoints of the second (Delta*t = Float(5, -2) ) and third (Delta*t = Float(5, -3) ) approximations and the difference of the two.

> txydatalist3[nops(txydatalist3)];

[4.000, -1.754592724, .5693176792]

> txydatalist2[nops(txydatalist2)];

[4.00, -1.854889335, .5700158079]

> txydatalist3[nops(txydatalist3)]-txydatalist2[nops(txydatalist2)];

[0, .100296611, -0.6981287e-3]

Now, Maple has even more powerful numerics, using not Euler's Method but a Runge-Kutta approximation of degree 4.

> g:=dsolve({D(x)(t)=y(t),D(y)(t)=-x(t)+(1-x(t)^2)*y(t),x(0)=1,y(0)=1},
[x(t),y(t)],type=numeric);

g := proc (rkf45_x) local i, rkf45_s, outpoint, r1, r2; option `Copyright (c) 1993 by the University of Waterloo. All rights reserved.`; global loc_control, loc_y0, loc_y1; outpoint := evalf(rkf45_x);...

Here's what this gets for an endpoint.

> g(4);

[t = 4, x(t) = -1.743955298641851, y(t) = .5689230883748396]

> with(plots):

And here's the x and y graphs.

> plot1:=odeplot(g,[t,x(t)],0..4):
plot2:=odeplot(g,[t,y(t)],0..4,color=blue):

display([plot1,plot2]);

[Plot]

And the phase plane.

> odeplot(g,[x(t),y(t)],0..4);

[Plot]

And here we have them all together, the latest addition in cyan, barely visible next to the black (Delta*t = Float(5, -3) ) curve.

> dsolveplot:=odeplot(g,[x(t),y(t)],0..4,color=cyan):
display([fieldplot,eulerplot,eulerplot2,eulerplot3,dsolveplot]);

[Plot]

Here's the difference between the dsolve,numeric endpoint and the Euler's Method (Delta*t = Float(5, -3) ) endpoint.

> subs(g(4),[t,x(t),y(t)])-txydatalist3[nops(txydatalist3)];

[0, 0.10637438e-1, -0.3945978e-3]

These two are fairly close.  No wonder the cyan curve is barely visible.