In [1]:
from pylab import *
%matplotlib inline
from matplotlib import animation

# nastavitve za izris grafov (http://matplotlib.org/1.3.1/users/customizing.html)
rc('text', usetex=True)
rc('font', size=12, family='serif', serif=['Computer Modern'])
rc('xtick', labelsize='small')
rc('ytick', labelsize='small')
rc('legend', fontsize='medium')
rc('figure', figsize=(5, 3))
rc('lines', linewidth=2.0)
rc('axes', color_cycle=['k'])
rc('contour', negative_linestyle='solid')

Animacije

Pripravimo animacijo utripanja dveh vzmetnih nihal z masama \(m\) in koeficientoma vzmeti \(k\), sklopljenih s šibkejšo vzmetjo s koeficientom \(k^\prime\). Na začetku je raztezek vzmeti prvega nihala A, vzmet drugega pa je neraztegnjena. Obe uteži na začeku mirujeta. Rešiti moramo sklopljen sistem diferencialnih enačb

\[m\ddot{x_1}=-kx_1+k^\prime(x_2-x_1),\]

\[m\ddot{x_2}=-kx_2-k^\prime(x_2-x_1),\]

z začetnimi pogoji \(x_1(0)=A\), \(x_2(0)=0\), \(\dot{x_1}(0)=0\) in \(\dot{x_2}(0)=0\). Rešitev je

\[x_1(t)=\frac{A}{2}\left(\cos(\omega_1 t)+\cos(\omega_2 t)\right),\]

\[x_2(t)=\frac{A}{2}\left(\cos(\omega_1 t)-\cos(\omega_2 t)\right),\]

z \(\omega_1=\sqrt{\frac{k}{m}}\) in \(\omega_2=\sqrt{\frac{k+2k^\prime}{m}}\). V animaciji utripanje.gif je prikazana ena perioda utripanja za \(A=3\,\)cm, \(\omega_1=10\pi\,\)s\(^{-1}\) in \(\omega_2=12\pi\,\)s\(^{-1}\).

In [4]:
fig, ((axa), (axb)) = subplots(2, 1, figsize=(6, 3))
axa.set_xlim([0, 30])
axa.set_ylim([-1, 1])
vzmet1,=axa.plot([], [])
vzmet2,=axa.plot([], [])
vzmet3,=axa.plot([], [])
utez1,=axa.plot([], [], 'or', markersize=40)
utez2,=axa.plot([], [], 'ob', markersize=40)
axa.set_xlabel(r'Polo\v zaj (cm)')
axa.set_yticks([])
axa.grid()
axb.set_xlim([0, 1])
axb.set_ylim([-3, 3])
axb.set_xlabel(r'\v Cas (s)')
axb.set_ylabel(r'Odmik (cm)')
axb.grid()
crta,=axb.plot([], [])

A=3.0
w1=5.0 * 2 * pi
w2=6.0 * 2 * pi
x1t=lambda t: 0.5 * A * (cos(w1 * t) + cos(w2 * t))
x2t=lambda t: 0.5 * A * (cos(w1 * t) - cos(w2 * t))

t=linspace(0, 1, 200)
axb.plot(t, x1t(t), 'r', t, x2t(t), 'b')

def init():
    vzmet1.set_data([], [])
    vzmet2.set_data([], [])
    vzmet3.set_data([], [])
    utez1.set_data([], [])
    utez2.set_data([], [])
    crta.set_data([], [])

nf=200;    
def animate(f):    
    t=f / float(nf)
    x1=x1t(t)
    x2=x2t(t)
    vzmet1.set_data([0, 10 + x1], [0, 0])
    setp(vzmet1, lw=20 * 10 / (10 + x1))
    vzmet2.set_data([10 + x1, 20 + x2], [0, 0])
    setp(vzmet2, lw=10 * 10 / (10 - x1 + x2))
    vzmet3.set_data([20 + x2, 30], [0, 0])
    setp(vzmet3, lw=20 * 10 / (10 - x2))
    utez1.set_data([10 + x1], [0])
    utez2.set_data([20 + x2], [0])
    crta.set_data([t, t], [-A, A])
    fig.tight_layout(pad=0.3)

anim=animation.FuncAnimation(fig, animate, init_func=init, frames=nf, interval=25, blit=True)
anim.save('utripanje.gif', writer='imagemagick');
close()

Naloga

  1. Pripravi animacijo vodoravnega meta žoge z maso \(m\), na katero poleg sile teže (\(g=9.81\,\)m/s\(^2\)) deluje tudi zaviralna sila \(\mathbf{F}_\mathrm{u}\), za katero velja kvadratni zakon upora: \(\mathbf{F}_\mathrm{u}=-cmv\mathbf{v}\), \(c=1\,\)m\(^{-1}\). Žogo vržemo z višine \(1\,\)m nad vodoravnimi tlemi z začetno hitrostjo \(1\,\)m/s. Od tal se žoga odbija elastično. Animacijo pripravi v formatu "animated GIF". Velikost oddane datoteke naj bo največ \(5\,\)MB, uporabiš lahko program za stiskanje datotek v format RAR.