You are on page 1of 10

Math 128A Spring 2002

Sergey Fomel

Handout # 27
May 7, 2002

Answers to Homework 11: Numerical Solution of ODE:
Multistep Methods )
1. Derive a variable-step Adams-Bashforth method of the form
yk+1 = yk + h k Ak f (xk , yk ) + h k Bk f (xk−1 , yk−1 ) ,

(1)

where xk+1 = xk +h k , h k = αk h k−1 , and yk approximates y(xk ) – the solution of the initial-value
problem 
0
y (x) = f (x, y)
(2)
y(x0 ) = y0
Considering αk and h 0 as given, derive appropriate expressions for the coefficients Ak and Bk
and determine the order of the method.
Answer:
To derive this method, we can use linear interpolation to approximate the derivative of the
function y(x):
y 0 (x) ≈ P(x) =

f (xk , yk ) (x − xk−1 ) − f (xk−1 , yk−1 ) (x − xk )
.
h k−1

The predicted value of y(xk+1 ) is then approximated as follows:
xk+1
xk+1
Z
Z
0
y(xk+1 ) = y(xk ) +
y (x) d x ≈ yk +
P(x) d x
xk

xk

f (xk , yk )
= yk +
h k−1

xk+1
Z

xk+1
Z
(x − xk ) d x .

xk

xk

f (xk−1 , yk−1 )
(x − xk−1 ) d x −
h k−1

We find that
1
Ak =
h k h k−1

xk+1
Z
(x − xk−1 ) d x =
xk

and
1
Bk = −
h k h k−1

1
h k h k−1

h kZ
+h k−1

t dt =

(h k + h k−1 )2 − h 2k−1
αk
= 1+
,
2 h k h k−1
2

h k−1
xk+1
Z
(x − xk ) d x = −
xk

1
h k h k−1

Z

h 2k
αk
h k t dt = −
=− .
2 h k h k−1
2

0

To determine the local error of this method, we can integrate the error of the polynomial interpolation:
xk+1
Z
y 000 (ξx )
(x − xk−1 ) (x − xk ) d x ,
E=
2
xk

1

B = −2. with the Taylor method. Answer: We can find the coefficients. we arrive at a system of linear equations for the coefficients of the approximation h y 0 (xk+1 ) ≈ A y(xk+1 ) + B y(xk ) + C y(xk−1 ) . we can apply the weighted mean-value theorem for integrals to deduce that E = = xk+1 Z Zh k y 000 (ξ ) (t + h k−1 ) t dt (x − xk−1 ) (x − xk ) d x = 2 xk 0 ! 3 2 000 y (ξ ) h k−1 αk (2 αk + 3) y 000 (ξ ) h 3k h 2k h k−1 + = . xk+1 ] and ξ2 is a point in [xk−1 . xk+1 ]. and C = 1/2. Using the Taylor series expansions h3 h2 y(xk ) = y(xk+1 ) − h y 0 (xk+1 ) + y 00 (xk+1 ) − y 000 (ξ1 ) 2 6 and (2 h)3 000 y (ξ2 ) . y) . 2. (4) i=0 Derive a BDF method of the form A yk+1 + B yk + C yk−1 = h f (xk+1 . for example.where y 000 (x) is assumed to exist and ξx is some point between xk−1 and xk+1 (which depends on x). The method order is 2. (3) we can arrive at the backward differentiation formula (BDF) n X Ai yk+1−i ≈ h f (xk+1 . 2 . xk+1 ]. yk+1 ) . 2 3 2 12 y 000 (ξ ) 2 where ξ is some point in [xk−1 . Applying numerical differentiation to approximate the derivative y 0 (xk+1 ) in the ordinary differential equation y 0 (x) = f (x. We see that the local error has the order O(h 30 ). The equations are A+ B +C = 0 −B − 2 C = 1 1 B +2C = 0 2 and the solution is easily found to be A = 3/2. (5) find its error and compare it with the error of the Adams-Moulton method of the same order. y(xk−1 ) = y(xk+1 ) − 2 h y 0 (xk+1 ) + 2 h 2 y 00 (xk+1 ) − 6 where ξ1 is a point in [xk . Since the factor (x − xk−1 ) (x − xk ) does not change sign on the interval of integration. yk+1 ) .

 1 −h −h 1  3 yk+1 pk+1   = yk pk  . The bound on the magnitude of E AM is approximately eight times smaller than the bound on |E B D F |. 9 3 The local error of the second-order Adams-Moulton method is E AM = −y 000 (ξ ) h3 . The system takes the form  0 y (x) = p(x) p 0 (x) = y(x) with the initial conditions  y(0) = y0 p(0) = −y0 In the matrix form. xk−1 ]. (7) i=0 Answer: The first step is to rewrite the second-order equation as a system of two first-order equations. In Homework 10. not necessarily equal to ξ1 . the backward Euler method applied to this system is       yk pk+1 yk+1 +h = yk+1 pk+1 pk or. |y 000 (ξ2 )| .The error of the approximation is EBDF = −   2 h3 B h 3 000 C (2 h)3 000 y (ξ1 ) − y (ξ2 ) = y 000 (ξ1 ) − 2 y 000 (ξ2 ) A 6 A 6 9 Its magnitude is bounded by |E B D F | ≤ |y 000 (ξ1 )| + 2 |y 000 (ξ2 )|  2 h3  2 h3 ≤ max |y 000 (ξ1 )|. 12 where ξ is a point in [xk . Adams-Moulton methods have the general form n X yk+1 = yk + h Ai f (xk+1−i . yk+1−i ) . we found that Euler’s method can be unstable when applied to the initial-value problem  00  y (x) = y(x) y(0) = y0 (6)  0 y (0) = −y0 Prove that both the backward Euler method (Adams-Moulton of order 1) and the trapezoidal method (Adams-Moulton of order 2) are unconditionally stable in this case for the positive step h. 3. equivalently.

For any h > 0.Inverting the matrix.   = 1 − h/2 1 + h/2 k  y0 −y0  for all k ≥ 0. in this case. the numerical solution will decrease in magnitude at each step consistently with the exact solution y(x) = y0 e−x . The method takes the form         h pk h pk+1 yk+1 yk = + + pk+1 pk 2 yk 2 yk+1 or.  yk pk  1 = (1 + h)k   y0 −y0 for all k ≥ 0. in this case. the numerical solution will decrease in magnitude at each step consistently with the exact solution y(x) = y0 e−x .  1 −h/2 −h/2 1  yk+1 pk+1   1 h/2 h/2 1 =  yk pk   1 h/2 h/2 1 Inverting the matrix. For any value h > 0. the original system is underdetermined and can admit infinitely many solutions. the original system can admit infinitely many solutions. 4 . The case of the trapezoidal method is analyzed analogously. equivalently. p(x) = −y0 e−x . p(x) = −y0 e−x . we can express the method in the explicit form  yk+1 pk+1  −1  1 −h/2 1 = −h/2 1 h/2 " # 2 1 1 + h4 h = 2 2 h 1 + h4 1 − h4  h/2 1 yk pk  yk pk  y0 −y0  = 1 2 1 − h4 2  yk pk   The first step yields  y1 p1  = 1 " 1 + h4 h  yk pk 2 1 − h4 2 h 2 1 + h4 # 1 − h/2 = 1 + h/2  y0 −y0  By induction. We need to select a stable solution in the special case h = 1. we can express Euler’s method for this case in the explicit form   yk+1 pk+1 The first step yields   1 −h −h 1 = y1 p1  1 = 1 − h2  −1  yk pk 1 h h 1   1 = 1 − h2 y0 −y0   1 h h 1 1 = 1+h   yk pk   y0 −y0 By induction. because. because. We need to select a stable solution in the special case h = 2.

100 0.01 and h = 0. const double* y.010 0. int nstep.39661 × 10−7 Solution: C program: #include <stdio.storage slope(x.1. y2[n] . we approximated the number π by computing the integral Z1 2dx 1 + x2 (8) −1 A similar solution can be obtained from the initial-value problem   2  y 00 (x) = − y 0 (x) x y(−1) = 0  0 y (−1) = 1 (9) Solve this problem numerically on the interval x ∈ [−1.number of steps h .y.53020 × 10−5 6. (Programming) In Homework 9.001. f2[n] . h = 0.03666 × 10−3 6.number of equations in the system nstep .function pointer for the right-hand side */ void midpoint (int n.20849 × 10−5 6. step=0.f) . 1] using the following methods: (a) Adams-Bashforth of order 2 (b) Adams-Bashforth of order 2 as predictor followed by one correction step of AdamsMoulton of order 2 (c) Adams-Moulton of order 2 solving the quadratic equation for yk+1 Initialize each of these methods with the midpoint step (Runge-Kutta of order 2). double* f)) { int k.001 Adams-Bashforth 2. double h. Output the absolute error in approximating π = y(1) with the step sizes h = 0.14736 × 10−4 3. double* y.h" /* Function: midpoint -----------------Solves a system of ODEs by the midpoint method n .h> /* for output */ #include "ode. void (*slope)(double x. double* f1. 5 . double* y2.function values f1[n]. double x. Answer: Step size 0.46844 × 10−3 6.4.starting value of the variable y[n]. double* f2.step size x .18631 × 10−6 Adams-Bashforth-Moulton 5.78036 × 10−2 3.36360 × 10−7 Adams-Moulton 7.

double* y. for (k=0.function values f1[n]. y2[n] .y. step < nstep. for (k=0./* print initial conditions */ printf("%f ".*f2[k]-f1[k]). step < nstep. printf("%f ".number of steps ncorr . k < n. double h. k < n.y. for (step=0. x+=h. for (corr=0. k++) { y[k] += h*f2[k].f1).starting value of the variable y[n]. double* f2.step size x . int nstep. k < n.5*h*(3. void (*slope)(double x. } 6 /* Adams-Moulton */ /* corrector */ .y2. k++) { printf("%f ". } printf("\n").f1).y. k++) { /* Adams-Bashforth */ y2[k] = y[k] + 0.5*h*f1[k]. double* f1.y[k]). int ncorr. for (k=0. /* corrector */ } } /* Function: adams --------------Solves a system of ODEs by second-order Adams-Bashforth-Moulton method n . double* y2. k++) { y2[k] = y[k] + 0. for (step=0.x).f) .y[k]). for (k=0.x). double x. k++) { y2[k] = y[k] + 0.f2). f2[n] .number of equations in the system nstep . corr++) { slope (x. step++) { slope(x.function pointer for the right-hand side */ void adams (int n. corr. double* f)) { int k. const double* y. corr < ncorr. k < n.5*h. k < n.storage slope(x.number of correction steps h . for (k=0. /* predictor */ } x += h.5*h*(f2[k]+f1[k]). printf("%f ".y2. step.f2). step++) { slope(x. /* predictor */ } slope(x+0. } printf("\n").

).+h[k]. printf("%f ". pi_ode). step++) { t2 = t+h. f1. y."ABM error with h=%f: %g\n". double* f) { f[0] = y[1].-h*t*y1)/(sqrt(1.).h[k]. adams(2.} printf("%f ".+h*t2*y1*(2. f1. nstep[k]-1. } /* Adams-Moulton specialized for the pi ODE system */ void pi_moulton(int nstep. y2. 1.t.. for (k=0. adams(2. double* y) { int step.200. } } #include <stdio. h[k]. k < n. printf("%f %f %f\n".t. y. double t. fprintf(stderr. double h. f2. y. h[k].h> /* for output */ #include <math. f1[k] = f2[k].y[1]). h[k].. /* solve the quadratic equation */ y[1] = y1*(2. y1. y2[2].5*h*(y1+y[1]). -1. k++) { y[k] = y2[k]. midpoint(2. nstep[k]-1.. double pi. y[1] = 1. 7 .h> /* for math functions */ #include "ode. const double* y. y[0] = 0. y[2].y[1]). } } /* main program */ int main (void) { int k. y2..1. pi_ode). for (step=0.y[k]). -1. f1.x).01. y[1] = 1. h[]={0.h" /* right-hand side for the pi ODE system */ void pi_ode (double x.h[k]. k++) { y[0] = 0.y[0]. f1. pi_ode).+h[k]. step < nstep.001}. y2.fabs(pi-y[0])).-h*t*y1))+1. fprintf(stderr. } printf("\n"). double t2. 0. pi = acos(-1. f2.. 1.fabs(pi-y[0])). midpoint(2.y[0].0."AB error with h=%f: %g\n". nstep[]={20. k < 3. y. for (k=0. printf("%f %f %f\n". y[0] += 0. f2[2]. f1[2]. 1. f2. y2. t = t2. f[1] = -y[1]*y[1]*x. y1 = y[1].. pi_ode). -1.2000}.0. f2. h[k]. -1.

y2. (11) y(0) = 0 . y 00 (t) = −  G M y(t) 3/2 ..h[k]."AM error with h=%f: %g\n". A more direct approach to the same problem involves the equations of Newton’s mechanics for the two-body problem: x 00 (t) = −  G M x(t) x 2 (t) + y 2 (t) 3/2 . It is more stable in the case of the Adams-Bashforth-Moluton method. Time 1 2 3 Adams-Bashforth x error y error -0.00870902 -0. we studied the motion of a planet. f2. -1.108425 . 3. 2.628241 -0. midpoint(2. Does the periodicity hold? Output the error x(k) − x(0) and y(k) − y(0) for k = 1. -1.00446057 -0.fabs(pi-y[0])). x and y are the planet coordinates with respect to the star. f1. the step size h = 360 year. } return 0. h[k].. 1.130388 0.+h[k]. The appropriate initial conditions (for the planet position “in July”) are x(0) = a (1 − ) . G is the gravitational constant.572406 0. pi_moulton(nstep[k]-1. (Programming) In Homework 3. y (0) = a ω 1− where  is the orbit eccentricity. y. (12) x 0 (0) = 0 r 1+ 0 . pi_ode).748445 8 Adams-Bashforth-Moulton x error y error -0.112335 -0. fprintf(stderr. a = 1 AU. and M is the mass of the star. In terms of the orbit characteristics. x 2 (t) + y 2 (t) (10) where t is time.y[0] = 0. y). 1]. G M = ω2 a. Answer: The period of the numerical solutions is erroneous compared to the exact period of one year. } 5. h[k].6. where ω is angular frequency. y[1] = 1. Plot the solution (planet trajectory) for t ∈ [0.00954070 -0.399762 -0.360284 0..0766191 -0. ω = 2 π year . and a is the major semi-axis of the orbit. Solve the initial-value problem numerically using the following methods: (a) Adams-Bashforth of order 2 (b) Adams-Bashforth of order 2 as predictor followed by one correction step of AdamsMoulton of order 2 1 1 Take  = 0.

2 0 −0.2 0.4 −1.6 9 −0.6 −0.2 0 0.6 −1.8 −1.2 0 0.4 −0.4 −0.2 −0.2 −1 −0.2 0 −0.2 0.8 0.6 −0.4 0.2 −1 −0.8 −1.8 −0.4 −0.4 .8 −0.4 0.Adams-Bashforth: 0.2 −0.6 −1.6 0.4 −0.4 −1.6 −0.6 0.8 0.4 Adams-Bashforth-Moulton: 0.

y2. static double w. f2[4]. y0[2] = 0. double* f) { double r.Solution: C program: #include <stdio. h. y2. y2. y. double h.6. f[2] = . y0[1] = 0.y[1]-y0[1]). y. /* right-hand side for the newton ODE system */ void newton (double x. y2[4].+eps)/(1."Error at t=%d: %g %g\n". f1. ncorr. newton). newton). nstep=360. for (k=1.-eps).y[0]-y0[0]. k < 3.. f[3] = . y0[3] = a*w*sqrt((1.y[0]-y0[0]. f2. } midpoint(4. r *= sqrt(r). const double* y. r = y[0]*y[0]+y[1]*y[1]. newton)."Error at t=1: %g %g\n". } } return 0.. h.k+1. f1. f[1] = y[3]. fprintf(stderr. ncorr++) { for (k=0.. w = 2. 0. for (ncorr=0.*acos(-1.h> /* for output */ #include <math. f[0] = y[2].h" static const double a=1. k < 4. ncorr. f2. f2.y[1]-y0[1])..-eps)).). ncorr < 2.w*w*a*y[1]/r. static const double eps=0. f1. y[4]. y. nstep-1. 1./(double) nstep. k++) { adams(4. h. } /* main program */ int main (void) { int k. 0. ncorr.h> /* for math functions */ #include "ode. y0[0] = a*(1. f1[4].. k++) { y[k] = y0[k]. adams(4. fprintf(stderr.w*w*a*y[0]/r. } 10 . h. h = 1. nstep. y0[4].