Waves on a Piano String

Sasha Bakker. Physics 281 HW4. Shubha Tewari. 11/30/18.

In [2]:
"""
Waves on a Piano String.

This program solves the wave equation for a 1D piano string.

The string is of length L and initially at rest.
At time t = 0 it is struck with velocity v to have displacement d.

The displacement, "height", at each position for an array of times
is calculated. A plot of the propogating wave is made for each 
user input value of alpha. 

""" 

# Import Packages
import numpy as np
import matplotlib.pyplot as plt

# Calculates the time step for all positions
def timeStep(a,v,alpha):
    return (a*np.sqrt(alpha))/v

# Calculates the initial velocity at a position
def velocity(x,C,L,d,s):
    return (C/L**2)*x*(L-x)*np.exp( (-(x-d)**2)/(2*s**2))

# Calculates the height for any position at a new time
def anyStep(wave,alpha,x,t):
    return 2*(1-alpha)*wave[x,t] + alpha*(wave[x+1,t]+wave[x-1,t]) - wave[x,t-1]

# Initialize constants
v = 100 # velocity of wave on string (m/s)
L = 1 # string length (m)
d = 0.1 # displacement (m)
C = 1 # speed (m/s)
s = 0.03 # st.dev. (m)
a = 0.5/100 # spatial step (m) 
N = int(L/a) # Number of positions

# Request values for alpha and save to an array
quan = int(input("How many alphas would you like to try? "))
alphas = np.zeros(quan)
for q in range(quan): alphas[q] = float(input("alpha = "))

# Make a plot for each alpha
for q in range(quan):
    
    # Initialize variables
    alpha = alphas[q] # user input value
    h = timeStep(a,v,alpha) # time step
    n = int(0.1/h) # Number of times
    
    # Arrays
    wave = np.zeros([N,n], float) # position,time
    positions = np.linspace(0,L,N) # positions on the string
    times = np.linspace(0,0.1,n) # range of times 
    
    # Calculate the initial velocity at every position
    velocities = velocity(positions,C,L,d,s)
    
    # Calculate the heights for the first time step
    heights = h*velocities
    
    # Define the heights for the first time step
    wave[:,1] = heights 
    
    # Calculate heights for each (x,t) condition to fufill the "wave" array 
    for t in range(1,n-1):
        
        for x in range(1,N-1):
    
            wave[x,t+1] = anyStep(wave,alpha,x,t)
    
    # Create a new figure if necessary
    if q > 0:
        plt.figure()
    
    # Plot the height vs. position for specified times
    for k in range(0,n,100):
        plt.plot(positions,wave[:,k])

    # Label and show the plot
    plt.title("Piano Wave Height vs. Position on Wave\nalpha = " + str(alpha))
    plt.show()

Part 3

When the wave pulse encounters the right boundary, it is reflected over the x axis. As the wave is inverting, its amplitude decreases to zero, then increases in the negative y-direction, restoring the string’s equilibrium displacement, before it travels in the opposite horizontal direction prior to the reflection. When it encounters the left boundary, another reflection occurs, with the magnitude of the amplitude decreasing to zero, then increasing in the positive y-direction.

Part 4

When the hammer strikes the string, the string has a deformation at that point. The amplitude increases to create a narrow curve, which is two overlapping waves. The waves travel outward from the point of initial deformation. The two travelling waves creates a slowly widening hump. This hump propagates to the right and follows the reflection pattern as described in part 3.

Part A.

  • The first case is alpha = 0.25. As the wave is slowly widening over the time frame, it gains a small indent at the top. As the indent increases it becomes clear that there are two overlapping waves. When the wave is above the x-axis, the right wave has a greater amplitude than the left wave. When the hump is inverted, the left wave has the greater amplitude than the right wave.
  • The second case is alpha = 1. The slowly widening wave remains uniform as one clear distinct hump with a single amplitude. It does not clearly separate into two overlapping waves, unlike for alpha < 1.
  • The third case is alpha = 1.0025. The wave starts of like alpha = 1. The reflection process begins as the hump gets close to the boundary, x = L. As this happens, an almond shape forms by the boundary x = 0. As it is reflecting, the almond shape’s amplitude grows exponentially, and it expands horizontally. This almond soon over-powers the hump and the plot becomes an almond shape with ends fixed at x = 0, x = L. Its amplitude continues to grow. For each position on the almond shape, its amplitude continuously increases and flips over the x-axis. The positions to the left and right of a position will always have an opposite direction of amplitude. This is caused by the term dependent on the present position and time being a negative term in the next time step calculation.

Part B.

The values of alpha than can be assumed to yield reliable numerical solutions is for alpha < 1. When alpha is greater than 1, the plot is no longer a propagating wave. When the value equals one, the shape of the wave does not have an accurate enough approximation such that its hump is uniform, which does not resemble the physical appearance of a wave on a piano string. The smaller the alpha, the better the approximation because smaller steps are taken when calculating the height of the wave at a position for the next time.

Part C.

Alpha = 1 behaves as a boundary for stability due to the height equation’s term for dependence on the present position and time having a negative sign. Because of this, the sign of the height is oscillating and increasing at each position, and the height is no longer converting to a fixed value.