1 Exercice : Étude d’un problème mathématiquement mal posé
Considérons le problème de Cauchy \(
\begin{cases}
y'(t)=y^2(t)+t^2, & t\in[0;1-\varepsilon],\\
y(0)=1.
\end{cases}
\)
Soit \(\varepsilon=0.2\). Utiliser la méthode d’Euler explicite puis la méthode RK4 pour calculer la solution approchée avec un pas \(h=0.1\) et comparer les deux résultats en \(t=1\). Même exercice avec \(h=0.05\) et \(h=0.01\).
Répéter avec \(\varepsilon=0.1\) puis \(\varepsilon=0\).
Commenter les résultats (hint: tracer le champ de vecteurs).
1.1 Correction
Code
%reset -f%matplotlib inlinefrom matplotlib.pylab import*# rcdefaults()rcParams.update({<span class="st">'font.size'</span>: <span class="dv">16</span>})from scipy.optimize import fsolve# ODEphi =lambda t,y : y**2+t**2# SCHEMASdef EE(phi,tt,y0): h = tt[1]-tt[0] uu = [y0]for i inrange(len(tt)-1): uu.append( uu[i] + h*phi(tt[i],uu[i]) )return uudef EI(phi,tt,y0): h = tt[1]-tt[0] uu = [y0]for i inrange(len(tt)-1): uu.append( fsolve(lambda x : -x + uu[i] + h*phi(tt[i+1],x) , uu[i] )[0] )return uudef RK4(phi,tt,y0): h = tt[1]-tt[0] uu = [y0]for i inrange(len(tt)-1): k1 = phi( tt[i], uu[i] ) k2 = phi( tt[i]+h/2 , uu[i]+h*k1/2 ) k3 = phi( tt[i]+h/2 , uu[i]+h*k2/2 ) k4 = phi( tt[i+1] , uu[i]+h*k3 ) uu.append( uu[i] + (k1+2*k2+2*k3+k4)*h/6 )return uu# INITIALISATIONt0 =0tfinal =1y0 =1# DISCRETISATIONfor epsilon in [0.2, 0.1, 0]:print(f"Interval [0,{</span><span class="dv">1</span><span class="op">-</span>epsilon<span class="sc">}]")for h in [0.1,0.05,0.01]: N =int((1-epsilon)/h) tt = linspace(0,1-epsilon,N+1) # ne pas utiliser arange, pb avec les arrondis uu_EE = EE(phi,tt,y0) uu_EI = EI(phi,tt,y0) uu_RK4 = RK4(phi,tt,y0) h = tt[1]-tt[0]print(f"\tAvec h={</span>h<span class="sc">} on a \t EE({</span>tt[<span class="op">-</span><span class="dv">1</span>]<span class="sc">})={</span>uu_EE[<span class="op">-</span><span class="dv">1</span>]<span class="sc">:g},\t EI({</span>tt[<span class="op">-</span><span class="dv">1</span>]<span class="sc">})={</span>uu_EI[<span class="op">-</span><span class="dv">1</span>]<span class="sc">:g},\t RK4({</span>tt[<span class="op">-</span><span class="dv">1</span>]<span class="sc">})={</span>uu_RK4[<span class="op">-</span><span class="dv">1</span>]<span class="sc">:g}")
Interval [0,0.8]
Avec h=0.1 on a EE(0.8)=3.50783, EI(0.8)=4.99976, RK4(0.8)=5.84201
Avec h=0.05 on a EE(0.8)=4.20131, EI(0.8)=9.99988, RK4(0.8)=5.84811
Avec h=0.01 on a EE(0.8)=5.34276, EI(0.8)=6.56639, RK4(0.8)=5.84862
Interval [0,0.9]
Avec h=0.1 on a EE(0.9)=4.80232, EI(0.9)=4.99976, RK4(0.9)=14.0218
Avec h=0.05 on a EE(0.9)=6.4606, EI(0.9)=9.99988, RK4(0.9)=14.2712
Avec h=0.01 on a EE(0.9)=10.8041, EI(0.9)=28.1192, RK4(0.9)=14.3048
Interval [0,1]
Avec h=0.1 on a EE(1.0)=7.18955, EI(1.0)=4.99976, RK4(1.0)=735.099
Avec h=0.05 on a EE(1.0)=12.3209, EI(1.0)=9.99988, RK4(1.0)=175863
Avec h=0.01 on a EE(1.0)=90.7555, EI(1.0)=50.0038, RK4(1.0)=inf
Le problème présuppose qu’une solution existe sur l’intervalle \([0;1]\) alors qu’en fait aucune solution n’existe. La théorie générale dit qu’une solution unique existe pour un certain intervalle contenant \(t=0\), mais elle ne nous dit pas jusqu’où s’étend cet intervalle. Nous pouvons montrer qu’une solution existe pour \(t>\pi/4\). Cependant, la solution devient non bornée quelque part entre \(\pi/4\) et \(1\). En effet, la solution cherchée \(y\) est bornée par les deux fonctions suivantes: \(
z(t)\le y(t) \le w(t), \qquad t\in[0;1]
\) où \(
\begin{cases}
z'(t)=z^2(t), & t\in[0;1],\\
z(0)=1;
\end{cases}
\qquad
\begin{cases}
w'(t)=w^2(t)+1, & t\in[0;1],\\
w(0)=1.
\end{cases}
\) On trouve \(z(t)=\frac{1}{1-t}\) qui est définie sur \([0;1[\) et \(w(t)=\tan\left(t+\frac{\pi}{4}\right)\) qui est définie sur \([0;\pi/4[\).
Code
figure(figsize=(10,7))# quiverplot# define a grid and compute direction at each pointg1 = linspace(0,1,21)g2 = linspace(0,3,21)T,Y = meshgrid(g1,g2) # create a gridDT, DY =1, phi(T,Y) # compute growth rate on the gridM = sqrt(DT**2+DY**2) # norm growth rate M[ M==0 ] =1# avoid zero division errors quiver(T,Y, DT/M, DY/M, M, pivot='mid')# streamplot(T,Y, DT/M, DY/M, color=M)grid()xlabel('t')ylabel('y')title('Champ des pentes');
Cet exemple montre l’importance de l’interaction entre la théorie et le calcul numérique. Si vous vous contentez de calculer numériquement des solutions sans savoir qu’une solution existe, vous pouvez penser que vous avez réussi alors que vous êtes en train de calculer quelque chose qui n’existe pas. Prouvez l’existence et l’unicité avant de calculer. La théorie vient en premier. Par exemple, ce serait bien de connaître la taille de l’intervalle d’existence de la solution avant de calculer quoi que ce soit, mais ce n’est pas toujours possible. De même, il n’est pas évident, en regardant l’équation, de voir qu’il y a un problème pour \(t \to 1\). Les difficultés que nous avons rencontrées avec le calcul numérique suggèrent qu’il pourrait y avoir un problème théorique. Je ne dirais pas que la théorie ou le calcul viennent nécessairement en premier. Je dirais qu’il faut itérer entre les deux, en commençant par l’approche la plus facile à mettre en œuvre. Les résultats théoriques sont plus satisfaisants lorsqu’ils sont disponibles, mais la théorie ne nous en dit souvent pas autant que ce que nous aimerions savoir. En outre, les gens font des erreurs dans les calculs théoriques, tout comme dans les calculs numériques. Il est préférable que les travaux théoriques et numériques se valident mutuellement.
Ce problème montre l’importance de se préoccuper de l’existence et de l’unicité, mais les méthodes théoriques ne sont pas les seules méthodes pour explorer l’existence. Une bonne pratique numérique, c’est-à-dire l’essai de plus d’une taille de pas ou de plus d’une méthode numérique, est également précieuse. Quoi qu’il en soit, le problème montre que sans une certaine diligence - théorique ou numérique - vous pourriez naïvement calculer une “solution” approximative là où il n’existe aucune solution.
Source : https://www.johndcook.com/blog/2009/08/11/approximating-a-solution-that-doesnt-exist/
Source : (page 438 et 447) Boyce and DiPrima Elementary Differential Equations and Boundary Value Problems, seventh edition
2 Exercice : Étude d’un problème numériquement mal posé
Considérons le problème de Cauchy \(
\begin{cases}
y'(t)=3y(t)-4e^{-t}, & t\in[0;1],\\
y(0)=1+\varepsilon.
\end{cases}
\) 1. Calculer la solution exacte. 2. Utiliser la méthode RK4 pour calculer la solution approchée avec un pas \(h=\frac{1}{10}\) et comparer à la solution exacte pour trois valeurs des \(\varepsilon\), à savoir \(\varepsilon=1\), \(\varepsilon=\frac{1}{10}\) et \(\varepsilon=0\). 3. Même exercice avec la méthode d’Euler explicite. 3. Commenter les résultats.
2.1 Correction : solution exacte (avec SymPy)
La solution exacte est \(y(t)=\varepsilon e^{3t}+e^{-t}\).
Si \(\varepsilon=0\), la solution exacte devient donc \(y(t)=e^{-t}\) mais le problème est mal conditionné car toute (petite) erreur de calcul a le même effet qu’une perturbation de la condition initiale: on “réveil” le terme dormant \(e^{3t}\).
Code
%reset -fimport sympy as symsym.init_printing(pretty_print=True)sym.var('t,epsilon')y=sym.Function('y')edo=sym.Eq( sym.diff(y(t),t), 3*y(t)-4*sym.exp(-t) )print("EDO") display(edo)print("\nSolution generale") soln=sym.dsolve(edo,y(t))display(soln.expand())print("\nEn prenant en compte la CI on trouve") t0 =0y0 =1+epsilonconstants = sym.solve([soln.rhs.subs(t,t0) - y0])display(constants)print("\nSolution particuliere")sym.var('C1')solp = soln.subs(constants)display(solp.expand())
EDO
Solution generale
En prenant en compte la CI on trouve
Solution particuliere
3 Exercice : A-stabilité du schéma d’Euler expicite dans le cas d’un système
Soit le problème de Cauchy: \(\begin{cases}
y''(t)+1001y'(t)+1000y(t)=0, & \forall t \in \mathbb{R},\\
y(0)=1,\\
y'(0)=0.
\end{cases}\) 1. Écrire le problème comme un système de 2 EDO d’ordre 1 et en calculer la solution. 1. Écrire le schéma le schéma d’Euler explicite pour ce problème. 4. Pour quelles valeurs de \(h\) le schéma est A-stable?
3.1 Correction
Soit \(\mathbf{z}(t)=(y(t),y'(t))^T\) alors \(y''(t)+1001y'(t)+1000y(t)=0\) se réécrit \(
\mathbf{z}'(t)=
-\begin{pmatrix}
0&-1\\
1000&1001
\end{pmatrix}
\mathbf{z}(t)
\) Cette matrice a pour valeurs propres \(\lambda_1=1\) et \(\lambda_2=1000\) et pour vecteurs propres associés \(\mathbf{v}_1=(-1,1)^T\) et \(\mathbf{v}_2=(0,1000)^T\) (ci dessous le calcul formel des valeurs et vecteurs propes). Ainsi \(
\mathbf{z}(t)=c_1\mathbf{v}_1e^{-\lambda_1t}+c_2\mathbf{v}_2e^{-\lambda_2t}
\) et \(
y(t)=-c_1e^{-t}-c_2e^{-1001t}.
\) Il s’agit d’un problème stiff!
Code
%reset -fimport sympy as symbsymb.init_printing()symb.var('t')M = symb.Matrix(((0,-1), (1000,1001)))display(M)p=M.charpoly(t)display(symb.factor(p))P, D = M.diagonalize()display(P,D)display(symb.simplify(P*D*P**-1))
Le schéma est A-stable si \(\lim_{n\to+\infty}\mathbf{u}_{n+1}=\mathbf{0}\). Il faut donc que \(\begin{cases}
|1-1000h|<1\\
|1-h|<1
\end{cases}\) d’où la condition \(h<\frac{2}{1000}\).
4 Exercice : EDO d’ordre 2
Considérons le problème de Cauchy \(
\begin{cases}
y''(t)= ty(t), &t\in[0;4.5]\\
y(0)=0.355028053887817,\\
y'(0)=-0.258819403792807.
\end{cases}
\) Transformer l’EDO d’ordre 2 en un système de deux EDO d’ordre 1.
Calculer la valeur approchée de \(y\) en \(t=4.5\) obtenue avec le schéma RK4 avec un pas de discrétisation \(h=0.001\).
4.1 Correction
On appelle \(x(t)=y(t)\) et \(z(t)=y'(t)\), alors on a \(x'(t)=y'(t)=z(t)\) et \(z'(t)=y''(t)=ty(t)=tx(t)\) donc
5 Exercice : Étude théorique et numérique du mouvement d’un pendule
Considérons le problème du mouvement d’un pendule de masse \(m\) suspendu au point \(O\) par un fil non pesant de longueur \(\ell\).
On se propose d’étudier l’évolution au cours du temps \(t\ge0\) de l’angle \(\vartheta(t)\) autour du point \(0\).
L’angle \(\vartheta(t)\) est mesuré par rapport à une verticale passante par \(0\).
Considérons pour simplifier seulement la force de gravité \(g\).
La fonction \(\vartheta\) est alors solution de l’EDO d’ordre 2 \(
\vartheta''(t)=-\frac{g}{\ell}\sin(\vartheta(t)).
\) Si on introduit le paramètre \(\omega\) tel que \(\omega^2=\dfrac{g}{\ell}\), l’équation devient \(
\vartheta''(t)+\omega^2\sin(\vartheta(t))=0.
\) Pour simplicité on pose \(\omega=1\) et on note \(q=\vartheta\) et \(p=\vartheta'\). On peut alors transformer l’EDO d’ordre 2 en un système de deux EDO d’ordre 1: \(
\begin{cases}
q'(t)=p(t),\\
p'(t)=-\sin(q(t)).
\end{cases}
\) Considérons l’énergie totale du système: \(
E(q,p)=\underbrace{-\cos(q)}_{\text{Énergie potentielle}}+\underbrace{\frac{1}{2}p^2}_{\text{Énergie cinétique}}.
\)
Étude théorique
Montre analytiquement que l’énergie totale reste constante au cours du temps, i.e. que \(\frac{\mathrm{d}}{\mathrm{d}t}E(q(t),p(t))=0\).
Tracer avec Python les courbes de niveau de la fonction \((q,p)\mapsto E(q,p)\), i.e. les ensembles \(
\mathcal{N}_\kappa
=\{(q,p)\ |\ E(q,p)=\kappa\}
=\{(q,p)\ |\ p^2=2(\kappa+\cos(q))\}.
\) pour \((q,p)\in[-\pi;\pi]\times\mathbb{R}\).
Lorsque \(\vartheta\) est petit on peut considérer l’approximation \(\sin(\vartheta)\simeq\vartheta\). Calculer la solution exacte de cette équation approchée.
Étude numérique
Dans une simulation numérique on aimerait que la propriété de conservation de l’énergie soit préservée aussi bien que possible. Nous allons regarder ce qui se passe avec certaines méthodes vues en cours.
On notera \(x_n\approx q(t_n)=\vartheta(t_n)\) et \(y_n\approx p(t_n)=\vartheta'(t_n)\).
À chaque instant \(t_n\), on calculera les valeurs approchées de l’énergie cinétique \(E_c(t_n)=\frac{1}{2}y_n^2\), de l’énergie potentielle \(E_p(t_n)=-\cos(x_n)\) et de l’énergie totale \(E(t_n)=E_c(t_n)+E_p(t_n)\).
Choisissons \(h=t_{n+1}-t_n=0.1\) et \((x_0,y_0)=(\pi/4,0)\).
Dans un premier temps on se propose d’appliquer la méthode d’Euler explicite à la résolution du système.
Tracer \((t_n,x_n)\) et \((t_n,y_n)\) sur un même graphique;
sur un autre graphique représenter les trois énergies simultanément en fonction du temps;
tracer enfin \((x_n,y_n)\) sur un autre graphique et vérifier que la solution numérique tourne vers l’extérieur (i.e. l’énergie augmente au cours du temps).
Considérons le schéma obtenu en écrivant le schéma d’Euler explicite pour la première équation et le schéma d’Euler implicite pour la seconde.
Montrer que ce schéma peut s’écrire sous forme parfaitement explicite;
tracer \((t_n,x_n)\) et \((t_n,y_n)\) sur un même graphique;
sur un autre graphique représenter les trois énergies simultanément en fonction du temps;
tracer enfin \((x_n,y_n)\) sur un autre graphique. Que peut-on constater? Commenter les résultats.
On se propose d’appliquer les méthodes d’Euler modifiée, de Heun, AB2, AB3 et RK4 à la résolution du système. Pour chaque méthode:
Tracer \((t_n,x_n)\) et \((t_n,y_n)\) sur un même graphique;
sur un autre graphique représenter les trois énergies simultanément en fonction du temps;
tracer enfin \((x_n,y_n)\) sur un autre graphique. Que peut-on constater? Commenter les résultats.
5.1 Correction étude théorique
Il s’agit d’un système de deux EDO scalaires d’ordre 1 du type \(
\begin{cases}
q'(t)=\varphi_1(t,q(t),p(t)),\\
p'(t)=\varphi_2(t,q(t),p(t)),
\end{cases}
\qquad\text{avec}\qquad
\begin{cases}
\varphi_1(t,q(t),p(t))=p(t),\\
\varphi_2(t,q(t),p(t))=-\sin(q(t)).
\end{cases}
\)
L’énergie totale reste constante au cours du temps: \(\begin{align*}
\frac{\mathrm{d}}{\mathrm{d}t}E(q(t),p(t))
&=
\sin(q(t))q'(t)+p(t)p'(t)
{}=
\sin(q(t))p(t)+p(t)p'(t)
\\
&=
p(t)\left( \sin(q(t))+p'(t) \right)
{}=
p(t)\left( \sin(q(t))-\sin(q(t)) \right)=0.
\end{align*}\)
Courbes de niveau de la fonction \((q,p)\mapsto E(q,p)\):
\(\vartheta''(t)+\omega^2\vartheta(t)=0\) est une EDO d’ordre 2 homogène à coefficients constants dont la solution est \(\vartheta(t)=\vartheta(0)\cos(\omega t)+\frac{\vartheta'(0)}{\omega}\sin(\omega t)\).
def euler_progressif(phi1,phi2,tt,y0): h = tt[1]-tt[0] q = [y0[0]] p = [y0[1]]for i inrange(len(tt)-1): q.append(q[i]+h*phi1(tt[i],q[i],p[i])) p.append(p[i]+h*phi2(tt[i],q[i],p[i]))return [q,p][q_ep, p_ep] = euler_progressif(phi1,phi2,tt,y0)Ec_ep = [p**2/2for p in p_ep]Ep_ep = [-math.cos(q) for q in q_ep]Et_ep = [Ec_ep[i]+Ep_ep[i] for i inrange(len(Ec_ep))]print ('Euler explicite : |energie totale (t=Tfinal) - Energie totale (t=0)|=', abs(Et_ep[-1]-Et_ep[0]))figure(figsize=(18,5))subplot(131)plot(tt,q_ep,tt,p_ep)xlabel('t')legend(['x(t)','y(t)'])title('Euler progressif - x(t) et y(t)')subplot(132)plot(q_ep,p_ep)xlabel('x(t)')ylabel('y(t)')title('Euler progressif')subplot(133)plot(tt,Ec_ep,tt,Ep_ep,tt,Et_ep)xlabel('t')legend(['Cinetique','Potentielle','Totale'])title('Euler progressif - Energies');
Euler explicite : |energie totale (t=Tfinal) - Energie totale (t=0)|= 3.1764943624320936
5.2.2 Méthode d’Euler explicite/implicite
Schéma obtenu en écrivant le schéma d’Euler explicite pour la première équation et le schéma d’Euler implicite pour la seconde:
Dans notre cas \(\varphi_2(t_{n+1},x_{n+1},y_{n+1})=-\sin(x_{n+1})\) donc le schéma est parfaitement explicite:
Code
def euler_symplectique(phi1,phi2,tt,y0): h = tt[1]-tt[0] q = [y0[0]] p = [y0[1]]for i inrange(len(tt)-1): q.append(q[i]+h*phi1(tt[i],q[i],p[i])) p.append(p[i]+h*phi2(tt[i+1],q[i+1],p[i])) # il faudrait p[i+1] (schema implicite) mais comme dans notre cas phi2 ne depend pas de "p", le schema est explicitereturn [q,p][q_es, p_es] = euler_symplectique(phi1,phi2,tt,y0)Ec_es = [p**2/2for p in p_es]Ep_es = [-math.cos(q) for q in q_es]Et_es = [Ec_es[i]+Ep_es[i] for i inrange(len(Ec_es))]print ('Euler symplectique : |energie totale (t=Tfinal)-Energie totale (t=0)|=', abs(Et_es[-1]-Et_es[0]))figure(figsize=(18,5))subplot(131)plot(tt,q_es,tt,p_es)xlabel('t')legend(['x(t)','y(t)'])title('Euler symplectique - x(t) et y(t)')subplot(132)plot(q_es,p_es)xlabel('x(t)')ylabel('y(t)')title('Euler symplectique - y(x)')subplot(133)plot(tt,Ec_es,tt,Ep_es,tt,Et_es)xlabel('t')legend(['Cinetique','Potentielle','Totale'])title('Euler symplectique - Energies');
Euler symplectique : |energie totale (t=Tfinal)-Energie totale (t=0)|= 0.030048843024607974