Correction TP 2
Transcription
Correction TP 2
Correction TP 2 Script de la fonction Runge Kutta function [X]=runge_kutta(t0,tf,p,X0,meth) select meth case "Euler" then s=1;a=0;b=1;c=0; case "Point-Milieu" then s=2;a=[0 0;1/2 0];b=[0 1];c=[0 1/2]; case "Heun" then s=2;a=[0 0;2/3 0];b=[1/4 3/4];c=[0 2/3]; case "RK4" then s=4;a=[0 0 0 0;1/2 0 0 0; 0 1/2 0 0;0 0 1 0];b=[1/6 1/3 1/3 1/6];c=[0 1/2 1/2 1]; else error("méthode (meth) inconnue"); end //initialisation n=size(X0,2); dt=(t0-tf)/p; X=zeros(p+1,n); X(1,:)=X0; tk=t0; K=zeros(s,n); for k=1:p, //boucle en temps for i=1:s, ti=tk+c(i)*dt; Xi=X(k,:); for j=1:i-1, Xi=Xi+a(i,j)*dt*K(j,:); end, K(i,:)=F(Xi,ti); end, X(k+1,:)=X(k,:)+dt*b*K; tk=tk+dt; end, endfunction Script de la résolution d’une EDO par une méthode de Runge Kutta function Y=F(X,t) omg2=1;alpha=0; Y=[X(2) -omg2*X(1)+2*alpha*X(2)]; //cas du pendule linéaire + armotissement endfunction function X=solex(t0,tf,p,X0) //solution du pendule linéaire dt=(tf-t0)/p; T=(t0:dt:tf)’; T=T-t0; omg=1.;alpha=0; gam=sqrt(omg*omg-alpha*alpha); S=sin(gam*T);C=cos(gam*T); E=exp(-alpha*T); a=X0(2)/(gam-alpha); b=-alpha*X0(1)+gam*a; c=alpha*a+gam*X0(1); X=[E.*(a*S+X0(1)*C) E.*(b*C-c*C)]; endfunction 4 t0=0.; tf=20*%pi; X0=[%pi/2 0]; p=400; meth="RK4"; //temps initial //temps final //paramètre //nb points de discrétisation //méthode RK X=runge_kutta(t0,tf,p,X0,meth); //appel de la méthode RK //diagramme de phase figure("BackgroundColor",[1 1 1],"figure_name","Méthode "+ meth); subplot(121); title("Diagramme de phase"); square(-1,-1,1,1) plot(X(:,1),X(:,2),"k"); //Evolution temporelle subplot(122); title("Evolution temporelle"); dt=(tf-t0)/p; T=t0:dt:tf; plot(T,X(:,1),"r"); set(gca(),"auto_clear","off") S=solex(t0,tf,p,X0); plot(T,S(:,1),"k"); hl=legend([’sol. approchée’ ’sol. exacte’]); hl.legend_location="in_upper_left"; hl.background=-2; Les essais numériques ont été réalisés avec l’équation du pendule linéarisées (ω = 1, α = 1) sur l’intervalle de temps [0, 20π] discrétisé avec 400 points. La méthode d’Euler donne de très mauvais résultats (solution exponentiellement croissante). En fait elle converge mais il faut utiliser un très grand nombre de points de discrétisation. Ainsi pour obtenir la qualité de la méthode RK4, il faudrait mettre au moins 4004 points (RK4 est une méthode d’ordre 4 et Euler est seulement d’ordre 1)! Méthode d’Euler 5 Méthode de Heun Méthode du point milieu Méthode RK4 Fonction F pour le pendule non linéaire function Y=F(X,t) omg2=1;alpha=0; Y=[X(2) -omg2*X(1)+2*alpha*X(2)]; //cas du pendule linéaire + armotissement endfunction 6 L’effet de la non linéarité dans le cas du pendule non linéaire s’observe sur le diagramme de phase où l’orbite n’est plus circulaire mais demeure périodique (aux erreurs d’approximation près). Pendule non linéaire avec la méthode RK4 Courbe d’erreurs C 0 en échelle logarithmique figure("BackgroundColor",[1 1 1],"figure_name","Courbes d’’erreur"); set(gca(),"auto_clear","off") for q=1:200, N(q)=20+q*10; X=runge_kutta(t0,tf,N(q),X0,"Euler"); E=X-solex(t0,tf,N(q),X0); es(q)=norm(E(:,1),%inf); end, plot2d("ll",(tf-t0)./N,es,1); //plot en échelle log-log for q=1:200, N(q)=20+q*10; X=runge_kutta(t0,tf,N(q),X0,’Heun’); E=X-solex(t0,tf,N(q),X0); es(q)=norm(E(:,1),%inf); end, plot2d("ll",(tf-t0)./N,es,2); //plot en échelle log-log for q=1:200, N(q)=20+q*10; X=runge_kutta(t0,tf,N(q),X0,’RK4’); E=X-solex(t0,tf,N(q),X0); es(q)=norm(E(:,1),%inf); end, plot2d("ll",(tf-t0)./N,es,3); //plot en échelle log-log title("courbe d’’erreurs $\L^\infty$") hl=legend([’Euler’ ’Heun’ ’RK4’]); hl.legend_location="in_upper_left"; hl.background=-2; 7 Utilisation de la fonction Scilab : ode function Y=g(t,X), omg2=1;alpha=0; Y=[X(2) -omg2*X(1)+2*alpha*X(2)]; endfunction t=0:%pi/100:20*%pi; X=ode(X0,t0,t,g); //nombreux paramètres possibles dans ode (prédicteur-correcteur Adams par défaut) //diagramme de phase figure("BackgroundColor",[1 1 1],"figure_name","Scilab ode"); subplot(121); title("Diagramme de phase"); square(-1,-1,1,1) plot(X(1:2:$),X(2:2:$),"k"); //Evolution temporelle subplot(122); title("Evolution temporelle"); plot(t,X(1:2:$),"k"); 8