Uploaded by asatanin

Уравнение дюффинга

advertisement
Lab_work
8 февраля 2021 г.
В данной работе проводится качественный анализ поведения нелинейного осциллятора. Осциллятор Дуффинга является классическим примером нелинейной системы, наглядно иллюстрирующий возникновение хаотического движения. Уравнение в общем случае имеет вид:
ẍ + 2γ ẋ + ω 2 x + βx3 = F cos(Ωt)
(1)
1 Уравние Дуффинга
Рассматривая линейные системы вида
2γ ẋ + ω 2 x + ẍ = 0,
можно объяснить лишь узкий спектр явлений происходящих в природе. В общем случае система подчинается нелинейной системе дифференциальных уравнений. Однако важные результаты можно получить и на примере уравнения (2) путем учета зависимости собственной частоты
от амплитуды колебаний. Получим:
ω 2 x αx2 + 1 + γ ẋ + ẍ = 0.
Уравнение вида (3) с кубической нелинейностью может описывать, например, математический
маятник при небольших углах отклонения, груз и пружину с нелинейной жесткостью, частицу
αx2
βx4
в поле с потенциалом U =
+
и т.д.
2
4
2
Свободные колебания
Начнем анализ с исследования свободной системы, описываемой уравнением
ẍ + γ ẋ + ω 2 x + βx3 = 0.
Сделаем следующую замену: ẋ = y. Тогда уравнение (4) запишется в виде:
ẋ =
y
ẏ = − βx3 − ω 2 x − γy
Эта система двух дифференциальных уравнений первого порядка однозначно задает движение
осциллятора в момент времени t при заданных начальных условиях. Фазовое пространство
представляет собой плоскость
1
2.1 Положения равновесия
Положения равновесия определятся следующей системой алгебраических уравнений:
0=
y
3
0 = − βx − ω 2 x − γy
Решая данную систему уравнений, получаем:
P1 : { x =
s0, y = 0} )
(
ω2
P2 : x = i
,y = 0
γ
s
)
(
ω2
,y = 0 .
P3 : x = −i
γ
Заметим, что три положения равновесия существуют лишь тогда, когда ω и γ будут разных
знаков. При стремлении значений параметра β к нулю (переход к линейному осциллятору)
точки P2 и P3 уходят в ±∞ и остается только одно положение равновесия.
Поясним выше сказанное на примере консервативной системы с уравнением:
βx3 + ω 2 x + ẍ = 0
2 2
4
2
Ей соответствует гамильтониан вида: H = ω 2u + u4 + v2 . Поскольку решения лежат на линиях
уровня H, изобразим фазовый портрет:
[1]: #%matplotlib notebook
import numpy as np
import cmath as cm
import matplotlib.pyplot as plt
list1 = np.arange(-0.20, -0.16, 0.05)
list2 = np.arange(0, 1.2, 0.2)
listt = list1 + list2
omega = -2
def H(u, v, omega):
return -u**2 * omega**2 / 2 + u**4 / 4 + v**2 / 2
u = np.linspace(-4, 4, 100)
v = np.linspace(-4, 4, 100)
X, Y = np.meshgrid(u, v)
Z = H(X, Y, omega)
#plt.figure(figsize=(10,8), dpi=150)
plt.figure()
plt.xlabel('$x$')
2
plt.ylabel('$p$')
plt.contour(X, Y, Z, listt, colors='black')
plt.scatter(0, 0, c='r')
plt.scatter(np.real(1j * cm.sqrt(omega/1.0)), 0, c='r')
plt.scatter(-np.real(1j * cm.sqrt(omega/1.0)), 0, c='r')
plt.title('beta = 1, omega = ' + str(omega))
plt.autoscale()
plt.show()
2.2 Характер положений равновесия
Исследуем характер положений равновесия следующей системы в зависимости от параметров
осциллятора:
0=
y
.
3
0 = − βx − ω 2 x − γy
Для решения поставленной задачи последовательно линеаризуем систему в окрестности каж-
3
дого из положений равновесия P1 и P2 (P3 аналогично):
ẋ =
y
P1 :
2
ẏ = −ω x − γy
u̇ =
v
P2 :
v̇ = 2ω 2 u − γv
где u = x − i
q
.
ω2
β , v = y. Корни характеристического уравнения имеют вид:
r
γ2
− ω,
2 r 4
γ2
γ
P2 : λ21,2 = − ±
+ 2ω.
2
4
γ
P1 : λ11,2 = − ±
Рассмотрим только грубые положения равновесия (поведение фазовых траекторий в окрестности грубого положения равновесия качественно совпадает с поведением фазовых траекторий
линеаризованной системы в этой точке).
2.2.1 Случай A: sign (ω 2 β > 0)
Существует только одно положение равновесия в соответствие с (4).
2.2.2 I) β < 0, ω 2 < 0.
λ11 Re > 0, λ12 Re < 0 ⇒ положение равновесия типа седло. Рассуждение справедливо для любых
γ.
[2]: from matplotlib.widgets import Slider
Y, X = np.mgrid[-1:1:150j, -1:1:150j]
gamma = 0.1
U = Y
V = lambda gamma: gamma * Y + 1 * X + 1 * X**3
title = '$\omega^2 = \\beta = - 1, \gamma$ = {:.3f}'
def draw_streamplot(gamma, ax):
stream = ax.streamplot(X, Y, U, V(gamma), color=U, linewidth=1, cmap=plt.cm.
,→coolwarm, density=1)
ax.scatter(0, 0, c='r')
ax.set_xlabel('$x$')
ax.set_ylabel('$p$')
ax.set_title(title.format(gamma))
ax.autoscale()
return stream
4
def update(val):
ax.cla()
draw_streamplot(val,ax)
fig.canvas.draw_idle()
fig, ax = plt.subplots()
stream = draw_streamplot(gamma, ax)
ax.figure.colorbar(stream.lines, ax=ax)
fig.subplots_adjust(top=0.8)
axcolor = 'lightgoldenrodyellow'
bbox = ax.get_position()
axbeta = fig.add_axes([bbox.x0, bbox.y1+0.1, bbox.width, 0.03],␣
,→facecolor=axcolor)
sbeta = Slider(axbeta, 'gamma', 0.0, 2.0, valinit=gamma, valstep=0.1)
sbeta.on_changed(update)
plt.show()
5
2.2.3 II) β > 0, ω 2 > 0.
γ ∈ (−∞, −2ω ) - неустойчивый узел
γ ∈ (−2ω, 0) - неустойчивый фокус
γ ∈ (0, 2ω ) - устойчивый фокус
γ ∈ (2ω, +∞) - устойчивый узел
[3]: #plt.figure(figsize=(10,8), dpi=150)
plt.figure()
Y, X = np.mgrid[-1:1:150j, -1:1:150j]
gamma = 0.5
U = Y
V = -gamma * Y - 1 * X - 1 * X**3
plt.streamplot(X, Y, U, V, color=U, linewidth=1, cmap=plt.cm.coolwarm, density=2)
plt.scatter(0, 0, c='r')
plt.colorbar();
if gamma < -2:
plt.text(0.3, 0.5, 'Неустойчивый узел', color='blue', fontsize=11)
if -2 < gamma < 0:
plt.text(0.3, 0.5, 'Неустойчивый фокус', color='blue', fontsize=11)
if 0 < gamma < 2:
plt.text(0.3, 0.5, 'Устойчивый фокус', color='blue', fontsize=11)
if gamma > 2:
plt.text(0.3, 0.5, 'Устойчивый узел', color='blue', fontsize=11)
plt.xlabel('x')
plt.ylabel('p')
plt.title('$ \\beta = \omega^2 = 1, \gamma = $' + str(gamma))
plt.autoscale()
plt.show()
6
2.2.4 Случай Б: sign (ω 2 β < 0)
Существует 3 положения равновесия в соответствии с (4).
2.2.5 I) β < 0, ω 2 > 0.
P1 : неустойчивый узел
γ ∈ (−∞, −2ω ) :
P2 :
седло
P1 : неустойчивый фокус
γ ∈ (−2ω, 0) :
седло
P2 :
P1 : устойчивый фокус
γ ∈ (0, 2ω ) :
P2 :
седло
P1 : устойчивый узел
γ ∈ (2ω, +∞) :
P2 :
седло
.
[4]: #plt.figure(figsize=(10,8), dpi=150)
plt.figure()
Y, X = np.mgrid[-2:2:150j, -2:2:150j]
gamma = -3
U = Y
V = -gamma * Y - 1 * X + 1 * X**3
7
plt.streamplot(X, Y, U, V, color=U, linewidth=1, cmap=plt.cm.coolwarm, density=2)
plt.scatter(0, 0, c='r')
plt.colorbar()
plt.scatter(0, 0, c='r')
plt.scatter(np.real(1j * cm.sqrt(-1)), 0, c='r')
plt.scatter(-np.real(1j * cm.sqrt(-1)), 0, c='r')
if gamma < -2:
plt.text(0.3, 0.5, 'Неустойчивый узел', color='blue', fontsize=11)
if -2 < gamma < 0:
plt.text(0.3, 0.5, 'Неустойчивый фокус', color='blue', fontsize=11)
if 0 < gamma < 2:
plt.text(0.3, 0.5, 'Устойчивый фокус', color='blue', fontsize=11)
if gamma > 2:
plt.text(0.3, 0.5, 'Устойчивый узел', color='blue', fontsize=11)
plt.plot([0.07, 0.9], [0.07, 0.45], color='blue')
plt.text(-1.5, -0.5, 'Седла', color='blue', fontsize=11)
plt.plot([-1.05, -1.3], [-0.07, -0.37], color='blue')
#plt.savefig("out.png")
plt.xlabel('$x$')
plt.ylabel('$p$')
plt.title('$ \\beta = -1, \omega^2 = 1, \gamma = $' + str(gamma))
plt.autoscale()
plt.show()
8
2.2.6 II) β > 0, ω 2 < 0.
P1 : неустойчивый узел
γ ∈ (−∞, −2ω ) :
P2 :
седло
P1 : неустойчивый фокус
γ ∈ (−2ω, 0) :
седло
P2 :
P1 : устойчивый фокус
γ ∈ (0, 2ω ) :
P2 :
седло
P1 : устойчивый узел
γ ∈ (2ω, +∞) :
P2 :
седло
.
[5]: #plt.figure(figsize=(10,8), dpi=150)
plt.figure()
Y, X = np.mgrid[-2:2:150j, -2:2:150j]
gamma = -3
U = Y
V = -gamma * Y + 1 * X - 1 * X**3
plt.streamplot(X, Y, U, V, color=U, linewidth=1, cmap=plt.cm.coolwarm, density=2)
plt.scatter(0, 0, c='r')
plt.colorbar()
9
plt.scatter(0, 0, c='r')
plt.scatter(np.real(1j * cm.sqrt(-1)), 0, c='r')
plt.scatter(-np.real(1j * cm.sqrt(-1)), 0, c='r')
if gamma < -2:
plt.text(0.3, 0.5, 'Неустойчивый узел', color='blue', fontsize=11)
if -2 < gamma < 0:
plt.text(0.3, 0.5, 'Неустойчивый фокус', color='blue', fontsize=11)
if 0 < gamma < 2:
plt.text(0.3, 0.5, 'Устойчивый фокус', color='blue', fontsize=11)
if gamma > 2:
plt.text(0.3, 0.5, 'Устойчивый узел', color='blue', fontsize=11)
plt.plot([0.07, 0.9], [0.07, 0.45], color='blue')
plt.text(-1.5, -0.5, 'Седла', color='blue', fontsize=11)
plt.plot([-1.05, -1.3], [-0.07, -0.37], color='blue')
plt.savefig("out.png")
plt.xlabel('$x$')
plt.ylabel('$p$')
plt.title('$ \\beta = 1, \omega^2 =-1, \gamma = $' + str(gamma))
plt.autoscale()
plt.show()
10
2.3 2.2. Аналитическое и численное решения для линейного осциллятора
Чтобы не нарушать целостность повествования, для начала рассмотрим свободные колебания
линейного осциллятора, затем изучим динамику вынужденных колебаний, постепенно добавляя трение и внешнее воздействие.
2.3.1
Случай свободных колебаний без затухания
Свободная динамика системы описывается следующим уравнением:
ω02 x + ẍ = 0.
(2)
Решением данного уравнения является суперпозиция двух тригонометрических функций:
x (t) = A cos(w0 t) + B sin(w0 t),
(3)
p(t) = ẋ = − Aω0 sin(w0 t) + Bω0 cos(w0 t),
(4)
где коэффициенты A, B находятся из начальных условий: x (0) = x_0 = A, p(0) = p_0 =
Bω_0.
Данный случай не представляет особого интереса с точки зрения исследования динамики системы.
11
2.3.2
Случай свободных колебаний с затуханием
Учтем наличие диссипации в системе:
ω02 x + 2γ ẋ + ẍ = 0.
(5)
Следуя общим правилам решения линейных дифференциальных уравнений с постоянными
коэффициентами, составляем характеристическое уравнение, полагая x = eλt :
λ2 + 2γλ + ω02 = 0
(6)
Общее решение примет вид:
λ1,2 = −γ ±
q
γ2 − ω02
(7)
Здесь следует различать три случая: коэффициент затухания меньше собственной частоты
колебаний (γ < ω0 ), γ > ω0 , γ = ω0 .
q
Случай (fl < !0 ) Введем новую переменную: ω = ω02 − γ2 . Решение имеет вид гармонических колебаний с экспоненциально убывающей амплитудой:
x (t) =e−γt ( A cos(wt) + B sin(wt)),
p(t) = − γe
−γt
(8)
( A cos(wt) + B sin(wt)) + e
−γt
(− Aω sin(wt) + Bω cos(wt)),
(9)
p0 + γx0
.
ω
Если γ ω0 , то за время одного периода T = 2π/ω амплитуда затухающих колебаний почти
не менятся. В этом случае имеет смысл рассматривать средние за период квадраты координаты
и импульса, принебрегая изменением значением e−γt . Эти средние квадраты пропорциональны
e−2γt . Поэтому энергия системы убывает по закону:
A = x0 , B =
E = E0 e−2γt ,
(10)
x (t) = Ae(ω −γ)t + Be−(ω +γ)t ,
(11)
p(t) = A(ω − γ)e(ω −γ)t − B(ω + γ)e−(ω +γ)t ,
(12)
где E0 - начальная энергия системы.
Случай γ > ω0
ω=
q
γ2 − ω02 .
A=
x0
p0 − γx0
x0
p0 − γx0
+
,B =
−
.
2
2ω
2
2ω
12
При большом трении движение состоит в убывании | x |, т.е. в ассимптотическом приближении к
положению равновесия при t −→ ∞. Такое движение называется апериодическим затуханием.
Случай (fl = !0 )
ω = ω0 .
x (t) =( A + Bt)e−γt ,
p(t) = − γ( A + Bt)e
(13)
−γt
+ Be
−γt
,
A = x0 , B = p0 + γx0 .
Данный случай также является апериодическим затуханием.
Ниже мы предоставим код программы и графики.
[6]: import scipy as sp
from tqdm import trange, notebook
from odeintw import odeintw
# Численное решение
def diff_eq(z, t):
q, p = z
return [p, F*np.cos(2*np.pi/T * t) + Fm*np.cos(3*OMEGA * t) - 2*gamma*p +␣
,→k*(omega0)**2 * q - beta * q**3]
# Аналитическое решение для построения уравнений движения
def motion_analytical(t, x0, p0, omega0, gamma, F, Fm, OMEGA):
import numpy
# linear spectrum
if gamma == 0:
omega = omega0
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
B = (p0 - C*OMEGA - 3*C1*OMEGA) / omega
13
(14)
return [A * np.cos(omega * t) + B*np.sin(omega*t) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t)+ D1*np.cos(3*OMEGA*t) +␣
,→C1*np.sin(3*OMEGA*t),
-omega*A * np.sin(omega * t) + B*omega*np.cos(omega*t) -␣
,→OMEGA*D*np.sin(OMEGA*t)
+ OMEGA*C*np.cos(OMEGA*t) 3*OMEGA*C1*np.sin(3*OMEGA*t) + 3*OMEGA*D1*np.cos(3*OMEGA*t)]
# gamma < w0
elif gamma < omega0 and F == 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
return [np.exp(-gamma*t) * ( x0*np.cos(omega*t) + (p0 + gamma*x0)/
,→omega*np.sin(omega*t)),
-gamma*np.exp(-gamma*t) * ( x0*np.cos(omega*t) + (p0 + gamma*x0)/
,→omega*np.sin(omega*t)) +
omega*np.exp(-gamma*t) * ( -x0*np.sin(omega*t) + (p0 + gamma*x0)/
,→omega*np.cos(omega*t))]
# gamma > w0
elif gamma > omega0 and F == 0 and Fm == 0:
omega = np.sqrt(gamma**2 - omega0**2 )
return [np.exp(-gamma*t + omega*t) * ( x0/2 + (gamma*x0 + p0)/(2*omega)␣
,→) +
np.exp(-gamma*t - omega*t) * ( x0/2 - (gamma*x0 + p0)/(2*omega)),
(omega - gamma)*np.exp(-gamma*t + omega*t) * ( x0/2 + (gamma*x0␣
,→+ p0)/(2*omega) ) (omega + gamma)*np.exp(-gamma*t - omega*t) * ( x0/2 - (gamma*x0␣
,→+ p0)/(2*omega) )]
# gamma = w0
elif gamma == omega0 and F == 0 and Fm == 0:
omega = np.sqrt(gamma**2 - omega0**2 )
return [( x0 + (gamma*x0 + p0)*t ) * np.exp(-gamma*t),
-gamma*( x0 + (gamma*x0 + p0)*t ) * np.exp(-gamma*t) + (p0 +␣
,→gamma*x0)*np.exp(-gamma*t)]
# gamma < w0 with force F
elif gamma < omega0 and F > 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
A = x0 - D
14
B = (p0 + gamma*x0 - gamma*D - C*OMEGA) / (omega)
return [np.exp(-gamma*t) * (A*np.cos(omega*t) + B*np.sin(omega*t)) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t),
-gamma*np.exp(-gamma*t) * (A*np.cos(omega*t) + B*np.sin(omega*t))
+np.exp(-gamma*t) * (-A*np.sin(omega*t) + B*np.cos(omega*t)) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t)]
# gamma > w0 with force F
elif gamma > omega0 and F > 0 and Fm == 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
B = ( x0*(omega - gamma) + D*(gamma - omega) + C*OMEGA - p0 ) /(2*omega)
A = x0 - B - D
return [A*np.exp((-gamma + omega)*t) + B*np.exp(-(gamma + omega)*t) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t),
(-gamma + omega)*A*np.exp((-gamma + omega)*t) (gamma + omega)*B*np.exp(-(gamma + omega)*t) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t)]
# gamma = w0 with force F
elif gamma == omega0 and F > 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
A = x0 - D
B = p0 + gamma*x0 - gamma*D - C*OMEGA
return [(A+B*t)*np.exp(-gamma*t) + D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t),
-gamma*(A+B*t)*np.exp(-gamma*t) + B*np.exp(-gamma*t) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t)]
# gamma < w0 with two forces F and Fm
elif gamma < omega0 and F > 0 and Fm > 0:
omega = np.sqrt(omega0**2 - gamma**2)
15
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
B = (p0 + gamma*x0 - gamma*D - gamma*D1 - C*OMEGA - 3*C1*OMEGA) / (omega)
return [np.exp(-gamma*t) * (A*np.cos(omega*t) + B*np.sin(omega*t)) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t) + D1*np.cos(3*OMEGA*t) +␣
,→C1*np.sin(3*OMEGA*t),
-gamma*np.exp(-gamma*t) * (A*np.cos(omega*t) + B*np.sin(omega*t))
+np.exp(-gamma*t) * (-A*omega*np.sin(omega*t) + B*omega*np.
,→cos(omega*t)) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t) 3*OMEGA*D1*np.sin(3*OMEGA*t) + 3*OMEGA*C1*np.cos(3*OMEGA*t)]
# gamma > w0 with two forces F and Fm
elif gamma > omega0 and F > 0 and Fm > 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
B = ( x0*(omega - gamma) + D*(gamma - omega) + 3*D1*(gamma - omega) +
C*OMEGA + 3*C1*OMEGA - p0 ) /(2*omega)
A = x0 - B - D - D1
return [A*np.exp((-gamma + omega)*t) + B*np.exp(-(gamma + omega)*t) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t) + D1*np.cos(3*OMEGA*t) +␣
,→C1*np.sin(3*OMEGA*t),
(-gamma + omega)*A*np.exp((-gamma + omega)*t) (gamma + omega)*B*np.exp(-(gamma + omega)*t) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t) 3*OMEGA*C1*np.sin(3*OMEGA*t) + 3*OMEGA*D1*np.cos(3*OMEGA*t)]
16
# gamma = w0 with two forces F and Fm
elif gamma == omega0 and F > 0 and Fm > 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
B = p0 + gamma*x0 - gamma*D - C*OMEGA - gamma*D1 - C1*OMEGA*3
return [( A + B*t ) * np.exp(-gamma*t) +
D*np.cos(OMEGA*t) + C*np.sin(OMEGA*t)+ D1*np.cos(3*OMEGA*t) +␣
,→C1*np.sin(3*OMEGA*t),
-gamma*( A + B*t ) * np.exp(-gamma*t) + B*np.exp(-gamma*t) OMEGA*D*np.sin(OMEGA*t) + OMEGA*C*np.cos(OMEGA*t) 3*OMEGA*C1*np.sin(3*OMEGA*t) + 3*OMEGA*D1*np.cos(3*OMEGA*t)]
[7]: # линейный осциллятор без трения
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.0
F = 0.0
Fm = 0
OMEGA = 1.4
t = np.linspace(0, 100, 1000)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
# numerical
T = 1 / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
a = plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
17
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
[8]: # линейный осциллятор с трением gamma < omega0
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.1
F = 0.0
Fm = 0
OMEGA = 1.4
T = 1 / OMEGA
k = -1
beta = 0.1
t = np.linspace(0, 100, 1000)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
18
# numerical
T = 1 / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
a = plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
[9]: # линейный осциллятор с трением gamma > omega0
# analytical
x0 = 1
p0 = 0
omega0 = 1
19
gamma = 1.1
F = 0.0
Fm = 0
OMEGA = 1.4
T = 1 / OMEGA
k = -1
beta = 0.1
t = np.linspace(0, 100, 1000)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
# numerical
T = 1 / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
a = plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
20
[10]: # линейный осциллятор с трением gamma = omega0
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 1
F = 0.0
Fm = 0
OMEGA = 1.4
T = 1 / OMEGA
k = -1
beta = 0.1
t = np.linspace(0, 100, 1000)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
# numerical
T = 1 / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
21
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
a = plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
Различить гармонический сигнал и колебания затухающего осциллятора можно и формально математическим способом. Для этого следует воспользоваться аппаратом преобразования
Фурье, которое разлагает произвольную функцию времени по совокупности гармонических
колебаний.
Пусть f (t) — функция времени, удовлетворяющая достаточно общим условиям: Фунция f (t)
должна быть абсолютно интегрируемой в промежутке (−∞, +∞) и на любом конечном интервале удовлетворять условиям Дирихле, т.е. иметь не более чем конечное число разрывов
первого рода и этот интервал должен допускать разбиение на конечное число подинтервалов,
на которых f (t) меняется монотонно. Тогда ее можно представить в виде
0
F (ω ) =
Z +∞
−∞
22
f (t)e−iωt dt.
(15)
Функция | F (ω 0 )|2 - спектр мощности сигнала. Из него следует, что для затухающего колебания
спектр, вообще говоря, является сплошным: он состоит из гармонических сигналов со всеми
возможными частотами от −∞ до ∞. Если затухание мало γ < ω, то спектр имеет вид двух
острых пиков вблизи частот ω 0 = ±ω. Доминирующий вклад в полный сигнал дают спектральные составляющие с частотами, лежащими вблизи этих значений. Ширина пиков определяется величиной коэффициента затухания γ. Рассмотрим, например, поведение | F (ω 0 )|2
вблизи точки ω 0 = ω. Стоит заметить, что при t ∈ (−∞, 0) функция f (t), вообще говоря, не
существует по физическим причинам. Поэтому нижний предел в интеграле следует заменить
на 0, полагая, что в момент времени t = 0 функция определяется начальными условиями.
[11]: def spectrum_density_analytical(w1, x0, p0, omega0, gamma, F, Fm, OMEGA):
# linear spectrum
if gamma == 0:
omega = omega0
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
B = (p0 - C*OMEGA - 3*C1*OMEGA) / omega
,→
x_w1 = ( B * omega * ( ( ( omega )**( 2 ) + -1 * ( w1 )**( 2 ) ) )**(␣
-1 ) + \
( complex( 0,1 ) * A * w1 * ( ( ( omega )**( 2 ) + -1 * ( w1 )**( 2 ) \
) )**( -1 ) + ( C * OMEGA * ( ( ( OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) \
) )**( -1 ) + ( complex( 0,1 ) * D * w1 * ( ( ( OMEGA )**( 2 ) + -1 * \
( w1 )**( 2 ) ) )**( -1 ) + ( 3 * C1 * OMEGA * ( ( 9 * ( OMEGA )**( 2 \
) + -1 * ( w1 )**( 2 ) ) )**( -1 ) + complex( 0,-1 ) * D1 * w1 * ( ( \
-9 * ( OMEGA )**( 2 ) + ( w1 )**( 2 ) ) )**( -1 ) ) ) ) ) )
return abs(x_w1)**2
# gamma < w0
elif gamma < omega0 and F == 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
x_w1 = ( ( ( omega )**( 2 ) + ( ( gamma + complex( 0,1 ) * w1 ) )**( 2 )␣
,→) \
)**( -1 ) * ( p0 + ( 2 * gamma * x0 + complex( 0,1 ) * w1 * x0 ) )
return abs(x_w1)**2
#
gamma > w0
23
elif gamma > omega0 and F == 0 and Fm == 0:
omega = np.sqrt(gamma**2 - omega0**2 )
x_w1 = 1/2 * ( ( gamma + -1 * omega ) )**( -1 ) * ( omega )**( -1 ) * (␣
,→( \
gamma + ( omega + complex( 0,1 ) * w1 ) ) )**( -1 ) * ( complex( 0,1␣
,→\
) * w1 * ( p0 + gamma * x0 ) + omega * ( 2 * p0 + ( 4 * gamma *␣
,→x0 + \
complex( 0,1 ) * w1 * x0 ) ) )
return abs(x_w1)**2
# gamma = w0
elif gamma == omega0 and F == 0 and Fm == 0:
omega = np.sqrt(gamma**2 - omega0**2 )
x_w1 = ( ( gamma + complex( 0,1 ) * w1 ) )**( -2 ) * ( p0 + ( 2 * gamma␣
,→* x0 \
+ complex( 0,1 ) * w1 * x0 ) )
return abs(x_w1)**2
# gamma < w0 with force F
elif gamma < omega0 and F > 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
A = x0 - D
B = (p0 + gamma*x0 - gamma*D - C*OMEGA) / (omega)
x_w1 = ( B * omega * ( ( ( omega )**( 2 ) + ( ( gamma + complex( 0,1 ) *␣
w1 \
) )**( 2 ) ) )**( -1 ) + ( A * ( ( ( omega )**( 2 ) + ( ( gamma + \
complex( 0,1 ) * w1 ) )**( 2 ) ) )**( -1 ) * ( gamma + complex( 0,1 ) \
* w1 ) + ( ( ( OMEGA )**( 2 ) + ( ( gamma + complex( 0,1 ) * w1 ) \
)**( 2 ) ) )**( -1 ) * ( D * gamma + ( C * OMEGA + complex( 0,1 ) * D \
* w1 ) ) ) )
return abs(x_w1)**2
,→
# gamma > w0 with force F
elif gamma > omega0 and F > 0 and Fm == 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
24
,→
) + \
B = ( x0*(omega - gamma) + D*(gamma - omega) + C*OMEGA - p0 ) /(2*omega)
A = x0 - B - D
x_w1 = ( A * ( ( gamma + ( -1 * omega + complex( 0,1 ) * w1 ) ) )**( -1␣
( B * ( ( gamma + ( omega + complex( 0,1 ) * w1 ) ) )**( -1 ) + ( C * \
OMEGA + complex( 0,1 ) * D * w1 ) * ( ( ( OMEGA )**( 2 ) + -1 * ( w1 \
)**( 2 ) ) )**( -1 ) ) )
return abs(x_w1)**2
# gamma = w0 with force F
elif gamma == omega0 and F > 0 and Fm == 0:
omega = np.sqrt(omega0**2 - gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
A = x0 - D
B = p0 + gamma*x0 - gamma*D - C*OMEGA
,→
x_w1 = ( ( B + A * ( gamma + complex( 0,1 ) * w1 ) ) * ( ( gamma +␣
complex( \
0,1 ) * w1 ) )**( -2 ) + ( C * OMEGA + complex( 0,1 ) * D * w1 ) * ( \
( ( OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) ) )**( -1 ) )
return abs(x_w1)**2
# gamma < w0 with two forces F and Fm
elif gamma < omega0 and F > 0 and Fm > 0:
omega = np.sqrt(omega0**2 - gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9 *OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
B = (p0 + gamma*x0 - gamma*D - gamma*D1 - C*OMEGA - 3*C1*OMEGA) / (omega)
,→
w1 \
x_w1 = ( B * omega * ( ( ( omega )**( 2 ) + ( ( gamma + complex( 0,1 ) *␣
) )**( 2 ) ) )**( -1 ) + ( A * ( ( ( omega )**( 2 ) + ( ( gamma + \
complex( 0,1 ) * w1 ) )**( 2 ) ) )**( -1 ) * ( gamma + complex( 0,1 ) \
25
* w1 ) + ( ( ( ( OMEGA )**( 2 ) + ( ( gamma + complex( 0,1 ) * w1 ) \
)**( 2 ) ) )**( -1 ) * ( D * gamma + ( C * OMEGA + complex( 0,1 ) * D \
* w1 ) ) + ( ( 9 * ( OMEGA )**( 2 ) + ( ( gamma + complex( 0,1 ) * w1 \
) )**( 2 ) ) )**( -1 ) * ( D1 * gamma + ( 3 * C1 * OMEGA + complex( \
0,1 ) * D1 * w1 ) ) ) ) )
return abs(x_w1)**2
# gamma > w0 with two forces F and Fm
elif gamma > omega0 and F > 0 and Fm > 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
B = ( x0*(omega - gamma) + D*(gamma - omega) + 3*D1*(gamma - omega) +
C*OMEGA + 3*C1*OMEGA - p0 ) /(2*omega)
A = x0 - B - D - D1
,→
) + \
x_w1 = ( A * ( ( gamma + ( -1 * omega + complex( 0,1 ) * w1 ) ) )**( -1␣
( B * ( ( gamma + ( omega + complex( 0,1 ) * w1 ) ) )**( -1 ) + ( C * \
OMEGA * ( ( ( OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) ) )**( -1 ) + ( \
complex( 0,1 ) * D * w1 * ( ( ( OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) ) \
)**( -1 ) + ( 3 * C1 * OMEGA + complex( 0,1 ) * D1 * w1 ) * ( ( 9 * ( \
OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) ) )**( -1 ) ) ) ) )
return abs(x_w1)**2
# gamma = w0 with two forces F and Fm
elif gamma == omega0 and F > 0 and Fm > 0:
omega = np.sqrt(-omega0**2 + gamma**2)
C = 2*gamma*OMEGA*F/((omega0**2 - OMEGA**2)**2 + 4*gamma**2*OMEGA**2)
D = (omega0**2 - OMEGA**2)*F/((omega0**2 - OMEGA**2)**2 +␣
,→4*gamma**2*OMEGA**2)
C1 = 6*gamma*OMEGA*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
D1 = (omega0**2 - 9*OMEGA**2)*Fm/((omega0**2 - 9*OMEGA**2)**2 +␣
,→36*gamma**2*OMEGA**2)
A = x0 - D - D1
26
B = p0 + gamma*x0 - gamma*D - C*OMEGA - gamma*D1 - C1*OMEGA*3
x_w1 = ( B * ( ( gamma + complex( 0,1 ) * w1 ) )**( -2 ) + ( A * ( (␣
,→gamma + \
complex( 0,1 ) * w1 ) )**( -1 ) + ( C * OMEGA * ( ( ( OMEGA )**( 2 ) \
+ -1 * ( w1 )**( 2 ) ) )**( -1 ) + ( complex( 0,1 ) * D * w1 * ( ( ( \
OMEGA )**( 2 ) + -1 * ( w1 )**( 2 ) ) )**( -1 ) + ( 3 * C1 * OMEGA + \
complex( 0,1 ) * D1 * w1 ) * ( ( 9 * ( OMEGA )**( 2 ) + -1 * ( w1 \
)**( 2 ) ) )**( -1 ) ) ) ) )
return abs(x_w1)**2
[12]: import scipy as sp
# линейный осциллятор с трением gamma = omega0
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.01
F = 0.0
Fm = 0
OMEGA = 1.4
t = np.arange(0, 100, 0.1*2*np.pi/omega0)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
# numerical
T = 1 / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
a = plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
27
# spectral density
# analytical
ww = np.linspace(0, 5, 1000)
analit_psd = spectrum_density_analytical(ww, x0, p0, omega0, gamma, F, Fm, OMEGA)
analit_psd /= np.max(analit_psd)
plt.plot(ww, analit_psd, label='Exact PSD', lw=2)
#plt.xticks(np.arange(min(ww), max(ww)+1, 1.0))
plt.title('Spectral density for $\gamma$=' + str(gamma) + ', $omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
#plt.show()
# numerical
signal = num_q
fourier = np.abs(sp.fft.fft(signal))**2
fourier /= np.max(fourier)
n = signal.size
timestep = 0.1
freq = sp.fft.fftfreq(n, d=timestep)
mask = freq>=0
plt.plot(freq[mask], fourier[mask], 'ro', label='SciPy PSD', markersize=4)
#plt.plot(freq[~mask], fourier[~mask]) # отрицательная часть ввиду симметрии␣
,→преобразования Фурье
plt.legend()
plt.grid()
plt.xlim([0,3])
plt.show()
28
Шириной спектра можно считать величину 2γ
29
2.3.3
Вынужденные колебания с трением
Учтем наличие диссипации в системе и внешнее воздействие:
ω02 x + 2γ ẋ + ẍ = F cos(Ωt).
(16)
В данном случае решение уравнение будет представляться суммой решения соответствующего
неоднородного уравнения, которое было найдено выше, и решения частного неоднородного
уравнения. Решение неоднородного уравнения ищется в виде:
x̃ (t) = C cos(Ωt) + D sin(Ωt)
(17)
После подстановки в (16) имеем:
C=
x̃ (t) =C cos(Ωt) + D sin(Ωt),
(18)
p̃(t) = − CΩ sin(Ωt) + DΩ cos(Ωt),
(19)
F (ω02 − Ω2 )
2γΩF
,D =
2
2
2
2
2
2
((ω0 − Ω ) + 4γ Ω )
((ω0 − Ω2 )2 + 4γ2 Ω2 )
. Константы однородного решения находятся из начальных условий с учетом частного неоднородного решения.
Случай (fl < !0 )
x (t) =e−γt ( A cos(wt) + B sin(wt)) + C cos(Ωt) + D sin(Ωt),
p(t) = − γe
−γt
( A cos(wt) + B sin(wt)) + e
−γt
A = x0 − C, B =
Случай (fl > !0 )
ω=
q
(20)
(− Aω sin(wt) + Bω cos(wt)) − CΩ sin(Ωt) + DΩ cos(Ωt),
(21)
p0 + γx0 − γC − DΩ
.
ω
γ2 − ω02 .
x (t) = Ae(ω −γ)t + Be−(ω +γ)t + C cos(Ωt) + D sin(Ωt),
p(t) = A(ω − γ)e
(ω −γ)t
− B(ω + γ)e
A = x0 − B − C, B =
−(ω +γ)t
− CΩ sin(Ωt) + DΩ cos(Ωt),
(ω − γ)( x0 − C ) − p0 + DΩ
.
2ω
30
(22)
(23)
Случай (fl = !0 )
ω = ω0 .
x (t) =( A + Bt)e−γt + C cos(Ωt) + D sin(Ωt),
(24)
−γt
(25)
p(t) = − γ( A + Bt)e
+ Be
−γt
− CΩ sin(Ωt) + DΩ cos(Ωt),
A = x0 − C, B = p0 + γx0 − γC − DΩ.
[13]: def psd(w1):
return abs(( ( gamma -1 * omega0 ) * ( gamma + omega0 ) )**( 1/2 ) * ( ( (␣
,→gamma )**( \
2 ) + -1 * ( omega0 )**( 2 ) ) )**( -1/2 ) * ( ( OMEGA + -1 * w1 ) )**( -1 ) \
* ( ( OMEGA + w1 ) )**( -1 ) * ( ( complex( 0,-1 ) * ( omega0 )**( 2 ) + ( 2 \
* gamma + complex( 0,1 ) * w1 ) * w1 ) )**( -1 ) * ( F * w1 + ( OMEGA + \
-1 * w1 ) * ( OMEGA + w1 ) * ( complex( 0,-1 ) * p0 + ( complex( 0,-2 ) * \
gamma + w1 ) * x0 ) ))**2
# вынужденные колебания с трением gamma < omega0
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.01
F = 0.5
Fm = 0
OMEGA = 1.4
t = np.arange(0, 100, 0.1*2*np.pi/omega0)
plt.plot(t, motion_analytical(t, x0, p0, omega0, gamma, F, Fm,␣
,→OMEGA)[0],label='Exact', lw=3)
# numerical
T = 2*np.pi / OMEGA
k = -1
beta = 0.0
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
31
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
# spectral density
# analytical
nw = len(num_q)
ww = np.linspace(0, 100, 1375)
analit_psd = spectrum_density_analytical(ww, x0, p0, omega0, gamma, F, Fm, OMEGA)
#analit_psd /= np.mean(analit_psd)
analit_psd /= np.max(analit_psd)
#plt.plot(ww, analit_psd, label='Exact PSD 2', lw=2)
#plt.xticks(np.arange(min(ww), max(ww)+1, 1.0))
plt.title('Spectral density for $\gamma$=' + str(gamma) + ', $omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
#plt.show()
# numerical
signal = num_q
fourier = abs(sp.fft.fft(signal))**2
#fourier = np.mean(fourier)
fourier /= np.max(fourier)
n = signal.size
timestep = 0.1
freq = sp.fft.fftfreq(n, d=timestep)
mask = freq>=0
plt.plot(freq[mask], fourier[mask], label='SciPy PSD', lw=3)
#plt.plot(freq[~mask], fourier[~mask]) # отрицательная часть ввиду симметрии␣
,→преобразования Фурье
plt.grid()
#plt.xlim([0,3])
anl = psd(ww)
anl /= np.max(anl)
plt.plot(ww, anl, label='Exact PSD')
plt.legend()
plt.xlim([0, 5])
plt.xlabel('$\omega$')
plt.ylabel('$|x( \omega)|^2$')
plt.show()
32
В этом случае наблюдается появление гармоники на частоте Ω вынуждающей силы. При уста33
новившемся движении, когда система совершает вынужденные колебания, ее энергия остается неизменной, в то же время система от источника внешней силы непрерывно поглощает
энергию, которая диссипируется из-за наличия трения. Обозначим I (Ω) количество энергии,
поглощаемой в среднем в единицу времени, как функцию частоты внешней силы:
I (Ω) = 2F,
(26)
где F - среднее по периоду колебания значение диссипативной функции. В одномерном случае:
F = γ ẋ2 = γb2 Ω2 ,
где b =
√
C2 + D2 , tan (φ) = γ/ε, ε = Ω − ω.
F = γb2 Ω2 sin2 (Ωt + δ).
(27)
Среднее по времени от квадрата синуса равно 1/2, поэтому
I (ε) = γb2 Ω2 =
I (0) =
F2 γ
,
4( ε2 − γ2 )
(28)
F2
.
4γ
(29)
Построим резонансную кривую.
[14]: #
#
вынужденные колебания с трением gamma < omega0
analytical
def I(eps):
return (F**2 * gamma) / (4 * (eps**2 + gamma**2))
x0 = 1
p0 = 0
omega0 = 1
gammas = np.arange(0.01, 0.1, 0.02)
F = 0.5
Fm = 0
i = 1
for gamma in gammas:
I_0 = F**2 / 4 /gamma
epsilons = np.linspace(-2*gamma, 2*gamma, 1000)
plt.plot(epsilons, I(epsilons)/I_0, lw=3, label='$\gamma$'+ str(i) + '=' +␣
,→str(round(gamma, 3)))
34
plt.plot([gamma, gamma], [0, I(gamma)/I_0], '--', color='black')
plt.text(gamma, I(gamma)/I_0/3, '$\gamma$'+ str(i), color='red', fontsize=5)
plt.plot([-gamma, -gamma], [0, I(gamma)/I_0], '--', color='black')
plt.text(-gamma, I(gamma)/I_0/3, '$-\gamma$'+ str(i), color='red',␣
,→fontsize=5)
plt.plot([-gamma, gamma], [I(-gamma)/I_0, I(gamma)/I_0], '--', color='black')
plt.text(0, I(gamma)/I_0, '$1/2$', color='red', fontsize=15)
plt.axvline(x=0, lw=1, color='black')
i += 1
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.title('$I(\\varepsilon) / I(0)$')
#plt.grid()
plt.ylim([0, 1.1])
plt.show()
3 Нелинейный осциллятор Дуффинга
Наибольший интерес с точки зрения исследования хаоса в динамических системах представляет как раз нелинейный осциллятор. Уравнение такого осциллятора запишется как:
ẍ + 2γ ẋ + ω02 x + βx3 = F cos(Ωt).
(30)
Так как точное аналитическое решение невозможно, следует использовать приближенные ме35
тоды. В данном случае был выбрал метод усреденения Ван-дер-Поля.
Метод Ван-дер-Поля представляет собой простейший вариант метода усреднения. Он был разработан Б. Ван-дер-Полем (1920) для исследования различных автоколебательных процессов
в ламповом генераторе. Математическое обоснование этого метода было дано Л.И. Мандельштамоми, Н.Д. Папалекси (1934). Дальнейшее развитие метод усреднения получил в работах
Н.М. Крылова, Н.Н. Боголюбова, Ю.А. Митропольского и др.
Перепишем уравнение (30) в виде:
ẍ + ω02 x = −2γ ẋ − βx3 + F cos(Ωt),
(31)
причем будем считать, что частота внешнего воздействия близка к собственной частоте осциллятора, Ω = ω0 + δ, где расстройка частот δ мала. Члены, фигурирующие в правой части,
отвечают за диссипацию, нелинейность и внешнее воздействие. Если ими пренебречь,система
превращается в гармонический осциллятор. Если же они малы, то решение целесообразно
искать в виде квазигармонического колебания с медленно меняющейся амплитудой, для которой можно получить укороченное уравнение. Вообще, близость к линейной консервативной
системе является условием применимости метода Ван-дер-Поля. Это позволяет представить
решение в виде:
h
i
x (t) = Re A(t)eiω0 t ,
(32)
где A(t) - медленно меняющаяся по сравнениюс eiω0 t комплексная амплитуда (в связи с чем
этот метод называют также методом медленно меняющихсяа мплитуд). Продифференциируем
x ( t ):
ẋ = Ȧeiω0 t + iAeiω0 t + Ȧ∗ e−iω0 t − iA∗ e−iω0 t .
(33)
Стоит отметить, что вместо одной зависимой переменной x введены две: A и A∗ . Поэтому
можно наложить между этими величинами дополнительную связь. Удобно потребовать, чтобы
Ȧeiω0 t + Ȧ∗ e−iω0 t = 0.
(34)
ẋ = iAeiω0 t − iA∗ e−iω0 t ,
(35)
Тогда
Продифференцируем это уравнение ещё раз. Получим
ẍ = i Ȧeiω0 t − Aeiω0 t − i Ȧ∗ e−iω0 t + A∗ e−iω0 t
(36)
Представим член, ответственный за внешнее воздействие, в виде
F cos Ωt = Re FeiΩt =
36
f eiΩt + f ∗ e−iΩt
2
(37)
Подставляя все в исходное уравнение, можно получить:
iω0 t = −iω γAeiω0 t − iω γA∗ e−iω0 t
iω0 Ȧe
0
0
+β
1 3 3iω0 t
+ 38 | A|2 Aeiω0 t + 83 | A|2 A∗ e−iω0 t + 81 ( A∗ )3 e−3iω0 t
8A e
+ 12 FeiΩt + 12 f ∗ e−iΩt
(38)
Отметим, что в уравнении все члены одного порядка малости: они либо содержат производные
от медленно меняющейся амплитуды, либо пропорциональны малым параметрам γ, β. Умножим обе части уравнения на e−iω0 t /iω0 и проведем усреднение по периоду основной частоты
T = 2π/ω0 . Операция усреднее осуществляется следующим образом:
h f (t)i =
1
T
Z T
f (t)dt.
(39)
0
Считаем, что на этом масштабе времени изменением комплексных амплитуд можно пренебречь. Кроме того поскольку мы рассматриваем случай, когда частоты Ω и ω0 близки, то
член, содержащий экспоненту exp [i (Ω − ω0 ) t] = exp[iδt], также будет медленно меняющимся.
Тогда после устранения быстро осциллирующих членов приходим к укороченному уравнению
Ȧ = −γA −
3iβ
i f iδt
| A |2 A −
e
8ω0
2ω0
(40)
Для начала рассмотрим случай в отсутствии внешнего воздействия.
3.1 Нелинейный осциллятор Дуффинга при F = 0
В отсутствии внешнего воздействия, когда F = 0 , уравнение (40) переходит в укороченное
уравнение для автономного осциллятора Дуффинга:
Ȧ + γA −
3iβ| A|2 A
= 0.
2
(41)
Перейдем к уравнениям для вещественных амплитуды и фазы. Полагая A(t) = a(t) exp iϕ(t),
отделим в (41) вещественную и мнимую части. Получим
ȧ = − γa,
ϕ̇ =
3βa2
.
8ω0
(42)
Решая данную систему дифференциальных уравнений, полагая, что a(0) = a0 , ϕ(0) = ϕ0 ,
находим уравнения для a(t), ϕ(t):
a(t) = a0 e(−γt) ,
ϕ(t) =
e−2γt (3a20 β − 3a20 βe2γt + 16e2γt γϕ0 ω0 + 16δe2γt γtω0 )
,
16γω0
где a0 и ϕ0 определяются начальными условиями:
37
(43)
r
p0
,
ω0
p0
ϕ(0) = arctan(−
).
ω0 x 0
a (0) =
x02 +
(44)
[15]: def nonlinear_noforce(t):
import numpy
return a0 * ( numpy.e )**( -1 * gamma * t ) * numpy.cos( 1/16 * ( numpy.e \
)**( -2 * gamma * t ) * ( gamma )**( -1 ) * ( omega0 )**( -1 ) * ( 3 * ( \
a0 )**( 2 ) * beta + ( -3 * ( a0 )**( 2 ) * beta * ( numpy.e )**( 2 * \
gamma * t ) + ( 16 * ( numpy.e )**( 2 * gamma * t ) * gamma * phi0 * \
omega0 + 16 * delta * ( numpy.e )**( 2 * gamma * t ) * gamma * t * omega0 )␣
,→) \
) )
# нелинейные колебания с трением gamma < omega0 и beta > 0
# analytical
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.05
F = 0
Fm = 0
OMEGA = 1.01
beta = 0.0
a0 = np.sqrt(x0**2 + p0**2 / omega0**2)
phi0 = np.arctan(-p0 / x0 / omega0)
delta = -omega0
t = np.arange(0, 100, 0.1*2*np.pi/omega0)
plt.plot(t, nonlinear_noforce(t), label='Approximation', lw=3)
# numerical
T = 2*np.pi / OMEGA
k = -1
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
38
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
[16]: # numerical
signal = num_q
fourier = abs(sp.fft.fft(signal))**2
#fourier = np.mean(fourier)
fourier /= np.max(fourier)
n = signal.size
timestep = 0.1
freq = sp.fft.fftfreq(n, d=timestep)
mask = freq>=0
plt.plot(freq[mask], fourier[mask], label='SciPy PSD', lw=2)
#plt.plot(freq[~mask], fourier[~mask]) # отрицательная часть ввиду симметрии␣
,→преобразования Фурье
plt.grid()
39
plt.legend()
plt.xlim([0, 5])
plt.xlabel('$\omega$')
plt.ylabel('$|x( \omega)|^2$')
plt.show()
3.2 Нелинейный осциллятор Дуффинга при F > 0
В случае, когда F > 0 , уравнение (40) переходит в укороченное уравнение:
Ȧ = −γA −
iF iδt
3iβ
| A |2 A −
e .
8ω0
2ω0
(45)
Процедура аналогична вышеописанной, переходим к переменным амплитуда и фаза:
ȧ + γa =
F
sin(δt − ϕ),
2ω0
3βa2
F
ϕ̇ =
−
cos(δt − ϕ).
8ω0
2aω0
(46)
Система уравнений (46) является неавтономной, так как содержит члены зависящие явным
образом от времени. Однако, вводя величину (ψ = δ − ϕ) можно получить автономную систему
вида
40
F
sin(ψ),
2ω0
3βa2
F
ψ̇ = δ −
+
cos(ψ).
8ω0
2aω0
ȧ + γa =
(47)
Аналитическое решение данной системы затруднено, поскольку она сама нелинейна. Поэтому
ограничимся в этом случае численным решением.
[17]: # нелинейные колебания с трением gamma < omega0 и beta > 0, F > 0
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.05
F = 0.1
Fm = 0
OMEGA = 1.01
beta = 0.0
delta = OMEGA - omega0
T = 2*np.pi / OMEGA
k = -1
t = np.arange(0, 200, 0.01*2*np.pi/OMEGA)
z0 = [x0, p0]
sol1 = odeintw(diff_eq, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
# numerical
signal = num_q
fourier = abs(sp.fft.fft(signal))**2
#fourier = np.mean(fourier)
fourier /= np.max(fourier)
n = signal.size
timestep = 0.01
freq = sp.fft.fftfreq(n, d=timestep)
41
mask = freq>=0
plt.plot(freq[mask], fourier[mask], label='SciPy PSD', lw=2)
#plt.plot(freq[~mask], fourier[~mask]) # отрицательная часть ввиду симметрии␣
,→преобразования Фурье
plt.grid()
plt.legend()
plt.xlim([0, 5])
plt.xlabel('$\omega$')
plt.ylabel('$|x( \omega)|^2$')
plt.show()
42
Естественно ожидать, что в установившемся режиме вынужденных колебаний амплитуда постоянна, а частота равна частоте внешнего воздействия. Этому режиму соответствуют положения равновесия системы: a = a0 , ψ = ψ0 . Действительно, нетрудно убедиться, что в этом
случае
A(t) = a exp(iϕ) = a0 exp [i (δt − ψ0 )]
x (t) = Re Aeiω0 t = a0 cos (Ωt − ψ0 )
(48)
т.е. колебания происходят точно на частоте воздействия. Для определения положений равновесия получаем из ȧ = 0, ψ̇ = 0 следующие уравнения:
f
γa0 = 2ω0 sin ψ0
3a2
f
δ − 8ω00 a0 = − 2ω0 cos ψ0
(49)
Удобно исключить отсюда ψ0 . Возводя уравнения в квадрат и складывая, получаем соотношение, которое неявным образом определяет амплитуду колебаний как функцию амплитуды
и частоты вынуждающей силы
(γa0 )
2
+ a20
3βa20
δ−
8ω0
Если устремить параметр диссипации γ к нулю, то
43
2
=
f2
.
4ω02
(50)
a0 =
f
.
2ω0 δ − 3βa20 /4
(51)
Ввиду близости частот ω0 и Ω справедливо приближенное соотношение Ω2 − ω02 = (Ω −
ω0 )(Ω + ω0 ) ≈ 2ω0 δ.
Мы хотели бы детально проанализировать соотношение, описывающее нелинейный резонанс
в присутствии диссипации. Для этого преобразуем его к более удобной форме, минимизируя
количество переменных и параметров. Для определенности далее будем считать параметр
нелинейности β положительным.
Введем следующие обозначения: P = 3βF2 / 32γ3 ω03 - безразмерный параметр, характеризующий интенсивность внешнего воздействия, X = 3βa20 / (8γω0 ) − безразмерный параметр,
характеризующий интенсивность вынужденных колебаний, ∆ = δ/γ - безразмерная расстройка частоты. Тогда соотношение
X=
P
( X − ∆ )2 + 1
(52)
Придавая различные значения параметру интенсивности воздействия P, мы можем построить семейство кривых X = X (∆), представляющих собой резонансные кривые нелинейного
осциллятора в безразмерных координатах X и ∆
Если внешнее воздействие мало, т.е. P 1, то амплитуда вынужденных колебаний тоже мала
( X порядка P), и формула (52) приближенно приводится к виду
X=
P
∆2 + 1
[18]: x0 = 1
p0 = 0
omega0 = 1
gamma = 0.5
F = 0.5
Fm = 0
OMEGA = 1.01
beta = 0.1
delta = OMEGA - omega0
xrange = np.linspace(-3, 4, 1000)
yrange = np.linspace(0, 3, 1000)
Y, X = np.meshgrid(xrange,yrange)
# F is one side of the equation, G is the other
P = np.arange(0.4, 3.0, 0.4)
fmt = {}
44
(53)
strs = []
for i in range(len(P)):
strs.append('P= %.1f' % P[i])
for l, p, s in zip(range(len(P)), P, strs):
F = X
G = p / ( (X - Y)**2 +1 )
CS = plt.contour(Y, X, (F - G), [0], colors='k')
fmt[l] = s
plt.clabel(CS, inline=True, fmt=fmt[l], fontsize=8.5)
plt.xlabel('$\Delta$')
plt.ylabel('$X (\Delta) $')
plt.show()
Соответствующий график имеет вид колоколообразной кривой, характерной для линейного
резонанса и известной как «лоренцевский контур». С ростом параметра P амплитуда растет,
поправка X в знаменателе формулы (52) становится существенной, верхняя часть резонансной кривой постепенно отклоняется вправо, и кривая становится все более асимметричной.
Обратим внимание, что максимумы резонансных кривых X = P достигаются при X = ∆, т.е.
при
45
δ=
3βa20
= ∆ω ( a0 ) .
8ω0
Следовательно, при заданной амплитуде внешней силы амплитуда вынужденных колебаний
будет максимальна, когда расстройка в точности равна нелинейному сдвигу частоты свободных колебаний автономного осциллятора.
В линейном приближении зависимость амплитуды b вынужденных колебаний от амплитуды
f и частоты Ω внешней силы дается вблизи резонанса формулой аналогичной разобранной
выше:
b2 ε2 + γ2 = F2 /4ω02
Нелинейность колебаний приводит к появлению зависимоcтии их собственной частоты от амплитуды; напишем ее в виде
ω0 + κb2 ,
где постоянная κ выражается определенным образом через корфициент ангармоничности нелинейный сдвиг частот. Соответственно этому заменяем в малой разнице (Ω − ω0 )ω0 на
ω0 + κb2 .
Сохранив обозначение ε = Ω − ω0 , получим уравнение:
h
i
2
b2 ε − xb2 + γ2 = F2 /4ω02
По мере увеличения F кривая деформируется, сохраняя сначала свой характер - с одним
максимумом, он смещается в сторону положительных ∆.
При F > Fk характер кривой меняется, при каждом значении F > Fk существует определенная
область частот, в которой 3 корня. Границы этой области определяются следующим выражением:
db
−εb + κb3
= 2
dε
ε + γ2 − 4κεb2 + 3κ 2 b4
(54)
При достаточно больших амплитудах зависимость амплитуды колебаний от расстройки становится неоднозначной. В рассматриваемом случае, когда параметр нелинейности β положителен, область неоднозначности располагается при частотах воздействия несколько больших
частоты линейного резонанса.
3.2.1 Бифуркации при нелинейном резонансе
Прежде всего исследуем резонансную кривую на устойчивость. Зададим малые отклонения от
состояний равновесия, полагая a(t) = a0 + ξ (t), ψ(t) = ψ0 + η (t), и ли- неаризуем уравнения
(14.17). Получим
fη
ξ̇ + γξ = 2ω0 cos ψ0
9βa2 ξ
fη
a0 η̇ = δξ − 8ω00 − 2ω0 sin ψ0
Исключим отсюда ψ0 при помощи соотношений:
46
3βa3
ξ̇ + γξ = − δa0 − 8ω00 η
9βa2
a0 η̇ = δ − 8ω00 ξ − γa0 η
Полагая, что решения имеют вид ξ, η ∼ exp(rt), приходим к характеристическому уравнению,
которое после несложных преобразований можно записать в виде
(r + γ)2 = −(δ − ∆ω )(δ − 3∆ω )
где ∆ω ( a0 ) = 3βa20 /8ω0 − нелинейный сдвиг частоты собственных колебаний осциллятора.
Корни уравнения есть
q
r± = −γ ±
−(δ − ∆ω )(δ − 3∆ω )
Нетрудно видеть, что при δ < ∆ω и при δ > 3∆ω корни r± комплексны, и состояние равновесия
представляет собой устойчивый фокус. При ∆ω < δ < 3∆ω корни вещественны. Поскольку
корень r− , очевидно, всегда отрицателен, состояние равновесия может быть либо устойчивым
узлом, либо седлом. Смена характера устойчивости происходит при r+ = 0, т.е. при
(δ − ∆ω )(δ − 3∆ω ) = −γ2
Переходя к безразмерным переменным, введенным в предыдущем разделе, можно переписать
это уравнение в виде
(∆ − X )(∆ − 3X ) = −1
В то же время, если продифференцировать уравнение резонансной кривой по X, получим
следующее соотношение
(∆ − X ) + 2X (∆ − X )
2
∂∆
−1 +1 = 0
∂X
В области неоднозначности резонансная кривая имеет три ветви, границы между которыми
определяются из условия ∂∆/∂X = 0. Следовательно, вся промежуточная ветвь резонансной
кривой отвечает неустойчивым состояниям равновесия, а верхняя и нижняя - устойчивым.
3.3 Сложная динамика и хаос при вынужденных колебаниях нелинейного осциллятора
Ключевую роль играет представление о нелинейном резонансе, на основании которого формулируется простое условие возникновения хаоса – критерий перекрытия резонансов Б.В. Чирикова.
3.3.1 Резонанс на гармониках и субгармониках
Рассмотрим консервативный осциллятор при воздействии внешней силы, зависящей от времени с периодом T = 2π/Ω. Представим ее в виде ряда Фурье, причем коэффициенты разложения будем считать зависящими от текущего значения обобщенной координаты x :
ẍ + ω02 x = F ( x, t) =
∞
∑
m=−∞
f m ( x )e
imΩt
Ω
, f m (x) =
2π
Z 2π/Ω
F ( x, t)e−imΩt dt.
(55)
0
Это очень общая форма уравнения. Нелинейные осцилляторы, как с силовым, так и с параметрическим внешним воздействием, представляют собой его определенные частные случаи.
47
В нулевом приближении, пренебрегая совсем правой частью уравнения (55), находим решение
в виде x (0) = A cos ω0 t, где A− константа, определяющая амплитуду колебаний. Намереваясь
получить следующее приближение, мы должны подставить Это выражение в правую часть.
При этом каждый коэффициент f m ( x ) становится периодической функцией времени и может
быть, в свою очередь, представлен в виде ряда Фуpьe:
∞
f m ( A cos ω0 t) =
∑
m=−∞
f mn einω0 t , f mn =
ω0
2π
Z 2π/ω0
0
f m ( A cos ω0 t) e−inω0 t dt.
Поэтому для первого приближения получаем
ẍ (1) + ω02 x (1) =
∞
∞
∑
∑ f mn ei(mΩ+nω )t .
0
m=−∞ n=−∞
Если какой-либо из членов в правой части отвечает колебаниям точно на собственной частоте
осциллятора ω0 , то возникает резонанс: в решении x (1) появится колебательная составляющая,
амплитуда которой будет нарастать во времени по линейному закону - секулярный, или вековой
член (термин из небесной механики).
Резонанс и появление секулярных членов будет иметь место не только при совпадении частоты внешнего воздействия с собственной частотой, но и при выполнении соотношения между
частотами вида mΩ + nω0 = ±ω0 , или, что то же самое,
mΩ + kω0 = 0,
где m и k = n ∓ 1− целые числа. В этом случае говорят о резонансе на гармониках и субгармониках основной частоты Ω. Обычно коэффициенты Фурье f mn достаточно быстро убывают
с ростом индексов, так что существенными оказываются только «главные резонансы», характеризуемые относительно небольшими m и n.
Чтобы избежать секулярного роста возмущений, метод последовательных приближений модифицируют, принимая во внимание зависимость частоты собственных колебаний от амплитуды
ω = ω ( A ).
Предположим, что имеет место отстройка по частоте от резонанса ∆ω. Тогда амплитуда резонансного возмущения будет равна по порядку величины, очевидно,
∆A ∼
= f mn /[ω ( A)∆ω ], откуда ∆ω ∼
= f mn /[ω ( A)∆A]. С другой стороны, изменение частоты
в силу неизохронности осциллятора при изменении амплитуды на величину ∆A составит
∆ω ∼
= |dω ( A)/dA|∆A. Потребуем, чтобы оба частотных сдвига были одного порядка. Отсюда получаем величину, о которой будем говорить как о ширине нелинейного резонанса по
амплитуде
s
f mn
∆A ∼
=
ω ( A) · dω ( A)/dA
и, соответственно, ширину нелинейного резонанса по частоте
q
∆ω ∼
= |dω ( A)/dA|∆A ∼
= | f mn [ω ( A)]−1 dω ( A)/dA|.
48
3.4 Фазовое пространство
Вернемся к уравнению (1), положив в нем γ = 0.15, ω02 = −1, β = 1, Ω = 1.2, F = 0.2. Получим:
ẍ − x + 0.3ẋ + x3 = 0.2 cos(1.2t)
Численно решим это уравнение и построим фазовый портрет:
[19]: def diff_eq1(z, t):
q, p = z
return [p, F*np.cos(2*np.pi/T * t) + Fm*np.cos(3*OMEGA * t) - 2*gamma*p -␣
,→k*(omega0)**2 * q - beta * q**3]
def poincare(z0, N=1000, steps=1000):
n_steps = N
#
number of periods
X = np.zeros(n_steps + 1, dtype=complex)
P = np.zeros(n_steps + 1, dtype=complex)
q0, p0 = z0
P[0] = p0
X[0] = q0
#
solution for Poincare map
# mapping for (p, q, u, v)
for n in notebook.tqdm(range(1, n_steps + 1)):
tn = T * (n - 1)
p0 = P[n - 1]
x0 = X[n - 1]
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, [tn, tn + T], atol=1e-12, rtol=1e-12,␣
,→mxstep=steps)
#print(sol)
X[n] = sol[-1,0]
P[n] = sol[-1,1]
return X, P
x0 = 1
49
p0 = 0
omega0 = 1
gamma = 0.15
F = 0.2
Fm = 0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
tmax = 500
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
#plt.legend()
#plt.xlim([10, 20])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
plt.plot(num_q, num_p, label='phase trajectories')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait')
plt.show()
50
51
Фазовое пространство выглядит достаточно сложным, однако оно также включает в себя и
процесс затухания собственных колебаний. Как видно они затухают на временах ~30. Построим фазовый портрет на промежутке веремени от 60 до 120, например:
[20]: tleft = int(60/dt)
tright = int(120/dt)
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
plt.plot(num_q[tleft:tright], num_p[tleft:tright], label='phase trajectories')
plt.scatter(xT[tleft:tright], pT[tleft:tright], s=15, c='r', label='Poincare␣
,→map')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t[tleft:tright],num_q[tleft:tright])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
52
Фазовая траектория стала заметно проще и представляет собой предельный цикл. Не представляет труда проверить, что период равен 2π
Ω
53
3.4.1 Удвоение периода
Исследуем поведение системы в зависимости от амплитуды вынужденных колебаний. Все графики будут приведены для времен, когда собственные колебания практически затухли.
Увеличим амплитуду вынужденных колебаний с f = 0.15 до f =0.23. Получим:
[21]: x0 = 1
p0 = 0
omega0 = 1
gamma = 0.15
F = 0.28
Fm = 0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
tmax = 500
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT[tleft:tright], pT[tleft:tright], s=15, c='r', label='Poincare␣
,→map')
plt.plot(num_q[tleft:tright], num_p[tleft:tright], label='phase trajectories')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t[tleft:tright],num_q[tleft:tright])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
54
plt.show()
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
55
И на фазовом пространстве и на графике решения хорошо видно, что произошло удвоение
периода. Теперь он равен 4π/Ω. Еще раз увеличим амплитуду вынужденных колебаний. Получим:
[22]: x0 = 1
p0 = 0
omega0 = 1
gamma = 0.15
F = 0.29
Fm = 0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
tmax = 500
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT[tleft:tright], pT[tleft:tright], s=15, c='r', label='Poincare␣
,→map')
plt.plot(num_q[tleft:tright], num_p[tleft:tright], label='phase trajectories')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t[tleft:tright],num_q[tleft:tright])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
56
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
57
И на фазовом пространстве и на графике решения хорошо видно, что произошло удвоение
периода. Теперь он равен 8π/Ω. Еще раз увеличим амплитуду вынужденных колебаний. Получим:
[23]: # F = 0.37
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.15
F = 0.37
Fm = 0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
tmax = 500
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT[tleft:tright], pT[tleft:tright], s=15, c='r', label='Poincare␣
,→map')
plt.plot(num_q[tleft:tright], num_p[tleft:tright], label='phase trajectories')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait, F = ' + str(F))
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t[tleft:tright],num_q[tleft:tright])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
58
# F = 0.5
F = 0.5
tmax = 2000
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT, pT, s=15, c='r', label='Poincare map')
plt.plot(num_q, num_p, label='phase trajectories', lw=0.2)
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait, F = ' + str(F))
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t,num_q)
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
# F = 0.65
F = 0.65
tmax = 500
dt = 1e-1
t = np.arange(0, tmax, dt)
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
sol1 = poincare(z0)
xT, pT = np.real(sol1)
plt.figure()
59
plt.scatter(xT[tleft:tright], pT[tleft:tright], s=15, c='r', label='Poincare␣
,→map')
plt.plot(num_q[tleft:tright], num_p[tleft:tright], label='phase trajectories')
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Portrait, F = ' + str(F))
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(t[tleft:tright],num_q[tleft:tright])
plt.title('$x(t)$ for $\gamma$=' + str(gamma) + ', $\omega_0$=' + str(omega) +␣
,→', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.xlabel('$t$')
plt.ylabel('$x(t)$')
plt.grid()
plt.show()
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
60
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
61
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1000.0),␣
,→HTML(value='')))
62
3.5
Сечение Пуанкаре
При дальнейшем увеличении амплитуды вынуждающей силы такой способ изучения не слишком практичен. Удобно строить сечение Пуанкаре, которое представляет собой отображение
положения системы в моменты времени t0 , t0 + T, t0 + 2T... Понятно, что при удвоении периода
вместо одной точки на фазовой диаграмме появятся две и т.д.
Сечение Пуанкаре для случая F = 0.5 выглядит следующим образом:
[24]: # F = 0.5
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.15
F = 0.5
Fm = 0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
tmax = 2000
dt = 1e-3
t = np.arange(0, tmax, dt)
63
z0 = [x0, p0]
sol = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol[:, 0], sol[:, 1]
N = 4000
sol1 = poincare(z0, N)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT, pT, s=0.5, c='k', label='Poincare map')
#plt.plot(num_q, num_p, label='phase trajectories', lw=0.5)
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Poincare map, F = ' + str(F))
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
plt.figure()
plt.plot(num_q, num_p, label='phase trajectories', lw=0.1)
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Phase Trajectories, F = ' + str(F))
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=4000.0),␣
,→HTML(value='')))
64
65
При хаотическом движеним каждый период создает точку в произвольном месте на плоскости
( x, p), и «сумма» отдельных “снимков” может создавать странные узоры из точек со сложными
границами в плоскости ( x, p). Эти геометрические формы называют странными аттракторами
и характеризуются дробными размерностями.
4
Диагностика хаоса
4.1
Спектр мощности. Критерий перекрытия резонансов Чирикова
При малой амплитуде внешней силы ширина резонансов по частоте мала по сравнению с
расстоянием между ними, и их можно рассматривать независимо. Однако при достаточно
большой амплитуде ширина резонансов становится сравнимой с расстоянием между ними, и
говорят о перекрытии резонансов. В этом случае характер динамики изменяется. Качественно
ее можно представить себе как блуждание между различными резонансами, так что изображающая точка получает возможность посещать достаточно обширную область фазового пространства, и колебания становятся хаотическими. Утверждение, что перекрытие резонансов
отвечает возникновению хаоса, составляет содержание критерия Чирикова.
Ограничимся для простоты учетом резонансов только на гармониках частоты воздействия:
mΩ = ω ( A). Каждой m -ой гармонике будет соответствовать некоторый интервал по амплитуде, где имеет место резонанс: его центр располагается вблизи значения Am , получаемого
как корень уравнения mΩ = ω ( Am ) . Расстояние по частоте между
p соседними резонансами
∼
равно, очевидно, Ω, а ширина резонанса дается формулой ∆ω = | f m0 ω 0 ( A)/ω ( A)|. Введем
параметр, определяющий отношение двух указанных величин
s
∆ω
f m0 ω 0 ( Am )
K=
= Ω −1
|
Ω
ω ( Am )
При K << 1 резонансы изолированы друг от друга, и динамика регулярная. При K ≈ 1 воЗникает перекрытие резонансов, и колебания могут стать хаотическими. При K >> 1 будет
наблюдаться развитый хаос.
Если рассмотреть задачу о вынужденных колебаниях маятника или другого осциллятора, имеющего наряду с устойчивыми также неустойчивые состояния равновесия (седла), то наиболее
благоприятными для возникновения хаоса оказываются области в окрестности сепаратрис. В
самом деле, вблизи сепаратрисы период колебаний стремится к бесконечности, т.е. зависимость
периода и частоты колебаний от частоты очень сильная, а в формуле величина |ω 0 ( A)| , как
можно видеть, фигурирует в числителе. Поэтому даже при небольшой амплитуде воздействия,
когда в остальных областях фазового пространства движение еще вполне регулярное, вблизи
сепаратрисы образуется область хаоса, так называемых стохастический слой.
С ростом амплитуды воздействия ширина этого слоя, разумеется, увеличивается. С физической точки зрения, ситуация вполне очевидна. Колебания вблизи сепаратрисы отвечают тому,
что маятник при максимальном отклонении почти достигает верхней точки. Если его в этот
момент подтолкнуть, то он пойдет, соответственно, вперед или назад. Роль такого толчка выполняет внешняя сила, а результат зависит от того, на какой момент по отношению к фазе
воздействи япридется максимальное отклонение маятника. Существенное обстоятельство состоит в том, что движение обладает чувствительной зависимостью от начальных условий, а
это как раз основной атрибут хаотической динамики. В самом деле, если скорость чуть-чуть
66
больше, то маятник проскочит верхнее положение равновесия, если скорость чуть-чуть меньше
- не дойдет до него и двинется назад.
[25]: from scipy import signal
# нелинейные колебания с трением gamma < omega0 и beta > 0, F > 0
x0 = 0.01
p0 = 0
omega0 = 1
gamma = 0.0
F = 1
Fm = 0
OMEGA = 0.33
beta = 1
k = -1
delta = OMEGA - omega0
T = 2*np.pi / OMEGA
t = np.arange(0, 1000, 0.01*2*np.pi/OMEGA)
z0 = [x0, p0]
sol1 = odeintw(diff_eq1, z0, t, atol=1e-13, rtol=1e-13, mxstep=1000)
num_q, num_p = sol1[:, 0], sol1[:, 1]
plt.plot(t, num_q, label='ODEint')
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.legend()
#plt.xlim([10, 20])
plt.title('Time series for $\gamma$=' + str(gamma) + ', $\omega_0$=' +␣
,→str(omega0) + ', $F=$' + str(F) +
', $F_m=$' + str(Fm) + ', $\Omega=$' + str(OMEGA))
plt.grid()
plt.show()
N = 1001
steps=5000000
sol1 = poincare(z0, N, steps)
xT, pT = np.real(sol1)
plt.figure()
plt.scatter(xT, pT, s=0.5, c='k', label='Poincare map')
#plt.plot(num_q, num_p, label='phase trajectories', lw=0.5)
plt.xlabel(r'$x$')
plt.ylabel(r'$p$')
plt.title('Poincare map, F = ' + str(F))
#plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
67
print(len(num_q))
data = np.real(num_q)
fourier = abs(sp.fft.fft(data))**2
#fourier = np.mean(fourier)
fourier /= np.max(fourier)
n = data.size
timestep = 0.01
freq = sp.fft.fftfreq(n, d=timestep)
mask = freq>=0
plt.plot(freq[mask], fourier[mask], label='SciPy PSD', lw=2)
#plt.plot(freq[~mask], fourier[~mask]) # отрицательная часть ввиду симметрии␣
,→преобразования Фурье
plt.grid()
plt.legend()
plt.xlim([-0.1, 5])
plt.xlabel('$\omega$')
plt.ylabel('$|x( \omega)|^2$')
plt.show()
fs = 1e1
# signal.welch
f, Pxx_spec = signal.welch(data, fs, 'flattop', 1024, scaling='spectrum')
plt.figure()
plt.semilogy(f, np.abs(Pxx_spec))
plt.xlabel('frequency')
plt.ylabel('Linear spectrum')
plt.title('Power spectrum (scipy.signal.welch)')
#labels = ['$\omega$', '$2 \omega$', '$4 \omega$', '$6 \omega$', '$8 \omega$',␣
,→'$10 \omega$']
#plt.xticks(np.arange(0, freqs[-1] + 1, 1000), labels)
plt.show()
68
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=1001.0),␣
,→HTML(value='')))
69
5253
70
[26]: import math
def chirikov(z0):
x0, p0 = z0
a = math.sqrt(x0**2 + p0**2 / omega0**2)
wa = 1/8 * ( ( ( a )**( 2 ) * ( delta )**( 2 ) + ( a )**( 2 ) * ( gamma \
)**( 2 ) ) )**( -1 ) * ( 3 * ( a )**( 4 ) * beta * delta -1 * ( ( \
32 * ( a )**( 2 ) * ( delta )**( 2 ) * F + ( -9 * ( a )**( 8 ) * ( \
beta )**( 2 ) * ( gamma )**( 2 ) + 32 * ( a )**( 2 ) * F * ( gamma \
)**( 2 ) ) ) )**( 1/2 ) )
dwa = 1/4 * ( a )**( -1 ) * ( ( ( delta )**( 2 ) + ( gamma )**( 2 ) ) )**( \
-1 ) * ( ( a )**( 2 ) * ( 32 * ( delta )**( 2 ) * F + ( -9 * ( a )**( \
6 ) * ( beta )**( 2 ) + 32 * F ) * ( gamma )**( 2 ) ) )**( -1/2 ) * ( \
-16 * ( delta )**( 2 ) * F + ( -1 * ( 9 * ( a )**( 6 ) * ( beta )**( \
2 ) + 16 * F ) * ( gamma )**( 2 ) + 3 * ( a )**( 2 ) * beta * delta * \
( ( a )**( 2 ) * ( 32 * ( delta )**( 2 ) * F + ( -9 * ( a )**( 6 ) * \
( beta )**( 2 ) + 32 * F ) * ( gamma )**( 2 ) ) )**( 1/2 ) ) )
chir = math.sqrt(np.abs( F * dwa * ( wa )**( -1 ) ) )
return(chir)
chirikov(z0)
[26]: 10.000002651648671
4.2 Бифуркационная диаграмма и главный показатель Ляпунова
На рисунке показана возможная бифуркационная диаграмма для системы при амплитудах
воздействия в диапазоне 0 < F < 0.7. Вертикальная ось, помеченная r, представляет
собой
p
расстояние от точки на отображении Пуанкаре до начала координат (r = x2 + p2 ).
Старший показатель Ляпунова. Для оценки хаотичности системы используется старший показатель Ляпунова. Критерий стохастичности формулируется так: если все установившееся
траектории, располагающиеся в ограниченной области фазового пространства, неустойчивы,
то их поведение стохастическое. Если установившееся траектория находится в ограниченной
области фазового пространства, то она рано или поздно подойдет к той точке, из которой
вышла (в гамильтоновых системах это верно для любых траекторий). Пойдет ли она дальше
по этому пути? Нет, если траектория неустойчива, то отклонение должно нарастать. Таким
образом, если у траекторий и есть похожие участки, то через определенное время схожесть
исчезнет.
Простейший способ исследования устойчивости состоит в следующем: сначала вычисляется
некоторое решение x1 (t). Затем задается смещение начальных условий и процедура повторяется, находится новое решение x2 (t). Логарифм разности ln | x1 (t) − x2 (t)| строится как функция
времени: траектории разбиваются на последовательные ортезки, на каждом из них высчитывается логарифм разности, и среднее значение от логарифмов в конце отрезков дает искомую
71
величину λ. Если λ < 0, то движение считается регулярным, если λ > 0 - стохастическим.
[27]: from scipy.integrate import odeint
x0 = 1
p0 = 0
omega0 = 1
gamma = 0.15
Fm = 0.0
OMEGA = 1.2
T = 2*np.pi / OMEGA
beta = 1
k = -1
rs_up = []
rs_down = []
steps = 5000
# Take num_steps=4000 to get Figure 9.13.
num_steps = 7002
step = 0.0001
interval = num_steps * step
a, b = x0, p0
ns = np.linspace(0, num_steps, num_steps)
lyaps = []
lyaps1 = []
chirikovs = []
chirikovs1 = []
shift = 1e-1
# Ramp the amplitude of vibration, gamma, up.
for n in notebook.tqdm(ns):
F = step * n
t = np.linspace(0.0, (4*np.pi) / OMEGA, 200)
xs = odeint(diff_eq1, [a, b], t, mxstep=steps)
xs1 = odeint(diff_eq1, [a + shift, b], t, mxstep=steps)
dx = np.abs(xs[:, 0] - xs1[:, 0])
dp = np.abs(xs[:, 1] - xs1[:, 1])
Dist = np.sqrt(dx**2 + dp**2)
LogDist = np.log(Dist)
lyaps.append(np.mean(LogDist))
chirikovs.append(chirikov([a, b]))
for i in range(2):
a = xs[100, 0]
b = xs[100, 1]
r = np.sqrt(a**2 + b**2)
rs_up.append([n, r])
72
rs_up = np.array(rs_up)
lyaps = np.array(lyaps)
chirikovs = np.array(chirikovs)
# Ramp the amplitude of vibration, gamma, down.
for n in notebook.tqdm(ns):
F = interval - step * n
t = np.linspace(0.0, (4*np.pi) / OMEGA, 200)
xs = odeint(diff_eq1, [a, b], t, mxstep=steps)
xs1 = odeint(diff_eq1, [a + shift, b], t, mxstep=steps)
dx = np.abs(xs[:, 0] - xs1[:, 0])
dp = np.abs(xs[:, 1] - xs1[:, 1])
Dist = np.sqrt(dx**2 + dp**2)
LogDist = np.log(Dist)
lyaps1.append(np.mean(LogDist))
chirikovs1.append(chirikov([a, b]))
for i in range(2):
a = xs[100, 0]
b = xs[100, 1]
r = np.sqrt(a**2 + b**2)
rs_down.append([num_steps - n, r])
rs_down = np.array(rs_down)
lyaps1 = np.array(lyaps1)
chirikovs1 = np.array(chirikovs1)
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=7002.0),␣
,→HTML(value='')))
<ipython-input-26-d6f121899cda>:6: RuntimeWarning: invalid value encountered in
double_scalars
)**( 2 ) ) )**( -1 ) * ( 3 * ( a )**( 4 ) * beta * delta -1 * ( ( \
<ipython-input-26-d6f121899cda>:12: RuntimeWarning: invalid value encountered in
double_scalars
-1 ) * ( ( a )**( 2 ) * ( 32 * ( delta )**( 2 ) * F + ( -9 * ( a )**( \
<ipython-input-26-d6f121899cda>:16: RuntimeWarning: invalid value encountered in
double_scalars
( ( a )**( 2 ) * ( 32 * ( delta )**( 2 ) * F + ( -9 * ( a )**( 6 ) * \
HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=7002.0),␣
,→HTML(value='')))
[28]: plt.figure()
plt.plot(rs_up[:, 0]*step, 2*rs_up[:,1] + 2, 'r.', ms=0.1, label='$4r + 2$ up')
73
plt.plot(rs_down[:, 0]*step, 2*rs_down[:,1] + 2, 'b.', ms=0.1, label='$4r + 2$␣
,→down')
plt.axhline(y=0, lw=0.2)
plt.plot(ns*step, lyaps, 'k', ms=0.1, label='$\lambda$ (LogDist) up, shift=' +␣
,→str(shift))
plt.plot(ns*step, lyaps1[::-1]-5, 'orange', ms=0.1, label='$\lambda$ (LogDist)␣
,→down, shift=' + str(shift) +
',\n zero at y=-5')
plt.axhline(y=-5, lw=0.2)
plt.xlabel(r'$F$')
plt.ylabel(r'$r$')
# Plot legend.
lgnd = plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
#change the marker size manually for both lines
lgnd.legendHandles[0]._legmarker.set_markersize(6)
lgnd.legendHandles[1]._legmarker.set_markersize(6)
#plt.ylim([-0.1,0.1])
plt.show()
plt.figure()
plt.plot(ns*step, chirikovs, 'cyan', label='Chirikov\'s up')
plt.plot(ns*step, chirikovs1[::-1], 'green', label='Chirikov\'s down')
plt.axhline(y=0, color='r', lw=0.5)
plt.xlabel(r'$F$')
plt.ylabel(r'$Chirikov$')
# Plot legend.
lgnd = plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
#change the marker size manually for both lines
lgnd.legendHandles[0]._legmarker.set_markersize(6)
lgnd.legendHandles[1]._legmarker.set_markersize(6)
plt.show()
fig, axs = plt.subplots(2)
plt.subplots_adjust(hspace=0.7)
axs[0].plot(rs_up[:, 0]*step, rs_up[:,1], 'r.', ms=0.1, label='$4r + 2$ up')
axs[0].plot(rs_down[:, 0]*step, rs_down[:,1], 'b.', ms=0.1, label='$4r + 2$␣
,→down')
axs[0].axhline(y=0, lw=0.2)
axs[0].set_title('Largest Lyapunov exponent')
axs[1].plot(ns*step, chirikovs, 'red', label='Chirikov\'s up')
axs[1].plot(ns*step, chirikovs1[::-1], 'lime', label='Chirikov\'s down')
axs[1].axhline(y=0, lw=0.2)
axs[1].set_title('Chirikov\'s criteria')
axs[1].set(xlabel='$F$', ylabel='Chirikov\'s')
axs[0].set(xlabel='$F$', ylabel='$\lambda$')
fig, axs = plt.subplots(2)
74
plt.subplots_adjust(hspace=0.7)
fig.suptitle('Largest Lyapunov exponent')
axs[0].plot(ns*step, lyaps, 'k', ms=0.1)
axs[0].axhline(y=0, lw=0.2)
axs[0].set_title('$\lambda$ (LogDist) up')
axs[1].plot(ns*step, lyaps1[::-1], 'orange', ms=0.1)
axs[1].axhline(y=0, lw=0.2)
axs[1].set_title('r')
for ax in axs.flat:
ax.set(xlabel='$F$', ylabel='$\lambda$')
plt.show()
75
76
Параметр F увеличивается от нуля до 0.7, а затем уменьшается с F = 0.4 до нуля. Было использовано 4000 итераций. Сплошная кривая, лежащая приблизительно между 0 ≤ F ≤ 0.29,
соответствует регулярному движению. Когда F превышает значение 0.29, система переходит в
хаотический режим и возвращается к периодическому поведению в точке F = 0.34, затем подобная картина наблюдается еще раз. При уменьшении параметра F система возвращается по
периодическим путям, входит в хаотическую область, возвращаясь к стационарному решению
при F ≈ 0.28. Обратите внимание, что на этапе увеличения амплитуды силы, установившееся
состояние переходит в область, где система имеет два периода, примерно $ 0.28 < F < 0.29$.
4.3
Корреляционная функция
[29]: print(len(num_q))
data = num_q
Mc = int(len(data) / 2)
Mc = 500
sx = np.mean(data)
Vx = np.var(data)
Nsteps = 500
dxt = [data[i] - sx for i in range(Mc+1)]
R = []
for i in range(Mc):
summ = 0
for j in range(i, Nsteps):
summ += dxt[j]*dxt[j - i + 1]
R.append(summ / ((Nsteps + 1 - i) * Vx))
plt.figure()
plt.xlabel('$i$')
plt.ylabel('$R$')
#plt.tick_params(labelsize=lblsize)
plt.plot(R)
plt.show()
5253
77
[30]: # Plot autocorrelation
plt.acorr(data, maxlags=data.size-1)
# Add labels to autocorrelation plot
plt.title('Autocorrelation')
plt.xlabel('Lag')
plt.ylabel('Autocorrelation')
# Display the autocorrelation plot
plt.xlim([-2,len(data)])
plt.show()
78
[ ]:
79
Download