In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt
import math
import numpy as np
from scipy.integrate import solve_ivp
https://docs.scipy.org/doc/scipy-1.3.0/reference/generated/scipy.integrate.solve_ivp.html#scipy.integrate.solve_ivp (the new API)
https://docs.scipy.org/doc/scipy-1.3.0/reference/tutorial/integrate.html#ordinary-differential-equations-odeint (the old API)
C.f. "Toutes les mathématiques et les bases de l'informatique" de H.Stocker (Dunod) p.745
On pose $y_1 = y'$ et donc $y_1' = y''$.
On obtient alors le système couplé:
$$ \left\{ \begin{array}{ll} y_1' + 5 y_1^2 + 7 y^5 & = 6 x^3 \\ y' - y_1 & = 0 \end{array} \right. $$On pose :
On obtient alors le système couplé:
$$ \left\{ \begin{array}{ll} \color{red}{y_6} + 8x^2 \color{green}{y_4} + \ln y & = 0 \\ y_1 - y' & = 0 \\ y_2 - y_1' & = 0 \\ y_3 - y_2' & = 0 \\ y_4 - y_3' & = 0 \\ y_5 - y_4' & = 0 \\ y_6 - y_5' & = 0 \\ \end{array} \right. $$
In [ ]:
integration_range = [0, 15]
initial_values = [2]
# Define the dependent function f
def f(t, y):
dydt = t-y
return dydt
sol = solve_ivp(f, integration_range, initial_values)
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
In [ ]:
integration_range = [0, 15]
initial_values = [2]
# Define the dependent function f
def f(t, y):
dydt = t-y
return dydt
sol = solve_ivp(f, integration_range, initial_values, dense_output=True)
print(sol)
t = np.linspace(0, 15, 50)
y = sol.sol(t) # <- with dense_output=True, solve_ivp() returned a callable (function) solution instead of a sample (array)
plt.plot(t, y[0], 'o-');
In [ ]:
integration_range = [0, 15]
initial_values = [2]
# Define the dependent function f
def f(t, y):
dydt = t-y
#print(y.shape)
return dydt
sol = solve_ivp(f, integration_range, initial_values,
t_eval = np.linspace(0, 15, 30)) # <--
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
In [ ]:
integration_range = [0, 15]
initial_values = [-1]
def f(t, y):
dydt = -y + np.cos(3. * t)
return dydt
sol = solve_ivp(f, integration_range, initial_values,
t_eval = np.linspace(0, 15, 100))
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
In [ ]:
integration_range = [0, 10]
initial_values = [6]
c = 1.2
# Define the dependent function f
def f(t, y):
dydt = [c]
return dydt
sol = solve_ivp(f, integration_range, initial_values)
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
In [ ]:
integration_range = [0, 4]
initial_values = [6]
# Define the dependent function f
def f(t, y):
dydt = 2. * t**2 - 6. * t + 3.
return dydt
sol = solve_ivp(f, integration_range, initial_values,
t_eval=np.linspace(0, 4, 30))
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
For population growth, the rate of change of population is dependent upon the number of people as well as some constant of proportionality:
$$\frac{\text{d}}{\text{d}t} y(t) = c y(t)$$assuming
$$ \begin{align} y(0) & = 10 \\ c & = 1.02 \end{align} $$for some times between 0 and 3.
In [ ]:
integration_range = [0, 3]
initial_values = [10]
c = 1.02
# Define the dependent function f
def f(t, y):
dydt = c * y
return dydt
sol = solve_ivp(f, integration_range, initial_values,
t_eval=np.linspace(0, 3, 30))
print(sol)
plt.plot(sol.t, sol.y[0], 'o-');
Solve:
$$ \left\{ \begin{align} \frac{\text{d}}{\text{d}t} y_0(t) & = 4 \cos(3t) \\ \frac{\text{d}}{\text{d}t} y_1(t) & = -2 y_0(t) + 0.5 t \end{align} \right. $$assuming
$$ \begin{align} y_1(0) & = 0 \\ y_2(0) & = -3 \end{align} $$for some times between 0 and 5.
In [ ]:
integration_range = [0, 5]
initial_values = [0, -3]
# Define the dependent function f
def f(t, y):
dy1dt = 4. * math.cos(3. * t)
dy2dt = -2. * y[0] + 0.5 * t
return [dy1dt, dy2dt]
sol = solve_ivp(f, integration_range, initial_values,
t_eval=np.linspace(0, 5, 50))
print(sol)
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16, 4))
ax1.plot(sol.t, sol.y[0], 'o-', label="y1")
ax1.legend()
ax2.plot(sol.t, sol.y[1], 'o-', label="y2")
ax2.legend();
Solve:
$$ \frac{\text{d}^3}{\text{d}t^3} y(t) = c $$This third-order equation can be rewritten as a system of three first-order differential equations:
$$ \left\{ \begin{align} y_0 = y \\ \frac{\text{d}}{\text{d}t}y_0(t) & = \frac{\text{d}}{\text{d}t}y(t) = y_1 \\ \frac{\text{d}}{\text{d}t}y_1(t) & = \frac{\text{d}^2}{\text{d}t^2} y_0(t) = \frac{\text{d}^2}{\text{d}t^2} y(t) = y_2 \\ \frac{\text{d}}{\text{d}t}y_2(t) & = \frac{\text{d}^2}{\text{d}t^2} y_1(t) = \frac{\text{d}^3}{\text{d}t^3} y_0(t) = \frac{\text{d}^3}{\text{d}t^3} y(t) = c \\ \end{align} \right. $$$$ \Leftrightarrow \left\{ \begin{align} y_0 = y \\ \frac{\text{d}}{\text{d}t} y_0(t) & = y_1 \\ \frac{\text{d}}{\text{d}t} y_1(t) & = y_2 \\ \frac{\text{d}}{\text{d}t} y_2(t) & = c \\ \end{align} \right. $$assuming
$$ \begin{align} y_1(0) & = 6 \\ y_2(0) & = 2 \\ y_3(0) & = -4 \end{align} $$i.e.
and a constant acceleration of 1.3 over a period of 8 seconds.
In [ ]:
integration_range = [0, 8]
initial_values = [6, 2, -4]
c = 1.3
# Define the dependent function f
def f(t, y):
dy1dt = y[1]
dy2dt = y[2]
dy3dt = c
return [dy1dt, dy2dt, dy3dt]
sol = solve_ivp(f, integration_range, initial_values,
t_eval=np.linspace(0, 8, 50))
print(sol)
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(14, 4))
ax1.plot(sol.t, sol.y[0], 'o-', label="y1")
ax1.legend()
ax2.plot(sol.t, sol.y[1], 'o-', label="y2")
ax2.legend();
ax3.plot(sol.t, sol.y[2], 'o-', label="y3")
ax3.legend();
In [ ]:
integration_range = [5, 10]
initial_values = [1]
c = 1.2
# Define the dependent function f
def f(t, y):
dydt = [c]
return dydt
res = solve_ivp(f, integration_range, initial_values, t_eval=np.linspace(5, 10, 10))
print(res)
plt.plot(res.t, res.y[0], 'o-');
Here, we can see that scipy considers that the actual initial value $y(0) = 1$ is not for $t=0$ but for the start of the time span !