Yazıda scipy
paketinin içindeki odeint
çözücüyü işleyeceğiz. Sayısal çözümler önemli çünkü çoğu ODE sisteminin
analitik çözümü yoktur. Onları sayısal paketler kullanarak çözmek
gerekir.
Bir sarkaç denklemi düşünelim, bu denklem ikinci dereceden \(\theta\)’yi baz alan bir denklemdir,
\[ \ddot{\theta}(t) + \frac{b}{m} \dot{\theta}(t) + \frac{g}{L} \sin(\theta(t)) = 0 \]
Ya da \(m = 1\) dersek ve \(\frac{g}{L} = c\) ile
\[ \ddot{\theta}(t) + b \dot{\theta}(t) + c \sin(\theta(t)) = 0 \]
ki \(b,c\) dışarıdan tanımlanan sabitler, ve üst nokta zamansal türevi temsil ediyor.
Bu denklemi odeint
ile çözmek için onu ilk önce bir
birinci derece denklemler sistemine çevirmemiz gerekiyor.
\[ \omega(t) = \dot{\theta}(t) \]
dersek (okunuş olarak \(\omega\) omega, \(\theta\) theta),
\[ \dot{\theta} = \omega(t) \]
\[ \dot{\omega}(t) = -b \omega(t) - c\sin(\theta(t)) \]
elde ederiz. Şimdi pend
adlı bir fonksiyon
tanımlayalım,
= 0.25
b = 5.0
c
def pend(y, t):
= y
theta, omega return [omega, -b*omega - c*np.sin(theta)]
Bu fonksiyon ana ODE çözücünün denklemimiz hakkında bilgi aldığı
nokta, y
dizini içinde \(\dot{\theta}\) ve \(\dot{\omega}\) var, onları \(y\) içinde aynen bu sırada almayı
bekliyoruz ve yenilerini hesapladıktan sonra geri döndürürken de aynen
bu sırada döndürüyoruz. Mesela döndürülen dizinde ilk öğe
omega
var, bu doğru, çünkü biraz önce \(\dot{\theta} = \omega(t)\) tanımını
yapmıştık, yani ilk öğede theta
turevi geri vermiş olduk,
alırken theta,omega=y
ile theta
aldığımız
gibi.
t
değişkeninde çoğunlukla zaman tanımlanır, ve bu zaman
ilgilendiğimiz zaman aralığı belli (çoğunlukla eşit aralıklı) noktalar
üzerinden dizin olarak odeint
’e verilir, bunu
linspace
ile yapabiliriz. \(y\) için başlangıç şartlarını ayrı bir
değişken içinde, mesela y0
, tanımlarız, bu aynen
y
büyüklüğünde bir dizin olacaktır ve y
için
olduğu gibi ilk öğe theta
ikinci öğe omega
için başlangıç değerini tanımlayacak.
Hepsi bir arada
from scipy.integrate import odeint
= 0.25
b = 5.0
c
def pend(y, t):
= y
theta, omega return [omega, -b*omega - c*np.sin(theta)]
= np.linspace(0, 10, 101)
t
= [np.pi - 0.1, 0.0]
y0
= odeint(pend, y0, t)
sol
print (sol.shape)
(101, 2)
Başlangıç noktası \(\theta\) için \(\pi - 0.1\), yani şarkacın en üst noktasından biraz yanda. Açı olarak \(\theta=0\) sarkacın nötr durduğu nokta, \(\pi\) en üst noktası.
Sayısal çözüm sırasında bir dizi \(\theta,\omega\) elde edildi. Bu değerler
hesaplandıkları gibi zamansal sırada, bir dizin içindeler ve üstte
gördüğümüz gibi 101,2
boyutlu bir dizin bu. En son varılan
değer
print (sol[-1])
[0.02001168 1.56781812]
Degiskenleri grafiklersek
import matplotlib.pyplot as plt
0], 'b', label='theta(t)')
plt.plot(t, sol[:, 1], 'g', label='omega(t)')
plt.plot(t, sol[:, ='best')
plt.legend(loc't')
plt.xlabel(
plt.grid()'ode_mattuck_70_odeint_01.png') plt.savefig(
Şarkaçın hareketini görmek istiyorsak,
= 9.8 / c
L = L*np.sin(sol[:,0])
x1 = -L*np.cos(sol[:,0]) y1
from matplotlib.patches import Circle
import matplotlib.pyplot as plt
from numpy import cos, sin
def make_plot(fout,x1,y1):
= 0.05
r = plt.figure()
fig = fig.add_subplot(111)
ax -3,3)
ax.set_xlim(-3,3)
ax.set_ylim(0, x1], [0, y1], lw=2, c='k')
plt.plot([= Circle((0, 0), r/2, fc='k', zorder=10)
c0 = Circle((x1, y1), r, fc='b', ec='b', zorder=10)
c1
ax.add_patch(c0)
ax.add_patch(c1)
plt.savefig(fout)
for i in range(len(x1)):
if i % 5 == 0:
'frames/img{:04d}.png'.format(i),x1[i],y1[i]) make_plot(
Animasyon yaratabiliriz,
import os
"convert -loop 0 -delay 100 frames/*.png frames/pend.gif") os.system(
Sonuç [2]’de görülebilir.
Not: Bir ODE sistemini çözmek hakkında konuşurken bazen onu “entegre ettiğimiz’’ de söylenir. Bu aslında yanlış bir tarif değil, çünkü eşitliklerin sol tarafında \(\dot{x}_1\), \(\dot{x}_2\) gibi değişkenler var, bizim ilgilendiğimiz, çözerek elde etmek istediğimiz sonuç \(x_1\), \(x_2\) değerleri. Aslında yapılanın bir bakıma sistemi”ileri doğru işletmek’’ olduğu da söylenebilir, değişim denklemlerini kullanarak sistemın simülasyonunu yapıyoruz bir bakıma.
Kaynaklar
[1] SciPy.org, scipy.integrate.odeint, https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html
[2] Bayramlı, Sarkac Animasyonu, https://github.com/burakbayramli/classnotes/blob/master/ode/ode_mattuck_70_odeint/frames/pend.gif