A Wave Reflecting On A Boundary

An incident wave

$$ u_I(x, t) = F_I(t - x/c) $$

arrives perpendicularly at a boundary separating two media gives rise to a reflected wave

$$ u_R(x, t) = F_R(t + x/c) $$

Writing that the disturbance is zero at the boundary (which we set on the origin) we obtain the following

$$ u_I(0, t) + u_R(0, t) = 0 \; \forall t \Rightarrow F_R(t) = - F_I(t)$$

In the following lines, we plot that relation with a given waveform.

In [1]:
%matplotlib inline
In [2]:
from pylab import *
In [3]:
t = linspace(-10, 10, num=1000)
In [4]:
def waveform(t):  
    return sin(5*t) * exp(-abs(t**3))
In [5]:
plot(t, waveform(t))
Out[5]:
[<matplotlib.lines.Line2D at 0x520b1d0>]

By plotting the waveform at different $t - x/c$ (with $c$, the speed of the wave implicitly equal to 1) values, we can see it move forward.

In [6]:
x = linspace(-10, 10, num=1000)
In [7]:
plot(t, waveform(x), label='t=0')
plot(t, waveform(3 - x), label='t=3')
plot(t, waveform(7 - x), label='t=7')
legend(loc='lower left')
Out[7]:
<matplotlib.legend.Legend at 0x5341fb0>

Writing a function that sums up the adding of the waves gives the following result.

In [8]:
def plot_timestep(x, t):
    # incident wave
    inc = waveform(t - x)
    plot(x, inc, label='incident')
    # reflected wave
    ref = - waveform(t + x)
    plot(x, ref, label='reflected')
    # sum
    plot(x, inc + ref, label='sum', lw=2)
In [9]:
figure(figsize=(10, 7))
for ind, val in enumerate([-3, -0.5, 1, 4]):
    subplot(2, 2, ind + 1)
    plot_timestep(t, val)
    grid(True)
    legend(loc='lower right')
    title('time = %i' % val)
tight_layout()

This can now be compiled into an animation, courtesy of this nice article by Jake Vanderplas and a helpful comment.

In [10]:
from tempfile import NamedTemporaryFile

VIDEO_TAG = """<video controls>
 <source src="data:video/x-m4v;base64,{0}" type="video/mp4">
 Your browser does not support the video tag.
</video>"""

def anim_to_html(anim):
    if not hasattr(anim, '_encoded_video'):
        f = NamedTemporaryFile(suffix='.mp4', delete=False)
        anim.save(f.name, fps=20, extra_args=['-vcodec', 'libx264', '-pix_fmt', 'yuv420p'])
        video = open(f.name, "rb").read()
        f.close()
        anim._encoded_video = video.encode("base64")
    
    return VIDEO_TAG.format(anim._encoded_video)
In [11]:
from IPython.display import HTML

def display_animation(anim):
    plt.close(anim._fig)
    return HTML(anim_to_html(anim))
In [12]:
from matplotlib import animation

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(-10, 10), ylim=(-1, 4))
line_inc, = ax.plot([], [], lw=1, label='incident')
line_ref, = ax.plot([], [], lw=1, label='reflected')
line_sum, = ax.plot([], [], lw=2, label='sum')
vlines(0, -1, 4, linestyles='dashed', lw=4)
annotate("totally reflecting wall",
            xy=(0, 2), xycoords='data',
            xytext=(5, 3.25), textcoords='data',
            size=10, va="top", ha="center",
            arrowprops=dict(arrowstyle="simple",
                            connectionstyle="arc3,rad=-0.2"), 
            )
legend(loc='center right')

# initialization function: plot the background of each frame
def init():
    line_inc.set_data([], [])
    line_ref.set_data([], [])
    line_sum.set_data([], [])
    return line_inc, line_ref

# animation function.  This is called sequentially
def animate(i):
    x = linspace(-10, 10, 1000)
    t = linspace(-7, 7, num=100)[i]
    # incident wave
    inc = waveform(t - x)
    # reflected wave
    ref = - waveform(t + x)
    # sum
    total_wave = inc + ref
    line_inc.set_data(x, inc)
    line_ref.set_data(x, ref)
    line_sum.set_data(x, total_wave + 2)
    return line_inc, line_ref

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

# call our new function to display the animation
display_animation(anim)
Out[12]:

Comments