Metoda Heuna
Istota. Metoda Heuna jest prostym ulepszeniem metody Eulera. Zamiast opierać się wyłącznie na pochodnej w punkcie początkowym \( \mathbf{x}_n \), wykorzystuje średnie nachylenie na początku i na końcu kroku czasowego \( \Delta t \). Dla układu \( \dot{\mathbf{x}} = f(\mathbf{x}, t, \theta) \) metoda wykonuje najpierw krok Eulera (tzw. predyktor): \( \mathbf{x}_{n+1}^{(p)} = \mathbf{x}_n + \Delta t\, f(\mathbf{x}_n) \), a następnie koryguje wynik (korektor): \( \mathbf{x}_{n+1} = \mathbf{x}_n + \tfrac{\Delta t}{2}\big[ f(\mathbf{x}_n) + f(\mathbf{x}_{n+1}^{(p)}) \big] \). Zamiast przyjmować stałe nachylenie na całym przedziale (jak w metodzie Eulera), metoda Heuna uśrednia nachylenie z początku i końca kroku. Dzięki temu błąd globalny jest niższy niż w metodzie Eulera, przy stosunkowo niewielkim koszcie obliczeniowym.
Przykład. Dla równania \( \dot{x} = -2x \) z warunkiem początkowym \( x_0 = 1 \) i krokiem czasowym \( \Delta t = 0.1 \). W każdym kroku wykonujemy dwa etapy: predyktor i korektor.
Krok 1 (od \( x_0 \) do \( x_1 \)). Pochodna w punkcie \( x_0 = 1 \): \( f(x_0) = -2 \cdot 1 = -2 \), (predyktor), przybliżenie: \( x_{1}^{(p)} = x_0 + 0.1 \cdot (-2) = 0.8 \), pochodna w punkcie przewidywanym \( x_{1}^{(p)} = 0.8 \), \( f(x_{1}^{(p)}) = -2 \cdot 0.8 = -1.6 \). Nowe przybliżenie (średnia z dwóch nachyleń): \( x_1 = x_0 + \tfrac{0.1}{2}\big[ f(x_0) + f(x_{1}^{(p)}) \big] = 1 + 0.05 \cdot (-2 - 1.6) = 0.82. \)
Krok 2 (od \( x_1 \) do \( x_2 \)). Predyktor: \( f(x_1) = -2 \cdot 0.82 = -1.64 \), \( x_{2}^{(p)} = 0.82 + 0.1 \cdot (-1.64) = 0.656 \). Korektor: \( f(x_{2}^{(p)}) = -2 \cdot 0.656 = -1.312 \), \( x_2 = 0.82 + 0.05 \cdot (-1.64 - 1.312) \approx 0.6724. \)
W kolejnych krokach postępujemy identycznie: na początku kroku liczymy pochodną w \( x_n \), wykonujemy krok Eulera do punktu \( x_{n+1}^{(p)} \), a następnie korygujemy wynik, uśredniając pochodne w obu punktach. W porównaniu z metodą Eulera wartości \( x_n \) są bliższe rozwiązaniu dokładnemu, nawet przy takim samym kroku \( \Delta t \).
Zastosowanie. Metoda Heuna stanowi dobry kompromis między prostotą a dokładnością. Pozwala zachować większą stabilność i lepszy kształt trajektorii niż Euler, zwłaszcza przy umiarkowanych krokach czasowych. W układach chaotycznych nadal musimy uważać na wybór \( \Delta t \), ale dla wielu atraktorów metoda Heuna daje wyraźnie „czystsze” trajektorie niż Euler przy tym samym kroku. W praktyce metodę Heuna warto stosować, gdy metoda Eulera daje zbyt duże zniekształcenia trajektorii lub gdy chcemy szybko poprawić jakość integracji bez przechodzenia od razu do metod wyższego rzędu (np. RK4, Dormand–Prince).
Implementacja. W dodatku Attractor Builder każdy krok metody Heuna
realizuje funkcja step_heun. W przeciwieństwie do metody Eulera,
która korzysta tylko z pochodnej w punkcie bieżącym, metoda Heuna oblicza
pochodną dwukrotnie: w punkcie bieżącym oraz w punkcie przewidywanym
(predyktorze). Kod w dodatku ma postać:
def step_heun(rhs_func, p: Vector, params: dict, dt: float):
p_pred = p + rhs_func(p, params) * dt
avg_slope = 0.5 * (rhs_func(p, params) + rhs_func(p_pred, params))
return p + avg_slope * dt
Algorytm przebiega więc następująco: 1. Obliczamy pochodną w punkcie bieżącym \( p \): \( f(p) = rhs\_func(p, params) \). 2. Wykonujemy krok predyktora (Euler): \( p^{(p)} = p + \Delta t \, f(p) \). 3. Obliczamy pochodną w punkcie przewidywanym \( p^{(p)} \): \( f(p^{(p)}) \). 4. Uśredniamy nachylenie: \( \tfrac{1}{2}[ f(p) + f(p^{(p)}) ] \). 5. Obliczamy nowy punkt: \( p_{n+1} = p + \Delta t \cdot \tfrac{1}{2}[ f(p) + f(p^{(p)}) ]. \) Na przykład, gdy w Attractor Builder przyjmiemy (Lorenz):
Równania: dx/dt = a * (y - x) dy/dt = x * (b - z) - y dz/dt = x * y - c * z Parametry: | a = 10 | b = 28 | c = 8/3 | Ustawienia symulacji: Stan początkowy: x₀ = 0.01, y₀ = 0.01, z₀ = 0.01 Metoda: Heun Krok czasowy (dt): 0.01 Liczba kroków: 3 Faza rozgrzewki (burn-in): 0 Skala: 1
Krok 1. Punkt początkowy: x0 = 0.01; y0 = 0.01; z0 = 0.01. Pochodne: dx0 = 10*(y0-x0) = 10*(0.01-0.01) = 0 dy0 = x0*(28-z0) - y0 = 0.01*(28-0.01) - 0.01 = 0.2699 dz0 = x0*y0 - (8/3)*z0 ≈ 0.0001 - 0.02667 ≈ -0.02657 Predyktor (Euler): x_pred = x0 + 0.01*dx0 = 0.01 y_pred = y0 + 0.01*dy0 = 0.01 + 0.01*0.2699 ≈ 0.01270 z_pred = z0 + 0.01*dz0 ≈ 0.01 + 0.01*(-0.02657) ≈ 0.00973 Pochodne w punkcie przewidywanym (zaokrąglone): dxp = 10*(y_pred - x_pred) ≈ 10*(0.01270-0.01) ≈ 0.0270 dyp = x_pred*(28-z_pred) - y_pred ≈ 0.2672 dzp ≈ -0.0258 Średnie nachylenie: dx_avg ≈ (dx0 + dxp)/2 ≈ 0.0135 dy_avg ≈ (dy0 + dyp)/2 ≈ 0.2686 dz_avg ≈ (dz0 + dzp)/2 ≈ -0.0262 Nowy punkt (po 1. kroku Heuna): x1 = x0 + 0.01*dx_avg ≈ 0.0101349 y1 = y0 + 0.01*dy_avg ≈ 0.0126855 z1 = z0 + 0.01*dz_avg ≈ 0.0097380 Krok 2. Punkt wyjściowy: x1 ≈ 0.0101349; y1 ≈ 0.0126855; z1 ≈ 0.0097380. [analogicznie obliczamy predyktor, pochodne i średnie nachylenie] Nowy punkt: x2 ≈ 0.0105128 y2 ≈ 0.0154176 z2 ≈ 0.0094832 Krok 3. Punkt wyjściowy: x2 ≈ 0.0105128; y2 ≈ 0.0154176; z2 ≈ 0.0094832. Po wykonaniu predyktora i korektora Heuna otrzymujemy: x3 ≈ 0.0111181 y3 ≈ 0.0182607 z3 ≈ 0.0092354
W każdym kroku algorytm najpierw liczy wektor pochodnych w bieżącym punkcie (predyktor, odpowiednik Eulera), a następnie liczy go ponownie w punkcie przewidywanym i uśrednia oba nachylenia. Dzięki temu trajektoria lepiej oddaje prawdziwy kształt atraktora niż przy zastosowaniu prostej metody Eulera z tym samym krokiem \( \Delta t \).