239
Функция odeint() возвращает массив размера len(t) x len(y0).
Функция odeint() имеет много опций, управляющих ее работой. Опции
rtol (относительная погрешность) и atol (абсолютная погрешность)
определяют погрешность вычислений ei для каждого значения yi по формуле
e i rtol yi atol . Они могут быть векторами или скалярами. По умолчанию
rtol=atol=1.49012e-8.
Договоримся, что в начале всех примеров этого параграфа выполняется
следующее импортирование модулей и функций.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
Пример. Рассмотрим задачу Коши y 5t 3 y , y(1.5) 0.01 .
Создадим функцию, реализующую правую часть уравнения.
def dydt(y, t):
return -5*t**3*y
Вызываем солвер и строим график.
t = np.linspace(-1.5,1.5,31) # вектор моментов времени
y0 = 0.01 # начальное значение
y = odeint(dydt, y0, t) # решение уравнения
y = np.array(y).flatten() # преобразование массива
plt.plot(t, y,'-sr',linewidth=3 ) # построение графика
241
искомых функций, а второй – именем независимой переменной, даже если он
не используется при формировании функции.
def f(y, t):
y1, y2 = y # вводим имена искомых функций
return [y2,-0.2*y2-y1]
Решаем систему ОДУ.
t = np.linspace(0,20,41)
y0 = [0, 1]
w = odeint(f, y0, t)
w
array([[ 0. , 1. ],
[ 0.45623694, 0.79029901],
[ 0.76275767, 0.41642039],
[ 0.86239266, -0.01890162],
. . . . . . . . . . . .
[ 0.07506831, 0.1135842 ],
[ 0.11799752, 0.05551654]])
Первый столбец представляет значения функции y1 t , а второй – значения
функции y2 t в точках вектора t.
Выделяем вектора y1 и y2 из результирующей матрицы.
y1=w[:,0] # вектор значений решения
y2=w[:,1] # вектор значений производной
Строим график решения (значения искомой функции находятся в первом
столбце матрицы w, т.е. в векторе y1)
fig = plt.figure(facecolor='white') # следующий рисунок слева
plt.plot(t,y1, ' -o',linewidth=2)
plt.ylabel("z")
plt.xlabel("t")
plt.grid(True)
242
Чтобы сразу получит вектора решений y1 и y2 командой
[y1,y2]=odeint(...).T , мы использовали опцию full_output=False. Если
full_output=True, то функция odeint() возвращает дополнительную
информацию в форме словаря (см. справочную систему), и тогда операция
транспонирования не будет работать, точнее ее нужно применять к первому
элементу результата.
Пример. Решим дифференциальное уравнение y 2 на отрезке a; 100 с
1
t
начальными условиями ya ln a , ya 1/ a при a=0.001. Его точное
решение y ln t .
Приведем задачу к системе ОДУ первого порядка и решим ее с
относительной погрешностью rtol=0.5·10-4, 10-6, 10-8 (абсолютная погрешность
atol задана по умолчанию). Потом решим задачу с относительной
погрешностью rtol, заданной по умолчанию, и различными значениями
абсолютной погрешности atol=10-2,10-3,10-4. Построим графики
приближенных решений и график точного решения.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
a=0.001
y0=[log(a),1/a]
x = np.linspace(a,100,200)
z=np.log(x) # точное решение
fig = plt.figure(facecolor='white')
plt.hold(True)
reltol=[0.5e-4,1e-6,1e-8]
for tol in reltol:
[y1,y2]=odeint(f, y0, x, f ull_output=False, rtol=tol).T
plt.plot(x,y1,linewidth=2) # следующий рисунок слева
plt.plot(x,z,'k',linewidth=1) # график точного решения.
plt.grid(True)
fig = plt.figure(facecolor='white')
plt.hold(True)
abstol=[1e-2,1e-3,1e-4]
for tol in abstol:
[y1,y2]=odeint(f, y0, x, full_output=False, atol=tol).T
plt.plot(x,y1,linewidth=2) # следующий рисунок справа
plt.plot(x,z,'k',linewidth=1) # график точного решения.
243
plt.grid(True)
245
'cubic', а также быть целым положительным числом (порядок
интерполяционного сплайна). Вот простой пример.
from scipy.interpolate import interp1d
x = np.linspace(0, 12, num=13, endpoint=True)
y = np.sin(x)**2 # массив значений
f = interp1d(x, y,kind='cubic') # кубическая сплайн интерполяция
xx=np.linspace(0, 12, num=49, endpoint=True) # новый набор точек
fig = plt.figure(facecolor='white')
plt.plot(x, y, '-or', xx, f(xx),'--b',linewidth=3) # ломаная и сплайн
t = np.linspace(0,100,501)
y0 = [0, 2.1]
[y1,y2]=odeint(f, y0, t, full_output=False).T
fig = plt.figure(facecolor='white')
plt.plot(t,y1, linewidth=2) # график решения x(t) слева
plt.grid(True)
fig = plt.figure(facecolor='white')
plt.plot(y1,y2,linewidth=2) # фазовая траектория справа
plt.grid(True)
Для решения задачи выполните следующие команды
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
fun() # вызов основной функции
На левом рисунке показан график решения x(t), а на правом – фазовая
траектория.
246
■
Пример. Исследуем двухвидовую модель «хищник – жертва», впервые
построенную Вольтерра для объяснения колебаний рыбных уловов. Имеются
два биологических вида, численностью в момент времени t соответственно
x(t) и y(t). Особи первого вида являются пищей для особей второго вида
(хищников). Численности популяций в начальный момент времени известны.
Требуется определить численность видов в произвольный момент времени.
Математической моделью задачи является система дифференциальных
уравнений Лотки – Вольтерра
dx
dt a b y x
dy c d x y
dt
где a, b, c, d – положительные константы. Проведем расчет численности
популяций при a 3, c 1, d 1 для трех значений параметра b 4, 3, 2 .
Начальные значения положим x(0) 2, y(0) 1 .
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def f(y, t,params):
y1, y2 = y
a,b,c,d=params
return [y1*(a-b*y2),y2*(-c+d*y1)]
t = np.linspace(0,7,71)
y0 = [2, 1]
fig = plt.figure(facecolor='white')
plt.hold(True)
plt.legend(fontsize=12)
plt.grid(True)
plt.xlim(0,3)
247
plt.ylim(0,3)
t = np.linspace(0,7,71)
ic = np.linspace(1.0, 3.0, 11) # начальные значения для 1-й функции
fig = plt.figure(facecolor='white')
for r in ic:
y0 = [r, 1.0]
y = odeint(f, y0, t,args=([3,3,1,1],))
plt.plot(y[:,0],y[:,1],linewidth=2)
plt.grid(True) # следующий рисунок слева
248
Пример. Решим систему дифференциальных уравнений
0.1 y x z 1 x 3 ,
dx dy dz
y, x y 0.1 z
dt dt dt
с начальными условиями x(0) 1, y(0) 1, z (0) 0 и построим ее фазовый
портрет. Отличие от предыдущих задач состоит в том, что фазовая кривая
расположена в трехмерном пространстве.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D