⏱ 2h, déposer le notebook dans Moodle (si 1/3 temps supplémentaire, 2h40)
📚 Autorisés : notebooks de cours, notes personnelles.
:warning: le contrôle continu est composé de 3 exercices indépendants. Deux versions de chaque exercice sont proposées ou bien l’énoncé dépend de votre numéro étudiant.
Compléter ici :
NOM :
Prénom :
N° étudiant :
1 🌪️ Système - version 1
On considère le système d’équations différentielles suivant
Vérifier analytiquement que I(t)=x3(t)−2x(t)y(t)−y3(t) est un invariant.
Calculer une solution approchée avec la méthode de Heun avec 30 sous-intervalles. Tracer ensuite
les courbes x(t) et y(t),
la courbe paramétrée (x(t),y(t)),
la courbe I(t).
Pour estimer l’ordre de convergence de la méthode de Heun, on ne peut pas utiliser la solution exacte car elle n’est pas connue. On peut cependant utiliser l’invariant I(t) dont on connaît la valeur exacte. Vérifier sur l’invariant que l’ordre de convergence est au moins 2. Avez-vous une explication pour le résultat obtenu ?
On vérifie que I est bien un invariant pour le système donné. On peut calculer I′ à la main ou utiliser sympy.
I′(t)=ddtI(x(t),y(t))=∂I∂x⋅x′(t)+∂I∂y⋅y′(t)=3x2(t)x′(t)−2x(t)y′(t)−2x′(t)y(t)−3y2(t)y′(t)=(3x2(t)−2y(t))x′(t)−y′(t)(3y2(t)+2x(t))=y′(t)x′(t)−y′(t)x′(t)=0. On a donc bien I′(t)=0 ainsi I(t) est invariant et vaut I(0)=14 pour tout t.
Même si ce n’est pas explicitement demandé dans l’énoncé, c’est toujours une bonne idée d’afficher le portrait de phase pour ce genre de système. Ci-dessous on affiche, de plus, la courbe de niveau de l’invariant I(t) correspondant à I(t)=I(0).
# TEST 2 : ordre de convergence# ==============================H, err = [], []for k inrange(7): N +=2**k t_values = np.linspace(t0, tfin, N+1) uu = Heun_system(phi, t_values, yy0) II = Invariant(uu.T) err.append(np.linalg.norm(II-I_init)) H.append(t_values[1]-t_values[0])if err[-1] <1.e-14 :breakplt.loglog(H, err, 'o-', label='erreur')a,b = np.polyfit(np.log(H), np.log(err), 1)plt.loglog(H, np.exp(a*np.log(H)+b), label=f'pente {</span>a<span class="sc">:.2f}')plt.legend()plt.show()
L’ordre calculé sur l’invariant ne peut pas être inférieur à l’ordre théorique sur la solution. En revanche, il peut être meilleur grâce à la structure particulière de l’invariant et aux compensations possibles entre les erreurs sur chaque composante de la solution.
2 🌪️ Système - version 2
On considère le système d’équations différentielles suivant
Vérifier analytiquement que I(t)=y3(t)−x3(t)+2x(t)y(t) est un invariant.
Calculer une solution approchée avec la méthode d’Euler Modifiée avec 30 sous-intervalles. Tracer ensuite
les courbes x(t) et y(t),
la courbe paramétrée (x(t),y(t)),
la courbe I(t).
Pour estimer l’ordre de convergence de la méthode d’Euler Modifiée, on ne peut pas utiliser la solution exacte car elle n’est pas connue. On peut cependant utiliser l’invariant I(t) dont on connaît la valeur exacte. Vérifier sur l’invariant que l’ordre de convergence est au moins 2. Avez-vous une explication pour le résultat obtenu ?
Même si ce n’est pas explicitement demandé dans l’énoncé, c’est toujours une bonne idée d’afficher le portrait de phase pour ce genre de système. Ci-dessous on affiche, de plus, la courbe de niveau de l’invariant I(t) correspondant à I(t)=I(0).
# TEST 2 : ordre de convergence# ==============================H, err = [], []for k inrange(7): N +=2**k t_values = np.linspace(t0, tfin, N+1) uu = EM_system(phi, t_values, yy0) II = Invariant(uu.T) err.append(np.linalg.norm(II-I_init)) H.append(t_values[1]-t_values[0])if err[-1] <1.e-14 :breakplt.loglog(H, err, 'o-', label='erreur')a,b = np.polyfit(np.log(H), np.log(err), 1)plt.loglog(H, np.exp(a*np.log(H)+b), label=f'pente {</span>a<span class="sc">:.2f}')plt.legend()plt.show()
L’ordre calculé sur l’invariant ne peut pas être inférieur à l’ordre théorique sur la solution. En revanche, il peut être meilleur grâce à la structure particulière de l’invariant et aux compensations possibles entre les erreurs sur chaque composante de la solution.
3 👣 Schéma multi-pas linéaire - version 1
La méthode multi-pas linéaire suivante est-elle convergente ? Justifier.
un+1=−14un+12un−1+34un−2+h8(9φn+5φn−1)
Correction
Une méthode multi-pas linéaire est convergente ssi elle est consistante et zéro-stable.
Cette méthode est bien zéro-stable, car toutes les racines de son polynôme caractéristique sont dans le cercle unité et seule la racine 1 est sur la frontière du cercle unité.
Cependant, elle n’est pas consistante, car ξ(1)≠1.
Vérifions-le avec symmpy :
Code
from sympy import S, symbols, Symbol, latex, factor, solve, Eq, poly, Rational, rootsfrom IPython.display import display, Math, Markdown, Latex# ========================q =3# ========================r = Symbol('r')# ========================def xi(i, q): sa =sum((-j)**i * aa[j] for j inrange(q)) sb = b_m1 +sum((-j)**(i-1) * bb[j] for j inrange(1, q))if i ==1: sb += bb[0]return (sa).factor() + (i * sb).factor()# ========================aa = [-1/S(4), 1/S(2), 3/S(4)]bb = [9/S(8), -5/S(8), 0]b_m1 =0display(Markdown(f"C'est une méthode à ${</span>q <span class="op">=</span> <span class="sc">}$ pas")) display(Markdown(f"Pour étudier la zéro-stabilité, on écrit le premier polynôme caractéristique")) rho = poly(r**(q) -sum( aa[j] * r**(q-1-j) for j inrange(q)), r)texte =r"$\varrho(r)="+ latex(rho.as_expr(),order='old') +r"$"display(Math(texte))display(Markdown(f"Il a 3 racines :"))racines = roots(rho,r)for k,v in racines.items(): display(Markdown(f" - ${</span>latex(k)<span class="sc">}$ de module ${</span>latex(<span class="bu">abs</span>(k))<span class="sc">}\\approx {</span><span class="bu">float</span>(<span class="bu">abs</span>(k))<span class="sc">}$"))display(Markdown(f"Pour étudier la consistance, on calcule $\\xi(i)$"))for i inrange(2): display(Markdown(f"$\\xi({</span>i<span class="sc">}) = {</span>latex(xi(i, q))<span class="sc">}$"))
C’est une méthode à q=3 pas
Pour étudier la zéro-stabilité, on écrit le premier polynôme caractéristique
ϱ(r)=−34−r2+r24+r3
Il a 3 racines :
1 de module 1≈1.0
−58−√23i8 de module √32≈0.8660254037844386
−58+√23i8 de module √32≈0.8660254037844386
Pour étudier la consistance, on calcule ξ(i)
ξ(0)=1
ξ(1)=−32
4 👣 Schéma multi-pas linéaire - version 2
La méthode multi-pas linéaire suivante est-elle convergente ? Justifier.
un+1=−14un+12un−1+34un−2+h8(19φn+5φn−2)
Correction
Une méthode multi-pas est convergente ssi elle est consistante et zéro-stable.
Elle est zéro-stable, car toutes les racines de son polynôme caractéristique sont dans le cercle unité et seul 1 est sur la frontière du cercle unité.
Elle est aussi consistante d’ordre 3, car ξ(i)=1 pour i=1,2,3. Étant une méthode explicite à 3 pas, c’est l’ordre maximal possible d’après la première barrière de Dalquist.
Vérifions ces calculs avec sympy :
Code
from sympy import S, symbols, Symbol, latex, factor, solve, Eq, poly, Rational, rootsfrom IPython.display import display, Math, Markdown, Latex# ========================q =3# ========================r = Symbol('r')# ========================def xi(i, q): sa =sum((-j)**i * aa[j] for j inrange(q)) sb = b_m1 +sum((-j)**(i-1) * bb[j] for j inrange(1, q))if i ==1: sb += bb[0]return (sa).factor() + (i * sb).factor()# ========================aa = [-1/S(4), 1/S(2), 3/S(4)]bb = [19/S(8), 0, 5/S(8)]b_m1 =0display(Markdown(f"C'est une méthode à ${</span>q <span class="op">=</span> <span class="sc">}$ pas")) display(Markdown(f"Pour étudier la zéro-stabilité, on écrit le premier polynôme caractéristique")) rho = poly(r**(q) -sum( aa[j] * r**(q-1-j) for j inrange(q)), r)texte =r"$\varrho(r)="+ latex(rho.as_expr(),order='old') +r"$"display(Math(texte))display(Markdown(f"dont les racines sont :"))racines = roots(rho,r)for k,v in racines.items(): display(Markdown(f" - ${</span>latex(k)<span class="sc">}$ de module ${</span>latex(<span class="bu">abs</span>(k))<span class="sc">}\\approx {</span><span class="bu">float</span>(<span class="bu">abs</span>(k))<span class="sc">}$"))display(Markdown(f"Pour étudier la consistance (et l'ordre de consistance), on calcule $\\xi(i)$"))for i inrange(4): display(Markdown(f"$\\xi({</span>i<span class="sc">}) = {</span>latex(xi(i, q))<span class="sc">}$"))
C’est une méthode à q=3 pas
Pour étudier la zéro-stabilité, on écrit le premier polynôme caractéristique
ϱ(r)=−34−r2+r24+r3
dont les racines sont :
1 de module 1≈1.0
−58−√23i8 de module √32≈0.8660254037844386
−58+√23i8 de module √32≈0.8660254037844386
Pour étudier la consistance (et l’ordre de consistance), on calcule ξ(i)
ξ(0)=1
ξ(1)=1
ξ(2)=1
ξ(3)=1
5 🎨 Étude de l’ordre de convergence d’un schéma RK semi-implicite à 2 étages - version 1
On considère le schéma de Runge-Kutta explicite à 2 étages défini par le tableau de Butcher suivant :
1101/31/301/43/4
Après avoir calculé l’ordre de convergence théorique, implémenter le schéma et vérifier expérimentalement son ordre de convergence sur un exemple que vous choisirez.
Correction
On calcule l’ordre de convergence théorique du schéma de Runge-Kutta à 2 étages donné.
C’est un schéma semi-implicite. D’après la barrière de Butcher, l’ordre est au plus 4.
En vérifiant les conditions de convergence, on trouve que l’ordre est 2.
Code
# =============================================================================# Fonctions pour calculer les conditions de consistance pour un schéma RK.## La fonction ordre_RK calcule les conditions pour les ordres 1, 2, 3 et 4 (même si théoriquement cela n'est pas possible) # - affiche la matrice de Butcher# - affiche les conditions de consistance obtenues pour chaque ordre par la fonction ordre_i# - renvoie une liste d'équations pour une éventuelle résolution## Chaque fonction ordre_i calcule les conditions pour être d'ordre i# - peut afficher les conditions de consistance [actuellement en commentaire]# - renvoie la liste d'équations## =============================================================================import sympy sympy.init_printing()from IPython.display import display, Math, Markdownprlat =lambda*args : display(Math(''.join( sympy.latex(arg) for arg in args )))def ordre_RK(s, type="implicite", A=None, b=None, c=None): j = sympy.symbols('j')if A isNone:iftype=="implicite": A = sympy.MatrixSymbol('a', s, s)eliftype=="semi-implicite": A = sympy.Matrix(s, s, lambda i,j: sympy.Symbol('a{}{}'.format(i, j)) if i >= j else0)eliftype=="explicite": A = sympy.Matrix(s, s, lambda i,j: sympy.Symbol('a{}{}'.format(i, j)) if i > j else0)else: A = sympy.Matrix(A)if c isNone: c = sympy.symbols(f'c_0:{</span>s<span class="sc">}') if b isNone: b = sympy.symbols(f'b_0:{</span>s<span class="sc">}') display(Markdown("**Matrice de Butcher**")) But = matrice_Butcher(s, A, b, c) Eqs = [] display(Markdown(f"**On a {</span>s<span class="op">+</span><span class="dv">1</span><span class="sc">} conditions pour avoir consistance (= pour être d'ordre 1)**")) Eq_1 = ordre_1(s, A, b, c, j) Eqs.append(Eq_1) display(*Eq_1) display(Markdown("**On doit ajouter 1 condition pour être d'ordre 2**")) Eq_2 = ordre_2(s, A, b, c, j) Eqs.append([Eq_2]) display(Eq_2) display(Markdown("**On doit ajouter 2 conditions pour être d'ordre 3**")) Eq_3 = ordre_3(s, A, b, c, j) Eqs.append(Eq_3) display(*Eq_3) display(Markdown("**On doit ajouter 4 conditions pour être d'ordre 4**")) Eq_4 = ordre_4(s, A, b, c, j) Eqs.append(Eq_4) display(*Eq_4)return Eqsdef matrice_Butcher(s, A, b, c): But = sympy.Matrix(A) But = But.col_insert(0, sympy.Matrix(c)) last = [sympy.Symbol(" ")] last.extend(b) But = But.row_insert(s,sympy.Matrix(last).T) display(Math(sympy.latex(sympy.Matrix(But))))return Butdef ordre_1(s, A, b, c, j): texte =r"\sum_{j=1}^s b_j ="+f"{</span><span class="bu">sum</span>(b)<span class="sc">.</span>simplify()<span class="sc">}" texte +=r"\text{ doit être égale à }1"# display(Math(texte)) Eq_1 = [sympy.Eq( sum(b).simplify(), 1 )]for i inrange(s): somma = sympy.summation(A[i,j],(j,0,s-1)).simplify() texte =r'\sum_{j=1}^s a_{'</span><span class="op">+</span><span class="bu">str</span>(i)<span class="op">+</span><span class="vs">r'j}='+ sympy.latex( somma ) texte +=r"\text{ doit être égale à }"+sympy.latex(c[i])# display(Math( texte )) Eq_1.append(sympy.Eq( somma, c[i] ))return Eq_1 def ordre_2(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j='+sympy.latex(sum([b[i]*c[i] for i inrange(s)]).simplify()) texte +=r"\text{ doit être égale à }\frac{1}{2}"# display(Math(texte)) Eq_2 = sympy.Eq( sum([b[i]*c[i] for i inrange(s)]).simplify(), sympy.Rational(1,2) )return Eq_2def ordre_3(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j^2=' texte += sympy.latex( sum([b[i]*c[i]**2for i inrange(s)]).simplify() ) texte +=r"\text{ doit être égale à }\frac{1}{3}"# display(Math(texte)) Eq_3_1 = sympy.Eq( sum([b[i]*c[i]**2for i inrange(s)]).simplify(), sympy.Rational(1,3) ) texte =r'\sum_{i,j=1}^s b_i a_{ij} c_j=' somma =sum([b[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{6}"# display(Math(texte)) Eq_3_2 = sympy.Eq( sum([b[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,6) )return [Eq_3_1, Eq_3_2]def ordre_4(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j^3=' texte += sympy.latex( sum([b[i]*c[i]**3for i inrange(s)]).simplify() ) texte +=r"\text{ doit être égale à }\frac{1}{4}"# display(Math(texte)) Eq_4_1 = sympy.Eq( sum([b[i]*c[i]**3for i inrange(s)]).simplify(), sympy.Rational(1,4) ) texte =r'\sum_{i,j=1}^s b_i c_i a_{ij} c_j=' somma =sum([b[i]*c[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{8}"# display(Math(texte)) Eq_4_2 = sympy.Eq( sum([b[i]*c[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,8) ) texte =r'\sum_{i,j=1}^s b_i a_{ij} c_j^2=' somma =sum([b[i]*A[i,j]*c[j]**2for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{12}"# display(Math(texte)) Eq_4_3 = sympy.Eq( sum([b[i]*A[i,j]*c[j]**2for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,12) ) texte =r'\sum_{i,j,k=1}^s b_i a_{ij} a_{jk} c_k=' somma =sum([b[i]*A[i,j]*A[j,k]*c[k] for k inrange(s) for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{24}"# display(Math(texte)) Eq_4_4 = sympy.Eq( sum([b[i]*A[i,j]*A[j,k]*c[k] for k inrange(s) for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,24) )return [Eq_4_1, Eq_4_2, Eq_4_3, Eq_4_4]# =============================================================================# Calcul des conditions de consistance pour un schéma RK# On doit indiquer le nombre d'étages s et le type de schéma# parmi implicite, semi-implicite ou explicite# =============================================================================s =2type="semi-implicite"# implicite, semi-implicite, expliciteA = [[1, 0], [1/sympy.S(3), 0]]c = [1, 1/sympy.S(3)]b = [1/sympy.S(4),3/sympy.S(4)]display(Markdown(f"### Conditions pour un schéma {</span><span class="bu">type</span><span class="sc">} avec s = {</span>s<span class="sc">} étages "))Eqs = ordre_RK(s=s, type=type)display(Markdown(f"### Pour notre exemple on trouve "))Eqs = ordre_RK(s=s, type=type, A=A, b=b, c=c)
5.1 Conditions pour un schéma semi-implicite avec s = 2 étages
Matrice de Butcher
[c0a000c1a10a11b0b1]
On a 3 conditions pour avoir consistance (= pour être d’ordre 1)
b0+b1=1
a00=c0
a10+a11=c1
On doit ajouter 1 condition pour être d’ordre 2
b0c0+b1c1=12
On doit ajouter 2 conditions pour être d’ordre 3
b0c20+b1c21=13
a00b0c0+a10b1c0+a11b1c1=16
On doit ajouter 4 conditions pour être d’ordre 4
b0c30+b1c31=14
a00b0c20+a10b1c0c1+a11b1c21=18
a00b0c20+a10b1c20+a11b1c21=112
a200b0c0+a00a10b1c0+a10a11b1c0+a211b1c1=124
5.2 Pour notre exemple on trouve
Matrice de Butcher
[110131301434]
On a 3 conditions pour avoir consistance (= pour être d’ordre 1)
True
True
True
On doit ajouter 1 condition pour être d’ordre 2
True
On doit ajouter 2 conditions pour être d’ordre 3
True
False
On doit ajouter 4 conditions pour être d’ordre 4
False
False
False
False
On implemente le schéma et on vérifie expérimentalement son ordre de convergence sur le problème de Cauchy y′(t)=t2e−t−(3t2+1)y(t) avec y(0)=1.
6 🎨 Étude de l’ordre de convergence d’un schéma RK semi-implicite à 2 étages - version 2
On considère le schéma de Runge-Kutta explicite à 2 étages défini par le tableau de Butcher suivant :
0002/31/31/31/43/4
Après avoir calculé l’ordre de convergence théorique, implémenter le schéma et vérifier expérimentalement son ordre de convergence sur un exemple que vous choisirez.
Correction
On calcule l’ordre de convergence théorique du schéma de Runge-Kutta à 2 étages donné.
C’est un schéma semi-implicite. D’après la barrière de Butcher, l’ordre est au plus 4.
En vérifiant les conditions de convergence, on trouve que l’ordre est 3.
Code
# =============================================================================# Fonctions pour calculer les conditions de consistance pour un schéma RK.## La fonction ordre_RK calcule les conditions pour les ordres 1, 2, 3 et 4 (même si théoriquement cela n'est pas possible) # - affiche la matrice de Butcher# - affiche les conditions de consistance obtenues pour chaque ordre par la fonction ordre_i# - renvoie une liste d'équations pour une éventuelle résolution## Chaque fonction ordre_i calcule les conditions pour être d'ordre i# - peut afficher les conditions de consistance [actuellement en commentaire]# - renvoie la liste d'équations## =============================================================================import sympy sympy.init_printing()from IPython.display import display, Math, Markdownprlat =lambda*args : display(Math(''.join( sympy.latex(arg) for arg in args )))def ordre_RK(s, type="implicite", A=None, b=None, c=None): j = sympy.symbols('j')if A isNone:iftype=="implicite": A = sympy.MatrixSymbol('a', s, s)eliftype=="semi-implicite": A = sympy.Matrix(s, s, lambda i,j: sympy.Symbol('a{}{}'.format(i, j)) if i >= j else0)eliftype=="explicite": A = sympy.Matrix(s, s, lambda i,j: sympy.Symbol('a{}{}'.format(i, j)) if i > j else0)else: A = sympy.Matrix(A)if c isNone: c = sympy.symbols(f'c_0:{</span>s<span class="sc">}') if b isNone: b = sympy.symbols(f'b_0:{</span>s<span class="sc">}') display(Markdown("**Matrice de Butcher**")) But = matrice_Butcher(s, A, b, c) Eqs = [] display(Markdown(f"**On a {</span>s<span class="op">+</span><span class="dv">1</span><span class="sc">} conditions pour avoir consistance (= pour être d'ordre 1)**")) Eq_1 = ordre_1(s, A, b, c, j) Eqs.append(Eq_1) display(*Eq_1) display(Markdown("**On doit ajouter 1 condition pour être d'ordre 2**")) Eq_2 = ordre_2(s, A, b, c, j) Eqs.append([Eq_2]) display(Eq_2) display(Markdown("**On doit ajouter 2 conditions pour être d'ordre 3**")) Eq_3 = ordre_3(s, A, b, c, j) Eqs.append(Eq_3) display(*Eq_3) display(Markdown("**On doit ajouter 4 conditions pour être d'ordre 4**")) Eq_4 = ordre_4(s, A, b, c, j) Eqs.append(Eq_4) display(*Eq_4)return Eqsdef matrice_Butcher(s, A, b, c): But = sympy.Matrix(A) But = But.col_insert(0, sympy.Matrix(c)) last = [sympy.Symbol(" ")] last.extend(b) But = But.row_insert(s,sympy.Matrix(last).T) display(Math(sympy.latex(sympy.Matrix(But))))return Butdef ordre_1(s, A, b, c, j): texte =r"\sum_{j=1}^s b_j ="+f"{</span><span class="bu">sum</span>(b)<span class="sc">.</span>simplify()<span class="sc">}" texte +=r"\text{ doit être égale à }1"# display(Math(texte)) Eq_1 = [sympy.Eq( sum(b).simplify(), 1 )]for i inrange(s): somma = sympy.summation(A[i,j],(j,0,s-1)).simplify() texte =r'\sum_{j=1}^s a_{'</span><span class="op">+</span><span class="bu">str</span>(i)<span class="op">+</span><span class="vs">r'j}='+ sympy.latex( somma ) texte +=r"\text{ doit être égale à }"+sympy.latex(c[i])# display(Math( texte )) Eq_1.append(sympy.Eq( somma, c[i] ))return Eq_1 def ordre_2(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j='+sympy.latex(sum([b[i]*c[i] for i inrange(s)]).simplify()) texte +=r"\text{ doit être égale à }\frac{1}{2}"# display(Math(texte)) Eq_2 = sympy.Eq( sum([b[i]*c[i] for i inrange(s)]).simplify(), sympy.Rational(1,2) )return Eq_2def ordre_3(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j^2=' texte += sympy.latex( sum([b[i]*c[i]**2for i inrange(s)]).simplify() ) texte +=r"\text{ doit être égale à }\frac{1}{3}"# display(Math(texte)) Eq_3_1 = sympy.Eq( sum([b[i]*c[i]**2for i inrange(s)]).simplify(), sympy.Rational(1,3) ) texte =r'\sum_{i,j=1}^s b_i a_{ij} c_j=' somma =sum([b[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{6}"# display(Math(texte)) Eq_3_2 = sympy.Eq( sum([b[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,6) )return [Eq_3_1, Eq_3_2]def ordre_4(s, A, b, c, j): texte =r'\sum_{j=1}^s b_j c_j^3=' texte += sympy.latex( sum([b[i]*c[i]**3for i inrange(s)]).simplify() ) texte +=r"\text{ doit être égale à }\frac{1}{4}"# display(Math(texte)) Eq_4_1 = sympy.Eq( sum([b[i]*c[i]**3for i inrange(s)]).simplify(), sympy.Rational(1,4) ) texte =r'\sum_{i,j=1}^s b_i c_i a_{ij} c_j=' somma =sum([b[i]*c[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{8}"# display(Math(texte)) Eq_4_2 = sympy.Eq( sum([b[i]*c[i]*A[i,j]*c[j] for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,8) ) texte =r'\sum_{i,j=1}^s b_i a_{ij} c_j^2=' somma =sum([b[i]*A[i,j]*c[j]**2for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{12}"# display(Math(texte)) Eq_4_3 = sympy.Eq( sum([b[i]*A[i,j]*c[j]**2for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,12) ) texte =r'\sum_{i,j,k=1}^s b_i a_{ij} a_{jk} c_k=' somma =sum([b[i]*A[i,j]*A[j,k]*c[k] for k inrange(s) for j inrange(s) for i inrange(s)]).simplify() texte = texte + sympy.latex(somma) texte +=r"\text{ doit être égale à }\frac{1}{24}"# display(Math(texte)) Eq_4_4 = sympy.Eq( sum([b[i]*A[i,j]*A[j,k]*c[k] for k inrange(s) for j inrange(s) for i inrange(s)]).simplify(), sympy.Rational(1,24) )return [Eq_4_1, Eq_4_2, Eq_4_3, Eq_4_4]# =============================================================================# Calcul des conditions de consistance pour un schéma RK# On doit indiquer le nombre d'étages s et le type de schéma implicite, semi-implicite ou explicite# =============================================================================s =2type="semi-implicite"# implicite, semi-implicite, expliciteA = [[0, 0], [1/sympy.S(3), 1/sympy.S(3)]]b = [1/sympy.S(4), 3/sympy.S(4)]c = [0, 2/sympy.S(3)]display(Markdown(f"### Conditions pour un schéma {</span><span class="bu">type</span><span class="sc">} avec s = {</span>s<span class="sc">} étages "))Eqs = ordre_RK(s=s, type=type, A=A, b=b, c=c)
6.1 Conditions pour un schéma semi-implicite avec s = 2 étages
Matrice de Butcher
[0002313131434]
On a 3 conditions pour avoir consistance (= pour être d’ordre 1)
True
True
True
On doit ajouter 1 condition pour être d’ordre 2
True
On doit ajouter 2 conditions pour être d’ordre 3
True
True
On doit ajouter 4 conditions pour être d’ordre 4
False
False
False
False
On implemente le schéma et on vérifie expérimentalement son ordre de convergence sur le problème de Cauchy y′(t)=t2e−t−(3t2+1)y(t) avec y(0)=1.