Consider the motion of a frictionless vibrating string tethered at $x=0$ and $x=L$. The motion is given by the differential equation $$ \frac{\partial^2 u}{\partial t^2} c^2 = \frac{\partial^2 u}{\partial x^2} $$ where $u$ is the displacement perpendicular to $x$ and $c$ is a characteristic velocity that depends on the tension and mass per unit length of the string. This secound order differential equation can be solved by seperation of variables, and for a given initial waveform $f(x)$ solutions can be written as $$ u(x,t)=\sum_n A_n \phi(x)\cos(\omega t) $$ where $n=1,2,3,\ldots$, $\omega=n\pi c /L$, $$ \phi(x)=\sin(n\pi x/L) $$ and $$ A_n = \frac{2}{L}\int_0^L f(x)\phi_n(x)dx. $$ The tethered of the string dictates that $f(0)=f(L)=0$.
# Import modules
import numpy as np
import matplotlib.pyplot as plt
import IPython.display as ipd
# Initialize global variables
L=0.65 # m
c=2*220*L # 220 is the frequency of the first harmonic
print('L =',L,'m ;','c =',c,'m/s')
dx=L/1000
x=np.arange(0, L, dx)
f=x**4*(L-x)
f/=np.max(f)
plt.plot(x,f)
plt.title('Initial waveform')
plt.xlabel('x [m]')
plt.ylabel('f=u(x,t=0)')
plt.show()
# Return the "standing wave" solutions
def phi(n=1):
return np.sin(n*np.pi*x/L)
An=[]
nmax=30
for n in range(1,nmax+1):
An.append(2*np.trapz(f*phi(n=n)/L,x))
print('An =',An)
plt.plot(An)
plt.title("$A_n$ expansion coefficients")
plt.show()
def wave(t=0):
u=0*x;
n=0
for A in An:
n+=1
omega=n*np.pi*c/L
u += A*phi(n=n)*np.cos(omega*t)
return u
# Show wave at different times
for i in range(17):
rate=10000
t=i/rate
plt.plot(x,wave(t=t),label=' t=' + str(t) +' s')
plt.xlabel('x [m]')
plt.ylabel('u')
#plt.legend()
plt.show()
# Save animation as movie
import matplotlib.animation as animation
#fig, ax = plt.subplots(dpi=150)
fig, ax = plt.subplots()
line, = ax.plot(x, wave(t=0))
plt.xlabel('x [m]')
plt.ylabel('u')
plt.ylim(-1,1)
def init(): # only required for blitting to give a clean slate.
line.set_ydata([np.nan] * len(x))
return line,
def animate(i):
line.set_ydata(wave(t=i/22000)) # update the data.
return line,
ani = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True, save_count=300)
from matplotlib.animation import FFMpegWriter
writer = FFMpegWriter(fps=30, metadata=dict(artist='Ulf R. Pedersen (http://urp.dk)'), bitrate=3000)
ani.save("string.mp4", writer=writer)
ipd.Video("string.mp4")
# Write audiofile with sound
import scipy.io.wavfile
rate=44100
secounds=10.0
t=np.arange(0,secounds,1/rate)
sound=0*t
n=0
for A in An:
n=n+1
omega=n*np.pi*c/L
sound += A*np.sin(omega*t)
sound/=1.2*np.max(sound)
scipy.io.wavfile.write('sound.wav',rate=rate,data=sound)
ipd.Audio('sound.wav')
ipd.Video(data="./string.webm")