# One Sweep of Jacobi

*Task 1 of 5 · [Iterative Linear Solvers](https://gpu.rocks/learn/iterative-solvers-e73b8e1f.md) · GPU.js Learn*

A square metal plate, its edges clamped at fixed temperatures. What does the
inside settle to? Not "what happens next" — the answer once nothing happens any more.
That steady state solves `∇²u = 0`, and the 5-point stencil turns it into one
tiny equation per interior cell: **every cell equals the average of its four
neighbours**. Nine hundred equations, nine hundred unknowns, all tangled together.

Nobody inverts that matrix. You guess, and improve the guess. **Jacobi's
method** is that made literal: set every interior cell to the average of its
neighbours *as they were before this sweep*, and repeat. Because every cell reads
the previous iterate and nothing else, all 1,024 threads are independent — it is the pure
*gather* Thinking in Parallel calls the shape that always parallelises, and one
whole sweep is one kernel call.

The edges never move: they are the known values that pin the answer down. (Reaction–Diffusion
steps this same stencil *forward in time*; here we are solving for the state where
time has stopped.)

## Figures

- **everyone reads yesterday — which is exactly why everyone can go at once**

## Goal

**Goal:** finish the sweep kernel — interior cells return the average of
their four neighbours in `u`, boundary cells return their own value unchanged.

## Requirements

- Boundary cells — `x` or `y` equal to `0` or `size − 1` — return `u[y][x]` untouched
- Interior cells return `(left + right + up + down) / 4`: four neighbours, no centre
- Read only `u` — no cell may see a value written during this sweep

## Hint 1 — the edges come first

Guard the boundary before you do any arithmetic, so the neighbour reads below
can never leave the grid:

```js
if (x === 0 || y === 0 || x === this.constants.size - 1
    || y === this.constants.size - 1) {
  return u[y][x];
}
```

## Hint 2 — the four neighbours

Only ever vary *one* coordinate at a time: `u[y][x - 1]` and
`u[y][x + 1]` along the row, `u[y - 1][x]` and
`u[y + 1][x]` down the column. The centre `u[y][x]` is not part
of a Jacobi average.

## Hint 3 — the whole return

```js
return (u[y][x - 1] + u[y][x + 1]
      + u[y - 1][x] + u[y + 1][x]) / 4;
```

## Same idea elsewhere

Jacobi is the starting point of every multigrid solver on every platform — a CUDA
or WGSL version of this kernel is line-for-line the same gather, with a buffer swap where
your JavaScript assignment is. It is also why "matrix-free" is a phrase: nobody stores the
900×900 matrix this stencil stands for, because the kernel *is* the matrix.

## Starter code

```js
// One Jacobi sweep: every interior cell becomes the average of its four
// neighbours, read from the grid as it was BEFORE this sweep.
const gpu = new GPU({ mode });

const sweep = gpu.createKernel(function (u) {
  const x = this.thread.x;
  const y = this.thread.y;
  // TODO 1: the boundary is held fixed — return u[y][x] for any cell whose
  //         x or y is 0 or this.constants.size - 1.
  // TODO 2: every other cell returns the average of its four neighbours:
  //         u[y][x - 1], u[y][x + 1], u[y - 1][x], u[y + 1][x].
  return u[y][x];
}, { output: [32, 32], constants: { size: 32 } });

const next = await sweep(guess);
console.log('centre before:', guess[16][16], '→ after:', next[16][16]);
```

---

Interactive version: https://gpu.rocks/learn/iterative-solvers-e73b8e1f/1

[Next task](https://gpu.rocks/learn/iterative-solvers-e73b8e1f/2.md)
