{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## L3 Mathématiques - 2023/24 - Univ. Paris-Saclay\n",
    "## Analyse théorique et numérique des EDO - Année 2023/24\n",
    "---------------------------------------------------------------------------------------------------------------\n",
    "\n",
    "## TP 1 : Représentation des solutions d'une EDO et résolution approchée par le schéma d'Euler explicite\n",
    "---------------------------------------------------------------------------------------------------------------\n",
    "\n",
    "### Partie 1. Champs de vecteurs pour une EDO scalaire.\n",
    "\n",
    "Soit $f:\\mathbb{R}\\times\\mathbb{R}\\longrightarrow\\mathbb{R}$ une fonction de classe $C^1$ et considérons l'équation différentielle\n",
    "$$\n",
    "(E)\\ \\ \\ \\ \\ \\ \\ y'(t)=f(t,y(t)).\n",
    "$$\n",
    "\n",
    "\n",
    "Très souvent on ne sait pas résoudre explicitement l'équation différentielle $(E)$. Mais on peut avoir une idée de l’allure du graphe d'une solution de cette équation en observant le *champ de vecteurs*, ou *champ de vitesses*, associé, qui est l'application \n",
    "$$\n",
    "V:(t,y)\\mapsto\\big(1,f(t,y)\\big).\n",
    "$$\n",
    "En effet, en un point $(t,y(t))$ du graphe d'une solution $t\\mapsto y(t)$ de l'équation $y'=f(t,y)$, le vecteur vitesse $(1,y'(t))$, qui est égal au vecteur $(1,f(t,y(t)))$, est tangent au graphique en ce point. La connaissance de la fonction $f$ en chaque point (t,y) permet donc de représenter ces vecteurs tangents même si l'on ne connait pas la solution de $(E)$. Et si l'on en trace un grand nombre de ces vecteurs, issus de points uniformément répartis dans le plan (t,y), on obtient une représentation du champ de vecteurs associé à l'équation différentielle qui permet souvent de *deviner* les graphes des solutions puisqu'il s'agit de courbes dont les tangentes en leurs points sont des vecteurs de ce champs de vecteurs.\n",
    "\n",
    "On va dans cette feuille représenter des champs de vecteurs, dans un premier temps pour une EDO dont la solution on sait calculer, et superposer dans le plan $(t,y)$ le graphique de la solution. On fera ensuite pareil pour une EDO dont on ne sait pas calculer la solution analytique, et on utilisera le schéma d'Euler explicite pour obtenir une *solution numérique* approchée. \n",
    "\n",
    "*On représente chaque vecteur vitesse $V(P)$ en un point $P=(\\bar{t},\\bar{y})$ du plan, par une flèche correspondant au segment $[P,P+\\varepsilon V(P)],$ avec $\\varepsilon$ petit, partant de $P$ et pointant vers $P+\\varepsilon V(P)$. En python, on peut utiliser la fonction* `quiver` *du module* `matplotlib` *pour représenter les champs de vecteurs.* \n",
    "\n",
    "### Exercice 1. Représentation des solutions d'une EDO et des champs de vecteurs.\n",
    "\n",
    "Nous nous intéressons aux deux équations suivantes :\n",
    "\n",
    "\\begin{equation}\\tag{1}\n",
    "y'=-ty,\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\\tag{2}\n",
    "y'=ty^2.\n",
    "\\end{equation}\n",
    "\n",
    "Les solutions d'un problème de Cauchy, de donnée initiale $y(0)=y_0$, avec $y_0\\in\\mathbb{R}$ donné, pour chacune des équations (1) et (2) sont respectivement (**exercice : retrouver les expressions de ces solutions**) :\n",
    "\n",
    "Pour l'équation (1) :\n",
    "$$\n",
    "y(t)=y_0 e^{-\\frac{t^2}{2}}.\n",
    "$$\n",
    "\n",
    "Pour l'équation (2) :\n",
    "$$\n",
    "y(t)=\\frac{y_0}{{1}-y_0\\frac{t^2}{2}}.\n",
    "$$\n",
    "\n",
    "\n",
    "**Question 1).** Pour l'équation (1) :\n",
    " - Sur python, tracer dans l'intervalle $[-3,3]$, la solution de (1) qui vérifie $y(0)=1.$ Tracer ensuite sur le même graphique la solution qui vérifie la condition initiale $y(0)=2.$ Donner un titre et mettre des légendes sur vos graphiques.\n",
    "\n",
    " - Tracer dans le même graphique le champ de vecteurs associé à cette équation, en utilisant les commandes :\n",
    " \n",
    "`t=np.linspace(-5,5,35) # abcisse des points de la grille\n",
    " y=np.linspace(0,2.1,23) # ordonnées des points de la grille\n",
    " T,Y=np.meshgrid(t,y) # grille de points dans le plan (t,y)\n",
    " U=np.ones(T.shape)/np.sqrt(1+f1(T,Y)**2) # matrice avec les composantes horizontales des vecteurs (1),                                                     normalisées\n",
    " V=f1(T,Y)/np.sqrt(1+f1(T,Y)**2) # matrice avec les composantes verticales des vecteurs (f(t,y)),                                                  normalisées\n",
    " plt.quiver(T,Y,U,V,angles='xy',scale=20,color='blue')`\n",
    " \n",
    " La figure sera plus lisible si on limite la fenêtre graphique au rectangle $[-5,5]\\times[0,2.1]$ avec la commande \n",
    " `plt.axis([-5,5,0,2.1])`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-5.0, 5.0, 0.0, 2.1)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 160860 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Fonction f définissant l'EDO\n",
    "def f1(t,y):\n",
    "    return -t*y\n",
    "\n",
    "# Solution exacte \n",
    "def uex1(t,y0):\n",
    "    return y0 * np.exp(-t**2 /2)\n",
    "\n",
    "plt.figure(1)\n",
    "\n",
    "## Solutions de l'EDO 1 telles que y(0)=1 et y(0)=2\n",
    "\n",
    "tt=np.linspace(-3, 3, 100) # vecteur représentant l'intervalle de temps\n",
    "y1=uex1(tt, 1) # sol. exacte avec y_0=1\n",
    "y2=uex1(tt, 2)  # sol. exacte avec y_0=2\n",
    "plt.plot(tt,y1,label='y(0)=1')\n",
    "plt.plot(tt,y2,label='y(0)=2')\n",
    "\n",
    "##Tracé du champ de vecteurs\n",
    "\n",
    "plt.title('Solution exacte pour y0 et y1')\n",
    "plt.legend()\n",
    "plt.xlabel('t')\n",
    "plt.ylabel('y')\n",
    "\n",
    "t=np.linspace(-5,5,35) # abcisse des points de la grille  \n",
    "y=np.linspace(0,2.1,23) # ordonnées des points de la grille  \n",
    "T,Y=np.meshgrid(t,y) # grille de points dans le plan (t,y)  \n",
    "U=np.ones(T.shape)/np.sqrt(1+f1(T,Y)**2) # matrice avec les composantes horizontales des vecteurs (1), normalisées  \n",
    "V=f1(T,Y)/np.sqrt(1+f1(T,Y)**2) # matrice avec les composantes verticales des vecteurs (f(t,y)), normalisées  \n",
    "plt.quiver(T,Y,U,V,angles='xy',scale=20,color='cyan')\n",
    "plt.axis([-5,5,0,2.1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 2.** Refaire le même exercice pour l'équation (2), en adaptant les intervalles de représentation des différentes solutions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_531/2612752924.py:11: RuntimeWarning: divide by zero encountered in divide\n",
      "  return y0 / (1 - y0 * t**2 / 2)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(-2.0, 2.0, -4.0, 4.0)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 231728 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Fonction f définissant l'EDO\n",
    "def f2(t,y):\n",
    "    return t * y**2\n",
    "\n",
    "# Solution exacte \n",
    "def uex2(t,y0):\n",
    "    return y0 / (1 - y0 * t**2 / 2)\n",
    "\n",
    "plt.figure(1)\n",
    "\n",
    "## Solutions de l'EDO 1 telles que y(0)=1 et y(0)=2\n",
    "\n",
    "tt=np.linspace(-3, 3, 100) # vecteur représentant l'intervalle de temps\n",
    "y1=uex2(tt, 1) # sol. exacte avec y_0=1\n",
    "y2=uex2(tt, 2)  # sol. exacte avec y_0=2\n",
    "plt.plot(tt,y1,label='y(0)=1')\n",
    "plt.plot(tt,y2,label='y(0)=2')\n",
    "\n",
    "##Tracé du champ de vecteurs\n",
    "\n",
    "plt.title('Solution exacte pour y0 et y1')\n",
    "plt.legend()\n",
    "plt.xlabel('t')\n",
    "plt.ylabel('y')\n",
    "\n",
    "xmin, xmax = -2, 2\n",
    "ymin, ymax = -4, 4\n",
    "\n",
    "t=np.linspace(xmin, xmax,35) # abcisse des points de la grille  \n",
    "y=np.linspace(ymin, ymax) # ordonnées des points de la grille  \n",
    "T,Y=np.meshgrid(t,y) # grille de points dans le plan (t,y)  \n",
    "U=np.ones(T.shape)/np.sqrt(1+f2(T,Y)**2) # matrice avec les composantes horizontales des vecteurs (1), normalisées  \n",
    "V=f1(T,Y)/np.sqrt(1+f2(T,Y)**2) # matrice avec les composantes verticales des vecteurs (f(t,y)), normalisées  \n",
    "plt.quiver(T,Y,U,V,angles='xy',scale=20,color='cyan')\n",
    "plt.axis([xmin, xmax, ymin, ymax])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Partie 2. Calcul d'une solution approchée d'une EDO par le schéma d'Euler explicite.\n",
    "\n",
    "On considère le problème de Cauchy pour l'équation différentielle $(E),$ \n",
    "\\begin{equation}\n",
    "(PC)\\ \\ \\ \\ \\ \\begin{cases}\n",
    "  y'(t) & =  f(t,y(t)), \\\\\n",
    "  y(t_0) & =  y_0,\n",
    "\\end{cases} \n",
    "\\end{equation}\n",
    "où l'instant initial $t_0\\in\\mathbb{R}$ et la valeur initiale $y_0\\in\\mathbb{R}$ sont donnés. \n",
    "\n",
    "On suppose que ce problème a une unique solution $y:J\\longrightarrow\\mathbb{R}$ définie dans un intervalle $J\\subseteq\\mathbb{R}.$ On s'intéresse ici à trouver numériquement une solution approchée de $y$, dans un intervalle de la forme $[t_0, t_0+T]\\subseteq J$, avec $T>0$. \n",
    "\n",
    "Pour ce faire, on se donne $h>0$ *petit* et on considère une subdivision uniforme de pas $h$ de l'intervalle $[t_0, t_0+T]$. On peut procéder comme suit :\n",
    "\n",
    " - on se donne $N\\in\\mathbb{N}$ *grand* \n",
    " \n",
    " - on définit $h=\\frac{T}{N}$ \n",
    " \n",
    " - on définit les **N+1** points $t_n=t_0+n h,\\ n=0,\\dots,N$ :\n",
    "$$\n",
    "t_0,\\ \\ t_1=t_0+h,\\ \\ \\cdots,\\ \\ t_N=t_0+Nh=t_0+T. \n",
    "$$\n",
    "\n",
    "On cherche alors des valeurs (réelles) $y^0,\\ y^1,\\cdots,\\ y^N$ qui approchent la solution exacte $t\\mapsto y(t)$ de $(PC)$ respectivement aux points $t_0,\\ t_1,\\cdots,\\ t_N.$ On va définir ces valeurs par un *schéma numérique*.\n",
    "\n",
    "On pose $y^0=y_0$ (*ceci est légitime car on veut que $y^0\\approx y(t_0)$ et $t\\mapsto y(t)$ vérifie $y(t_0)=y_0$*). \n",
    "\n",
    "Soit $n\\in\\{1,\\dots,N\\}.$ Pour calculer une valeur $y^n$ approchant $y(t_n)$, la solution exacte à l'instant $t_n$, on peut approcher la dérivée de $y$ par un taux d'accroissement au point $t_n$ et utiliser l'équation $(E).$ La solution exacte de $(E)$ vérifie\n",
    "\n",
    "$$\n",
    "y'(t_n)=f(t_n,y(t_n)),\n",
    "$$\n",
    "\n",
    "en chaque point $t_n$, et \n",
    "\n",
    "$$\n",
    "y'(t_n)\\approx \\frac{y(t_n+h)-y(t_n)}{h}=\\frac{y(t_{n+1})-y(t_n)}{h}.\n",
    "$$\n",
    "\n",
    "On remplace alors l'équation $y'(t)=f(t,y(t))$ par l'équation $\\frac{y(t+h)-y(t)}{h}=f(t,y(t)),$\n",
    "en chaque point $t_n$ de la subdivision considérée, autrement dit on cherche $y^1,\\dots,y^N$ solutions de \n",
    "$$\n",
    "\\frac{y^{n+1}-y^n}{h}=f(t_n,y^n).\n",
    "$$\n",
    "\n",
    "Le schéma d'Euler explicite consiste alors à définir la suite $(y_0,\\dots,y^N)_{N}$ des valeurs approchées comme ci-dessous. \n",
    "\n",
    "**Schéma d'Euler explicite** :   \n",
    "\n",
    "$$\n",
    "\\begin{cases}\n",
    "y^0=y_0,\\\\\n",
    "y^{n+1}=y^{n}+h f(t_n,y^{n}),\\ \\ \\ \\textrm{pour }\\ n\\in\\{0,\\dots,N-1\\}.\n",
    "\\end{cases}.\n",
    "$$  \n",
    "\n",
    "**Question 1.** Écrire une fonction python de la forme\n",
    "\n",
    "`euler_exp(t0, T, y0, h, f)`\n",
    "\n",
    "prenant en argument  l'instant initiale **t0**, la longueur **T** de l'intervalle de temps $[t_0,t_0+T],$ la donnée initiale $y_0$, le pas de temps $h$ et la fonction $f$ définissant le second membre de l'EDO. Cette fonction `euler_exp` devra retourner deux vecteurs : \n",
    "\n",
    "- $[t_0,\\, t_1,\\, ...,\\, t_N],$  tableau `numpy` unidimensionnel de taille $(N+1)$ représentant la subdivision de l'intervalle $[t_0,t_0+T]$ de pas $h$ considérée, \n",
    "\n",
    "- $[y_0,\\, y_1,\\, ...,\\, y_N],$ tableau `numpy` de taille $(N+1)$ représentant la solution approchée aux instants $t_n,\\ n=0,\\dots,N.$\n",
    "\n",
    "**Quelques remarques pour la programmation du schéma d'Euler.** \n",
    "\n",
    "- Pour programmer le schéma d'Euler, on peut aussi construire une fonction python de la forme `euler_exp(t0, T, y0, N,f)`, en donnant comme argument le nombre de points $N$ que l'on considère dans la subdivision de l'intervalle $[t_0,t_0+T].$ Dans ce cas, il faudra définir le pas $h$ à l'intérieur de la fonction.\n",
    "\n",
    "- Veuiller à bien faire attention à la taille des vecteurs que vous définissez, et que cette taille soit cohérente avec le pas $h$ défini : si $h=1/N$, le vecteur $[t_0,\\, t_1,\\, ...,\\, t_N]$ contenant les points $t_n=t_0+nh,\\ n=0,\\dots,N$, est de taille N+1.\n",
    "\n",
    "**Question 2.** Calculer la solution approchée obtenue par la méthode d'Euler explicite pour le problème de Cauchy pour l'équation (1) de la partie 1, de donnée initiale $y(0)=1$.\n",
    " Tracer sur une même fenêtre graphique :\n",
    "\n",
    "- La solution exacte sur l'intervalle $[0,1]$ discrétisée avec un pas de temps de $10^{-4}$ ;\n",
    "\n",
    "- Les 3 solutions approchées sur le même intervalle obtenues avec la méthode d'Euler pour les trois pas de temps $h=1/5,\\ h=1/10,\\ h=1/50$ (obtenus respectivement avec $N=5,\\ 10,\\ 100$).\n",
    "\n",
    "Rajouter des légendes à votre graphique."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 74232 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 66876 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Euler explicite\n",
    "def euler_exp(t0,T,y0,h,f):\n",
    "    t = np.arange(t0, t0+T+h, h)\n",
    "    y = np.empty(t.size)\n",
    "    y[0] = y0\n",
    "    N = len(t)-1\n",
    "    for n in range(N):\n",
    "        y[n+1] = y[n] + h * f(t[n], y[n])\n",
    "    return t, y\n",
    "\n",
    "t0=0\n",
    "T=1\n",
    "y0=1\n",
    "\n",
    "for f, uex in zip([f1, f2], [uex1, uex2]):\n",
    "    plt.figure()\n",
    "    t = np.arange(0, 1, 1e-3)\n",
    "    y = uex(t, y0)\n",
    "    plt.plot(t, y, label='Solution exacte')\n",
    "\n",
    "    for h in [1/5, 1/10, 1/50]:\n",
    "        tt, y = euler_exp(t0, T, y0, h, f)\n",
    "        plt.plot(tt, y, label=f'Solution approchée pour h={h}')\n",
    "    \n",
    "    plt.title(f\"Solutions exacte et approchées de la fonction {f.__name__}\")\n",
    "    plt.legend()\n",
    "    plt.xlabel('t')\n",
    "    plt.ylabel('y')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Partie 3. Modèles de croissance d'une population.\n",
    "\n",
    "#### Modèle de Verhulst.\n",
    "\n",
    "Considérons une population d'individus isolée dont on note $P(t)$ sa taille à l'instant $t.$ \n",
    "\n",
    "Le modèle le plus simple pour décrire l'évolution de cette population est le modèle de Malthus, donné par l'équation différentielle\n",
    "\\begin{equation*}\n",
    "P'(t)=(n-d)P(t),\n",
    "\\end{equation*}\n",
    "où $n$ et $d$ sont des constantes positives qui représentent respectivement les taux de naissances et de décès de la population.\n",
    "\n",
    "Ce modèle prévoit que si $n>d$, la population grandit exponentiellement, si $d>n$, la population décroît et tend vers l'extinction.\n",
    "\n",
    "Un deuxième modèle suppose que la croissance de la population est inhibée par la limitation des ressources et que la population ne dépasse pas une taille critique donnée par une constante $K>0.$ Si on note $P_0\\ge0$ la population à l'instant initiale, l'évolution de la population est modélisée par les équations \n",
    "\n",
    "\\begin{equation}\n",
    "\\begin{cases}\n",
    "P'(t)=(n-d)P(t)\\big(1-\\frac{P(t)}{K}\\big),\\\\\n",
    "P(0)=P_0.\n",
    "\\end{cases}\n",
    "\\tag{V}\n",
    "\\end{equation}\n",
    "\n",
    "#### Questions théoriques à réfléchir à la maison.\n",
    "\n",
    "Pour le modèle de Verhulst, le théorème de Cauchy-Lipschitz garantit l'existence d'une solution maximale, définie dans un intervalle $J$ tel que $0\\in J$.\n",
    "\n",
    "**Question 1.** Quelle est la solution maximale de $(V)$ lorsque  $P_0=0$ et lorsque $P_0=K$ ?\n",
    "\n",
    "**Question 2.** Montrer que si $n-d>0$, quelque soit $P_0>0$, la solution maximale de $(V)$ est globale à droite et tend vers $K$, lorsque $t\\to+\\infty$.\n",
    "\n",
    "**Question 3. à faire sur python.**\n",
    "\n",
    "On considère dans cette question $n=1,\\ d=0.75$ et $K=200.$ Utiliser le schéma d'Euler explicite pour obtenir une solution approchée du problème $(V)$, de donnée initiale $P_0=10,$ dans l'intervalle de temps $[0,50],$ avec un pas $h=0.5.$ Représenter graphiquement la solution obtenue. \n",
    "\n",
    "Illustrer, dans le même graphique, l'évolution de la population lorsque la donnée initiale est telle que $P_0>K.$ Interpréter le résultat obtenu.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f978e12a3e0>"
      ]
     },
     "execution_count": 175,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 219176 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Modèle de Verhulst\n",
    "n=1\n",
    "d=0.75\n",
    "K=200\n",
    "\n",
    "def fV(t,P):\n",
    "    return (n-d)*P*(1-P/K)\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "P0 = 10\n",
    "h = 0.5\n",
    "t0, T = 0, 50\n",
    "\n",
    "\n",
    "for P in range(1, K+100, 15):\n",
    "    tt, yy = euler_exp(t0, T, P, h, fV)\n",
    "    plt.plot(tt, yy, label=f'Solution approchée pour h={h}')\n",
    "    \n",
    "plt.title(f\"Solution approchée du modèle de Verhulst pour la population d'individus\")\n",
    "plt.xlabel('t')\n",
    "plt.ylabel('y')\n",
    "\n",
    "t=np.linspace(t0, T, 35) # abcisse des points de la grille  \n",
    "y=np.linspace(0, K+100, 23) # ordonnées des points de la grille  \n",
    "T,P=np.meshgrid(t,y) # grille de points dans le plan (t,y)  \n",
    "U=np.ones(T.shape)/np.sqrt(1+fV(T,P)**2) # matrice avec les composantes horizontales des vecteurs (1), normalisées  \n",
    "V=fV(T,P)/np.sqrt(1+fV(T,P)**2) # matrice avec les composantes verticales des vecteurs (f(t,y)), normalisées  \n",
    "plt.quiver(T,P,U,V,angles='xy',scale=20,color='cyan')\n",
    "plt.legend(fontsize=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "#### Un modèle d'évolution d'une population de saumons.\n",
    "\n",
    "Le modèle suivant décrit l'évolution du nombre d'individus d'une population de saumons :\n",
    "\n",
    "\\begin{equation}\n",
    "\\begin{cases}\n",
    "P'(t)=(2-\\cos(t))P(t)-\\frac 12 P^2(t)-1,\\\\\n",
    "P(0)=P_0,\n",
    "\\end{cases}\n",
    "\\tag{S}\n",
    "\\end{equation}\n",
    "\n",
    "où $P_0$ est la population à l'instant initial. Le terme positif périodique $2-\\cos(t)$ correspond à un taux de naissances saisonnier. Le modèle suppose que les décès sont proportionnels au carré du nombre d'individus dans la population et le terme indépendante avec signe négatif $-1$ modélise une proportion d'individus péchés.\n",
    "\n",
    "**Question 4.**\n",
    "\n",
    "Utiliser le schéma d'Euler explicite pour obtenir une solution approchée du problème $S$, de donnée initiale $P_0=5,$ dans l'intervalle de temps $[0,10],$ avec un pas $h=0.1.$ Représenter graphiquement la solution obtenue. \n",
    "\n",
    "Représenter dans le même graphique le champ de vecteurs associé au modèle $(S)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.quiver.Quiver at 0x7f978e8646a0>"
      ]
     },
     "execution_count": 170,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 190328 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def fS(t,P):\n",
    "    return (2-np.cos(t))*P-(P**2)/2-1\n",
    "\n",
    "P0=5\n",
    "t0=0\n",
    "T=10\n",
    "h=0.1\n",
    "\n",
    "plt.figure()\n",
    "tt, yy = euler_exp(t0, T, P0, h, fS)\n",
    "plt.plot(tt, yy, label=f'Solution approchée pour h={h}')\n",
    "    \n",
    "plt.title(f\"Solutions approchée du modèle de Verhulst pour une population de saumons\")\n",
    "plt.legend()\n",
    "plt.xlabel('t')\n",
    "plt.ylabel('y')\n",
    "\n",
    "t=np.linspace(t0, T, 35) # abcisse des points de la grille  \n",
    "y=np.linspace(0, 6, 23) # ordonnées des points de la grille  \n",
    "T,P=np.meshgrid(t,y) # grille de points dans le plan (t,y)  \n",
    "U=np.ones(T.shape)/np.sqrt(1+fS(T,P)**2) # matrice avec les composantes horizontales des vecteurs (1), normalisées  \n",
    "V=fS(T,P)/np.sqrt(1+fS(T,P)**2) # matrice avec les composantes verticales des vecteurs (f(t,y)), normalisées  \n",
    "plt.quiver(T,P,U,V,angles='xy',scale=20,color='cyan')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
