fichier Maple : numeric-proc.mws

Résolution numérique d'une équation différentielle d'ordre 1

Nous verrons ici quelques techniques de résolution numérique d'équations différentielles pour des équations d'ordre 1 . Toutes les méthodes classiques sont implantées dans Maple, mais on peut également définir soi-même la procédure qui nous intéresse .

Nous résoudrons ici l'équation suivante y' = x + y avec la condition initiale y( 0 ) = 1

On cherche à déterminer y(1) ou à estimer une courbe solution quand x varie de 0 à 1.

Plutôt que d'utiliser les routines déjà implantées dans Maple, on programmera ici les procédures permettant d'utiliser les méthodes d'Euler, d'Euler amélioré et de Runge-Kutta.

Méthode d'Euler

La procédure suivante appliquera la méthode d'euler avec n étapes pour estimer la solution de l'équation

y' = f( x , y) en x =b en connaissant la valeur initiale y ( a ) = c . La variable ynew représente la nouvelle valeur de y à chaque itération.

> Euler:=proc(f,a,c,b,n)
local h,i,x,y,ynew;
  h:=(b-a)/n:
  x:=a: y:=c:
for i from 1 to n do
  ynew:=y+h*f(x,y):
  y:=ynew:
  x:=a+i*h:
end do:
[x,evalf(y)]:end;

Euler := proc (f, a, c, b, n) local h, i, x, y, yne...
Euler := proc (f, a, c, b, n) local h, i, x, y, yne...
Euler := proc (f, a, c, b, n) local h, i, x, y, yne...
Euler := proc (f, a, c, b, n) local h, i, x, y, yne...

Définissons la fonction f( x , y) à être utiliser par notre procédure et appliquons-la!

> f:=(x,y)->x+y;

> Euler(f,0,1,1,10);

f := proc (x, y) options operator, arrow; x+y end p...

[1, 3.187484920]

Si on désire voir tous les couples de points [x , y] calculés par la méthode, on modifie la procédure comme suit:

> Euler_detail:=proc(f,a,c,b,n)
local h,i,x,y,ynew;
  h:=(b-a)/n:
  x:=a: y:=c: print(evalf(a),evalf(c)):
for i from 1 to n do
  ynew:=y+h*f(x,y):
  y:=ynew:
  x:=a+i*h:print(evalf(x),evalf(y)):
end do:
end;

Euler_detail := proc (f, a, c, b, n) local h, i, x,...
Euler_detail := proc (f, a, c, b, n) local h, i, x,...
Euler_detail := proc (f, a, c, b, n) local h, i, x,...
Euler_detail := proc (f, a, c, b, n) local h, i, x,...

> Euler_detail(f,0,1,1,10);

0., 1.

.1000000000, 1.100000000

.2000000000, 1.220000000

.3000000000, 1.362000000

.4000000000, 1.528200000

.5000000000, 1.721020000

.6000000000, 1.943122000

.7000000000, 2.197434200

.8000000000, 2.487177620

.9000000000, 2.815895382

1., 3.187484920

Méthode d'Euler amlioré

Voici le code pour afficher seulement la valeur finale cherchée, toujours avec le même exemple.

> EulerAmel:=proc(f,a,c,b,n)
local h,i,x,y,ynew,k1,k2;
  h:=(b-a)/n:
  x:=a: y:=c:
for i from 1 to n do

   k1:=f(x,y):
   k2:=f(x+h,y+h*k1):
  ynew:=y+h*(k1+k2)/2:
  y:=ynew:
  x:=a+i*h:
end do:
[x,evalf(y)]:end;

EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...
EulerAmel := proc (f, a, c, b, n) local h, i, x, y,...

Exécutons cette procédure:

> EulerAmel(f,0,1,1,10);

[1, 3.428161693]

Si on désire voir tous les couples de points [x , y] calculés avec la méthode d'Euler amélioré, on utilise:

> EulerA_detail:=proc(f,a,c,b,n)
local h,i,x,y,ynew,k1,k2;
  h:=(b-a)/n:
  x:=a: y:=c: print(evalf(a),evalf(c)):
for i from 1 to n do

   k1:=f(x,y):
   k2:=f(x+h,y+h*k1):
  ynew:=y+h*(k1+k2)/2:
  y:=ynew:
  x:=a+i*h:print(evalf(x),evalf(y)):
end do:
end;

EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...
EulerA_detail := proc (f, a, c, b, n) local h, i, x...

Exécutons cette procédure:

> EulerA_detail(f,0,1,1,10);

0., 1.

.1000000000, 1.110000000

.2000000000, 1.242050000

.3000000000, 1.398465250

.4000000000, 1.581804101

.5000000000, 1.794893532

.6000000000, 2.040857353

.7000000000, 2.323147375

.8000000000, 2.645577849

.9000000000, 3.012363523

1., 3.428161693

Méthode de Runge-Kutta

Voici le code pour afficher seulement la valeur finale cherchée, toujours avec le même exemple.

> RungeK:=proc(f,a,c,b,n)
local h,i,x,y,ynew,k1,k2,k3,k4;
  h:=(b-a)/n:
  x:=a: y:=c:
for i from 1 to n do

   k1:=h*f(x,y):
   k2:=h*f(x+h/2,y+k1/2):
   k3:=h*f(x+h/2,y+k2/2):
   k4:=h*f(x+h,y+k3):
  ynew:=y+(k1+2*k2+2*k3+k4)/6:
  y:=ynew:
  x:=a+i*h:
end do:
[x,evalf(y)]:end;

RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...
RungeK := proc (f, a, c, b, n) local h, i, x, y, yn...

Exécutons cette procédure:

> RungeK(f,0,1,1,10);

[1, 3.436559488]

Si on désire voir tous les couples de points [x , y] calculés avec la méthode Runge-Kutta d'ordre 4, on utilise:

> RungeK_detail:=proc(f,a,c,b,n)
local h,i,x,y,ynew,k1,k2,k3,k4;
  h:=(b-a)/n:
  x:=a: y:=c: print(evalf(a),evalf(c)):
for i from 1 to n do
   k1:=h*f(x,y):    k2:=h*f(x+h/2,y+k1/2):    k3:=h*f(x+h/2,y+k2/2):    k4:=h*f(x+h,y+k3):
  ynew:=y+(k1+2*k2+2*k3+k4)/6:
  y:=ynew:
  x:=a+i*h: print(evalf(x),evalf(y)):
end do:
end;

RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...
RungeK_detail := proc (f, a, c, b, n) local h, i, x...

Exécutons cette procédure:

> RungeK_detail(f,0,1,1,10);

0., 1.

.1000000000, 1.110341667

.2000000000, 1.242805142

.3000000000, 1.399716994

.4000000000, 1.583648480

.5000000000, 1.797441277

.6000000000, 2.044235924

.7000000000, 2.327503253

.8000000000, 2.651079127

.9000000000, 3.019202828

1., 3.436559488

>