USMA1Q — Méthodes Numériques¶

Séance 10 — Équations différentielles ordinaires I : fondamentaux¶

Conservatoire National des Arts et Métiers

01 Avril 2026

nicholas-anton.collins-craft@enpc.fr


Un lien vers Google Colab qui peut faire tourner le notebook qui contient les exercices se trouve ici :

https://colab.research.google.com/github/nickcollins-craft/USMA1Q-Methodes-Numeriques/blob/main/

Plan du cours¶

Jour Sujet
03 mars Fondamentaux de la programmation en Python
04 mars (matin) Fonctions, listes approfondies, fichiers et graphiques
04 mars (après-midi) Calcul numérique avec NumPy
11 mars (matin) Tableaux en mémoire, matrices & précision numérique
11 mars (après-midi) Résolution des systèmes linéaires
18 mars (matin) Interpolation & recherche des racines
18 mars (après-midi) Systèmes d'équations non linéaires
25 mars (matin) Intégration numérique I
25 mars (après-midi) Intégration numérique II (Monte Carlo)
01 avril (matin) Équations différentielles ordinaires I
01 avril (après-midi) Équations différentielles ordinaires II
08 avril Examen

Plan de la séance (indicatif)¶

Horaire Sujet
0:00 – 0:55 Méthode d'Euler (explicite)
0:55 – 1:50 Méthodes de Runge-Kutta (RK2, RK4)
1:50 – 2:00 ☕ Pause
2:00 – 2:30 Pas adaptatif & scipy.integrate.solve_ivp
2:30 – 3:40 Stabilité : méthodes explicites vs implicites
3:40 – 3:45 Récapitulatif

Motivation — pourquoi résoudre des EDO numériquement ?¶

De nombreux phénomènes en science des matériaux sont décrits par des équations différentielles ordinaires (EDO) :

PhénomèneÉquation différentielle
Refroidissement (loi de Newton)\(\frac{\mathrm{d}T}{\mathrm{d}t} = -k(T - T_{\text{env}})\)
Cinétique de transformation (Avrami)\(\frac{\mathrm{d}\xi}{\mathrm{d}t} = n k t^{n-1}(1-\xi)\)
Fluage (loi puissance)\(\frac{\mathrm{d}\varepsilon}{\mathrm{d}t} = A\sigma^n e^{-Q/(RT)}\)
Oscillateur amorti\(m\frac{\mathrm{d}^2x}{\mathrm{d}t^2} + c\frac{\mathrm{d}x}{\mathrm{d}t} + kx = 0\)

Problème : la plupart de ces équations n'ont pas de solution analytique simple.
Il faut donc les résoudre numériquement.

Forme générale d'une EDO¶

Problème de valeur initiale (IVP — Initial Value Problem) :

$$\frac{\mathrm{d}y}{\mathrm{d}t} = f(t, y), \quad y(t_0) = y_0$$

  • $y(t)$ : fonction inconnue (température, fraction transformée, déformation...)
  • $f(t, y)$ : la dérivée de $y$ en fonction de $t$ et $y$ elle-même
  • $y_0$ : condition initiale

Objectif : calculer $y(t)$ pour $t \in [t_0, t_f]$

1 · Méthode d'Euler (explicite)¶

Idée : approximer la dérivée par une différence finie, puis avancer pas à pas.

$$\frac{\mathrm{d}y}{\mathrm{d}t} \approx \frac{y_{n+1} - y_n}{h}$$

où $h$ est le pas de temps (time step), $y_{n}$ est la valeur actuelle, et $y_{n+1}$ est la valeur qu'on cherche.

En remplaçant dans l'EDO :

$$\frac{y_{n+1} - y_n}{h} = f(t_n, y_n)$$

d'où la formule d'Euler explicite :

$$\boxed{y_{n+1} = y_n + h \cdot f(t_n, y_n)}$$

Exemple 1 : loi de refroidissement de Newton¶

Une pièce en acier refroidit depuis 800°C dans l'air à 25°C :

$$\frac{\mathrm{d}T}{\mathrm{d}t} = -k(T - T_{\text{env}}), \quad T(0) = 800\,\text{°C}$$

avec $k = 0.05\,\text{s}^{-1}$ et $T_{\text{env}} = 25\,\text{°C}$.

La solution analytique (qui permettre d'évaluer l'exactitude de notre solution numérique) :

$$T(t) = T_{\text{env}} + (T_0 - T_{\text{env}})e^{-kt} = 25 + 775\,e^{-0.05t}$$

In [15]:
import numpy as np
import matplotlib.pyplot as plt

# Paramètres
k = 0.05  # s^-1
T_env = 25.0  # °C
T0 = 800.0  # °C

# EDO : dT/dt = f(t, T)
def f_cooling(t, T):
    return -k * (T - T_env)

# Solution analytique
def T_exact(t):
    return T_env + (T0 - T_env) * np.exp(-k * t)

Implémentation de la méthode d'Euler¶

In [16]:
def euler_method(f, t0, tf, y0, h):
    N = int((tf - t0) / h) + 1  # Nombre de points dans la grille
    t = np.linspace(t0, tf, N)  # Grille de temps
    y = np.zeros(N)             # Tableau pour stocker les solutions numériques
    y[0] = y0                   # Condition initiale
    
    # Pour chaque point de la grille, calculer la solution numérique
    for n in range(N - 1):
        y[n + 1] = y[n] + h * f(t[n], y[n])
    
    return t, y
In [17]:
# Résolution avec différents pas de temps
t0, tf = 0, 100  # secondes

t_euler_1, T_euler_1 = euler_method(f_cooling, t0, tf, T0, 1)
t_euler_5, T_euler_5 = euler_method(f_cooling, t0, tf, T0, 5)
t_euler_20, T_euler_20 = euler_method(f_cooling, t0, tf, T0, 20)

Observations¶

  • Petit $h$ (h = 1 s) → solution proche de l'exacte, mais nombreuses étapes
  • Grand $h$ (h = 20 s) → rapide mais erreur visible, la solution dérive

Compromis vitesse–précision : faut-il toujours choisir un $h$ très petit ?

L'erreur locale — l'erreur fait à chaque pas¶

Développement de Taylor de la vraie solution¶

Si on connaît $y(t_n)$ et qu'on veut calculer $y(t_{n+1}) = y(t_n + h)$, le développement de Taylor nous dit :

$$y(t_n + h) = y(t_n) + h \cdot y'(t_n) + \frac{h^2}{2} \cdot y''(t_n) + \frac{h^3}{6} \cdot y'''(t_n) + \ldots$$

Comme $y'(t_n) = f(t_n, y(t_n))$ (par définition de l'EDO), on peut réécrire :

$$y(t_n + h) = y(t_n) + h \cdot f(t_n, y(t_n)) + \frac{h^2}{2} \cdot y''(t_n) + \mathcal{O}(h^3)$$

Ce que fait Euler¶

La méthode d'Euler calcule :

$$y_{n+1}^{\text{Euler}} = y_n + h \cdot f(t_n, y_n)$$

Elle utilise seulement les deux premiers termes du développement de Taylor !

L'erreur de troncature locale¶

En comparant les deux :

$$\text{Erreur locale} = y(t_n + h) - y_{n+1}^{\text{Euler}} = \frac{h^2}{2} \cdot y''(t_n) + \mathcal{O}(h^3)$$

Le terme dominant est $\frac{h^2}{2} y''(t_n)$, donc l'erreur locale est $\mathcal{O}(h^2)$.

Interprétation géométrique¶

  • Euler approxime par une droite : $y \approx y_n + h \cdot (\text{pente})$
  • La vraie solution suit une parabole (au moins) : $y \approx y_n + h \cdot (\text{pente}) + \frac{h^2}{2} \cdot (\text{courbure})$

Intuition clé : Euler ignore la courbure de la solution (le terme en $y''$). Plus le pas $h$ est grand, plus cette approximation linéaire s'éloigne de la vraie courbe. L'écart grandit comme l'aire sous la parabole d'erreur, d'où le facteur $h^2$.

Note : C'est pour ça qu'on dit qu'Euler est une méthode d'ordre 1 : elle utilise un développement de Taylor d'ordre 1 (constant + linéaire), et l'erreur vient du premier terme négligé, qui est d'ordre 2.

L'erreur globale — l'erreur cumulée sur tout l'intervalle $[t_0, t_f]$¶

Pour aller de $t_0$ à $t_f$, on doit faire $N = (t_f - t_0)/h$ pas. Les erreurs locales s'accumulent :

$$\text{Erreur globale} \approx N \times \text{(erreur locale)} \approx \frac{t_f - t_0}{h} \times h^2 = (t_f - t_0) \times h$$

Donc l'erreur globale est $\mathcal{O}(h)$ — ordre 1.

Conséquence pratique : si on divise $h$ par 2, on fait deux fois plus de pas, mais chaque pas est quatre fois plus précis → l'erreur globale est divisée par 2.

Convergence empirique¶

Vérification : traçons $\log(\text{erreur})$ en fonction de $\log(h)$.

Si l'erreur globale suit $\text{erreur} \approx C \times h$, alors : $$\log(\text{erreur}) = \log(C) + \log(h)$$

On doit obtenir une droite de pente 1 en échelle log-log.

In [18]:
# Calcul de l'erreur pour différents h
h_range = np.array([20, 10, 5, 2, 1, 0.5, 0.2])
errors = []

for h in h_range:
    t_euler, T_euler = euler_method(f_cooling, t0, tf, T0, h)
    T_exact_at_tf = T_exact(tf)
    error = abs(T_euler[-1] - T_exact_at_tf)
    errors.append(error)

errors = np.array(errors)

À vous de faire les exercices 1.1 et 1.2 !¶

2 · Méthodes de Runge-Kutta¶

Problème avec Euler : erreur globale $\mathcal{O}(h)$ — il faut un $h$ très petit pour être précis.

Idée des méthodes de Runge-Kutta : évaluer la pente $f(t, y)$ en plusieurs points dans l'intervalle $[t_n, t_{n+1}]$, puis faire une moyenne pondérée.

Cela améliore considérablement la précision !

Méthode du point milieu (RK2)¶

Au lieu d'utiliser la pente au début de l'intervalle, utilisons la pente au milieu :

  1. Calculer un demi-pas d'Euler pour estimer $y$ au milieu : $$y_{\text{mid}} = y_n + \frac{h}{2}f(t_n, y_n)$$

  2. Évaluer la pente au milieu : $$k_2 = f\left(t_n + \frac{h}{2}, y_{\text{mid}}\right)$$

  3. Avancer d'un pas complet avec cette pente : $$\boxed{y_{n+1} = y_n + h \cdot k_2}$$

In [19]:
def rk2_method(f, t0, tf, y0, h):
    """
    Résolution d'une EDO par la méthode de Runge-Kutta d'ordre 4.
    """
    N = int((tf - t0) / h) + 1
    t = np.linspace(t0, tf, N)
    y = np.zeros(N)
    y[0] = y0
    
    for n in range(N - 1):
        k1 = f(t[n], y[n])
        k2 = f(t[n] + h/2, y[n] + h/2 * k1)
        
        y[n + 1] = y[n] + h * k2
    
    return t, y

Analyse d'erreur de RK2 (méthode du point milieu)¶

Pourquoi RK2 est-il plus précis qu'Euler ?¶

Rappel Euler : on utilise la pente au début de l'intervalle → erreur $\mathcal{O}(h^2)$ par pas

RK2 (point milieu) : on utilise la pente au milieu de l'intervalle → erreur $\mathcal{O}(h^3)$ par pas

L'intuition géométrique¶

Imaginez que vous voulez approximer une courbe :

  • Euler : trace une droite depuis le point de départ avec la pente initiale
  • RK2 : fait d'abord un petit saut au milieu pour "tester" la pente là-bas, puis utilise cette pente centrale

La pente au milieu de l'intervalle représente mieux la pente moyenne sur tout l'intervalle !

Erreur locale vs globale¶

Erreur de troncature locale : $\mathcal{O}(h^3)$ par pas

En utilisant la pente au point milieu, on capture mieux la courbure de la solution. L'erreur diminue comme $h^3$ au lieu de $h^2$.

Erreur globale : $\mathcal{O}(h^2)$

Sur l'intervalle $[t_0, t_f]$, il faut $N = (t_f - t_0)/h$ pas :

$$\text{Erreur globale} \approx N \times \text{(erreur locale)} \approx \frac{t_f - t_0}{h} \times h^3 = (t_f - t_0) \times h^2$$

Conséquence pratique : si on divise $h$ par 2, l'erreur est divisée par 4 !
C'est beaucoup mieux qu'Euler (division par 2 seulement).

Méthode de Runge-Kutta d'ordre 4 (RK4)¶

La méthode RK4 classique évalue la pente en quatre points :

$$\begin{align} k_1 &= f(t_n, y_n) \\ k_2 &= f\left(t_n + \frac{h}{2}, y_n + \frac{h}{2}k_1\right) \\ k_3 &= f\left(t_n + \frac{h}{2}, y_n + \frac{h}{2}k_2\right) \\ k_4 &= f(t_n + h, y_n + h k_3) \end{align}$$

Puis calcule une moyenne pondérée :

$$\boxed{y_{n+1} = y_n + \frac{h}{6}(k_1 + 2k_2 + 2k_3 + k_4)}$$

Avec le même logique d'analyse qu'avant, on obtient que le RK4 prends en compte des termes d'ordre supérieure, donc l'erreur locale devient $\mathcal{O}(h^{5})$. Par conséquence, l'erreur globale est $\mathcal{O}(h^4)$ — très précis !

Implémentation de RK4¶

In [20]:
def rk4_method(f, t0, tf, y0, h):
    """
    Résolution d'une EDO par la méthode de Runge-Kutta d'ordre 4.
    """
    N = int((tf - t0) / h) + 1
    t = np.linspace(t0, tf, N)
    y = np.zeros(N)
    y[0] = y0
    
    for n in range(N - 1):
        k1 = f(t[n], y[n])
        k2 = f(t[n] + h/2, y[n] + h/2 * k1)
        k3 = f(t[n] + h/2, y[n] + h/2 * k2)
        k4 = f(t[n] + h, y[n] + h * k3)
        
        y[n + 1] = y[n] + (h / 6) * (k1 + 2*k2 + 2*k3 + k4)
    
    return t, y

Comparaison Euler vs RK2 vs RK4¶

In [21]:
# Résolution avec le même pas de temps h = 10 s
h = 10
t_euler, T_euler = euler_method(f_cooling, t0, tf, T0, h)
t_rk2, T_rk2 = rk2_method(f_cooling, t0, tf, T0, h)
t_rk4, T_rk4 = rk4_method(f_cooling, t0, tf, T0, h)

print("Erreur Euler :", abs(T_euler[-1] - T_exact(tf)))
print("Erreur RK4   :", abs(T_rk4[-1] - T_exact(tf)))
Erreur Euler : 4.465072986791238
Erreur RK4   : 0.020714566028654957

Observation¶

Avec le même nombre de pas ($h = 10$ s), RK4 est très proche de la solution exacte et RK2 est peu éloigné alors qu'Euler dévie nettement.

Règle pratique : RK4 est le « cheval de bataille » pour les problèmes lisses. Pour une précision donnée, il nécessite beaucoup moins de pas qu'Euler.

À vous de faire les exercices 2.1 et 2.2 !¶

☕ Pause — 10 minutes¶

3 · Pas adaptatif et scipy.integrate.solve_ivp¶

Problème : choisir $h$ à la main est délicat.

  • Trop grand → erreur importante
  • Trop petit → calcul lent, inutilement précis

Solution : pas adaptatif — ajuster automatiquement $h$ en surveillant l'erreur.

Méthodes à pas adaptatif¶

Stratégie : comparer deux estimations de $y_{n+1}$ calculées avec des méthodes d'ordres différents.

Exemple : RK45 (Dormand-Prince)

  • Calcule $y_{n+1}$ avec une méthode RK d'ordre 4 et une d'ordre 5
  • Utilise les mêmes évaluations de fonction pour les deux
  • Différence entre les deux = estimation de l'erreur

Si erreur > tolérance → réduire $h$
Si erreur < tolérance → augmenter $h$

scipy.integrate.solve_ivp¶

Python fournit un solveur d'EDO moderne avec pas adaptatif :

from scipy.integrate import solve_ivp

sol = solve_ivp(f, [t0, tf], [y0], method='RK45', rtol=1e-6, atol=1e-9, dense_output=True)

Paramètres importants :

  • f(t, y) : fonction définissant $\mathrm{d}y/\mathrm{d}t = f(t, y)$
  • [t0, tf] : intervalle de temps
  • [y0] : condition initiale (toujours un array !)
  • method : 'RK45', 'RK23', 'Radau', 'BDF', etc.
  • rtol, atol : tolérances relative et absolue
  • dense_output=True : interpolation continue de la solution

Exemple avec solve_ivp¶

In [22]:
from scipy.integrate import solve_ivp

# Résolution du refroidissement avec solve_ivp
sol = solve_ivp(f_cooling, [t0, tf], [T0], method='RK45', 
                rtol=1e-6, atol=1e-9, dense_output=True)

print("Nombre de pas utilisés :", len(sol.t))
print("Temps final :", sol.t[-1])
print("T finale (numérique) :", sol.y[0, -1])
print("T finale (exacte)    :", T_exact(tf))
print("Erreur :", abs(sol.y[0, -1] - T_exact(tf)))
Nombre de pas utilisés : 23
Temps final : 100.0
T finale (numérique) : 30.22192017312949
T finale (exacte)    : 30.221908924291238
Erreur : 1.1248838251987081e-05

Observation¶

  • solve_ivp ajuste automatiquement $h$ : au début (où $T$ change rapidement), les pas sont petits
  • Plus tard (où $T$ évolue lentement), les pas sont grands
  • Cela optimise précision et vitesse sans intervention manuelle

Interpolation dense de la solution¶

Avec dense_output=True, on obtient une fonction sol.sol(t) qui interpole la solution entre les pas.

In [23]:
# Évaluer la solution à des temps arbitraires
t_dense = np.linspace(t0, tf, 1000)
T_dense = sol.sol(t_dense)[0]

À vous de faire les exercices 3.1 et 3.2 !¶

4 · Stabilité : méthodes explicites vs implicites¶

Pourquoi ne pas toujours utiliser RK4 avec un grand $h$ ?

Certaines EDO sont raides (stiff) — les méthodes explicites deviennent instables si $h$ est trop grand.

Exemple d'instabilité¶

Considérons :

$$\frac{\mathrm{d}y}{\mathrm{d}t} = -1000\,y, \quad y(0) = 1$$

Solution exacte : $y(t) = e^{-1000t}$ — décroissance très rapide.

Essayons Euler avec $h = 0.003$ s :

In [24]:
# EDO raide
lam = -1000

def f_stiff(t, y):
    return lam * y

# Euler avec h = 0.003
t0_stiff, tf_stiff = 0, 0.01
y0_stiff = 1.0
h_unstable = 0.003

t_unstable, y_unstable = euler_method(f_stiff, t0_stiff, tf_stiff, y0_stiff, h_unstable)

print("y(tf) numérique :", y_unstable[-1])
print("y(tf) exact     :", np.exp(lam * tf_stiff))
y(tf) numérique : -8.0
y(tf) exact     : 4.5399929762484854e-05

Que se passe-t-il ?¶

La méthode d'Euler explose ! Les valeurs oscillent et divergent.

Raison : Euler explicite a une région de stabilité limitée.

Pour $\frac{\mathrm{d}y}{\mathrm{d}t} = \lambda y$, Euler est stable seulement si :

$$|1 + h\lambda| < 1$$

Pour $\lambda = -1000$, il faut $h < 0.002$ s.

Notons que le pas $h$ qu'il faut pour la stabilité ne garantie pas que la solution est precise, seulement qu'elle n'explose pas.

In [25]:
# Avec h = 0.001 (stable)
h_stable = 0.001
t_stable, y_stable = euler_method(f_stiff, t0_stiff, tf_stiff, y0_stiff, h_stable)

t_exact_stiff = np.linspace(t0_stiff, tf_stiff, 500)
y_exact_stiff = np.exp(lam * t_exact_stiff)

Problèmes raides (stiff)¶

Un problème est raide quand il contient des échelles de temps très différentes :

  • Des phénomènes rapides (transitoires)
  • Des phénomènes lents (évolution à long terme)

Les méthodes explicites (Euler, RK4) sont inefficaces : elles nécessitent $h$ très petit pour rester stables, même quand la solution évolue lentement.

Solution : méthodes implicites.

Méthode d'Euler implicite (backward)¶

Au lieu d'évaluer $f$ au point $n$ (connu), on l'évalue au point $n+1$ (inconnu) :

$$\boxed{y_{n+1} = y_n + h \cdot f(t_{n+1}, y_{n+1})}$$

C'est une équation implicite pour $y_{n+1}$ — il faut la résoudre à chaque pas !

Avantage : stable pour tout $h$ (A-stable). Permet d'utiliser des pas plus grands sur les problèmes raides.

Inconvénient : plus coûteux par pas (résolution d'équation non linéaire).

Implémentation d'Euler implicite¶

Pour une fonction non linéaire, on est obligé d'utiliser une méthode itérative (comme Newton-Raphson) à chaque pas (pourquoi on a étudié telles méthodes !).

In [ ]:
def euler_backward(f, t0, tf, y0, h, tol=1e-8, max_iter=50):
    N = int((tf - t0) / h) + 1  # Nombre de points dans la grille
    t = np.linspace(t0, tf, N)  # Grille de temps
    y = np.zeros(N)             # Tableau pour stocker les solutions numériques
    y[0] = y0                   # Condition initiale
    eps = 1e-8                  # Utilise différences finies pour approximer la dérivée du résidu
    for n in range(N - 1):
        y_new = y[n] + h * f(t[n], y[n])  # Prédiction initiale (Euler explicite)
        # Newton-Raphson : résout g(y_{n+1}) = y_{n+1} - y_n - h*f(t_{n+1}, y_{n+1}) = 0
        for iteration in range(max_iter):  # Fait des itérations de Newton-Raphson
            g = y_new - y[n] - h * f(t[n + 1], y_new)  # Résidu
            # Dérivée de g par rapport à y_new g'(y) = 1 - h*f'(y), où f'(y) est la derivée de f par rapport à y_new
            f_y = (f(t[n + 1], y_new + eps) - f(t[n + 1], y_new)) / eps  # Approximation avec différences finies
            g_prime = 1 - h * f_y
            # Mise à jour de y_new avec la formule de Newton-Raphson
            y_new = y_new - g / g_prime
            # Si le résidu est suffisamment petit, on peut arrêter les itérations
            if abs(g) < tol:
                break
        # Enregistre la solution et passe au point suivant
        y[n + 1] = y_new
    return t, y
In [27]:
# Résolution avec Euler implicite, h = 0.005 (plus grand que la limite de stabilité explicite)
h_backward = 0.005
t_backward, y_backward = euler_backward(f_stiff, t0_stiff, tf_stiff, y0_stiff, h_backward)

print("y(tf) numérique :", y_backward[-1])
print("y(tf) exact     :", np.exp(lam * tf_stiff))
y(tf) numérique : 0.02777777777777778
y(tf) exact     : 4.5399929762484854e-05

Méthodes implicites dans solve_ivp¶

Pour les problèmes raides, utilisez :

  • method='Radau' : méthode implicite de Runge-Kutta (ordre 5)
  • method='BDF' : Backward Differentiation Formulas (ordre variable, jusqu'à 5)

Ces méthodes détectent et gèrent automatiquement la raideur.

In [28]:
# Résolution avec RK45 (explicite) — observe la difficulté
sol_explicit = solve_ivp(f_stiff, [t0_stiff, tf_stiff], [y0_stiff], method='RK45', rtol=1e-6, atol=1e-9)

# Résolution avec BDF (implicite)
sol_implicit = solve_ivp(f_stiff, [t0_stiff, tf_stiff], [y0_stiff], method='BDF', rtol=1e-6, atol=1e-9)

print("RK45 (explicite) — nombre de pas :", len(sol_explicit.t))
print("BDF (implicite)  — nombre de pas :", len(sol_implicit.t))
print("RK45 (explicite) — nombre d'évaluations de f :", sol_explicit.nfev)
print("BDF (implicite)  — nombre d'évaluations de f :", sol_implicit.nfev)
RK45 (explicite) — nombre de pas : 41
BDF (implicite)  — nombre de pas : 107
RK45 (explicite) — nombre d'évaluations de f : 248
BDF (implicite)  — nombre d'évaluations de f : 214

Observation¶

  • RK45 doit prendre beaucoup de petits pas pour rester stable → coûteux
  • BDF peut utiliser des pas plus grands → moins d'évaluations de fonction

Règle pratique : si solve_ivp prend un nombre anormalement élevé de pas, essayez une méthode implicite (BDF ou Radau).

À vous de faire les exercices 4.1 et 4.2 !¶

Points clés de la séance¶

Méthode Ordre Stabilité Usage
Euler explicite $\mathcal{O}(h)$ Limitée Problèmes simples où avec un petit pas de temps inhérent
RK4 $\mathcal{O}(h^4)$ Bonne pour problèmes lisses Cheval de bataille général
RK45 adaptatif $\mathcal{O}(h^5)$ Automatique solve_ivp par défaut
Euler implicite $\mathcal{O}(h)$ A-stable Problèmes raides, plasticity
BDF, Radau Ordre élevé A-stable Problèmes raides complexes