MTH3007b Weekly Problems 2

Original Documents: Problem Sheet / Provided Solutions

Vibes: …

Used Techniques:


2.1. Error Scaling for Forward Euler

Question

You run forward Euler with and find an error of in . What error would you expect if you halved the step size to ?

Forward (explicit) Euler is a first-order method, meaning its Global truncation error scales as . Halving therefore halves the error.

So if error at is :


2.2. Error Scaling for Ralston’s Method

Question

You run Ralston’s method with and find an error of . What error would you expect for ?

Ralston’s method is a second-order Runge-Kutta method, so its GTE scales as . Halving reduces the error by a factor of .

So if error at is :


2.3. Implementing Ralston’s Method and Verifying Second-Order Convergence

Question

Implement Ralston’s method for with , , , . Verify numerically that the method is second order by checking the error ratio as is halved.

Ralston’s method is a two-stage Runge-Kutta scheme with coefficients chosen to minimise the truncation error bound. The update is:

import numpy as np
 
forcing_coefficient = 1.0
decay_rate = 22.0
time_start = 0.0
time_end = 1.0
initial_value = 1.0
 
def g(t: float, y: float) -> float:
    return forcing_coefficient * t - decay_rate * y
 
def y_exact(t: float) -> float:
    return (
        np.exp(-decay_rate * t) * (initial_value + forcing_coefficient / decay_rate ** 2)
        + forcing_coefficient * t / decay_rate
        - forcing_coefficient / decay_rate ** 2
    )
 
def ralston_step(g, t: float, y: float, time_step: float) -> float:
    k1 = g(t, y)
    k2 = g(t + 2 * time_step / 3, y + 2 * time_step * k1 / 3)
    return y + time_step * (k1 / 4 + 3 * k2 / 4)
 
def run_ralston(time_step: float) -> float:
    number_of_steps = int(round((time_end - time_start) / time_step))
    current_t = time_start
    current_y = initial_value
    for _ in range(number_of_steps):
        current_y = ralston_step(g, current_t, current_y, time_step)
        current_t += time_step
    return current_y
 
y_true = y_exact(time_end)
print(f"{'dt':>10} {'y(1)':>14} {'error':>14} {'ratio':>8}")
previous_error = None
for time_step in [0.1, 0.05, 0.025, 0.0125]:
    y_numerical = run_ralston(time_step)
    error = abs(y_numerical - y_true)
    ratio = previous_error / error if previous_error is not None else float('nan')
    print(f"{time_step:>10.4f} {y_numerical:>14.8f} {error:>14.6e} {ratio:>8.2f}")
    previous_error = error

The ratio column should converge to as decreases, confirming second-order convergence - each halving of reduces the error by a factor of .

Why second order? The Local truncation error of Ralston’s method is per step (it matches the Taylor series up to and including the term). With steps, the Global truncation error is .