Note
Go to the end to download the full example code.
An elastic KdV soliton-soliton collision#
Korteweg and de Vries’s 1895 equation,
finally explained Russell’s wave mathematically – and revealed something
stranger still: a fast, tall soliton overtaking a slower, shorter one
passes straight through it, each recovering its exact original
amplitude and speed afterward, merely phase-shifted. Here two exact
kdv_soliton() humps of speed
\(c=9\) and \(c=4\) (amplitude \(c/2\)) are launched on a
periodic domain with the faster one trailing; propagating the sum
forward with kdv_evolve() lets the
fast soliton catch up to and pass through the slow one. This “elastic
collision” is utterly unlike an ordinary nonlinear wave, which would
break up or change shape on impact.
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import find_peaks
from physicskit.fields import kdv_evolve, kdv_evolve_frames, kdv_soliton, plot_field_1d
A fast, tall soliton launched behind a slower, shorter one#
The faster soliton overtakes and passes straight through the slower one#
Elastic collision: both amplitudes survive completely unchanged (\(c/2\) = 4.5 and 2.0), only their positions are shifted.
peaks, _ = find_peaks(u, height=1.0)
surviving = sorted(round(float(h), 1) for h in u[peaks])
fig, ax = plot_field_1d(x, u0, label="t = 0")
plot_field_1d(x, u, ax=ax, label="after collision")
ax.set_title(f"surviving amplitudes: {surviving}")
fig.tight_layout()
print(f"surviving amplitudes after collision: {surviving} (expected [2.0, 4.5])")
![surviving amplitudes: [2.0, 4.5]](../../../../_images/sphx_glr_plot_kdv_elastic_collision_001.png)
surviving amplitudes after collision: [2.0, 4.5] (expected [2.0, 4.5])
A space-time diagram: watching the pass-through itself#
The before/after comparison above only shows the two endpoints; recording
every intermediate snapshot with kdv_evolve_frames()
(the same Strang-split integrator, restructured only to also keep a
history) and stacking them into an image shows the actual collision: two
ridges of different slope (speed) converging, visibly merging into one
taller ridge as the fast soliton overtakes the slow one, then separating
again afterward with each ridge’s slope unchanged – the elastic
pass-through, not a mere before/after coincidence.
n_frames = 120
frames, times = kdv_evolve_frames(u0, x, dt=0.0005, steps_per_frame=6000 // n_frames, n_frames=n_frames)
fig2, ax2 = plt.subplots()
extent = (x.min(), x.max(), times.min(), times.max())
im = ax2.imshow(frames, extent=extent, origin="lower", aspect="auto", cmap="viridis")
fig2.colorbar(im, ax=ax2, label="u(x, t)")
ax2.set_xlabel("x")
ax2.set_ylabel("t")
ax2.set_title("Space-time diagram: fast soliton overtakes and passes through the slow one")
fig2.tight_layout()

Total running time of the script: (0 minutes 1.209 seconds)