Skip to content
Snippets Groups Projects
Commit dfb1c2e1 authored by Olivier Cots's avatar Olivier Cots
Browse files

add tp1

parent c98ffa6b
No related branches found
No related tags found
No related merge requests found
...@@ -10,7 +10,7 @@ Cours de contrôle optimal de l'ENSEEIHT pour le département Sciences du Numér ...@@ -10,7 +10,7 @@ Cours de contrôle optimal de l'ENSEEIHT pour le département Sciences du Numér
**TP** **TP**
* TBD * [TP1 - Intégration numérique](tp/ode-etu.ipynb)
**Notes de cours - ressources** **Notes de cours - ressources**
......
%% Cell type:markdown id: tags:
# Intégration numérique avec Julia, une introduction
%% Cell type:markdown id: tags:
## Introduction
Pour la documentation voir
[documentation de DifferentialEquations.jl](https://diffeq.sciml.ai/stable/)
Il nous faut tout d'abord importer les bons packages de Julia.
%% Cell type:code id: tags:
``` julia
using DifferentialEquations
using Plots
```
%% Cell type:markdown id: tags:
## Exemple 1
Nous allons ici résoudre le problème à valeur initiale
$$(IVP)\left\{\begin{array}{l}
\dot{x}_1(t)=x_1(t)+x_2(t)+\sin t\\
\dot{x}_2(t)=-x_1(t)+3x_2(t)\\
x_1(0)=-9/25\\
x_2(0)=-4/25,
\end{array}\right.
$$
- Ecrire la fonction $f$ qui permet d'écrire l'équation différentielle sous la forme $\dot{x}(t)=f(t,x(t))$.
- Vérifier que la solution de $(IVP$ est
$$\begin{align*}
x_1(t)&= (-1/25)(13\sin t+9\cos t)\\
x_2(t)&= (-1/25)(3\sin t+4\cos t).
\end{align*}$$
- Coder la fonction $f$ et exécuter le code ci-dessous. Commentaires ?
%% Cell type:code id: tags:
``` julia
# Remarque :
# un problème IVP est une équation différentielle ordinaire
# (EDO en français, ODE en anglais)
# avec en plus une condition initiale.
function exemple1(x,p,t)
# Second membre de l'IVP
# p : vecteur de paramètres
# t : variable de temps
xpoint = similar(x)
# A COMPLETER/MODIFIER
xpoint = zeros(size(x))
return xpoint
end
p = [] # pas de paramètres
t0 = 0
tf = 10
tspan = (t0, tf) # intervalle d'intégration
x0 = [-9/25, -4/25] # condition initiale
prob = ODEProblem(exemple1, x0, tspan, p) # définition du problème IVP
sol = solve(prob) # résolution du problème IVP
p1 = plot(sol, label = ["x₁(t)" "x₂(t)"], title = "default options") # affichage de la solution
```
%% Cell type:markdown id: tags:
## Le contrôle du pas
Les bons intégrateurs numériques ont une mise à jour automatique du pas. Pour les
[méthodes de Runge-Kutta](https://fr.wikipedia.org/wiki/Méthodes_de_Runge-Kutta)
par exemple, sur un pas $[t_0, t_{1}]$ on calcule par 2 schémas différents deux solutions approchées à l'instant $t_{1}$ : $x_{1}$ et $\hat{x}_{1}$ dont l'erreur locale est respectivement en $O(h^p)$ et $O(h^{p+1})$ (les erreurs globales sont elles en $O(h^{p-1})$ et $O(h^p)$). Ainsi on peut estimer l'erreur locale du schéma le moins précis à l'aide de la différence $x_{1}-\hat{x}_{1}$. On peut alors estimer le pas de façon à avoir la norme de cette différence inférieure à une tolérance donnée `Tol` ou encore à avoir
$$\frac{\|x_{1}-\hat{x}_{1}\|}{\mathrm{Tol}}<1.$$
En pratique on considère des tolérences absolue et relative composante par composante et on définit : $sc_i = \mathrm{Atol}_i + \max(|x_{0i}|,|x_{1i}|)\, \mathrm{Rtol}_i$. On calcule alors le pas de façon à avoir
$$err = \sqrt{\frac{1}{n}\sum_{i=1}^n\left(\frac{x_{1i}-\hat{x}_{1i}}{sc_i}\right)^2}<1.$$
Référence : [Hairer, Nørsett, Wanner (2008) Solving Ordinary Differential Equations I Nonstiff Problems](https://link.springer.com/book/10.1007/978-3-540-78862-1).
Dans `Julia`, on peut modifier les valeurs par défaut : reltol = 1.e-3 et abstol = 1.e-6
(lorsque ces valeurs sont des scalaires, on considère les mêmes quantités pour toutes les composantes).
Réaliser l'intégration numérique pour
- reltol = 1e-3 et abstol = 1e-6
- reltol = 1e-6 et abstol = 1e-9
- reltol = 1e-10 et abstol = 1e-15
et afficher les résultats en ajoutant la solution.
%% Cell type:code id: tags:
``` julia
sol = solve(prob, reltol = 1e-3, abstol = 1e-6)
p1 = plot(sol, label = ["x₁(t)" "x₂(t)"], title = "reltol=1e-3, abstol=1e-6") # lw = linewidth
#
# A COMPLETER/MODIFIER
p2 = plot()
p3 = plot()
#
T = t0:(tf-t0)/100:tf
sinT = sin.(T) # opération vectorielle
cosT = cos.(T)
p4 = plot(T,[(-1/25)*(13*sinT+9*cosT) (-1/25)*(3*sinT+4*cosT)], label = ["x₁(t)" "x₂(t)"], title = "Solution exacte")
plot(p1,p2,p3,p4, size=(900, 600))
```
%% Cell type:markdown id: tags:
## Pendule simple
### Introduction
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
$$ ml^2\ddot{\alpha}(t)+mlg\sin(\alpha(t)) +k\dot{\alpha}(t)=0,$$
où $\ddot{\alpha}(t)$ désigne la dérivée seconde de l'angle $\alpha$ par rapport au temps $t$.
- En prenant comme variable d'état $x=(x_1,x_2)=(\alpha, \dot{\alpha})$, écrire la fonction $f$ qui permet d'écrire l'équation différentielle sous la forme $\dot{x}(t) = f(t,x(t))$
- Coder cette fonction ci-dessous et exécuter le code. D'après-vous, observez-vous une oscillation ou une rotation du pendule ?
%% Cell type:code id: tags:
``` julia
```
%% Cell type:code id: tags:
``` julia
function pendule(x,p,t)
# Second membre de l'IVP
# p : vecteur de paramètres
# t : variable de temps. Ici le temps n'intervient pas explicitement.
xpoint = similar(x)
# A COMPLETER/MODIFIER
xpoint = zeros(size(x))
return xpoint
end
#
g = 9.81; l = 10; k = 0; m = 1;
p = [g, l, k, m] # paramètres constants
theta0 = pi/3
x0 = [theta0, 0] # état initial
t0 = 0.
tf = 3*pi*sqrt(l/g)*(1 + theta0^2/16 + theta0^4/3072) # 2*approximation de la période
tspan = (t0, tf) # instant initial et terminal
prob = ODEProblem(pendule,x0,tspan,p) # défini le problème en Julia
sol = solve(prob) # réalise l'intégration numérique
plot(sol, label = ["x₁(t)" "x₂(t)"]) # affichage de la solution
```
%% Cell type:markdown id: tags:
## Diagramme de phases
- Exécutez le code et interprétez le graphique.
- On considère le cas où $k=0.15$ (on introduit un frottement). Que se passe-t-il ?
%% Cell type:code id: tags:
``` julia
#
g = 9.81; l = 1.5; k = 0; m = 1;
p = [g, l, k, m] # paramètres constants
plot()
for theta0 in 0:(2*pi)/10:2*pi
theta0_princ = theta0
tf = 3*pi*sqrt(l/g)*(1 + theta0_princ^2/16 + theta0_princ^4/3072) # 2*approximation of the period
tspan = (0.0,tf)
x0 = [theta0 0]
prob = ODEProblem(pendule, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlabel = "x1", ylabel = "x2", legend = false, lw = 0.5, color="blue") # lw = linewidth
end
theta0 = pi-10*eps()
x0 = [theta0 0]
tf = 50 # problem for tf=50 1/4 of the period!
tspan = (0.0,tf)
prob = ODEProblem(pendule, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlims = (-2*pi,4*pi), xlabel = "x1", ylabel = "x2", legend = false, lw = 0.5, color="green") # lw = linewidth
theta0 = pi+10*eps()
x0 = [theta0 0]
tf = 50
tspan = (0.0,tf)
prob = ODEProblem(pendule, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlims = (-2*pi,4*pi), xlabel = "x1", ylabel = "x2", legend = false, lw = 0.5, color="green") # lw = linewidth
# circulation case
for thetapoint0 in 0:1.:4
tf = 10
tspan = (0.,tf)
x0 = [-pi thetapoint0] # thetapoint0 > 0 so theta increases from -pi to ...
prob = ODEProblem(pendule, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlabel = "x1", ylabel = "x2", legend = false, lw = 0.5, color="red") # lw = linewidth
end
for thetapoint0 in -4:1.:0
tf = 10
tspan = (0.,tf)
x0 = [3*pi thetapoint0] # thetapoint0 < 0 so theta decreases from 3pi to ...
prob = ODEProblem(pendule, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlabel = "x1", ylabel = "x2", legend = false, lw = 0.5, color="purple") # lw = linewidth
end
plot!([-pi 0 pi 2*pi 3*pi], [0 0 0 0 0], seriestype=:scatter)
plot!(xlims = (-pi,3*pi), size=(900, 600))
```
%% Cell type:markdown id: tags:
## Modèle de Van der Pol
### Exemple de cycle limite
L'équation différentielle considérée est l'équation de Van der Pol
$$(IVP)\left\{\begin{array}{l}
\dot{y}_1(t)=y_2(t)\\
\dot{y}_2(t)=(1-y_1^2(t))y_2(t)-y_1(t)\\
y_1(0)=2.00861986087484313650940188\\
y_2(0)=0
\end{array}\right.
$$
jusqu'au temps $t_f=T=6.6632868593231301896996820305$, où $T$ est la période de la solution.
Résolvez et visualisez la solution pour les points de départ :
- x0 = [2.00861986087484313650940188,0]
- [x01 , 0] pour x01 dans -2:0.4:0
- [0 , x02] pour x02 dans 2:1:4
%% Cell type:code id: tags:
``` julia
function vdp(x,p,t)
# Van der Pol model
# second member of the IVP
# x : state
# real(2)
# p : parameter vector
# t : time, variable not use here
# real
# Output
# xpoint : vector of velocity
# same as x
xpoint = similar(x)
# A COMPLETER/MODIFIER
xpoint = zeros(size(x))
return xpoint
end
#
t0 = 0.;
tf = 6.6632868593231301896996820305
tspan = (t0, tf)
mu = 1; p = [mu]
plot()
# Trajecctoires intérieures
for x01 in -2:0.4:0
x0 = [x01,0]
prob = ODEProblem(vdp, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlabel = "x₁(t)", ylabel = "x₂(t)", legend = false, color = "blue")
end
# Trajecctoires extérieures
for x02 in 2.5:0.5:4
x0 = [0.,x02]
prob = ODEProblem(vdp, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol,vars=(1,2), xlabel = "x₁(t)", ylabel = "x₂(t)", legend = false, color = "green")
end
# Trajecctoires périodique
x0 = [2.00861986087484313650940188,0]
prob = ODEProblem(vdp, x0, tspan, p, reltol = 1.e-8, abstol = 1.e-8)
sol = solve(prob)
plot!(sol, vars=(1,2), xlabel = "x₁(t)", ylabel = "x₂(t)", legend = false, color = "red", lw = 2.)
#
plot!([0], [0], seriestype=:scatter) # point visualisation
plot!(xlims = (-2.5,5), size=(900, 600))
```
%% Cell type:markdown id: tags:
## Flots en dimension 2
### Flot des extrémales pour le problème de contrôle optimal
On considère le problème de contrôle optimal suivant:
$$ \frac{1}{2}\int_0^{1} u^2(t)\,\mathrm{d}t \to \min, $$
sous les contraintes
$$ \dot{x}(t) = -x(t) + u(t)$$
$$ x(0)=x_0=-1,\quad x(1)=0. $$
Le but est ici de tracer les extrémales et le flot associé pour des points initiaux $z(0) = (x_0, p(0))$.
%% Cell type:code id: tags:
``` julia
function plot_traj!(plt, F, z0, tf)
"""
Plot the trajectories in the phase plan of the ode ż(t)=F(z(t)),
for the initial points given in the z0, until the time tf.
-------
parameters (input)
------------------
plt : plot object
F : function F(z)
z0 : vector of vector of initial points
z0[i] = ith initial point
tf : final time
returns
-------
nothing
"""
tspan = (0 , tf)
for i ∈ 1:length(z0)
prob = ODEProblem((z, _, _) -> F(z), z0[i], tspan, []) # défini le problème en Julia
sol = solve(prob)
plot!(plt, sol, vars = (1,2), legend = false, color = :blue)
end
return nothing
end;
```
%% Cell type:code id: tags:
``` julia
function plot_flow!(plt, F, z0, tf)
"""
For times t ∈ range(0, tf, 4), plot the solution at time t of the Cauchy
problems ż(s) = F(z(s)), z(0) = z0[i].
-------
parameters (input)
------------------
plt : plot object
F : function F(z)
z0 : vector of vector of initial points
z0[i] = ith initial point
tf : final time
returns
-------
nothing
"""
tspan = (0, tf)
T = range(0, tf, length=4)
for i ∈ 1:length(z0)
prob = ODEProblem((z, _, _) -> F(z), z0[i], tspan, []) # défini le problème en Julia
sol = solve(prob)
for t in T
plot!(plt, [sol(t)[1]], [sol(t)[2]], seriestype = :scatter, legend = false,
markerstrokecolor = :green, markersize = 1)
end
end
return nothing
end;
```
%% Cell type:markdown id: tags:
On note $z = (x, p)$ la paire état, état adoint. On note $F(t, z)$ le système hamiltonien donné par le PMP, c-a-d:
$$
F(t, z) = (\frac{\partial H}{\partial p}(t, z, u(z)), -\frac{\partial H}{\partial x}(t, z, u(z)))
$$
où $u(z)$ est le contrôle maximisant.
- Codez ci-dessous la fonction $F$ et visualiser son flot.
- Visualisez l'extrémale la plus proche de la solution.
%% Cell type:code id: tags:
``` julia
function F(z)
zpoint = similar(z)
# A COMPLETER/MODIFIER
zpoint = zeros(size(z))
return zpoint
end
t0 = 0
tf = 1
# initialize plot
plt = plot()
ymin = -0.2
ymax = 2.5
# plot some trajectories
z0 = [[-1, p0] for p0 ∈ range(ymin, ymax, length=50)]
plot_traj!(plt, F, z0, tf)
# plot some endpoints of the flow
z0 = [[-1, p0] for p0 ∈ range(ymin, ymax, length=200)]
plot_flow!(plt, F, z0, tf)
# additional plots
plot!(plt, xlims = (-1.2, 2), ylims = (ymin, ymax))
plot!(plt, [-1, -1], [ymin, ymax], linestyle = :dot, color = :black)
plot!(plt, [0, 0], [ymin, ymax], linestyle = :dot, color = :black, size=(900, 600), xlabel = "x", ylabel = "p")
```
%% Cell type:markdown id: tags:
### Flot des extrémales pour le problème de conrôle optimal
On considère le problème de contrôle optimal suivant:
$$ \frac{1}{2}\int_0^{1} u^2(t)\,\mathrm{d}t \to \min, $$
sous les contraintes
$$ \dot{x}(t) = -x(t) + \alpha x^2(t) + u(t)$$
$$ x(0)=x_0=-1,\quad x(1)=0. $$
Le but est ici de tracer les extrémales et le flot associé pour des points initiaux $z(0) = (x_0, p(0))$.
%% Cell type:code id: tags:
``` julia
function F(z)
α = 1.5
zpoint = similar(z)
zpoint[1] = -z[1] + α*z[1]^2 + z[2]
zpoint[2] = (1. - 2*α*z[1])*z[2]
return zpoint
end
t0 = 0
tf = 1
# initialize plot
plt = plot()
ymin = -0.2
ymax = 2.5
# plot some trajectories
z0 = [[-1, p0] for p0 ∈ range(ymin, ymax, length=50)]
plot_traj!(plt, F, z0, tf)
# plot some endpoints of the flow
z0 = [[-1, p0] for p0 ∈ range(ymin, ymax, length=200)]
plot_flow!(plt, F, z0, tf)
# additional plots
plot!(plt, xlims = (-1.2, 2), ylims = (ymin, ymax))
plot!(plt, [-1, -1], [ymin, ymax], linestyle = :dot, color = :black)
plot!(plt, [0, 0], [ymin, ymax], linestyle = :dot, color = :black, size=(900, 600), xlabel = "x", ylabel = "p")
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment