{ "cells": [ { "cell_type": "markdown", "id": "b8b9cbb6-7d46-4378-9df9-9a6287861d89", "metadata": {}, "source": [ "# MT94/P26/TD - Equations différentielles, systèmes dynamiques" ] }, { "cell_type": "markdown", "id": "0fb02a9b-e519-49de-8664-987ab9e2f2e4", "metadata": {}, "source": [ "## Entrée en matière\n", "### Schémas à un pas" ] }, { "cell_type": "markdown", "id": "edd2ba70-a179-4a0f-b6a4-ea1ea6dff465", "metadata": {}, "source": [ "On considère la fonction $y:[0,T]\\rightarrow\\mathbb{R}$ solution d'un problème de Cauchy, c'est à dire une équation différentielle munie d'une condition initiale en $t=0$\n", "\\begin{align}\n", "y'&=f(t,y),\\,t\\in[0,T]\\\\\n", "y(0)&=y_0.\n", "\\end{align}\n", "On suppose que $f$ vérifie les conditions du théorème de Cauchy-Lipschitz, ce qui garantit l'existence et l'unicité de la solution. Pour $N\\in\\mathbb{N}^*$ on considère une discrétisation uniforme de l'intervalle $[0,T]$ sous la forme d'une suite $(t_n)_{n=0\\dots N}$ définie par $t_n=nh$ où $h=T/N$. \n", "\n", "Un schéma à un pas a pour but de construire une suite $(y_n)_{n=0\\dots N}$ approchant les valeurs de la solution $y$ aux points $t_n$, c'est à dire $(y(t_n))_{n=0\\dots N}$, en considérant l'équation de récurrence\n", "$$\n", "y_{n+1}=y_n+h\\phi(t_n,y_n;h),\\,n\\in\\{0\\dots N-1\\}.\n", "$$" ] }, { "cell_type": "markdown", "id": "ac3a58c2-8178-4b39-96cd-4a07d83fe1db", "metadata": {}, "source": [ "En cours nous avons vu les schémas suivants :\n", "1. Schéma d'Euler\n", "$$\n", "y_{n+1}=y_n+hf(t_n,y_n).\n", "$$\n", "2. Schéma d'Euler-Cauchy\n", "\\begin{align*}\n", "k_1&=f(t_n,y_n),\\\\\n", "k_2&=f(t_n+h,y_n+hk_1),\\\\\n", "y_{n+1}&=y_n+\\frac{h}{2}(k_1+k_2).\n", "\\end{align*}\n", "\n", "3. Schéma du point milieu\n", "\\begin{align*}\n", "k_1&=f(t_n,y_n),\\\\\n", "k_2&=f(t_n+\\frac{h}{2},y_n+\\frac{h}{2} k_1),\\\\\n", "y_{n+1}&=y_n+hk_2.\n", "\\end{align*}\n", "4. Schéma de Runge et Kutta d'ordre 4\n", "\\begin{align*}\n", "k_1&=f(t_n,y_n),\\\\\n", "k_2&=f(t_n+\\frac{h}{2},y_n+\\frac{h}{2} k_1),\\\\\n", "k_3&=f(t_n+\\frac{h}{2},y_n+\\frac{h}{2} k_2),\\\\\n", "k_4&=f(t_n+h,y_n+hk_3),\\\\\n", "y_{n+1}&=y_n+\\frac{h}{6}(k_1+2k_2+2k_3+k_4).\n", "\\end{align*}\n" ] }, { "cell_type": "markdown", "id": "cae4309c-bff4-424c-abd7-a4f910ed9aa5", "metadata": {}, "source": [ "## Evaluation de l'ordre des schémas\n", "Nous allons évaluer expérimentalement l'ordre de ces schémas, c'est à dire la valeur de l'entier $p$ tel que\n", "\\begin{equation}\n", "e(h)=Ch^p+h^p\\epsilon(h),\n", "\\end{equation}\n", "où\n", "$$\n", "e(h)=\\max_{n\\in\\{0\\dots N\\}} |y(t_n)-y_n|,\n", "$$\n", "et où $t\\rightarrow y(t)$ est la solution de l'équation différentielle :\n", "\\begin{align}\n", "y'&=-ty+t,\\,t\\in[0,4],\\tag{2}\\\\\n", "y(0)&=0.\n", "\\end{align}\n", "Voici comment organiser votre travail :" ] }, { "cell_type": "markdown", "id": "2fb0430d-683b-4deb-98f0-2ad3284c6dc3", "metadata": {}, "source": [ "1. Calculez la solution exacte de (2)." ] }, { "cell_type": "code", "execution_count": 62, "id": "e2284bf9-1677-4435-a0d6-57e649e726e3", "metadata": {}, "outputs": [], "source": [ "ytrue=#(t)->(1-exp(-0.5*t.^2));" ] }, { "cell_type": "markdown", "id": "55a7ee82-35f5-41fd-a516-06f400048abc", "metadata": {}, "source": [ "2. Ecrivez une fonction scilab calculant le second-membre de l'équation différentielle (E) :" ] }, { "cell_type": "code", "execution_count": 63, "id": "ad419712-5526-4047-97c2-6ec31a6021e7", "metadata": {}, "outputs": [], "source": [ "function dydt=f1(t,y)\n", " dydt=-t*y+t;\n", "endfunction" ] }, { "cell_type": "markdown", "id": "409b605e-c60b-4ce0-9d71-62ab7684e4a0", "metadata": {}, "source": [ "3. Ecrivez une fonction Scilab acceptant comme argument $y_0$, un vecteur contenant $(t_n)_{n=0\\dots N}$ et l'identificateur de la fonction Scilab calculant $f$, et renvoyant dans un vecteur les approximations $y_n$ pour $n=0\\dots N$ données par le Schéma d'Euler :" ] }, { "cell_type": "code", "execution_count": 64, "id": "0d77bc15-f4ef-4632-9282-dc7087e7daa4", "metadata": {}, "outputs": [], "source": [ "function y=euler(f,t,y0)\n", " n=length(t);\n", " y=zeros(1,n);\n", " h=t(2)-t(1);\n", " y(1)=y0;\n", " for k=1:n-1\n", " y(k+1)=y(k)+h*f(t(k),y(k));\n", " end\n", "endfunction" ] }, { "cell_type": "markdown", "id": "4ab6db49-8d13-4d31-9bd3-bc726128b884", "metadata": {}, "source": [ "4. Testez votre fonction en représentant graphiquement les approximations $y_n$ superposées à la solution exacte $y(t)$, ceci pour des valeurs croissantes de $N$." ] }, { "cell_type": "code", "execution_count": 65, "id": "662c2ce3-7001-4caa-9fb6-6185ca8f6f47", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "024130.51.52.53.5010.20.40.60.81.2EulerN=10" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for N = [10]\n", " t = linspace(0,4,N+1);\n", " u = linspace(0,4,500);\n", " y = euler(f1,t,0);\n", " scf(); // cree une nouvelle fenetre graphique\n", " plot(t,y,\"x\",u,ytrue(u))\n", " legend(\"Euler\",\"$1-\\exp(-t^2/2)$\",4)\n", " title(\"N=\"+string(N))\n", "end\n" ] }, { "cell_type": "markdown", "id": "fa1ac3ad-1222-4531-ab65-36188dd9d8c6", "metadata": {}, "source": [ "5. Calculez et représentez graphiquement l'erreur de convergence $e(h)$ pour\n", "$$\n", "N\\in\\{1,3,5,10,22,47,100,216,465,1000\\}\n", "$$\n", "en fonction de $h$ en utilisant une échelle logarithmique pour les abscisses et les ordonnées. Vérifiez que l'on obtient une droite de pente égale à l'ordre du schéma (on pourra utiliser la fonction `reglin`)." ] }, { "cell_type": "code", "execution_count": 66, "id": "6a7463be-a872-4231-867a-1232205cdf99", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "10-210-110010-310-210-1he(h)ordre experimental = 1.06" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "e = [];\n", "valN = [5,10,22,47,100,216,465,1000];\n", "h = 4./valN;\n", "for N = valN\n", " t = linspace(0,4,N+1);\n", " y = euler(f1,t,0);\n", " e = [e, max(abs(y-ytrue(t)))];\n", "end\n", "\n", "a = reglin(log(h),log(e));\n", "plot(\"ll\",h,e,'o')\n", "xlabel(\"h\")\n", "ylabel(\"e(h)\")\n", "title(sprintf(\"ordre experimental = %4.2f\",a))\n", "e_euler = e;" ] }, { "cell_type": "markdown", "id": "2c5c8822-346f-4b87-8553-902970a2d227", "metadata": {}, "source": [ "6. Recommencez les deux points précédents pour les trois autres schémas." ] }, { "cell_type": "markdown", "id": "da2e97f3-f263-4693-a214-f736769a2be9", "metadata": {}, "source": [ "### Schéma d'Euler-Cauchy" ] }, { "cell_type": "code", "execution_count": 67, "id": "57fe3ec3-44ea-4c61-8743-2b6facefc969", "metadata": {}, "outputs": [], "source": [ "function y=euler_cauchy(f,t,y0)\n", " n=length(t);\n", " y=zeros(1,n);\n", " h=t(2)-t(1);\n", " y(1)=y0;\n", " for k=1:n-1\n", " k1 = f(t(k),y(k));\n", " k2 = f(t(k)+h,y(k)+h*k1);\n", " y(k+1) = y(k) + h/2*(k1+k2);\n", " end\n", "endfunction" ] }, { "cell_type": "code", "execution_count": 68, "id": "0bf27f5a-24c8-47b9-9c85-23a23db1f44f", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "024130.51.52.53.5010.20.40.60.8EulerN=10" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for N = [10]\n", " t = linspace(0,4,N+1);\n", " u = linspace(0,4,500);\n", " y = euler_cauchy(f1,t,0);\n", " scf(); // cree une nouvelle fenetre graphique\n", " plot(t,y,\"x\",u,ytrue(u))\n", " legend(\"Euler\",\"$1-\\exp(-t^2/2)$\",4)\n", " title(\"N=\"+string(N))\n", "end" ] }, { "cell_type": "code", "execution_count": 69, "id": "14d9eed2-6633-4313-8719-82c957c42305", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "10-210-110010-610-510-410-310-210-1100he(h)ordre experimental = 2.28" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "e = [];\n", "for N = valN\n", " t = linspace(0,4,N+1);\n", " y = euler_cauchy(f1,t,0);\n", " e = [e, max(abs(y-ytrue(t)))];\n", "end\n", "\n", "a = reglin(log(h),log(e));\n", "plot(\"ll\",h,e,'o')\n", "xlabel(\"h\")\n", "ylabel(\"e(h)\")\n", "title(sprintf(\"ordre experimental = %4.2f\",a))\n", "e_euler_cauchy = e;" ] }, { "cell_type": "markdown", "id": "c5bba872-16d6-49e8-a816-2292c5cd0867", "metadata": {}, "source": [ "### Point milieu" ] }, { "cell_type": "code", "execution_count": 70, "id": "ee6476d5-b8d1-4d0f-b683-96337618a9a9", "metadata": {}, "outputs": [], "source": [ "function y=point_milieu(f,t,y0)\n", " n=length(t);\n", " y=zeros(1,n);\n", " h=t(2)-t(1);\n", " y(1)=y0;\n", " for k=1:n-1\n", " k1 = f(t(k),y(k));\n", " k2 = f(t(k)+h/2,y(k)+h/2*k1);\n", " y(k+1) = y(k) + h*k2;\n", " end\n", "endfunction" ] }, { "cell_type": "code", "execution_count": 71, "id": "e38c5b0f-b654-46c2-af1d-885dd3329033", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "024130.51.52.53.5010.20.40.60.8Point milieuN=10" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for N = [10]\n", " t = linspace(0,4,N+1);\n", " u = linspace(0,4,500);\n", " y = point_milieu(f1,t,0);\n", " scf(); // cree une nouvelle fenetre graphique\n", " plot(t,y,\"x\",u,ytrue(u))\n", " legend(\"Point milieu\",\"$1-\\exp(-t^2/2)$\",4)\n", " title(\"N=\"+string(N))\n", "end" ] }, { "cell_type": "code", "execution_count": 72, "id": "e0b6a61f-b70a-4f4b-89c0-7bfb13d106bc", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "10-210-110010-710-610-510-410-310-210-1100he(h)ordre experimental = 2.20" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "e = [];\n", "for N = valN\n", " t = linspace(0,4,N+1);\n", " y = point_milieu(f1,t,0);\n", " e = [e, max(abs(y-ytrue(t)))];\n", "end\n", "\n", "a = reglin(log(h),log(e));\n", "plot(\"ll\",h,e,'o')\n", "xlabel(\"h\")\n", "ylabel(\"e(h)\")\n", "title(sprintf(\"ordre experimental = %4.2f\",a))\n", "e_point_milieu = e;" ] }, { "cell_type": "markdown", "id": "25b50f74-7111-4763-94e3-3e7eee2146bb", "metadata": {}, "source": [ "### Runge-Kutta d'ordre 4" ] }, { "cell_type": "code", "execution_count": 73, "id": "13f87429-0eb7-4454-9f88-88752047bffc", "metadata": {}, "outputs": [], "source": [ "function y=rk4(f,t,y0)\n", " n=length(t);\n", " y=zeros(1,n);\n", " h=t(2)-t(1);\n", " y(1)=y0;\n", " for k=1:n-1\n", " k1 = f(t(k),y(k));\n", " k2 = f(t(k)+h/2,y(k)+h/2*k1);\n", " k3 = f(t(k)+h/2,y(k)+h/2*k2);\n", " k4 = f(t(k)+h,y(k)+h*k3);\n", " y(k+1) = y(k)+h/6*(k1+2*k2+2*k3+k4);\n", " end\n", "endfunction" ] }, { "cell_type": "code", "execution_count": 74, "id": "667409dc-63df-400b-98ca-5cfcd9edca5d", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "024130.51.52.53.5010.20.40.60.8RK4N=10" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for N = [10]\n", " t = linspace(0,4,N+1);\n", " u = linspace(0,4,500);\n", " y = rk4(f1,t,0);\n", " scf(); // cree une nouvelle fenetre graphique\n", " plot(t,y,\"x\",u,ytrue(u))\n", " legend(\"RK4\",\"$1-\\exp(-t^2/2)$\",4)\n", " title(\"N=\"+string(N))\n", "end" ] }, { "cell_type": "code", "execution_count": 75, "id": "038d8fb7-66e3-4b94-91aa-560fa8ea414a", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "10-210-110010-1210-910-610-3he(h)ordre experimental = 4.25" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "e = [];\n", "for N = valN\n", " t = linspace(0,4,N+1);\n", " y = rk4(f1,t,0);\n", " e = [e, max(abs(y-ytrue(t)))];\n", "end\n", "\n", "a = reglin(log(h),log(e));\n", "plot(\"ll\",h,e,'o')\n", "xlabel(\"h\")\n", "ylabel(\"e(h)\")\n", "title(sprintf(\"ordre experimental = %4.2f\",a))\n", "e_rk4 = e;" ] }, { "cell_type": "markdown", "id": "00d816b6-ff52-43db-942e-a95daf9f6096", "metadata": {}, "source": [ "7. Pour terminer, superposer sur un même graphique les graphes des erreurs $h\\rightarrow e(h)$ (pour les 4 schémas) ainsi que l'approximation de $y(t)$ renvoyée par la macro `cvode` de Scilab. Cherchez dans la page d'aide de `cvode` comment il est possible de contrôler cette précision." ] }, { "cell_type": "code", "execution_count": 108, "id": "6f08a816-062c-49a0-966d-b3da35cde044", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "10-210-110010-1410-1110-810-510-2he(h)EulerEuler CauchyPoint milieuRK4cvode" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "e = [];\n", "for N = valN\n", " t = linspace(0,4,N+1);\n", " [_,y] = cvode(f1,t,0,atol=1e-14,rtol=1e-14);\n", " e = [e, max(abs(y-ytrue(t)))];\n", "end\n", "e_cvode = e;\n", "plot(\"ll\",h,[e_euler;e_euler_cauchy;e_point_milieu;e_rk4;e_cvode],\"-o\");\n", "legend(\"Euler\",\"Euler Cauchy\",\"Point milieu\",\"RK4\",\"cvode\",-1);\n", "xlabel(\"h\")\n", "ylabel(\"e(h)\")" ] }, { "cell_type": "markdown", "id": "dfa81591-b394-424a-a83b-49f0d002c82c", "metadata": {}, "source": [ "## Application : le pendule\n", "\n", "

\n", "$\\theta(t)$\n", "

\n", "Le pendule que nous allons considérer est représenté sur la figure ci-dessus. Nous supposerons que la tige reliant un poids de masse $M$ à l'axe de rotation est de masse négligeable devant $M$. Nous choisissons de mesurer la déviation du pendule de la position verticale d'équilibre stable par l'angle $\\theta(t)$ mesuré positivement comme défini sur la figure." ] }, { "cell_type": "markdown", "id": "0779f58a-5dd7-4d38-a8c9-a93f556556f9", "metadata": {}, "source": [ "Si l'on applique les relations de la dynamique pour les solides en rotation autour d'un axe, on obtient l'équation différentielle suivante :\n", "\\begin{equation}\n", "\\left\\{\\begin{array}{rcl}\n", "\\theta''(t) &=& - \\displaystyle\\frac{g}{L}\\sin\\theta(t),\\\\\n", "\\theta(0)&=&\\theta_0,\\\\\n", "\\theta'(0)&=&0.\n", "\\end{array}\\right.\n", "\\tag{3}\n", "\\end{equation}\n", "La valeur de $\\theta_0$ donne la déviation initiale du pendule, et on a considéré que la vitesse angulaire initiale est nulle. \n" ] }, { "cell_type": "markdown", "id": "40979f0b-0d35-4501-a720-72c13f6b37b4", "metadata": {}, "source": [ "1. Montrer que l'on peut approcher (sous certaines conditions que l'on précisera) la solution de cette équation différentielle par la fonction\n", "$$\n", "\\phi(t) = \\theta_0\\cos\\left(\\sqrt{\\frac{g}{L}}t\\right)\n", "$$\n", "que l'on appellera dans la suite \"solution linéarisée\"." ] }, { "cell_type": "markdown", "id": "9eeb83fd-ee24-4ff5-bd50-a01236cf28e5", "metadata": {}, "source": [ "Si on suppose que $\\theta_0$ est petit, on peut approcher $\\sin(\\theta)$ par son développement à l'ordre 1, ce qui donne l'équation différentielle\n", "\\begin{equation}\n", "\\left\\{\\begin{array}{rcl}\n", "\\phi''(t) &=& - \\displaystyle\\frac{g}{L}\\phi(t),\\\\\n", "\\phi(0)&=&\\theta_0,\\\\\n", "\\phi'(0)&=&0,\n", "\\end{array}\\right.\n", "\\tag{4}\n", "\\end{equation}\n", "dont on cherche les solutions sous la forme $\\phi(t)=a\\cos(\\omega_0t)+b\\sin(\\omega_0t)$, où $\\omega_0=\\sqrt{g/L}$. Les deux conditions initiales permettent de trouver $b=0$ et $a=\\theta_0$." ] }, { "cell_type": "markdown", "id": "553bf165-d622-40e4-9755-d8f37807d160", "metadata": {}, "source": [ "2. On pose $y=\\left(\\theta,\\theta'\\right)$, \n", "écrire (3) sous la forme d'un système de deux équations du premier ordre en temps $y'=f(t,y)$ et écrire la fonction Scilab calculant $f$ :" ] }, { "cell_type": "code", "execution_count": 128, "id": "78b8f050-269b-4fa9-8fab-8285ed48ec39", "metadata": {}, "outputs": [], "source": [ "function dydt=fpendule(t,y)\n", " g=9.81;\n", " L=1;\n", " theta=y(1);\n", " thetaprime=y(2);\n", " dydt = [thetaprime; -g/L*sin(theta)];\n", "endfunction" ] }, { "cell_type": "markdown", "id": "40bee13a-ab5f-4b33-a9f1-77623f76edf6", "metadata": {}, "source": [ "3. Superposer sur un même graphique la solution linéarisée et l'approximation de $\\theta(t)$ donnée par Scilab avec la fonction `cvode` pour les valeurs de $\\theta_0$ dans l'ensemble\n", "$$\n", "\\left\\{\\frac{\\pi}{32},~\\frac{\\pi}{16},~\\frac{\\pi}{8},~\\frac{\\pi}{2},~\\frac{3\\pi}{4},~\\frac{63\\pi}{64}\\right\\}\\cdot\n", "$$" ] }, { "cell_type": "code", "execution_count": 124, "id": "fcba8f8e-35b9-40aa-bf19-05f5f3c87774", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "0102468135790-4-224-3-113t" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "t = linspace(0,10,500);\n", "theta = [];\n", "for theta0 = %pi./[32,16,8,2,4/3,64/63]\n", " [_,y] = cvode(fpendule,t,[theta0;0],rtol=1e-6);\n", " theta = [theta;y(1,:)];\n", "end\n", "plot(t,theta)\n", "xlabel(\"t\")\n", "ylabel(\"$\\theta(t)$\")" ] }, { "cell_type": "markdown", "id": "31fa4a35-aa33-4436-8082-32fae9989bde", "metadata": {}, "source": [ "On peut aussi représenter les courbes paramétriques $(\\theta(t),\\theta'(t))$ dans le plan de phase :" ] }, { "cell_type": "code", "execution_count": 127, "id": "1a1ae580-3d42-45f8-9f16-7b662f239006", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "0-4-224-3-1130-8-6-4-22468Portrait de phase" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "t = linspace(0,10,500);\n", "theta = [];\n", "for theta0 = %pi./[32,16,8,2,4/3,64/63]\n", " [_,y] = cvode(fpendule,t,[theta0;0],rtol=1e-6);\n", " plot(y(1,:),y(2,:))\n", "end\n", "xlabel(\"$\\theta$\")\n", "ylabel(\"$\\theta$\")\n", "title(\"Portrait de phase\")" ] }, { "cell_type": "code", "execution_count": null, "id": "731d9be3-f022-402d-aeb5-2c0e5b135a0f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Scilab", "language": "scilab", "name": "scilab" }, "language_info": { "file_extension": ".sci", "help_links": [ { "text": "MetaKernel Magics", "url": "https://metakernel.readthedocs.io/en/latest/source/README.html" } ], "mimetype": "text/x-scilab", "name": "scilab", "version": "0.10.2" } }, "nbformat": 4, "nbformat_minor": 5 }