Splines cubiques — Conditions frontières et résolution

Objectifs d'apprentissage

À la fin de cette leçon, vous serez en mesure de :

  • Identifier et appliquer les différents types de conditions frontières
  • Construire le système linéaire complet pour les splines cubiques
  • Résoudre le système tridiagonal par l'algorithme de Thomas
  • Comparer les effets des différentes conditions frontières

Prérequis

  • Splines cubiques — Principe et construction
  • Résolution de systèmes tridiagonaux

Rappel : le problème à compléter

Dans la leçon précédente, nous avons établi que le système pour les dérivées secondes contient équations pour inconnues.

Il manque 2 équations correspondant aux conditions aux extrémités et .


Type 1 : Spline naturelle

Définition

La spline naturelle impose une courbure nulle aux extrémités :

Interprétation physique

Cela correspond à un ruban flexible dont les extrémités sont libres (non contraintes). Le ruban se termine avec une courbure nulle.

Système résultant

Pour un pas constant , le système devient :


Type 2 : Spline parabolique (not-a-knot)

Définition

On impose que les deux premiers (et deux derniers) polynômes soient identiques au premier nœud intérieur :

Interprétation

Les segments extrêmes se comportent comme des paraboles, avec une courbure constante.

Système résultant

Les équations aux bords deviennent :

  • Première ligne : (en substituant )
  • Dernière ligne : (en substituant )

Type 3 : Extrapolation linéaire

Définition

Les valeurs de et sont obtenues par extrapolation linéaire :

Système résultant

Cette condition modifie également la structure du système en ajoutant des termes aux lignes extrêmes.


Type 4 : Pentes imposées

Définition

On spécifie les dérivées premières aux extrémités :

Équations supplémentaires

En utilisant et la formule de :

Ce qui donne une relation linéaire supplémentaire entre et .

Visualisation interactive

S''(x₀) = S''(xₙ) = 0 : la courbure est nulle aux extrémités

Les trois conditions donnent la même spline à l'intérieur, mais diffèrent aux extrémités.

Exemple complet : 4 points avec spline naturelle

Données

ixᵢyᵢ
114
22-2
333
441

Le pas est constant : .

Construction du système

Avec la spline naturelle : et .

Le système se réduit à 2 équations pour et :

Calcul des seconds membres :

Le système devient :

Résolution

Par élimination de Gauss ou substitution :

  • De la première ligne :
  • De la deuxième ligne :

Multiplions la deuxième par 4 et soustrayons :

Résultat

Calcul des coefficients

Pour le premier polynôme sur :

Donc :


Comparaison des types de conditions

Même données, différentes conditions

Pour les 4 points :

TypeS₁S₂S₃S₄
Type 1 (naturelle)020.4-15.60
Type 2 (parabolique)15.515.5-11.5-11.5
Type 3 (extrapolation)2911-7-25
💡

Observation

Les valeurs intérieures et varient selon les conditions aux bords, mais les différences sont plus marquées près des extrémités. Loin des bords, les splines se ressemblent davantage.


Algorithme de Thomas (système tridiagonal)

Structure du problème

Un système tridiagonal a la forme :

Phase de factorisation (forward sweep)

On élimine les en modifiant et :

Pour :

Phase de substitution (back substitution)

Pour :

Complexité

L'algorithme de Thomas est en , ce qui est optimal pour un système tridiagonal.


Algorithme complet en Python

spline_complete.pypython
import numpy as np

def resoudre_tridiagonal(a, b, c, d):
  """
  Résout un système tridiagonal Ax = d par l'algorithme de Thomas.

  Paramètres:
      a : sous-diagonale (a[0] non utilisé)
      b : diagonale principale
      c : sur-diagonale (c[n-1] non utilisé)
      d : second membre

  Retourne:
      x : solution
  """
  n = len(d)
  c_prime = np.zeros(n)
  d_prime = np.zeros(n)

  # Forward sweep
  c_prime[0] = c[0] / b[0]
  d_prime[0] = d[0] / b[0]

  for i in range(1, n):
      denom = b[i] - a[i] * c_prime[i - 1]
      c_prime[i] = c[i] / denom if i < n - 1 else 0
      d_prime[i] = (d[i] - a[i] * d_prime[i - 1]) / denom

  # Back substitution
  x = np.zeros(n)
  x[n - 1] = d_prime[n - 1]

  for i in range(n - 2, -1, -1):
      x[i] = d_prime[i] - c_prime[i] * x[i + 1]

  return x

def spline_naturelle(x, y):
  """
  Calcule une spline cubique naturelle.

  Paramètres:
      x : abscisses (n points)
      y : ordonnées

  Retourne:
      S : dérivées secondes aux noeuds
      a, b, c, d : coefficients des polynômes
  """
  n = len(x)
  h = np.diff(x)

  # Construire le système pour S_2, ..., S_{n-1}
  # (S_1 = S_n = 0 pour spline naturelle)
  m = n - 2  # nombre d'inconnues intérieures

  if m == 0:
      # Cas de 2 points : segment linéaire
      S = np.zeros(n)
      a = np.zeros(n - 1)
      b = np.zeros(n - 1)
      c = (y[1:] - y[:-1]) / h
      d = y[:-1].copy()
      return S, a, b, c, d

  # Diagonales du système
  diag_a = np.zeros(m)
  diag_b = np.zeros(m)
  diag_c = np.zeros(m)
  rhs = np.zeros(m)

  for i in range(m):
      idx = i + 1  # indice dans le tableau original
      diag_b[i] = 2 * (h[idx - 1] + h[idx])
      if i > 0:
          diag_a[i] = h[idx - 1]
      if i < m - 1:
          diag_c[i] = h[idx]
      rhs[i] = 6 * ((y[idx + 1] - y[idx]) / h[idx] - (y[idx] - y[idx - 1]) / h[idx - 1])

  # Résoudre
  S_int = resoudre_tridiagonal(diag_a, diag_b, diag_c, rhs)

  # Reconstruire S complet
  S = np.zeros(n)
  S[1:n-1] = S_int

  # Calculer les coefficients
  a = np.zeros(n - 1)
  b = np.zeros(n - 1)
  c = np.zeros(n - 1)
  d = np.zeros(n - 1)

  for i in range(n - 1):
      a[i] = (S[i + 1] - S[i]) / (6 * h[i])
      b[i] = S[i] / 2
      c[i] = (y[i + 1] - y[i]) / h[i] - h[i] * (S[i + 1] + 2 * S[i]) / 6
      d[i] = y[i]

  return S, a, b, c, d

def evaluer_spline(x_data, a, b, c, d, x_eval):
  """Évalue la spline en un ou plusieurs points."""
  x_eval = np.atleast_1d(x_eval)
  result = np.zeros_like(x_eval)

  for j, x in enumerate(x_eval):
      # Trouver l'intervalle
      i = np.searchsorted(x_data, x) - 1
      i = max(0, min(i, len(a) - 1))

      dx = x - x_data[i]
      result[j] = a[i] * dx**3 + b[i] * dx**2 + c[i] * dx + d[i]

  return result if len(result) > 1 else result[0]

# Exemple
x = np.array([1, 2, 3, 4], dtype=float)
y = np.array([4, -2, 3, 1], dtype=float)

S, a, b, c, d = spline_naturelle(x, y)

print("Dérivées secondes S :")
print(f"  S = {S}")

print("\nCoefficients des polynômes :")
for i in range(len(a)):
  print(f"  Q_{i+1}(x) : a={a[i]:.2f}, b={b[i]:.2f}, c={c[i]:.2f}, d={d[i]:.2f}")

# Évaluation
x_test = np.linspace(1, 4, 50)
y_test = evaluer_spline(x, a, b, c, d, x_test)

print(f"\nSpline en x=1.5 : {evaluer_spline(x, a, b, c, d, 1.5):.4f}")
print(f"Spline en x=2.5 : {evaluer_spline(x, a, b, c, d, 2.5):.4f}")

Exemple avec 6 points

Données

ixᵢyᵢ
114
22-2
333
441
554
660

Résultats comparés

TypeS₁S₂S₃S₄S₅S₆
Type 1021.47-19.9016.11-14.530
Type 216.8916.89-18.4614.96-11.39-11.39
Type 338.611-16.613.4-7-27.4

Résumé

TypeConditionUtilisation typique
Type 1 (naturelle)Par défaut, sans information aux bords
Type 2 (parabolique)Prolongement naturel aux extrémités
Type 3 (extrapolation)Extrapolation linéaire des SContinuité de la courbure au-delà
Type 4 (pentes)Quand les pentes sont connues
  • L'algorithme de Thomas résout le système tridiagonal en
  • Le choix des conditions frontières dépend du contexte et des informations disponibles
  • Les différences sont plus marquées près des extrémités

Pour aller plus loin

Les prochaines leçons présenteront les courbes de Bézier et les B-splines, qui offrent une approche différente pour définir des courbes lisses, particulièrement adaptée au design assisté par ordinateur.