Home > three_d.js > Examples

## KdV solitons

The Korteweg-de Vries equation is the non-linear PDE ut + uxxx + 6uux = 0. It allows soliton solutions – solitary waves that do not lose their shape, the non-linearity of the equation somehow perfectly offsetting the dispersion – which are appropriately-scaled sech2 functions.

The JavaScript on this page numerically solves the KdV equation with the split-step FFT method, following the very handy page on Wikiwaves, written by Michael Meylan. For the Fourier transforms I have used Nick Jones' jsfft.

The calculation is a pretty heavy one, and on my phone the controls become quite unresponsive (it takes a few seconds to register when I tap 'Pause', but it does eventually halt the calculation). Choices below the plot for the initial values of u are a single soliton (default); two solitons, which collide and show a phase shift; and a couple of non-soliton waves – one a sech2 function of the wrong height-to-width ratio, and a sine wave that roughly approximates the single soliton choice, but which immediately breaks apart. I find the top-down view the most rewarding.

The calculation will start when you click the appropriate phrase below the plot.

Mouse controls: Left-click and drag to rotate; alt (Mac)- or ctrl (Windows)-click-drag or middle-click-drag to pan; scroll or shift-click-drag to zoom. Touch screen controls: one finger to rotate; two-finger scroll to pan; pinch to zoom. Click/tap on the cube icons to snap to a side-on view.

Initial state: Start calculation.

Reset.

You can see how the plot is constructed in the HTML source:

• The basic idea is to initialise `params.data.z` to have values of zero in the row/column corresponding to t=0, and null values elsewhere. This is done in `init_plot()`, which also sets the axes (time goes to the x-axis, x goes to the y-axis, fun).
• The position axis for the PDE (y-axis in the plot) has its axis reversed compared to what I want from t-x-u axes, so I use `params.y_scale_bounds = [10.5, -10.5];` to have it the right way round.
• Immediately after initialising, `init_wave()` reads what sort of initial wave form is chosen, fills in a `complex_array.ComplexArray` called `kdv_u` (global variable) and then calls `three_d.set_surface_point_z()` to fill in the correct initial values at t=0.
• The calculation starts by calling `integrate_system()`, which then gets repeatedly called in `requestAnimationFrame()`. First it calls `step_forward()`, asking for 3000 time steps, to update `kdv_u`. Then the values of `kdv_u` are copied into the next row of the plot, via `three_d.set_surface_point_z()`.
• The grid is too fine for the mesh to look nice at the standard zoom, so it is hidden as soon as the calculation starts with `three_d.hide_mesh()`. The mesh needs to be shown before the calculation starts, though, so that the initial wave can be seen. (Surfaces of zero width are never drawn.)

Posted 2016-12-22.

Home > three_d.js > Examples