USMA1Q — Méthodes Numériques¶

Séance 6 — Interpolation & Recherche des racines¶

Conservatoire National des Arts et Métiers

18 Mars 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) Résolution des systèmes non linéaires
25 mars Intégration numérique
02 avril Équations différentielles
08 avril Examen

Plan de la séance (indicatif)¶

Horaire Sujet
0:00 – 1:00 Interpolation : linéaire, splines cubiques, dérivées
1:00 – 1:50 Interpolation pratique : extrapolation, lissage, 2D
1:50 – 2:00 ☕ Pause
2:05 – 2:45 Recherche des racines scalaires
2:45 – 3:40 Combiner interpolation et recherche des racines

Motivation — pourquoi interpoler ?¶

Les données expérimentales sont discrètes : on mesure aux instants donnés, et pas pour tous les temps entre le début et le fin.

Mais les calculs nécessitent souvent une fonction continue :

Problème Ce dont on a besoin
Évaluer k(T) à une température intermédiaire Interpolant continu
Calculer dT/dt sur une courbe de refroidissement Dérivée du spline
Trouver la résistance limite à 0,2 % d'écart Racine d'une équation
Cartographier la dureté sur toute une plaque Interpolation 2D

Idée centrale : on construit une fonction $f(x)$ qui passe exactement par les données mesurées, puis on l'évalue là où on en a besoin.

1 · Principaux outils d'interpolation¶

⚠️ Pourquoi pas un polynôme de degré élevé ?¶

Avec $n$ points, il existe un unique polynôme de degré $n-1$ passant exactement par tous. C'est une mauvaise idée en pratique :

import numpy as np
import matplotlib.pyplot as plt

# 10 points équidistants sur [-1, 1]
x_data = np.linspace(-1, 1, 10)
y_data = 1 / (1 + 25 * x_data**2)   # fonction de Runge

coeffs = np.polyfit(x_data, y_data, deg=9)   # polynôme de degré 9
x_fin = np.linspace(-1, 1, 300)
y_poly = np.polyval(coeffs, x_fin)

Le polynôme oscille très fortement aux extrémités (phénomène de Runge) même s'il passe par tous les points. C'est mathématiquement exact mais numériquement inutilisable.

Interpolation linéaire — np.interp()¶

Relie les points successifs par des segments droits.

x_new = np.linspace(x_data.min(), x_data.max(), 300)
y_lin = np.interp(x_new, x_data, y_data)   # interp = interpoler

Propriétés :

  • Continu mais non différentiable aux nœuds (angle)
  • Très stable : ne peut pas osciller entre les nœuds
  • Adapté pour des données bruitées ou des tables de propriétés

Limites :

  • La dérivée est constante par morceaux (ordre 1 seulement)
  • Mauvaise approximation si les données varient vite

Spline cubique — scipy.interpolate.CubicSpline¶

Relie les points par des morceaux cubiques avec continuité de la dérivée première et seconde.

from scipy.interpolate import CubicSpline

cs = CubicSpline(x_data, y_data)  # cs = cubic spline
y_spl = cs(x_new)                 # évaluation
dy_spl = cs(x_new, nu=1)          # dérivée première (nu = order)
d2y_spl = cs(x_new, nu=2)         # dérivée seconde
integrale = cs.integrate(a, b)    # intégrale sur [a, b]

Propriétés :

  • Continu avec dérivée 1ère et 2ème continues → courbe lisse
  • Haute précision pour des données lisses
  • La dérivée est disponible gratuitement sans besoin de la definir nous même !

Conditions aux limites :

Option Signification
bc_type='not-a-knot' (défaut) Les deux prémieres segments sont assumés d'être la même polynôme (on utilise quand on n'a pas de l'information sur les conditions aux limites)
bc_type='periodic' Les fonctions sont assumées périodiques avec une période de x[-1] - x[0], et on doit avoir y[-1] == y[0]
bc_type='natural' $f''=0$ aux extrémités
bc_type='clamped' $f'=0$ aux extrémités

Quel outil choisir ?¶

Situation Outil recommandé Raison
Données bruitées np.interp() ne sur-ajuste pas
Données de simulation propres CubicSpline lisse, dérivée exacte
Besoin de la dérivée CubicSpline dérivée analytique par morceaux
Besoin de l'intégrale CubicSpline .integrate(a, b)
Table de propriétés matériaux np.interp() simple et robuste

Règle d'or : si vous ne connaissez pas la physique sous-jacente, préférez l'interpolation linéaire pour les données bruitées et les splines pour les données propres ou les résultats de simulation.

In [ ]:
# ── Démonstration : interpolation de la conductivité thermique ──
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline

# Données de conductivité thermique de l'acier 316L
data = np.loadtxt('conductivite_thermique.csv', delimiter=',', skiprows=1)
T_data = data[:, 0]  # °C
k_data = data[:, 1]  # W/(m·K)

# Grille fine pour l'évaluation
T_fin = np.linspace(T_data.min(), T_data.max(), 300)

# Interpolation linéaire
k_lin = np.interp(T_fin, T_data, k_data)

# Spline cubique
cs = CubicSpline(T_data, k_data)
k_spl = cs(T_fin)
dk_spl = cs(T_fin, nu=1)   # dk/dT

print('k à 400 °C (linéaire) :', round(np.interp(400, T_data, k_data), 3), 'W/(m·K)')
print('k à 400 °C (spline)  :', round(float(cs(400)), 3), 'W/(m·K)')

À vous de faire l'exercice 1 !¶

2 · Interpolation pratique¶

⚠️ Danger de l'extrapolation¶

Un spline (ou tout interpolant) peut diverger très rapidement hors de la plage de données :

T_extrap = np.linspace(0, 1100, 400)   # dépasse les données (max = 900 °C)
k_extrap = cs(T_extrap)  # Hors de [20, 900] : résultats sans justification !

Règle : ne jamais extrapoler sans vérifier que les prédictions sont plausibles.

Spline de lissage — make_smoothing_spline¶

Pour des données bruitées, on veut un spline qui passe près des points sans suivre le bruit :

from scipy.interpolate import make_smoothing_spline
spl_lisse = make_smoothing_spline(x_data, y_data, lam=0.5)
# lam : paramètre de lissage — grand = plus lisse, petit = suit les données
y_lisse = spl_lisse(x_new)

Interpolation 2D¶

Données sur une grille régulière : RegularGridInterpolator¶

from scipy.interpolate import RegularGridInterpolator
# x_grid, y_grid : vecteurs 1D des coordonnées de la grille
# Z : tableau 2D des valeurs Z[i, j] = f(x_grid[i], y_grid[j])
interp = RegularGridInterpolator((x_grid, y_grid), Z)
z_new = interp([[x_new, y_new]])   # évaluer en un nouveau point

Données éparses (nuage de points) : griddata¶

from scipy.interpolate import griddata
# points : tableau (N, 2) des coordonnées (x, y)
# values : tableau (N,) des valeurs mesurées
# xi     : grille sur laquelle interpoler — créée avec np.meshgrid
# method : 'linear', 'cubic', 'nearest'
xi, yi = np.meshgrid(np.linspace(0, 100, 50), np.linspace(0, 80, 40))
zi = griddata(points, values, (xi, yi), method='cubic')

À vous de faire l'exercice 2 !¶

☕ Pause — 10 minutes¶

3 · Recherche des racines scalaires¶

Tout problème de seuil se reformule en « trouver $x$ tel que $f(x) = 0$ » :

Trois familles de méthodes :

  1. Encadrement (bracketing) — lent mais garanti
  2. Newton — rapide mais a besoin d'une dérivée et d'une bonne valeur de départ
  3. Hybride — fusion intelligente → scipy.optimize.brentq()

Méthode de la bissection¶

Idée : si $f(a) < 0$ et $f(b) > 0$ pour une $f(x)$ continue, il y a une racine dans $[a, b]$. On évalue $f$ au milieu $c = (a+b)/2$ et on garde la moitié qui contient encore la racine.

def bisection(f, a, b, tol=1e-8, max_iter=100):
    for i in range(max_iter):
        c = (a + b) / 2
        if abs(f(c)) < tol or (b - a) / 2 < tol:
            return c, i + 1
        if f(a) * f(c) < 0:
            b = c
        else:
            a = c
    return (a + b) / 2, max_iter

Convergence : linéaire — l'intervalle est divisé par 2 à chaque itération → $n$ itérations donnent une précision $|b-a| / 2^n$.

Avantage : garanti de converger si $f$ est continue et que la racine est encadrée.

Méthode de Newton–Raphson¶

Idée : à chaque étape, remplacer $f$ par sa tangente et trouver la racine de cette droite.

$$x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$$

def newton(f, df, x0, tol=1e-8, max_iter=50):
    x = x0
    for i in range(max_iter):
        fx = f(x)
        if abs(fx) < tol:
            return x, i + 1
        x = x - fx / df(x)
    return x, max_iter

Convergence : quadratique près de la racine — le nombre de chiffres corrects double à chaque itération.

Inconvénients :

  • Nécessite $f'(x)$ (souvent calculé séparément ou approximé numériquement)
  • Peut diverger si le point de départ est trop loin ou si $f'(x) \approx 0$

Méthode de la sécante & quadratique inverse¶

Méthode de la sécante (secant method)¶

Approxime $f'(x_n)$ par la pente de la droite reliant les deux derniers points : $$x_{n+1} = x_n - f(x_n) \cdot \frac{x_n - x_{n-1}}{f(x_n) - f(x_{n-1})}$$

  • Pas besoin de $f'$ explicitement
  • Convergence super-linéaire ($\approx x^{1.618}$), plus rapide que la bissection, plus robuste que Newton
  • Nécessite deux points de départ $x_0$ et $x_1$

Interpolation quadratique inverse (inverse quadratic interpolation)¶

Approche une racine via un polynôme quadratique évalué en 3 points $(x_{n-2}, x_{n-1}, x_n)$ puis extrapole à $y = 0$.

  • Convergence encore plus rapide que la méthode de la sécante
  • Peut devenir instable si les trois points sont mal placés

scipy.optimize.brentq() — la méthode hybride¶

L'algorithme de Brent (Brent's method) combine intelligemment :

  • Bissection — pour garantir la convergence
  • Sécante — pour accélérer
  • Interpolation quadratique inverse — pour accélérer encore plus

Il n'utilise la bissection que quand les autres méthodes seraient dangereuses.

from scipy.optimize import brentq

def f(x):
    return x**3 - 2*x - 5

racine = brentq(f, a=2, b=3)   # encadrement : f(2) < 0, f(3) > 0
print('racine =', racine)

C'est la méthode à utiliser en pratique pour les problèmes scalaires — rapide, robuste, et ne demande qu'un encadrement.

À vous de faire les exercices 3.1 et 3.2 !¶

4 · Combiner interpolation et recherche des racines¶

Le problème pratique¶

En pratique, on n'a pas une formule analytique — on a des données :

temps  | température
-------|------------
0 s    | 1090 °C
6 s    | 1087.7 °C
...

Stratégie :

  1. Interpoler les données avec un spline cubique → $T(t)$
  2. Calculer $dT/dt = T'(t)$ via cs(t, nu=1)
  3. Calculer $d^2T/dt^2 = T''(t)$ via cs(t, nu=2)
  4. Balayer $T''(t)$ pour détecter les changements de signe → encadrements
  5. Appliquer brentq sur chaque encadrement → temps exacts
  6. Les températures correspondantes sont les temperatures de transformation

Trouver plusieurs racines¶

Pour une fonction qui possède plusieurs racines, il faut :

  1. Scanner $f(x)$ sur une grille grossière et chercher les changements de signe
  2. Pour chaque paire $(x_i, x_{i+1})$ où $f(x_i) \cdot f(x_{i+1}) < 0$ → encadrement
  3. Affiner chaque encadrement avec brentq
from scipy.optimize import brentq

def trouver_racines(f, t_scan):
    """Trouve toutes les racines de f sur la grille t_scan."""
    f_vals = f(t_scan)
    racines = []
    for i in range(len(t_scan) - 1):
        if f_vals[i] * f_vals[i + 1] < 0:   # changement de signe
            r = brentq(f, t_scan[i], t_scan[i + 1])
            racines.append(r)
    return racines

À vous de faire l'exercice 4 !¶

Points clés de la séance¶

Concept Ce qu'il faut retenir
np.interp() Interpolation linéaire rapide — robuste pour données bruitées
CubicSpline Spline cubique lisse — dérivées et intégrales gratuits via nu=
Phénomène de Runge Ne jamais ajuster un polynôme de degré élevé sur beaucoup de points
Extrapolation Toujours dangereuse — rester dans la plage des données
griddata Interpolation 2D sur nuage de points éparses
Bissection Lente mais garantie — nécessite un encadrement
Newton–Raphson Rapide (quadratique) mais nécessite $f'$ et un bon point de départ
brentq Méthode hybride recommandée — from scipy.optimize import brentq
Stratégie combinée Données → spline → résidu → brentq
Plusieurs racines Scanner les changements de signe, puis encadrer chacun