{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Intégration numérique avec Julia, une introduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction\n", "Il nous faut tout d'abord importer les bons packages de Julia" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# import Pkg; Pkg.add(\"DifferentialEquations\")\n", "# Pkg.add(\"Plots\")\n", "# import Pkg; Pkg.add(\"ODEInterfaceDiffEq\")\n", "using DifferentialEquations\n", "using Plots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pendule simple\n", "### Introduction\n", "On s'intéresse ici au pendule simple. Les principes physiques de la mécanique classique donnent comme équation qui régit l'évolution du mouvement\n", "$$ ml^2\\ddot{\\alpha}(t)+mlg\\sin(\\alpha(t)) + k\\dot{\\alpha}(t)=0,$$\n", "où $\\ddot{\\alpha}(t)$ désigne la dérivée seconde de l'angle $\\alpha$ par rapport au temps $t$. \n", "\n", "On prend ici comme variable d'état qui décrit le système $x(t)=(x_1(t),x_2(t))=(\\alpha(t), \\dot{\\alpha}(t))$. Le système différentiel du premier ordre que l'on obtient s'écrit alors\n", "$$\n", "\\left\\{\\begin{array}{l}\n", "\\dot{x}_1(t) = x_2(t)\\\\\n", "\\dot{x}_2(t) = -\\frac{g}{l}\\sin(x_1(t))-kx_2(t)\\\\\n", "x_1(0) = x_{0,1}=\\alpha_0\\\\\n", "x_2(0) = x_{0,2}=\\dot{\\alpha}_0\n", "\\end{array}\\right.\n", "$$\n", "### Cas où la fonction second membre renvoie xpoint" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pendule (generic function with 1 method)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function pendule(x,p,t)\n", "# second member of the IVP\n", "# x : state\n", "# real(2)\n", "# p : parameter vector\n", "# t : time, variable not use here\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", " g = p[1]; l = p[2]; k = p[3]\n", " xpoint = similar(x)\n", " xpoint[1] = x[2]\n", " xpoint[2] = -(g/l)*sin(x[1]) - k*x[2]\n", " return xpoint\n", "end\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "g = 9.81; l = 10; k = 0;\n", "p = [g,l,k] # constantes\n", "theta0 = pi/3\n", "t0 = 0.\n", "tf = 3*pi*sqrt(l/g)*(1 + theta0^2/16 + theta0^4/3072) # 2*approximation de la période\n", "tspan = (t0,tf) # instant initial et terminal\n", "x0 = [theta0,0] # état initial\n", "prob = ODEProblem(pendule,x0,tspan,p) # défini le problème en Julia\n", "sol = solve(prob) # réalise l'intégration numérique\n", "plot(sol, label = [\"x_1(t)\" \"x_2(t)\"]) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cas où xpoint est le premier argument modifié de la fonction second membre" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pendule1! (generic function with 1 method)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function pendule1!(xpoint,x,p,t)\n", "# second member of the IVP\n", "# x : state\n", "# real(2)\n", "# p : parameter vector\n", "# t : time, variable not use here\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", " g = p[1]; l = p[2]; k = p[3]\n", " xpoint = similar(x)\n", " xpoint[1] = x[2]\n", " xpoint[2] = -(g/l)*sin(x[1]) - k*x[2]\n", " return nothing\n", "end" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "g = 9.81; l = 10; k = 0;\n", "p = [g,l,k] # constantes\n", "theta0 = pi/3\n", "t0 = 0.\n", "tf = 3*pi*sqrt(l/g)*(1 + theta0^2/16 + theta0^4/3072) # 2*approximation de la période\n", "tspan = (t0,tf) # instant initial et terminal\n", "x0 = [theta0,0] # état initial\n", "prob = ODEProblem(pendule1!,x0,tspan,p) # défini le problème en Julia\n", "sol = solve(prob) # réalise l'intégration numérique\n", "plot(sol, label = [\"x_1(t)\" \"x_2(t)\"]) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'instruction `xpoint = similar(x)` **crée une variable locale xpoint** et on a perdu le paramètre formel `xpoint`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pendule2! (generic function with 1 method)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function pendule2!(xpoint,x,p,t)\n", "# second member of the IVP\n", "# x : state\n", "# real(2)\n", "# p : parameter vector\n", "# t : time, variable not use here\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", " g = p[1]; l = p[2]; k = p[3]\n", " xpoint[1] = x[2]\n", " xpoint[2] = -(g/l)*sin(x[1]) - k*x[2]\n", " return nothing\n", "end" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "g = 9.81; l = 10; k = 0.;\n", "p = [g,l,k] # constantes\n", "theta0 = pi/3\n", "t0 = 0.\n", "tf = 3*pi*sqrt(l/g)*(1 + theta0^2/16 + theta0^4/3072) # 2*approximation de la période\n", "tspan = (t0,tf) # instant initial et terminal\n", "x0 = [theta0,0] # état initial\n", "prob = ODEProblem(pendule2!,x0,tspan,p) # défini le problème en Julia\n", "sol = solve(prob) # réalise l'intégration numérique\n", "plot(sol, label = [\"x_1(t)\" \"x_2(t)\"]) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Diagrammes de phases" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "g = 9.81; l = 10; k = 0.; # si k = 0.15 donc on a un amortissement\n", "p = [g l k]\n", "plot()\n", "for theta0 in 0:(2*pi)/10:2*pi\n", " theta0_princ = theta0\n", " tf = 3*pi*sqrt(l/g)*(1 + theta0_princ^2/16 + theta0_princ^4/3072) # 2*approximation of the period\n", " tspan = (0.0,tf)\n", " x0 = [theta0 0]\n", " prob = ODEProblem(pendule,x0,tspan,p)\n", " sol = solve(prob)\n", " plot!(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) # lw = linewidth\n", "end\n", "theta0 = pi-10*eps()\n", "x0 = [theta0 0]\n", "tf = 70 # problem for tf=50 1/4 of the period!\n", "tspan = (0.0,tf)\n", "prob = ODEProblem(pendule,x0,tspan,p)\n", "sol = solve(prob)\n", "plot!(sol,vars=(1,2), xlims = (-2*pi,4*pi), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) # lw = linewidth\n", "\n", "theta0 = pi+10*eps()\n", "x0 = [theta0 0]\n", "tf = 70\n", "tspan = (0.0,tf)\n", "prob = ODEProblem(pendule,x0,tspan,p)\n", "sol = solve(prob)\n", "plot!(sol,vars=(1,2), xlims = (-2*pi,4*pi), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) # lw = linewidth\n", "\n", "# circulation case\n", "for thetapoint0 in 0:0.2:2 \n", " tf = 10\n", " tspan = (0.,tf)\n", " x0 = [-pi thetapoint0] # thetapoint0 > 0 so theta increases from -pi to ...\n", " prob = ODEProblem(pendule,x0,tspan,p)\n", " sol = solve(prob)\n", " plot!(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) # lw = linewidth\n", "end\n", "for thetapoint0 in -2:0.2:0\n", " tf = 10\n", " tspan = (0.,tf)\n", " x0 = [3*pi thetapoint0] # thetapoint0 < 0 so theta decreases from 3pi to ...\n", " prob = ODEProblem(pendule,x0,tspan,p)\n", " sol = solve(prob)\n", " plot!(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) # lw = linewidth\n", "end\n", "plot!([-pi 0 pi 2*pi 3*pi], [0 0 0 0 0], seriestype=:scatter)\n", "plot!(xlims = (-pi,3*pi))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Modèle de Van der Pol\n", "### Exemple de cycle limite\n", "L'équation différentielle considérée est l'équation de Van der Pol\n", "$$(IVP)\\left\\{\\begin{array}{l}\n", "\\dot{y}_1(t)=y_2(t)\\\\\n", "\\dot{y}_2(t)=(1-y_1^2(t))y_2(t)-y_1(t)\\\\\n", "y_1(0)=2.00861986087484313650940188\\\\\n", "y_2(0)=0\n", "\\end{array}\\right.\n", "$$\n", "$t_f=T=6.6632868593231301896996820305$\n", "\n", "\n", "La solution de ce problème de Cauchy est périodique de période $T$.\n", "\n", "Résoudre et de visualiser la solution pour les points de départ :\n", "- x0 = [2.00861986087484313650940188,0]\n", "- [x01 , 0] pour x01 in -2:0.4:0\n", "- [0 , x02] pour x02 in 2:1:4\n", "\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "vdp (generic function with 1 method)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function vdp(x,p,t)\n", "# Van der Pol model\n", "# second member of the IVP\n", "# x : state\n", "# real(2)\n", "# p : parameter vector\n", "# t : time, variable not use here\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", "# To complete\n", "# xpoint = similar(x)\n", "# xpoint[1] = x[2]\n", "# xpoint[2] = (1-x[1]^2)*x[2] - x[1]\n", " xpoint = [x[2] , (1-x[1]^2)*x[2] - x[1]]\n", " return xpoint\n", "end" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x0 = [2.0086198608748433, 0.0], p = [1], tspan = (0.0, 6.66328685932313)\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "tf = 6.6632868593231301896996820305\n", "tspan = (0.0, tf)\n", "x0 = [2.00861986087484313650940188,0]\n", "mu = 1\n", "p = [mu]\n", "t0 = 0.;\n", "tspan = (t0,tf)\n", "println(\"x0 = $x0, p = $p, tspan = $tspan\")\n", "prob = ODEProblem(vdp,x0,tspan,p)\n", "sol = solve(prob)\n", "plot(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false)\n", "for x01 in -2:0.4:0 #4.5:4.5\n", " x0 = [x01,0]\n", " prob = ODEProblem(vdp,x0,tspan,p)\n", " sol = solve(prob)#,force_dtmin=true)# \n", " plot!(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false) \n", "end\n", "for x02 in 2:1:4\n", " x0 = [0.,x02]\n", " prob = ODEProblem(vdp,x0,tspan,p)\n", " sol = solve(prob)#solve(prob,Tsit5(),reltol=1e-8,abstol=1e-8)\n", " plot!(sol,vars=(1,2), xlabel = \"x_1\", ylabel = \"x_2\", legend = false)\n", "end\n", "plot!([0], [0], seriestype=:scatter) # point visualisation\n", "plot!(xlims = (-2.5,5))\n", " \n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La solution périodique est ici ce qu'on appelle un **cycle limite**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Modèle de Lorentz\n", "## Chaos\n", "$$(IVP)\\left\\{\\begin{array}{l}\n", "\\dot{x}_1(t)=-\\sigma x_1(t)+\\sigma x_2(t)\\\\\n", "\\dot{x}_2(t)=-x_1(t)x_3(t)+rx_1(t)-x_2(t)\\\\\n", "\\dot{x}_3(t)=x_1(t)x_2(t)-bx_3(t)\\\\\n", "x_1(0)=-8\\\\\n", "x_2(0)=8\\\\\n", "x_3(0)=r-1\n", "\\end{array}\\right.\n", "$$\n", "avec $\\sigma=10, r=28, b=8/3$.\n", "\n", "Calculer et visualisé la solution de ce problème\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "lorentz (generic function with 1 method)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function lorentz(x,p,t)\n", "# Lorentz model\n", "# second member of the IVP\n", "# x : state\n", "# real(3)\n", "# p : parameter vector\n", "# t : time, variable not use here\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", "# To complete\n", " sigma = p[1]; rho = p[2]; beta = p[3];\n", " xpoint = similar(x)\n", " xpoint[1] = sigma*(x[2]-x[1])\n", " xpoint[2] = x[1]*(rho-x[3]) - x[2]\n", " xpoint[3] = x[1]*x[2] - beta*x[3]\n", " return xpoint \n", "end" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "xpoint = [160.0, -16.0, -136.0]\n" ] } ], "source": [ "# test de la fonction lorent!\n", "sigma = 10.; rho = 28.; beta = 8/3;\n", "p = [sigma rho beta]\n", "#x0 = [1.1,0.0,0.0]\n", "x0 = [-8, 8, rho-1]\n", "xpoint = x0\n", "xpoint = lorentz(x0,p,0)\n", "println(\"xpoint = $xpoint\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Main\n", "#\n", "x0 = [-8, 8, rho-1]\n", "tspan = (0.0,100.0)\n", "prob = ODEProblem(lorentz,x0,tspan,p)\n", "sol = solve(prob)\n", "plot(sol,vars=(1,2,3), xlabel = \"x_1\", ylabel = \"x_2\", zlabel = \"x_3\", legend = false)\n", "plot!([x0[1]], [x0[2]], [x0[3]], seriestype=:scatter) # point visualisation\n", "#annotate!([x0[1],x0[2],x0[3],text(\". Point de départ\", 10,:left)])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p1 = plot(sol,vars=(0,1),ylabel = \"x_1(t)\", legend = false)\n", "p2 = plot(sol,vars=(0,2),ylabel = \"x_2(t)\", legend = false)\n", "p3 = plot(sol,vars=(0,3),xlabel = \"t\", ylabel = \"x_3(t)\", legend = false)\n", "plot(p1,p2,p3,layout=(3,1))#,legend=false)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Attention à bien utiliser les codes\n", "Nous allons ici résoudre le problème à valeur initiale\n", "$$(IVP)\\left\\{\\begin{array}{l}\n", "\\dot{x}_1(t)=x_1(t)+x_2(t)+\\sin t\\\\\n", "\\dot{x}_2(t)=-x_1(t)+3x_2(t)\\\\\n", "x_1(0)=-9/25\\\\\n", "x_2(0)=-4/25,\n", "\\end{array}\\right.\n", "$$\n", "dont la solution est\n", "\\begin{align*}\n", "x_1(t)&= (-1/25)(13\\sin t+9\\cos t)\\\\\n", "x_2(t)&= (-1/25)(3\\sin t+4\\cos t).\n", "\\end{align*}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "function exemple1(x,p,t)\n", "# second member of the IVP\n", "# Input\n", "# x : state\n", "# real(2)\n", "# p : parameter vector\n", "# t : time\n", "# real\n", "# Output\n", "# xpoint : vector of velocity\n", "# same as x\n", " xpoint = similar(x) # xpoint est un objet de même type que x\n", " xpoint[1] = x[1] + x[2] + sin(t)\n", " xpoint[2] = -x[1] + 3*x[2] \n", "# xpoint = [x[1]+x[2]+sin(t), -x[1] + 3*x[2]]\n", " return xpoint \n", "end\n", "p = []\n", "t0 = 0.; tf = 8\n", "tspan = (t0,tf)\n", "x0 = [-9/25 , -4/25]\n", "prob = ODEProblem(exemple1,x0,tspan,p) # défini le problème en Julia\n", "sol = solve(prob, DP5()) # réalise l'intégration numérique\n", " # avec ode45 de matlab\n", "p1 = plot(sol, label = [\"x_1(t)\" \"x_2(t)\"], title = \"ode45 de Matlab\") #, lw = 0.5) # lw = linewidth\n", "sol = solve(prob, DP5(), reltol = 1.e-6, abstol = 1.e-9)\n", "p2 = plot(sol, label = [\"x_1(t)\" \"x_2(t)\"], title = \"reltol=1.e-6, abstol=1.e-9\") #, lw = 0.5)\n", "sol = solve(prob, DP5(), reltol = 1.e-10, abstol = 1.e-15)\n", "p3 = plot(sol, label = [\"x_1(t)\" \"x_2(t)\"], title = \"reltol=1.e-10, abstol=1.e-16\") #, lw = 0.5)\n", "T = t0:(tf-t0)/100:tf\n", "sinT = map(sin,T) # opération vectorielle\n", "cosT = map(cos,T)\n", "p4 = plot(T,[(-1/25)*(13*sinT+9*cosT) (-1/25)*(3*sinT+4*cosT)], label = [\"x_1(t)\" \"x_2(t)\"], xlabel = \"t\", title = \"Solution exacte\")\n", "plot(p1,p2,p3,p4)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.4.1", "language": "julia", "name": "julia-1.4" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.4.1" } }, "nbformat": 4, "nbformat_minor": 2 }