Skip to content
Projects

Travelling wave animation

A Gaussian pulse splitting into two halves that travel in opposite directions.

d’Alembert’s solution of the wave equation utt=c2uxxu_{tt} = c^2 u_{xx} with u(x,0)=e−x2u(x, 0) = e^{-x^2} and ut(x,0)=0u_t(x, 0) = 0 is

u(x,t)=12[e−(x−ct)2+e−(x+ct)2].u(x, t) = \tfrac12\left[e^{-(x - ct)^2} + e^{-(x + ct)^2}\right].

Press play, or drag the slider. Plotly figures keep their frames, so animations work as well.

Loading figure…
travelling_wave.py
import numpy as np
import plotly.graph_objects as go
c = 1.0
x = np.linspace(-10.0, 10.0, 400)
times = np.linspace(0.0, 7.0, 36)
def u(t: float) -> np.ndarray:
return 0.5 * (np.exp(-((x - c * t) ** 2)) + np.exp(-((x + c * t) ** 2)))
frames = [go.Frame(data=[go.Scatter(x=x, y=u(t))], name=f"{t:.1f}") for t in times]
steps = [
{
"label": f.name,
"method": "animate",
"args": [
[f.name],
{"mode": "immediate", "frame": {"duration": 0, "redraw": False}},
],
}
for f in frames
]
fig = go.Figure(
data=[go.Scatter(x=x, y=u(0.0), fill="tozeroy", line={"width": 3})],
frames=frames,
layout={
"title": "d'Alembert solution of the wave equation",
"xaxis": {"title": "x", "range": [-10, 10]},
"yaxis": {"title": "u", "range": [0, 1.05]},
"margin": {"b": 130},
"updatemenus": [
{
"type": "buttons",
"showactive": False,
"x": 0.0,
"y": -0.3,
"buttons": [
{
"label": "Play",
"method": "animate",
"args": [
None,
{
"frame": {"duration": 80, "redraw": False},
"fromcurrent": True,
},
],
},
{
"label": "Pause",
"method": "animate",
"args": [
[None],
{"mode": "immediate", "frame": {"duration": 0}},
],
},
],
}
],
"sliders": [
{
"steps": steps,
"y": -0.3,
"x": 0.15,
"len": 0.85,
"currentvalue": {"prefix": "t = "},
}
],
},
)
fig.show()