summaryrefslogtreecommitdiff
path: root/tutorials/module_3/3_6_Explicit_Methods.md
blob: 15ed87afd6dff3b653937b73477902cfba849ecc (plain)
1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Explicit Methods

## Euler's Method
<img 
    style="display: block; 
           margin-left: auto;
           margin-right: auto;
           width: 50%;"
    src="fw_eulers.png" 
    alt="Forward Eulers">
Eulers method or more specifically Forwards Eulers method is one of the simplest methods for solving ODE's. The idea of the Forward Euler method is to approximate the solution curve by taking small time steps, each step moving forward along the tangent given by the slope $f(t,y)$. At each step, the method updates the solution using the formula
$$ 
y_{n+1} = y_n + h f(t_n, y_n)
$$
where $h$ is the chosen step size. This makes the method an **explicit method**, since the new value $y_{n+1}$​ is computed directly from known quantities at step $n$. Let's try and code this in python

```python
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-poster')
%matplotlib inline

# Define parameters
f = lambda t, s: np.exp(-t) # ODE
h = 0.1 # Step size
t = np.arange(0, 1 + h, h) # Numerical grid
s0 = -1 # Initial Condition

# Explicit Euler Method
s = np.zeros(len(t))
s[0] = s0

for i in range(0, len(t) - 1):
    s[i + 1] = s[i] + h*f(t[i], s[i])

plt.figure(figsize = (12, 8))
plt.plot(t, s, 'bo--', label='Approximate')
plt.plot(t, -np.exp(-t), 'g', label='Exact')
plt.title('Approximate and Exact Solution \
for Simple ODE')
plt.xlabel('t')
plt.ylabel('f(t)')
plt.grid()
plt.legend(loc='lower right')
plt.show()
```

Although Forward Euler’s method is easy to implement and provides insight into how numerical integration works, it is not very accurate for larger step sizes and can become unstable for certain types of problems, especially stiff ODEs. Its accuracy is **first-order**, meaning the local error per step scales with $h^2$, and the global error across an interval scales with $h$. Because of this, Forward Euler is often used as a starting point for understanding numerical ODE solvers and as a baseline for comparing more advanced methods like Heun’s method or Runge–Kutta.

## Heun's Method
<img 
    style="display: block; 
           margin-left: auto;
           margin-right: auto;
           width: 40%;"
    src="https://upload.wikimedia.org/wikipedia/commons/c/ce/Karl_Heun.jpg" 
    alt="Karl Heun">

Heun’s method introduced by German Mathematician Karl Heun is a refinement of the Forward Euler method. Like Euler’s method, it starts from the initial value problem
$$
\frac{dy}{dt} = f(t, y), \quad y(t_0) = y_0
$$
The idea is to improve accuracy by not relying solely on the slope at the beginning of the interval. Instead, Heun’s method first uses Forward Euler to make a **prediction** of the next value, then computes the slope again at this predicted point, and finally averages the two slopes to make a **correction**. Mathematically, the update step is
$$
y_{n+1} = y_n + \frac{h}{2}\big[f(t_n, y_n) + f(t_{n+1}, y_n + h f(t_n, y_n))\big]
$$
This averaging of slopes makes the method **second-order accurate**, which means its global error decreases proportionally to $h^2$ rather than just $h$, as in Forward Euler.
<img 
    style="display: block; 
           margin-left: auto;
           margin-right: auto;
           width: 50%;"
    src="heuns_method.png" 
    alt="Heun's Method">
In practice, Heun’s method provides a significant improvement in accuracy without adding much computational cost. It still only requires evaluating the function $f(t,y)$ twice per step, making it more efficient than higher-order methods like Runge–Kutta while being more stable and reliable than Forward Euler.
## Classical Runge-Kutta
Also known as the **classical fourth-order Runge–Kutta (RK4)** method. It takes four slope evaluations per step: one at the beginning, two at intermediate points, and one at the end of the step. These slopes are then combined in a weighted average to update the solution. RK4 is accurate to **fourth order**, meaning the global error scales as $h^4$, which is far more accurate than Euler or Heun for the same step size. In practice, this makes RK4 the “workhorse” of many ODE solvers where stability and accuracy are needed but the system is not excessively stiff.

**SciPy’s `solve_ivp`**, build on this idea with adaptive Runge–Kutta methods. For example, `RK45` is an adaptive solver that pairs a 4th-order method with a 5th-order method, comparing the two at each step to estimate the error. Based on this estimate, the solver adjusts the step size automatically: smaller steps in regions where the solution changes quickly, and larger steps where the solution is smooth. This makes `RK45` both efficient and robust, giving you the accuracy benefits of Runge–Kutta methods while also taking away the burden of manually choosing an appropriate step size.

## Problem 1: Exponential decay

## Problem 2: The Predator-Pray Model

## Problem 3: Swinging Pendulum