Debug solver convergence issues after physics changes. Use when the simulation fails to converge or oscillates after modifying physics parameterizations.
Use this when main.py fails to converge or convergence is slow/oscillating.
The solver prints per-iteration residuals at the Anderson acceleration level (year-to-year periodic cycle). Grep for them:
uv run python backend/main.py --resolution 5 --headless 2>&1 | grep -Ei "^iter |Converged|Failed to converge"
Output format:
iter 0: RMS=11.830K 95p=27.280K max=55.889K
iter 1: RMS=2.405K 95p=4.618K max=18.185K
| Pattern | Likely cause |
|---|---|
| RMS decreasing but max stays high | One grid cell or small region oscillating between years |
| RMS oscillating, never settling | Physics don't admit a stable periodic solution — year-to-year mapping has no fixed point |
| Diverging (RMS increasing) | Positive feedback loop with no restoring force |
solver.py (~line 1253):max_idx = np.unravel_index(np.argmax(np.abs(monthly_temp_diff)), monthly_temp_diff.shape)
max_month, max_lat_idx, max_lon_idx = max_idx
nlat_grid, nlon_grid = monthly_temp_diff.shape[1], monthly_temp_diff.shape[2]
max_lat = -90 + 90/nlat_grid + max_lat_idx * 180/nlat_grid
max_lon = 180/nlon_grid + max_lon_idx * 360/nlon_grid
print(f"iter {iter_idx:2d}: ... @({max_lat:+.1f},{max_lon:.1f},mon={max_month})")
Revert after debugging. 2. Is there a feedback loop? Trace the physics chain at the oscillating location. Does the parameterization create a self-amplifying cycle? 3. Is the forcing area too large relative to ITCZ sensitivity? Broad forcings coupled to ITCZ position are inherently destabilizing — the wider the forced area, the stronger the feedback on the ITCZ itself.