MTH3007b Weekly Problems 11

Original Documents: Problem Sheet / Provided Solutions

Vibes: …

Used Techniques:


Note

Session 11 is a revision session. The PDF instructs: retry all exercises from previous sessions, plus the following Chapra & Canale exercises. Stochastic ODEs are not included in the Chapra & Canale list but could be asked for the test.


11. Chapra & Canale Exercise List

The following exercises are recommended from Chapra & Canale Numerical Methods for Engineers:

1st Order ODEs (Chapter 25)

ExerciseType
25.1Solve a simple 1st order IVP numerically, compare methods
25.3Apply Euler and higher-order methods to a decay ODE
25.4Apply RK4 to a 1st order ODE, check convergence
25.5Stiff ODE: compare explicit vs implicit Euler stability
25.6Step-size control and error estimation
25.17Numerical solution of a nonlinear 1st order ODE
25.19System of 1st order ODEs from a physical model
25.21Comparison of methods: accuracy and computational cost

Systems of 1st Order ODEs (Chapters 25, 28)

ExerciseType
25.7Predator-prey or coupled ODE system
25.25Stiff system of ODEs
28.10Boundary value problem reduced to system of ODEs

2nd Order ODEs Reduced to 1st Order Systems (Chapter 25)

ExerciseType
25.16Second-order ODE: reduce to system, solve numerically
25.18Oscillator or spring-mass system as 1st order system
25.22Higher-order ODE reduction with initial conditions

1D Monte Carlo Integration (Chapter 22)

ExerciseType
22.1MC estimate of a definite integral, assess error
22.2Verify error scaling
22.3Comparison: MC integration vs quadrature rules

PDEs: FTCS and BTCS (Chapter 30)

ExerciseType
30.71D heat equation: FTCS implementation and stability

PDEs with Neumann BCs (Chapter 30)

ExerciseType
30.161D heat equation with insulated boundary (Neumann BC)

Revision Recap by Block

Block A: ODEs

RK4 template - the pattern to memorise:

import numpy as np
 
def rk4_step(g, t: float, y: float, time_step: float) -> float:
    """Advance one step using the classical fourth-order Runge-Kutta method."""
    k1 = g(t, y)
    k2 = g(t + time_step / 2, y + time_step * k1 / 2)
    k3 = g(t + time_step / 2, y + time_step * k2 / 2)
    k4 = g(t + time_step, y + time_step * k3)
    return y + time_step / 6 * (k1 + 2 * k2 + 2 * k3 + k4)

For systems, becomes a numpy array Z and returns an array. The step function is identical.

Implicit Euler for :

Order summary:

MethodOrderStable
Explicit Euler1Conditional ()
Implicit Euler1Unconditional
Ralston2Conditional
Implicit Trapezoid2Unconditional
RK44Conditional

Block B: PDEs

FTCS - explicit, conditional stability :

BTCS - implicit, unconditionally stable, requires solving :

Neumann BC (insulated end, at ): use imaginary point , replacing and in the last row by .

Liebmann (2D Laplace steady state):

iterate until .


Block C: Stochastic

Wiener process (Euler-Maruyama, exact):

Ornstein-Uhlenbeck process:

First-passage time: run the OU loop, record elapsed time when , average over walkers.

Monte Carlo integration:


Worked Example: C25.19 (System of ODEs from Physical Model)

A typical Chapra & Canale system ODE problem: a spring-mass-damper described by . Reduce to a 1st order system with , :

import numpy as np
import matplotlib.pyplot as plt
 
mass = 1.0
damping_coefficient = 0.5
spring_constant = 4.0
forcing_amplitude = 1.0
forcing_frequency = 2.0
 
def g_system(t: float, state: np.ndarray) -> np.ndarray:
    displacement, velocity = state
    forcing = forcing_amplitude * np.cos(forcing_frequency * t)
    d_displacement = velocity
    d_velocity = (forcing - damping_coefficient * velocity - spring_constant * displacement) / mass
    return np.array([d_displacement, d_velocity])
 
def rk4_step_vec(g, t: float, state: np.ndarray, time_step: float) -> np.ndarray:
    k1 = g(t, state)
    k2 = g(t + time_step / 2, state + time_step * k1 / 2)
    k3 = g(t + time_step / 2, state + time_step * k2 / 2)
    k4 = g(t + time_step, state + time_step * k3)
    return state + time_step / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
 
time_step = 0.01
time_end = 20.0
number_of_steps = int(round(time_end / time_step))
t_values = np.zeros(number_of_steps + 1)
state_array = np.zeros((2, number_of_steps + 1))
t_values[0] = 0.0
state_array[:, 0] = np.array([0.0, 0.0])  # starts at rest
 
for step_index in range(number_of_steps):
    t_values[step_index + 1] = t_values[step_index] + time_step
    state_array[:, step_index + 1] = rk4_step_vec(
        g_system, t_values[step_index], state_array[:, step_index], time_step
    )
 
plt.plot(t_values, state_array[0, :], label='Displacement x(t)')
plt.xlabel('t')
plt.ylabel('x')
plt.legend()
plt.title('Spring-Mass-Damper (RK4)')
plt.show()