.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/ode_dynamics/integrators/plot_02_runge_kutta.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_ode_dynamics_integrators_plot_02_runge_kutta.py: Runge, Heun and Kutta: Runge-Kutta methods ========================================== Runge (1895), Heun (1900) and Kutta (1901) matched more terms of the solution's Taylor series without computing any derivatives of :math:`f`. They did it by sampling the slope at several points inside each step and combining the samples. Heun's two-stage method is second order, and Kutta's classical four-stage method .. math:: y_{n+1} = y_n + \tfrac{h}{6}(k_1 + 2k_2 + 2k_3 + k_4) is fourth order: halving :math:`h` divides the error by 16. .. GENERATED FROM PYTHON SOURCE LINES 19-46 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mathematicskit.integrators import njit, rk4_integrate @njit def oscillator(state, t, params): return np.array([state[1], -state[0]]) def euler_final(h, n): y = np.array([1.0, 0.0]) for i in range(n): y = y + h * oscillator(y, i * h, None) return y def heun_final(h, n): y = np.array([1.0, 0.0]) for i in range(n): k1 = oscillator(y, i * h, None) k2 = oscillator(y + h * k1, (i + 1) * h, None) y = y + 0.5 * h * (k1 + k2) return y .. GENERATED FROM PYTHON SOURCE LINES 47-49 Error at t = 2 pi for the harmonic oscillator --------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 49-73 .. code-block:: Python t_end = 2 * np.pi ns = 2 ** np.arange(4, 12) hs = t_end / ns exact = np.array([1.0, 0.0]) errors = { "Euler (1 stage)": [np.linalg.norm(euler_final(h, n) - exact) for h, n in zip(hs, ns, strict=False)], "Heun (2 stages)": [np.linalg.norm(heun_final(h, n) - exact) for h, n in zip(hs, ns, strict=False)], "Kutta RK4 (4 stages)": [ np.linalg.norm(rk4_integrate(oscillator, np.array([1.0, 0.0]), 0.0, h, n, np.zeros(1))[1][-1] - exact) for h, n in zip(hs, ns, strict=False) ], } fig, ax = plt.subplots(figsize=(7, 4.5)) for (label, err), order in zip(errors.items(), (1, 2, 4), strict=False): ax.loglog(hs, err, "o-", label=label) print(f"{label}: error ratio for halved h = {err[-2] / err[-1]:.2f} (expected {2**order})") ax.set_xlabel("h") ax.set_ylabel("|error| after one period") ax.set_title("Runge-Kutta: more stages, higher order") ax.legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/ode_dynamics/integrators/images/sphx_glr_plot_02_runge_kutta_001.png :alt: Runge-Kutta: more stages, higher order :srcset: /api/gallery/ode_dynamics/integrators/images/sphx_glr_plot_02_runge_kutta_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Euler (1 stage): error ratio for halved h = 2.01 (expected 2) Heun (2 stages): error ratio for halved h = 4.00 (expected 4) Kutta RK4 (4 stages): error ratio for halved h = 16.00 (expected 16) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.066 seconds) .. _sphx_glr_download_api_gallery_ode_dynamics_integrators_plot_02_runge_kutta.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/ode_dynamics/integrators/plot_02_runge_kutta.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_runge_kutta.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_runge_kutta.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_runge_kutta.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_