Let a first-order initial-value problem be given in the form
u ′ ( t ) = f ( t , u ( t ) ) , a ≤ t ≤ b , u ( a ) = u 0 . \begin{split}
u'(t) &= f\bigl(t,u(t)\bigr), \qquad a \le t \le b,\\
u(a)& =u_0.
\end{split} u ′ ( t ) u ( a ) = f ( t , u ( t ) ) , a ≤ t ≤ b , = u 0 . We represent a numerical solution of an IVP by its values at a finite collection of nodes, which for now we require to be equally spaced:
t i = a + i h , h = b − a n , i = 0 , … , n . t_i = a + ih, \qquad h=\frac{b-a}{n}, \qquad i=0,\ldots,n. t i = a + ih , h = n b − a , i = 0 , … , n . The number h h h is called the step size .
Because we don’t get exactly correct values of the solution at the nodes, we need to take some care with the notation. From now on we let u ^ ( t ) \hat{u}(t) u ^ ( t ) denote the exact solution of the IVP. The approximate value at t i t_i t i computed at the nodes by our numerical methods will be denoted by u i ≈ u ^ ( t i ) u_i\approx \hat{u}(t_i) u i ≈ u ^ ( t i ) . Because we are given the initial value u ( a ) = u 0 u(a)=u_0 u ( a ) = u 0 exactly, there is no need to distinguish whether we mean u 0 u_0 u 0 as the exact or the numerical solution.
Consider a piecewise linear interpolant to the (as yet unknown) values u 0 , u 1 , … u_0,u_1,\ldots u 0 , u 1 , … , u n u_n u n . For t i < t < t i + 1 t_i < t < t_{i+1} t i < t < t i + 1 , its slope is
u i + 1 − u i t i + 1 − t i = u i + 1 − u i h . \frac{u_{i+1} - u_{i}}{t_{i+1}-t_i} = \frac{u_{i+1}-u_i}{h}. t i + 1 − t i u i + 1 − u i = h u i + 1 − u i . We can connect this derivative to the differential equation by following the model of u ′ = f ( t , u ) u'=f(t,u) u ′ = f ( t , u ) :
u i + 1 − u i h = f ( t i , u i ) , i = 0 , … , n − 1. \frac{u_{i+1}-u_i}{h} = f(t_i,u_i), \qquad i=0,\ldots,n-1. h u i + 1 − u i = f ( t i , u i ) , i = 0 , … , n − 1. We could view the left-hand side as a forward-difference approximation to u ′ ( t ) u'(t) u ′ ( t ) at t = t i t=t_i t = t i . We can rearrange the equation to get Euler’s method , our first method for IVPs.
Algorithm 6.2.1 (Euler’s method for an IVP)
Given the IVP u ′ = f ( t , u ) u'=f(t,u) u ′ = f ( t , u ) , u ( a ) = u 0 u(a)=u_0 u ( a ) = u 0 , and the nodes (6.2.2) , iteratively compute the sequence
u i + 1 = u i + h f ( t i , u i ) , i = 0 , … , n − 1. u_{i+1}=u_i + h f(t_i,u_i), \qquad i=0,\ldots,n-1. u i + 1 = u i + h f ( t i , u i ) , i = 0 , … , n − 1. Then u i u_i u i is approximately the value of the solution at t = t i t=t_i t = t i .
Euler’s method marches ahead in t t t , obtaining the solution at a new time level explicitly in terms of the latest value.
A basic implementation of Euler’s method is shown in Function 6.2.2 .
Euler’s method for an initial-value problemAbout the code
The ivp
input argument is an ODEProblem
, like in Demo 6.1.2 . It has fields ivp.f
, ivp.tspan
, ivp.u0
, and ivp.p
that fully define the problem. The outputs are vectors of the nodes and approximate solution values at those nodes.
Euler’s method for an initial-value problem1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function [t, u] = eulerivp(ivp, a, b, n)
% EULERIVP Euler's method for a scalar initial-value problem.
% Input:
% ivp structure defining the IVP
% a, b endpoints of time interval (scalars)
% n number of time steps (integer)
% Output:
% t selected nodes (vector, length n+1)
% u solution values (array, m by (n+1))
du_dt = ivp.ODEFcn;
u0 = ivp.InitialValue;
p = ivp.Parameters;
% Define time discretization.
h = (b - a) / n;
t = a + (0:n) * h;
% Initialize solution array.
u = zeros(length(u0), n+1);
u(:, 1) = u0;
% Time stepping.
for i = 1:n
u(:, i+1) = u(:, i) + h * du_dt(t(i), u(i), p);
end
About the code
The ivp
input argument is the same structure that is used with the built-in solve
solvers. The outputs t
and u
are row vectors of the same length, like the fields in a solution object output by solve
. While the entries of u
could be simplified to u(1)
, u(i)
, etc., we chose a column-access syntax like u(:, i)
that will prove useful for what’s coming next in the chapter.
Euler’s method for an initial-value problem1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def euler(dudt, tspan, u0, n):
"""
euler(dudt,tspan,u0,n)
Apply Euler's method to solve the IVP u'=`dudt`(u,t) over the interval `tspan` with
u(`tspan[1]`)=`u0`, using `n` subintervals/steps. Return vectors of times and solution
values.
"""
a, b = tspan
h = (b - a) / n
t = np.linspace(a, b, n+1)
u = np.tile(np.array(u0), (n+1, 1))
for i in range(n):
u[i+1] = u[i] + h * dudt(t[i], u[i])
return t, u.T
6.2.1 Local truncation error ¶ Let u ^ ( t ) \hat{u}(t) u ^ ( t ) be the exact solution of the IVP (6.2.1) , and suppose that somehow we have access to it at t = t i t=t_i t = t i , so that u i = u ^ ( t i ) u_i=\hat{u}(t_i) u i = u ^ ( t i ) . How good is u i + 1 u_{i+1} u i + 1 as an approximation to u ^ ( t i + 1 ) \hat{u}(t_{i+1}) u ^ ( t i + 1 ) ? The answer is revealed through a Taylor series:
u ^ ( t i + 1 ) − [ u i + h f ( t i , u i ) ] = u ^ ( t i + 1 ) − [ u ^ ( t i ) + h f ( t i , u ^ ( t i ) ) ] = [ u ^ ( t i ) + h u ^ ′ ( t i ) + 1 2 h 2 u ^ ′ ′ ( t i ) + O ( h 3 ) ] − [ u ^ ( t i ) + h u ^ ′ ( t i ) ] = 1 2 h 2 u ^ ′ ′ ( t i ) + O ( h 3 ) , \begin{split}
\hat{u}(t_{i+1}) - \bigl[ u_i + hf(t_i,u_i) \bigr]
&= \hat{u}(t_{i+1}) - \bigl[ \hat{u}(t_i) + hf\bigl(t_i,\hat{u}(t_i)\bigr) \bigr] \\
&= \bigl[ \hat{u}(t_i) + h \hat{u}'(t_i) + \tfrac{1}{2}h^2 \hat{u}''(t_i) + O(h^3) \bigr] - \bigl[ \hat{u}(t_i) + h\hat{u}'(t_i) \bigr] \notag \\
&= \tfrac{1}{2}h^2 \hat{u}''(t_i) + O(h^3),
\end{split} u ^ ( t i + 1 ) − [ u i + h f ( t i , u i ) ] = u ^ ( t i + 1 ) − [ u ^ ( t i ) + h f ( t i , u ^ ( t i ) ) ] = [ u ^ ( t i ) + h u ^ ′ ( t i ) + 2 1 h 2 u ^ ′′ ( t i ) + O ( h 3 ) ] − [ u ^ ( t i ) + h u ^ ′ ( t i ) ] = 2 1 h 2 u ^ ′′ ( t i ) + O ( h 3 ) , where we used the fact that u ^ \hat{u} u ^ satisfies the differential equation.
We now introduce some formalities.
Euler’s method is the particular case of (6.2.7) with ϕ ( t , u , h ) = f ( t , u ) \phi(t,u,h) = f(t,u) ϕ ( t , u , h ) = f ( t , u ) , but we will see other one-step methods in later sections.
In close analogy with Convergence of finite differences , we define truncation error as the residual of (6.2.7) when the exact solution is inserted.
The following follows immediately from the definitions.
If ϕ ( t , u , 0 ) = f ( t , u ) \phi(t,u,0)=f(t,u) ϕ ( t , u , 0 ) = f ( t , u ) for any function u u u , then the method (6.2.7) is consistent.
6.2.2 Convergence ¶ While the local truncation error is straightforward to calculate from its definition, it is not the quantity we want to know about and control.
Definition 6.2.3 (Global error of an IVP solution)
Given an IVP whose exact solution is u ^ ( t ) \hat{u}(t) u ^ ( t ) , the global error of approximate solution values u 0 , u 1 , … , u n u_0,u_1,\ldots,u_n u 0 , u 1 , … , u n at times t i t_i t i in (6.2.2) is the vector [ u ^ ( t i ) − u i ] i = 0 , … , n [ \hat{u}(t_i) - u_i ]_{\,i=0,\ldots,n} [ u ^ ( t i ) − u i ] i = 0 , … , n .
At times the term global error may be interpreted as the max-norm of the global error vector, or as its final value.
By our definitions, the local error in stepping from t i t_i t i to t i + 1 t_{i+1} t i + 1 is h τ i + 1 ( h ) h\tau_{i+1}(h) h τ i + 1 ( h ) . To reach the time t = b t=b t = b from t = a t=a t = a with step size h h h , we need to take n = ( b − a ) / h n=(b-a)/h n = ( b − a ) / h steps. If we want to reach, say, t = ( a + b ) / 2 t=(a+b)/2 t = ( a + b ) /2 , then we would have to take n / 2 n/2 n /2 steps, and so on. In fact, to reach any fixed time in the interval, we need to take O ( n ) = O ( h − 1 ) O(n)=O(h^{-1}) O ( n ) = O ( h − 1 ) steps. By expressing the local error with a factor of h h h taken out, the LTE τ itself is accounting for the simple accumulation of error caused by taking O ( n ) O(n) O ( n ) steps.[1]
However, global error is not as simple as a sum of local errors. As explained in Theorem 6.1.2 and illustrated in Demo 6.1.5 , each step causes a perturbation of the solution that can grow as t t t advances. Thus, we have to account for the flow evolution of individual step truncation errors as well as their mere accumulation. That is the subject of the following theorem.
Suppose that the unit local truncation error of the one-step method (6.2.7) satisfies
∣ τ i + 1 ( h ) ∣ ≤ C h p , |\tau_{i+1}(h)| \le C h^p, ∣ τ i + 1 ( h ) ∣ ≤ C h p , and that
∣ ∂ ϕ ∂ u ∣ ≤ L \left| \frac{\partial \phi}{\partial u} \right| \le L ∣ ∣ ∂ u ∂ ϕ ∣ ∣ ≤ L for all t ∈ [ a , b ] t\in[a,b] t ∈ [ a , b ] , all u u u , and all h > 0 h>0 h > 0 . Then the global error satisfies
∣ u ^ ( t i ) − u i ∣ ≤ C h p L [ e L ( t i − a ) − 1 ] = O ( h p ) , |\hat{u}(t_i) - u_i| \le \frac{Ch^p}{L} \left[ e^{L(t_i-a)} - 1
\right] = O(h^p), ∣ u ^ ( t i ) − u i ∣ ≤ L C h p [ e L ( t i − a ) − 1 ] = O ( h p ) , as h → 0 h\rightarrow 0 h → 0 .
Define the global error sequence ϵ i = u ^ ( t i ) − u i ϵ_i=\hat{u}(t_i)-u_i ϵ i = u ^ ( t i ) − u i . Using (6.2.7) , we obtain
ϵ i + 1 − ϵ i = u ^ ( t i + 1 ) − u ^ ( t i ) − ( u i + 1 − u i ) = u ^ ( t i + 1 ) − u ^ ( t i ) − h ϕ ( t i , u i , h ) , ϵ_{i+1} - ϵ_i = \hat{u}(t_{i+1}) - \hat{u}(t_i) - ( {u}_{i+1} - u_i ) =
\hat{u}(t_{i+1}) - \hat{u}(t_i) - h\phi(t_i,u_i,h), ϵ i + 1 − ϵ i = u ^ ( t i + 1 ) − u ^ ( t i ) − ( u i + 1 − u i ) = u ^ ( t i + 1 ) − u ^ ( t i ) − h ϕ ( t i , u i , h ) , or
ϵ i + 1 = ϵ i + [ u ^ ( t i + 1 ) − u ^ ( t i ) − h ϕ ( t i , u ^ ( t i ) , h ) ] + h [ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h ) ] . ϵ_{i+1} = ϵ_i + [\hat{u}(t_{i+1}) - \hat{u}(t_i) - h\phi(t_i,\hat{u}(t_i),h)] +
h[\phi(t_i,\hat{u}(t_i),h)- \phi(t_i,u_i,h)]. ϵ i + 1 = ϵ i + [ u ^ ( t i + 1 ) − u ^ ( t i ) − h ϕ ( t i , u ^ ( t i ) , h )] + h [ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h )] . We apply the triangle inequality, (6.2.8) , and (6.2.9) to find
∣ ϵ i + 1 ∣ ≤ ∣ ϵ i ∣ + C h p + 1 + h ∣ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h ) ∣ . |ϵ_{i+1}| \le |ϵ_i| + Ch^{p+1} + h \left| \phi(t_i,\hat{u}(t_i),h)- \phi(t_i,u_i,h)\right|. ∣ ϵ i + 1 ∣ ≤ ∣ ϵ i ∣ + C h p + 1 + h ∣ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h ) ∣ . The Fundamental Theorem of Calculus implies that
∣ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h ) ∣ = ∣ ∫ u i u ^ ( t i ) ∂ ϕ ∂ u d u ∣ ≤ ∫ u i u ^ ( t i ) ∣ ∂ ϕ ∂ u ∣ d u ≤ L ∣ u ^ ( t i ) − u i ∣ = L ∣ ϵ i ∣ . \begin{split}
\left| \phi(t_i,\hat{u}(t_i),h)- \phi(t_i,u_i,h)\right|
& = \left| \int_{u_i}^{\hat{u}(t_i)} \frac{\partial \phi}{\partial u} \,du \right|\\
& \le \int_{u_i}^{\hat{u}(t_i)} \left|\frac{\partial \phi}{\partial u}\right| \,du \\[1mm]
& \le L | \hat{u}(t_i)-u_i| = L\, |ϵ_i|.
\end{split} ∣ ϕ ( t i , u ^ ( t i ) , h ) − ϕ ( t i , u i , h ) ∣ = ∣ ∣ ∫ u i u ^ ( t i ) ∂ u ∂ ϕ d u ∣ ∣ ≤ ∫ u i u ^ ( t i ) ∣ ∣ ∂ u ∂ ϕ ∣ ∣ d u ≤ L ∣ u ^ ( t i ) − u i ∣ = L ∣ ϵ i ∣. Thus
∣ ϵ i + 1 ∣ ≤ C h p + 1 + ( 1 + h L ) ∣ ϵ i ∣ ≤ C h p + 1 + ( 1 + h L ) [ C h p + 1 + ( 1 + h L ) ∣ ϵ i − 1 ∣ ] ⋮ ≤ C h p + 1 [ 1 + ( 1 + h L ) + ( 1 + h L ) 2 + ⋯ + ( 1 + h L ) i ] . \begin{split}
|ϵ_{i+1}| &\le Ch^{p+1} + (1 + hL) |ϵ_i| \\
&\le Ch^{p+1} + (1 + hL) \bigl[ Ch^{p+1} + (1 + hL) |ϵ_{i-1}|
\bigr]\\
&\;\vdots \\
&\le Ch^{p+1} \left[ 1 + (1+hL) + (1+hL)^2 + \cdots + (1+hL)^i
\right].
\end{split} ∣ ϵ i + 1 ∣ ≤ C h p + 1 + ( 1 + h L ) ∣ ϵ i ∣ ≤ C h p + 1 + ( 1 + h L ) [ C h p + 1 + ( 1 + h L ) ∣ ϵ i − 1 ∣ ] ⋮ ≤ C h p + 1 [ 1 + ( 1 + h L ) + ( 1 + h L ) 2 + ⋯ + ( 1 + h L ) i ] . To get the last line we applied the inequality recursively until reaching ϵ 0 ϵ_0 ϵ 0 , which is zero. Replacing i + 1 i+1 i + 1 by i i i and simplifying the geometric sum, we get
∣ ϵ i ∣ ≤ C h p + 1 ( 1 + h L ) i − 1 ( 1 + h L ) − 1 = C h p L [ ( 1 + h L ) i − 1 ] . |ϵ_i| \le Ch^{p+1}\frac{(1+hL)^i - 1}{(1+hL)-1} = \frac{Ch^p}{L}
\left[ (1+hL)^i - 1 \right]. ∣ ϵ i ∣ ≤ C h p + 1 ( 1 + h L ) − 1 ( 1 + h L ) i − 1 = L C h p [ ( 1 + h L ) i − 1 ] . We observe that 1 + x ≤ e x 1+x \le e^x 1 + x ≤ e x for x ≥ 0 x\ge 0 x ≥ 0 (see Exercise 5 ). Hence ( 1 + h L ) i ≤ e i h L (1+hL)^i \le e^{i h L} ( 1 + h L ) i ≤ e ih L , which completes the proof.
The theorem justifies one more general definition.
We could restate Theorem 6.2.1 as saying that the global error has the same order of accuracy as the LTE. Note, however, that the O ( h p ) O(h^p) O ( h p ) convergence hides a leading constant that grows exponentially in time. When the time interval is bounded as h → 0 h\to 0 h → 0 , this does not interfere with the conclusion, but the behavior as t → ∞ t\to\infty t → ∞ contains no such guarantee.
Convergence of Euler’s methodWe consider the IVP u ′ = sin [ ( u + t ) 2 ] u'=\sin[(u+t)^2] u ′ = sin [( u + t ) 2 ] over 0 ≤ t ≤ 4 0\le t \le 4 0 ≤ t ≤ 4 , with u ( 0 ) = − 1 u(0)=-1 u ( 0 ) = − 1 .
f(u, p, t) = sin((t + u)^2);
tspan = (0.0, 4.0);
u0 = -1.0;
ivp = ODEProblem(f, u0, tspan)
Here is the call to Function 6.2.2 .
t, u = FNC.euler(ivp, 20)
plot(t, u, m=2, label="n=20",
xlabel=L"t", ylabel=L"u(t)", title="Solution by Euler's method")
We could define a different interpolant to get a smoother picture above, but the derivation of Euler’s method assumed a piecewise linear interpolant. We can instead request more steps to make the interpolant look smoother.
t, u = FNC.euler(ivp, 50)
plot!(t, u, m=2, label="n=50")
Increasing n n n changed the solution noticeably. Since we know that interpolants and finite differences become more accurate as h → 0 h\to 0 h → 0 , we should anticipate the same behavior from Euler’s method. We don’t have an exact solution to compare to, so we will use a DifferentialEquations
solver to construct an accurate reference solution.
u_exact = solve(ivp, Tsit5(), reltol=1e-14, abstol=1e-14)
plot!(u_exact, l=(2, :black), label="reference")
Now we can perform a convergence study.
n = [round(Int, 5 * 10^k) for k in 0:0.5:3]
err = []
for n in n
t, u = FNC.euler(ivp, n)
push!(err, norm(u_exact.(t) - u, Inf))
end
pretty_table((n=n, err=err), header=["n", "Inf-norm error"])
The error is approximately cut by a factor of 10 for each increase in n n n by the same factor. A log-log plot also confirms first-order convergence. Keep in mind that since h = ( b − a ) / n h=(b-a)/n h = ( b − a ) / n , it follows that O ( h ) = O ( n − 1 ) O(h)=O(n^{-1}) O ( h ) = O ( n − 1 ) .
plot(n, err, m=:o, label="results",
xaxis=(:log10, L"n"), yaxis=(:log10, "Inf-norm global error"),
title="Convergence of Euler's method")
# Add line for perfect 1st order.
plot!(n, 0.05 * (n / n[1]) .^ (-1), l=:dash, label=L"O(n^{-1})")
Convergence of Euler’s methodWe consider the IVP u ′ = sin [ ( u + t ) 2 ] u'=\sin[(u+t)^2] u ′ = sin [( u + t ) 2 ] over 0 ≤ t ≤ 4 0\le t \le 4 0 ≤ t ≤ 4 , with u ( 0 ) = − 1 u(0)=-1 u ( 0 ) = − 1 . We need to define the function for the right-hand side of the ODE, the interval for the independent variable, and the initial value.
ivp = ode;
ivp.ODEFcn = @(t, u, p) sin((t + u)^2);
ivp.InitialValue = -1;
a = 0; b = 4;
Here is the call to Function 6.2.2 .
[t, u] = eulerivp(ivp, a, b, 20);
clf, plot(t, u, '.-')
xlabel('t')
ylabel('u(t)')
title('Solution by Euler''s method') % ignore this line
We could define a different interpolant to get a smoother picture above, but the derivation of Euler’s method assumed a piecewise linear interpolant. We can instead request more steps to make the interpolant look smoother.
[t, u] = eulerivp(ivp, a, b, 50);
hold on, plot(t, u, '.-')
legend('20 steps', '50 steps')
Increasing n n n changed the solution noticeably. Since we know that interpolants and finite differences become more accurate as h → 0 h\to 0 h → 0 , we should anticipate the same behavior from Euler’s method. We don’t have an exact solution to compare to, so we will use a built-in solver to construct an accurate reference solution.
ivp.AbsoluteTolerance = 1e-13;
ivp.RelativeTolerance = 1e-13;
u_exact = solutionFcn(ivp, a, b);
Now we can perform a convergence study.
n = round(5 * 10.^(0:0.5:3));
err = [];
for k = 1:length(n)
[t, u] = eulerivp(ivp, a, b, n(k));
err(k) = norm(u_exact(t) - u, Inf);
end
table(n', err', VariableNames=["n", "inf-norm error"])
The error is approximately cut by a factor of 10 for each increase in n n n by the same factor. A log-log plot also confirms first-order convergence. Keep in mind that since h = ( b − a ) / n h=(b-a)/n h = ( b − a ) / n , it follows that O ( h ) = O ( n − 1 ) O(h)=O(n^{-1}) O ( h ) = O ( n − 1 ) .
clf
loglog(n, err, 'o-')
hold on, loglog(n, 0.5 * err(end) * (n / n(end)).^(-1), '--')
xlabel('n')
ylabel('inf-norm error') % ignore this line
title('Convergence of Euler''s method') % ignore this line
legend('error', 'O(n^{-1})', 'location', 'southwest') % ignore this line
Convergence of Euler’s methodWe consider the IVP u ′ = sin [ ( u + t ) 2 ] u'=\sin[(u+t)^2] u ′ = sin [( u + t ) 2 ] over 0 ≤ t ≤ 4 0\le t \le 4 0 ≤ t ≤ 4 , with u ( 0 ) = − 1 u(0)=-1 u ( 0 ) = − 1 .
f = lambda t, u: sin((t + u) ** 2)
tspan = [0.0, 4.0]
u0 = -1.0
t, u = FNC.euler(f, tspan, u0, 20)
fig, ax = subplots()
ax.plot(t, u[0, :], "-o", label="$n=20$")
xlabel("$t$"), ylabel("$u(t)$")
title("Solution by Euler's method")
legend()
We could define a different interpolant to get a smoother picture above, but the derivation of Euler’s method assumed a piecewise linear interpolant. We can instead request more steps to make the interpolant look smoother.
t, u = FNC.euler(f, tspan, u0, 200)
ax.plot(t, u[0, :], label="$n=200$")
ax.legend()
fig
Increasing n n n changed the solution noticeably. Since we know that interpolants and finite differences become more accurate as h → 0 h\to 0 h → 0 , we should anticipate the same behavior from Euler’s method. We don’t have an exact solution to compare to, so we will use solve_ivp
to construct an accurate reference solution.
from scipy.integrate import solve_ivp
sol = solve_ivp(f, tspan, [u0], dense_output=True, atol=1e-8, rtol=1e-8)
ax.plot(t, sol.sol(t)[0, :], "--", label="accurate")
ax.legend()
fig
Now we can perform a convergence study.
n_ = array([int(5 * 10**k) for k in arange(0, 3, 0.5)])
err_ = zeros(6)
results = PrettyTable(["n", "error"])
for j, n in enumerate(n_):
t, u = FNC.euler(f, tspan, u0, n)
err_[j] = norm(sol.sol(t)[0, :] - u[0, :], inf)
results.add_row((n, err_[j]))
print(results)
The error is approximately cut by a factor of 10 for each increase in n n n by the same factor. A log-log plot also confirms first-order convergence. Keep in mind that since h = ( b − a ) / n h=(b-a)/n h = ( b − a ) / n , it follows that O ( h ) = O ( n − 1 ) O(h)=O(n^{-1}) O ( h ) = O ( n − 1 ) .
loglog(n_, err_, "-o", label="results")
plot(n_, 0.5 * (n_ / n_[0])**(-1), "--", label="1st order")
xlabel("$n$"), ylabel("inf-norm error")
title("Convergence of Euler's method")
legend()
Euler’s method is the ancestor of the two major families of IVP methods presented in this chapter. Before we describe them, though, we generalize the initial-value problem itself in a crucial way.
6.2.3 Exercises ¶ ✍ Do two steps of Euler’s method for the following problems using the given step size h h h . Then, compute the error using the given exact solution.
(a) u ′ = − 2 t u , u ( 0 ) = 2 ; h = 0.1 ; u ^ ( t ) = 2 e − t 2 u' = -2t u, \ u(0) = 2;\ h=0.1;\ \hat{u}(t) = 2e^{-t^2} u ′ = − 2 t u , u ( 0 ) = 2 ; h = 0.1 ; u ^ ( t ) = 2 e − t 2
(b) u ′ = u + t , u ( 0 ) = 2 ; h = 0.2 ; u ^ ( t ) = − 1 − t + 3 e t u' = u + t, \ u(0) = 2;\ h=0.2;\ \hat{u}(t) = -1-t+3e^t u ′ = u + t , u ( 0 ) = 2 ; h = 0.2 ; u ^ ( t ) = − 1 − t + 3 e t
(c) t u ′ + u = 1 , u ( 1 ) = 6 , h = 0.25 ; u ^ ( t ) = 1 + 5 / t t u' + u = 1, \ u(1) = 6, \ h = 0.25;\ \hat{u}(t) = 1+5/t t u ′ + u = 1 , u ( 1 ) = 6 , h = 0.25 ; u ^ ( t ) = 1 + 5/ t
(d) u ′ − 2 u ( 1 − u ) = 0 , u ( 0 ) = 1 / 2 , h = 0.25 ; u ^ ( t ) = 1 / ( 1 + e − 2 t ) u' - 2u(1-u) = 0, \ u(0) = 1/2, \ h = 0.25; \ \hat{u}(t) = 1/(1 + e^{-2t}) u ′ − 2 u ( 1 − u ) = 0 , u ( 0 ) = 1/2 , h = 0.25 ; u ^ ( t ) = 1/ ( 1 + e − 2 t )
⌨ For each IVP, solve the problem using Function 6.2.2 . (i) Plot the solution for n = 320 n=320 n = 320 . (ii) For n = 10 ⋅ 2 k n=10\cdot2^k n = 10 ⋅ 2 k , k = 2 , 3 , … , 10 k=2,3,\ldots,10 k = 2 , 3 , … , 10 , compute the error at the final time and make a log-log convergence plot, including a reference line for first-order convergence.
(a) u ′ = − 2 t u , 0 ≤ t ≤ 2 , u ( 0 ) = 2 ; u ^ ( t ) = 2 e − t 2 u' = -2t u, \ 0 \le t \le 2, \ u(0) = 2;\ \hat{u}(t) = 2e^{-t^2} u ′ = − 2 t u , 0 ≤ t ≤ 2 , u ( 0 ) = 2 ; u ^ ( t ) = 2 e − t 2
(b) u ′ = u + t , 0 ≤ t ≤ 1 , u ( 0 ) = 2 ; u ^ ( t ) = − 1 − t + 3 e t u' = u + t, \ 0 \le t \le 1, \ u(0) = 2;\ \hat{u}(t) = -1-t+3e^t u ′ = u + t , 0 ≤ t ≤ 1 , u ( 0 ) = 2 ; u ^ ( t ) = − 1 − t + 3 e t
(c) ( 1 + t 3 ) u u ′ = t 2 , 0 ≤ x t ≤ 3 , u ( 0 ) = 1 ; u ^ ( t ) = [ 1 + ( 2 / 3 ) ln ( 1 + x t 3 ) ] 1 / 2 (1+t^3)uu' = t^2,\ 0 \le xt \le 3, \ u(0) =1;\ \hat{u}(t) = [1+(2/3)\ln (1+xt^3)]^{1/2} ( 1 + t 3 ) u u ′ = t 2 , 0 ≤ x t ≤ 3 , u ( 0 ) = 1 ; u ^ ( t ) = [ 1 + ( 2/3 ) ln ( 1 + x t 3 ) ] 1/2
(d) u ′ − 2 u ( 1 − u ) = 0 , 0 ≤ t ≤ 2 , u ( 0 ) = 1 / 2 ; u ^ ( t ) = 1 / ( 1 + e − 2 t ) u' - 2u(1-u) = 0, \ 0 \le t \le 2, \ u(0) = 1/2; \ \hat{u}(t) = 1/(1 + e^{-2t}) u ′ − 2 u ( 1 − u ) = 0 , 0 ≤ t ≤ 2 , u ( 0 ) = 1/2 ; u ^ ( t ) = 1/ ( 1 + e − 2 t )
(e) v ′ − ( 1 + x 2 ) v = 0 , 1 ≤ x ≤ 3 , v ( 1 ) = 1 , v ^ ( x ) = e ( x 3 + 3 x − 4 ) / 3 v' - (1+x^2) v = 0, \ 1 \le x \le 3, \ v(1) = 1, \ \hat{v}(x) = e^{(x^3+3x-4)/3} v ′ − ( 1 + x 2 ) v = 0 , 1 ≤ x ≤ 3 , v ( 1 ) = 1 , v ^ ( x ) = e ( x 3 + 3 x − 4 ) /3
(f) v ′ + ( 1 + x 2 ) v 2 = 0 , 0 ≤ x ≤ 2 , v ( 0 ) = 2 , v ^ ( x ) = 6 / ( 2 x 3 + 6 x + 3 ) v' + (1+x^2) v^2 = 0, \ 0 \le x \le 2, \ v(0) = 2, \ \hat{v}(x) = 6/(2x^3+6x+3) v ′ + ( 1 + x 2 ) v 2 = 0 , 0 ≤ x ≤ 2 , v ( 0 ) = 2 , v ^ ( x ) = 6/ ( 2 x 3 + 6 x + 3 )
(g) u ′ = 2 ( 1 + t ) ( 1 + u 2 ) , 0 ≤ t ≤ 0.5 , u ( 0 ) = 0 , u ^ ( t ) = tan ( 2 t + t 2 ) u' = 2(1+t)(1+u^2), \ 0 \le t \le 0.5, \ u(0) = 0, \ \hat{u}(t) = \tan(2t + t^2) u ′ = 2 ( 1 + t ) ( 1 + u 2 ) , 0 ≤ t ≤ 0.5 , u ( 0 ) = 0 , u ^ ( t ) = tan ( 2 t + t 2 )
✍ Here is an alternative to Euler’s method:
v i + 1 = u i + h f ( t i , u i ) , u i + 1 = u i + h f ( t i + h , v i + 1 ) . \begin{split}
v_{i+1} &= u_i + h f(t_i,u_i),\\
u_{i+1} &= u_i + hf(t_{i}+h,v_{i+1}).
\end{split} v i + 1 u i + 1 = u i + h f ( t i , u i ) , = u i + h f ( t i + h , v i + 1 ) . (a) Write out the method explicitly in the general one-step form (6.2.7) (i.e., clarify what ϕ is for this method).
(b) Show that the method is consistent.
✍ Consider the problem u ′ = k u u'=ku u ′ = k u , u ( 0 ) = 1 u(0)=1 u ( 0 ) = 1 for constant k k k and t > 0 t>0 t > 0 .
(a) Find an explicit formula in terms of h h h , k k k , and i i i for the Euler solution u i u_i u i at t = i h t=ih t = ih .
(b) Find values of k k k and h h h such that ∣ u i ∣ → ∞ |u_i|\to\infty ∣ u i ∣ → ∞ as i → ∞ i\to\infty i → ∞ while the exact solution u ^ ( t ) \hat{u}(t) u ^ ( t ) is bounded as t → ∞ t\to\infty t → ∞ .
✍ Prove the fact, used in the proof of Theorem 6.2.1 , that 1 + x ≤ e x 1+x\le e^x 1 + x ≤ e x for all x ≥ 0 x\ge 0 x ≥ 0 .
✍ Suppose that the error in making a step is also subject to roundoff error ϵ i + 1 \epsilon_{i+1} ϵ i + 1 , so that the total local error per unit step is C h p + ϵ i + 1 h − 1 Ch^p+\epsilon_{i+1} h^{-1} C h p + ϵ i + 1 h − 1 ; assume that ∣ ϵ i + 1 ∣ ≤ ϵ |\epsilon_{i+1}| \le \epsilon ∣ ϵ i + 1 ∣ ≤ ϵ for all i i i and that the initial condition is known exactly. Generalize Theorem 6.2.1 for this case.