Task 3 of 5
You have been told where the line is. Now measure it — and measure it the way a GPU makes cheap: not by running sixteen simulations one after another, but by running all sixteen in the same kernel launch.
The grid below is 64 columns by 16 rows, and each row is its own universe: a
64-cell ring, seeded with one hot cell, stepped with its own
dts[row]. Nothing couples the rows, so the Laplacian here is the 1D one,
left + right − 2·centre, along x only. Reach for the
familiar 5-point stencil and row 3's instability leaks into row 4.
Rings are one-dimensional, so dims = 1 and the limit moves:
dt ≤ dx²/(2·D·1) = 1, twice what it was on the 2D grid. That factor is
not decoration — it is the number of neighbours taking a bite out of the centre. After
90 steps the answer is unmissable: the stable rows have flattened to a few hundredths,
and the row on the other side of the line is at 10³.
dt whose row is still under 1 — and compare it with
dx²/(2·D·1).dts[this.thread.y]x only: left + right − 2·centre — rows must not read each other|u|; a row survived if that is below 1dt on a line that says measured, and the predicted limit beside itthis.thread.y is the row, so dts[this.thread.y] is this
ring's step size. Turn it into a diffusion number the same way as before:
const a = this.constants.diff * dts[r]
/ (this.constants.dx * this.constants.dx);return u[r][x] + a * (u[r][xl] + u[r][xr] - 2 * u[r][x]); — note the
2, not 4. Only the row index r never varies.
Plain JavaScript on the finished grid:
for (let r = 0; r < ROWS; r++) {
let m = 0;
for (let x = 0; x < CELLS; x++) {
const a = Math.abs(u[r][x]);
if (!(a <= m)) m = a; // so a NaN cannot hide
}
if (m < 1 && dts[r] > measured) {
measured = dts[r];
}
}This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.