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]: