import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
from IPython.display import HTML
Wave Equation
Import required libraries
Set up the values for the wave equation
= 2*np.pi # Length of the string
L = 100 # Number of spatial points
Nx = 100 # Number of time steps
Nt = L/(Nx-1) # Spatial step size
dx = 5 # Wave speed
v = np.sqrt(1)*dx/v # Time step size
dt
print(f"dt: {dt}s")
# Initialize the spring
= np.linspace(0, L, Nx)
x = np.zeros(Nx)
y = np.zeros(Nx)
y_old
# initial disturbance
= np.sin(x)
y_old # Apply fixed boundary conditions
0] = y_old[Nx-1] = 0
y_old[0] = y[Nx-1] = 0
y[
# make sure the C calculated comes out to 1
= (v*dt/dx)**2
C print(C)
dt: 0.012693303650867852s
1.0
The partial differential equation we are solving is \[ \frac{\partial^2 y}{\partial^2 t} = \frac{T}{\mu} \frac{\partial^2 y}{\partial^2 x} \] Then to solve the differential equation we can use the formula \[ y_{i+1,j}= 2y_{i,j} -y_{i-1,j} + C(y_{i,j+1} - 2y_{i,j} + y_{i,j-j}) \] where the i index represents time and the j index represents position. C is defined by \[ C=(T/\mu)(\Delta t)^2/(\Delta x)^2 \] for the first timestep, we dont have a previous time, so instead we use our initial velocity condition \(\frac{\partial y}{\partial t} = 0\) at \(t=0\) which in turn we can use the forward difference formula and the previous formula for the differential equation to gain a new formula \[ y_{i,j}= y_{i-1,j} + \frac{1}{2}C(y_{i-1,j+1} - 2y_{i-1,j} + y_{i-1,j+1j}) \] One important thing to note is that for the numerical approximation to be stable, \(C<=1\) where the theoretical solution is when equivalence holds
# compute initial timestep assuming initial velocity is 0
1:-1] = y_old[1:-1] + 0.5 * C * (y_old[2:] - 2 * y_old[1:-1] + y_old[:-2])
y[def update_string(y_old, y):
= np.zeros(Nx)
y_new # Use np slices to compute everything in parallel,
1:-1] = 2*y[1:-1] - y_old[1:-1] + C*(y[2:] - 2*y[1:-1] + y[:-2])
y_new[# Update arrays for next iteration
= y[:]
y_old[:] = y_new[:] y[:]
Finally we can plot the data and also view it as an animation
# Set up the plot
= plt.subplots()
fig, ax = ax.plot(x, y)
line, -1.5, 1.5)
ax.set_ylim(0, L)
ax.set_xlim('Vibrating String')
ax.set_title('Position (m)')
ax.set_xlabel('Displacement (m)')
ax.set_ylabel(# Animation function
= 2
skip def animate(frame):
global y_old, y, y_new, skip
for _ in range(skip):
update_string(y_old, y)
line.set_ydata(y)return line,
# Create animation
= FuncAnimation(fig, animate, frames=Nt, blit=True, interval=dt*1000*skip)
ani '../../videos/standing_wave.mp4', writer='ffmpeg', fps=1/(dt*skip))
ani.save( HTML(ani.to_jshtml())