# Solver Changes

## Origin

Based on [GNP](https://github.com/jiechenjiechen/GNP) (Paper: arXiv 2406.00809v3).
Original source: `GNP/solver/GMRES.py`.

## What we changed

- Wrapped GMRES as class `FGMRES` with config in constructor (restart, max_iters, rtol, timeout) instead of per-call arguments — cleaner reuse as inner solver for `GMRESPreconditioner`
- Return structured `SolverResult` dataclass instead of raw tuple `(x, iters, hist_abs_res, hist_rel_res, hist_time)`
- Defined `Preconditioner` Protocol (`apply(r) -> Tensor`) as formal interface — GNP uses duck typing
- Early return for zero RHS (`norm_b < 1e-15`) to avoid division by zero
- Added breakdown detection (`H[j+1,j] < 1e-14`) with early exit — GNP divides by zero silently
- Removed residual consistency warning (`np.allclose` check) — noisy in practice, not actionable
- Arnoldi: parameter order changed to `(A, m, v0)` for consistency; uses `torch.randn` instead of `torch.normal`
- `x0` is cloned to avoid mutating caller's tensor — GNP modifies in-place
