Task 2 of 5

Watch the Residual Fall

Iterating is easy; knowing when to stop is the skill. The honest measure is the residual: take the current guess, put it back into the equation, and see how badly it is violated. For "every cell equals the average of its four neighbours" that is the 5-point Laplacian — left + right + up + down − 4·centre — the same stencil Reaction–Diffusion uses to diffuse, borrowed here as a scorecard. Zero where the equation holds, large where it does not.

Boundary cells have no equation to violate: they are given, not solved. Their residual is 0 by definition rather than by accident, and saying so in the kernel keeps the edge from polluting the score forever.

A grid of numbers is not a progress report, so collapse it to one: the root-mean-square over the grid. Totalling a grid on the GPU is the halving ladder Reductions builds; at 1,024 cells the read-back is cheaper than the ladder, so this sum happens in plain JavaScript.

Goal: complete the residual kernel and the rmsOf helper. The sweep loop is already wired and will print the residual every 10 sweeps — you should watch it fall by a factor of about 36.

Requirements

Hint 1 — the kernel is the stencil, unaveraged

Same five reads as the Jacobi sweep, assembled differently: the update divides the neighbour sum by 4, the residual subtracts 4 × centre from it.

return u[y][x - 1] + u[y][x + 1] + u[y - 1][x]
     + u[y + 1][x] - 4 * u[y][x];
Hint 2 — the reduction is ordinary JavaScript

residual(u) hands back a plain 2D array of numbers, so:

let sum = 0;
for (let y = 0; y < 32; y++) {
  for (let x = 0; x < 32; x++) sum += grid[y][x] * grid[y][x];
}
return Math.sqrt(sum / (32 * 32));

Square, mean, root — in that order. Divide by every cell in the grid, not just the interior ones.

Same idea elsewhere

Every production solver stops on a residual, not on a sweep count, and every one of them argues about how often to measure it: the norm needs a reduction across the whole device and then a read-back to the host, which is a synchronisation point in CUDA, WebGPU and MPI alike. Checking every iteration can cost more than the iterations do — the usual answer is exactly what this task does, sample it every few sweeps.

All tasks in Iterative Linear Solvers

  1. One Sweep of Jacobi
  2. Watch the Residual Fall
  3. Colour the Board
  4. Two Halves Make a Sweep
  5. The Race

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.