Chapter 1: First-order equations

Direction fields

Here's how to make a direction field for the first-order differential equation
         dy/dt = 2*sin(t) - y .

>    with(DEtools):

>    dfieldplot( diff(y(t),t) = 2*sin(t)-y(t), y(t),
            t=0..5, y=-6..6, arrows=line );

[Maple Plot]

If you don't put in "arrows=line", you get arrow-heads on your mini-tangents.

>   

A numerical method: Euler's

Euler's method in Maple

>    h:=0.1:          # This is our step-size.
n:=ceil(4.0/h):  # This calculates how many steps
                 # of size  h  we need to take, to get to 4.0.
t:=0.0:
y:=0.05:         # The initial condition.
data[0]:=[t,y]:  # We store the initial point so we can
                 # plot it later.
for i from 1 to n do    # This is how to make a block of
                        # code get executed n times.
   mk := y + sin(y*t):
   y := y + h*mk:
   t := t + h:
   data[i] := [t,y]:  # Store the current point so we can
                      # plot it later.
od:              # This ("do" backwards) marks the end
                 # of the "do" block.
t:='t': y:='y':  h:='h':  # Clean up
  
datalist1 := [ seq( data[i], i=0..n ) ];
                 # This puts all the data into a list
                 # suitable for plotting.
plot( datalist1, 0..4, 0..8, style=POINT, color=red);
                 # This plots the (approximation to the)
                 # solution, with a horizontal (t) range
                 # from 0 to 4, and a vertical (y) range
                 # of 0 to 8. The POINT style means each
                 # data point is marked with a symbol of
                 # some kind. If "style=POINT" were omitted,
                 # the data points would be joined with
                 # straight line segments (try it!).

datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...
datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...
datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...
datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...
datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...
datalist1 := [[0., .5e-1], [.1, .55e-1], [.2, .6104999723e-1], [.3, .6837596656e-1], [.4, .7726469836e-1], [.5, .8808126415e-1], [.6, .1012920302], [.7, .1174950144], [.8, .1374598974], [.9, .162180528...

[Maple Plot]

>   

>   

>   

Estimating the error by repeating the computation with a smaller step size

Euler's method gives only an approximation to the solution.
To test the accuracy, we can do the computation over again,
 but with a value of  h  that is half of the old value.  Then

   -  the new approximate solution should be more accurate than the old approximation, and

   - the difference between the two approximations can be used to estimate the error in the new approximation.

>    h:= 0.1/2:       # This is our step-size, half of the value above.
n:=ceil(4.0/h):  # This calculates how many steps
                 # of size  h  we need to take, to get to 4.0.
t:=0.0:
y:=0.05:         # The initial condition.
data[0]:=[t,y]:  # We store the initial point so we can
                 # plot it later.
for i from 1 to n do    # This is how to make a block of
                        # code get executed n times.
   mk := y + sin(y*t):
   y := y + h*mk:
   t := t + h:
   data[i] := [t,y]:  # Store the current point so we can
                      # plot it later.
od:              # This ("do" backwards) marks the end
                 # of the "do" block.
t:='t': y:='y':  h:='h':  # Clean up
  
datalist2 := [ seq( data[i], i=0..n ) ];
                 # This puts all the data into a list
                 # suitable for plotting.
plot( datalist2, 0..4, 0..8, style=POINT, color=blue);
                 # This plots the (approximation to the)
                 # solution, with a horizontal (t) range
                 # from 0 to 4, and a vertical (y) range
                 # of 0 to 8. The POINT style means each
                 # data point is marked with a symbol of
                 # some kind. If "style=POINT" were omitted,
                 # the data points would be joined with
                 # straight line segments (try it!).

datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...
datalist2 := [[0., .5e-1], [.5000000000e-1, .5250000000e-1], [.1000000000, .5525624985e-1], [.1500000000, .5829534219e-1], [.2000000000, .6164731879e-1], [.2500000000, .6534614230e-1], [.3000000000, .6...

[Maple Plot]

>    p1:=plot( datalist1 ,style=point, color=red ):
p2:=plot( datalist2 ,style=point, color=blue  ):
with(plots):        # (See Section below on combining plots)
display([p1,p2]);   # (See Section below on combining plots)

Warning, the name changecoords has been redefined

[Maple Plot]

>   

>    errorbarset := {}:
for i from 1 to nops(datalist1) do
  xvalue := op(1,op(i,datalist1)):
  yendvalue := op(2,op(i,datalist1)):
  ycenter := op(2,op(2*i-1,datalist2)):
  width := abs(ycenter-yendvalue):
  errorbarset := errorbarset union
      {[ [xvalue,ycenter-width],
         [xvalue,ycenter+width] ]}:
od:
errorbarplot := plot(errorbarset,color=black):
with(plots):
display({p1,p2,errorbarplot});

[Maple Plot]

We expect that the exact solution will pass through each of the vertical error
bars, shown here as black line segments.

 

Making sure the step-size h is small enough

>    print([`step-size h`,`steps n`,`approx. y(4)`]): # table header.
h:=0.1:
for j from 1 to 7 do # We will try 7 different step sizes.        

   n:=ceil(4.0/h):  # Compute the needed number of steps
                     # for the current step-size.
   t:=0.0:
   y:=0.05:   
   for i from 1 to n do
      mk := y + sin(y*t):
      y := y + h*mk:
      t := t + h:
   od:              
   print([h,n,y]):
   h := h/2.0:     # Halve the step-size.
od:


[`step-size h`, `steps n`, `approx. y(4)`]

[.1, 40, 7.761384776]

[.5000000000e-1, 80, 8.569406097]

[.2500000000e-1, 160, 9.081137621]

[.1250000000e-1, 320, 9.330392890]

[.6250000000e-2, 640, 9.470109917]

[.3125000000e-2, 1280, 9.545526378]

[.1562500000e-2, 2560, 9.584681579]

>    9.584681599-9.545526386;

.39155213e-1

>    [9.584681599 - .039155213,
9.584681599 + .039155213];

[9.545526386, 9.623836812]

Euler's method with two different step sizes,
for an example problem with an exact solution

>   

and approximate the solution on the interval  t = T0 = 0 to t = T = 2, by means of Euler's method.

This is done twice, for h = 0.1 and for h = 0.05.
Plots of the two approximate solutions are combined with
a plot of error bars based on comparing the approximate solutions,
and a plot of the exact solution.

>    h:=0.1:    # step size
T0:=0.0:   # initial time
y0:=0.2:   # initial y value
T:=2.0:    # time we want to get to
datalist1 := 'datalist1': datalist2 := 'datalist2':
for itry from 1 to 2 do
   t:=T0:
   y:=y0:
   data[0]:=[t,y]:
   n:=ceil((T-t)/h);
   for i from 1 to n do
      mk := y + sin(t):
      y := y + h*mk:
      t := t + h:
      data[i]:=[t,y]:
   od:
   if(itry=1) then datalist1:= [ seq( data[i], i=0..n ) ] fi;
   if(itry=2) then datalist2:= [ seq( data[i], i=0..n ) ] fi;
  
   h := h/2: # reduce the step size by a factor of 2
             # and start over again
od:
p1:=plot( datalist1 ,style=point, color=red ):
p2:=plot( datalist2 ,style=point, color=blue  ):
errorbarset := {}:
for i from 1 to nops(datalist1) do
  xvalue := op(1,op(i,datalist1)):
  yendvalue := op(2,op(i,datalist1)):
  ycenter := op(2,op(2*i-1,datalist2)):
  width := abs(ycenter-yendvalue):
  errorbar := [[xvalue,ycenter-width],           [xvalue,ycenter+width]]:
  errorbarset := errorbarset union {errorbar}:
od:
errorbarplot := plot(errorbarset,color=black):
t:='t':      # exact solution obtained by the technique of                                                            # integrating factors; see the text
yexact := exp(t)*(y0 + int(exp(-s)*sin(s),s=0..t)):
exactsolnplot:=plot( yexact, t=0..2,color=black):
with(plots): # (See Section below on combining plots)
display([p1,p2,errorbarplot,exactsolnplot]);
h:='h': T0:='T0': t:='t': T:='T': y:='y': y0:='y0':

[Maple Plot]

>   

>   

Plotting a function (such as an analytical solution)

Say you have found that

y := 1/(1/4+15*exp(-4*t))

is a solution of your differential equation. You can plot the solution  like this
(the same way you plot any function):

>    y:= 'y': t:='t':
y := 1/(1/4 + 15*exp(-4*t)):
plot(y,t=0..3);

[Maple Plot]

>   

What is Maple doing to plot a function?

When asked to plot a function as above, Maple simply selects a large number of values of the

independent variable (t in the above example), evaluates the function at each of them, and then joins

the corresponding points with straight lines. You can see the points it's choosing by selecting

the "point" style:

>    plot(y,t=0..3,style=point);

[Maple Plot]

Usually it chooses enough points so that when it joins them with straight lines, the resulting polygonal arc

looks like a smooth curve. If it looks angular, you can increase the number of points used like this:

>    plot(y,t=0..3,style=point,numpoints=200);

[Maple Plot]

Ranges and labels

You can dictate a range for the vertical axis like this:

>    plot(y,t=0..3,2..4);

[Maple Plot]

You can add a label to the vertical axis, and a title,  like this:

>    plot(y,t=0..3,`hi ho`=2..4,title=`JR's plot`);

[Maple Plot]

Combining plots

Frequently you'll want to superimpose several plots.

If you simply want to plot several functions for which you have formulas, you simply put the

formulas in a comma-separated list enclosed by curly braces ({}):

>    plot({x^2,x^4},x=-1..1);

[Maple Plot]

To combine plots which are of differing types, such as a direction field and a plot of  an

analytical solution formula, you give each plot a name, and then use the "display" function

in the "plots" package.  

>    restart:
plot1:=plot( exp(-t),t=0..2):
with(DEtools):
plot2:=dfieldplot(diff(y(t),t)=-y(t),y(t),t=0..2,y=0..1):
with(plots):
display( [ plot1, plot2 ] );

Warning, the name changecoords has been redefined

[Maple Plot]

>