Skip to content

Drift-kinetic island/layer solver#318

Draft
logan-nc wants to merge 93 commits into
developfrom
feature/islands
Draft

Drift-kinetic island/layer solver#318
logan-nc wants to merge 93 commits into
developfrom
feature/islands

Conversation

@logan-nc

@logan-nc logan-nc commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Design plan (docs only) for Islands, a new GPEC submodule (src/Islands/): a steady-state, multi-species drift-kinetic solver for the resonant island/layer region that returns the growth moment Δ_cos(w, ω; p) and torque moment Δ_sin(w, ω; p) for arbitrary parameters — replacing the sum of regime-specific Modified Rutherford Equation terms with a single calculation, and in its small-amplitude limit reducing to the linear layer response so that error-field shielding, penetration, seeded-NTM onset, and island saturation become faces of one solution manifold.

Draft: this PR lands the design docs (docs/src/islands/, module conventions in src/Islands/CLAUDE.md) and the drift-kinetic reference library, revised against the Imada / Dudkovskaia / Leigh source set. No solver code yet.

🤖 Generated with Claude Code

logan-nc and others added 4 commits July 7, 2026 15:31
…an under src/islands

Design bundle for ISLET (Integrated SoLver for Evolving Tearing), a planned
steady-state multi-species drift-kinetic solver for the resonant island/layer
region, generalizing the Modified Rutherford Equation the way SLAYER generalized
linear layer theory. Revised against the full Imada/Dudkovskaia/Leigh reference
set in docs/resources/Drift_Kinetic_Island_References (see REVISION-2026-07-07).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…uthor-title convention

Renames the nine PDFs under docs/resources/Drift_Kinetic_Island_References to the
YEAR-Author-Title convention used by the rest of docs/resources, and extends the
.gitignore resources-PDF negation to subdirectories (!docs/resources/**/*.pdf) so
these tracked references match the existing docs/resources/*.pdf policy. Syncs the
filename references in the ISLET reference-library doc (docs/08).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e convention)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n into in-repo layout

Drop the working acronym ISLET in favour of the plain module name Islands, and
record the module-naming convention (simple intuitive names, not standalone-code
acronyms) in the repo-root CLAUDE.md.

Reconcile the design bundle from its standalone-package assumptions into the
in-repo layout:
- module conventions   -> src/Islands/CLAUDE.md
- overview             -> docs/src/islands/index.md
- design docs 00-08    -> docs/src/islands/design/
- Physics Book / state / derivations / papers / notes / LOG / QUESTIONS
                       -> docs/src/islands/{,state,derivations,papers,notes}
- benchmarks + figures -> benchmarks/islands/{,figures}
- verify harness       -> src/Islands/verify/
- tests                -> test/runtests_islands_*.jl (top-level test/)
- regression cases     -> integrated under regression-harness/ (islands_*)

Islands is a submodule of the GeneralizedPerturbedEquilibrium package (no separate
Project.toml), not a standalone subpackage; docs/03/06 updated accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@logan-nc logan-nc changed the title Islands: drift-kinetic island/layer solver — design plan Drift-kinetic island/layer solver Jul 8, 2026
@logan-nc logan-nc self-assigned this Jul 8, 2026
@logan-nc logan-nc added enhancement New feature or request WIP Work in progress labels Jul 8, 2026
logan-nc and others added 22 commits July 8, 2026 00:11
… infrastructure

Stand up the Islands submodule and the infrastructure the autonomous-run
protocol (design doc 06) assumes:
- src/Islands/Islands.jl (module Islands, skeleton) wired into the package
- docs/src/islands/LOG.md + QUESTIONS.md (session memory + blocker queue; Q1
  records that julia is not on the automation shell PATH)
- .claude/settings.json + hooks (guard-bash PreToolUse, stop-check Stop) for
  unattended dontAsk runs; physics-verifier subagent as the [VERIFY] backstop
- docs/src/islands/design/M1-launch-prompt.md (the milestone contract fed to
  the overnight loop)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…docs

The exported Islands module carries a docstring, which checkdocs=:exports
requires be covered in the manual. Add docs/src/islands.md with an @autodocs
block and wire it into make.jl (API Reference), matching the other submodule
pages. Fixes the missing_docs docs-build failure introduced by the module stub.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tings.json

/doctor flagged two deny rules as skipped: the :* prefix wildcard is only valid
at the end of a pattern. Rewrite them with a mid-pattern wildcard so the rules
load and again restrict the protected-branch pushes for any remote or flags.
A loaded OMFIT module leaks the conda env lib dir onto LD_LIBRARY_PATH, shadowing
Julia's bundled artifacts (CHOLMOD, glib/Cairo/GR) and producing false 'broken
build' blocks in the Stop hook. Strip the var for the julia smoke check via
env -u; this is a no-op on a clean shell and in CI.
M1 needs forward-mode AD for the JVP/AD-compatibility checks (design
docs/src/islands/design/04-numerics.md §9). Adds ForwardDiff to Project.toml
(already present transitively in the manifest); removes nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ck + verify harness

Land the milestone-M1 numerical skeleton (design 03 §1-2, 04; ladder A1/A2),
structure only — no [VERIFY] physics coefficients assigned in src/.

- phasespace/PhaseSpace.jl: the (x, ξ, y, E, σ) grids with layer-clustered maps.
  Fourier spectral ∂ξ; Fornberg high-order finite differences for ∂x/∂y on
  sinh-stretched grids (per-derivative window widths so D1 and D2 are both
  4th-order including boundaries); composite-Simpson quadrature weights;
  Gauss-Laguerre energy nodes. Pure numerics.
- operators/Operators.jl: AbstractTerm + apply! + residual! and the term structs
  of 03 §2 (ParallelStreaming, MagneticDrift with the :original/:improved toggle,
  ExBDrift as the (x,ξ) Poisson bracket, Collisions, GradientDrive, PerpTransport
  and RadiationSink L4 stubs, Quasineutrality field residual). Every physics
  coefficient is a supplied data field, never a literal; allocation-free and
  generic over eltype so ForwardDiff duals flow through.
- verify/Verify.jl: manufactured-solution (MMS) + AD-vs-finite-difference JVP
  harness, plus allocation probes. Manufactured coefficients are arbitrary
  order-unity test values (not physics), exercising the discretization only.
- Islands.jl: wire the three submodules.

physics-verifier: PASS (no [VERIFY]-policy violation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…to runtests

test/runtests_islands_grids.jl and test/runtests_islands_operators.jl, included
in test/runtests.jl:

- A1 per-operator MMS: 4th-order convergence for the ∂x/∂y differential terms,
  machine precision for the Fourier ∂ξ (drift) term; assembled kinetic residual
  converges at 4th order.
- A2: forward-mode-AD JVP of the (nonlinear) assembled residual matches the
  central finite-difference directional derivative to ~1e-9.
- Allocation regression: every apply! and residual! hot path allocates 0 bytes.
- Grid unit tests: Fourier exactness, mapped-FD order, Simpson/Gauss quadrature,
  layer-clustered packing, IslandGrid assembly and input validation.

All 53 Islands tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…path)

- docs/src/islands.md: document the M1 skeleton (PhaseSpace/Operators/Verify),
  restating the structure-only [VERIFY] discipline.
- LOG.md: M1 session entry (what moved / blocked / next).
- QUESTIONS.md: Q1 RESOLVED — julia is at the ncl2128 software dir and must be
  invoked with a clean LD_LIBRARY_PATH (OMFIT contamination); used here to run
  the suite locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Set up the next milestone (M2 — L0 solve machinery) for the autonomous loop,
mirroring the M1 launch-prompt bootstrap.

- docs/src/islands/design/M2-launch-prompt.md: the M2 milestone contract. Scope
  = full L0 solve machinery (solvers/, moments/, frames/, fields/, species/,
  neoclassical-matching BCs) as AD-compatible allocation-free structure with every
  physics coefficient a [VERIFY]-gated parameter. DoD = the physics-free structural
  gates (A5 null, assembled solve-MMS, A8 y_c conditioning, A4 conservation, A3
  parity, A7 ⟨∂²h/∂x²⟩=0) + suite + PR + Paper-I OUTLINE + the clearance queue.
  The York gates (B5a/b/c, B2, B4) are explicitly OUT — they need human-cleared
  physics; reaching one by hardcoding is a policy violation, not completion.
- QUESTIONS.md: seed the parallel-human clearance queue — Q2 (ratify D7/D8),
  Q3 (clear the L0 [CHECKED] coefficient set with exact cites), Q4 (open [VERIFY]s:
  the psi-tilde q_s'/q_s typo, B5a collisionality, acquire WCHH96 + Park 2022).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the overnight-loop framing (dontAsk/--continue header, unattended language,
Stop-hook exit-criteria) — M2 is driven interactively via /goal in auto mode.
Blocked coefficients are surfaced to the user to clear live rather than only
parked in QUESTIONS.md. The contract (scope, DoD, [VERIFY] hard rule, gated York
gates) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ylov solver

Matrix-free GMRES backend for the L0 solve (design docs/src/islands/design/04-numerics.md $5, $9).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…es, fields, moments

Land the Level-0 solve structure (design 03 §1-3, 04 §3-5; M2 contract), every
physics coefficient a supplied [VERIFY]-gated parameter — no literal in src/:

- solvers/Solvers.jl: matrix-free Newton-Krylov (Krylov.jl GMRES on a
  preallocated ForwardDiff JVP operator; Eisenstat-Walker forcing; backtracking
  line search; convergence on both norm and max-norm per 04 §5), YBlockJacobi
  physics-block preconditioner skeleton with TSVD-regularized pencil solves
  (the explicit y_c treatment of 04 §3), dense tiny-grid debug Jacobian, and a
  pseudo-arclength continuation scaffold with fold detection from day one.
- species/Species.jl: Species{AbstractBackground}, Maxwellian/SlowingDown,
  Bulk/Trace roles, validation + trace-criteria check (warn, never degrade) —
  the D3 first-class species plumbing (02 §1).
- frames/Frames.jl: Level0Parameters input vector (01 §5) and the frame
  conversion FORMS with every sign/normalization a NaN-defaulted gated
  FrameConvention field — an un-cleared convention poisons results instead of
  guessing (QUESTIONS Q3).
- fields/Fields.jl: Q(Ω)/h(Ω) flattened-electron closure structure (prefactor
  supplied), the coefficient-free A7 identity ⟨∂²h/∂x²⟩_Ω = 0, and the
  NaN-gated ElectronClosure constant set.
- moments/Moments.jl: J̄_∥ assembly from charge-scaled weighted moments,
  Δ_cos/Δ_sin projections with REQUIRED gated prefactors (ψ̃ open [VERIFY],
  sin normalization unpinned — QUESTIONS Q4), Ω label + ⟨·⟩_Ω average +
  channel-split diagnostics (pinned half-width convention).
- operators/: PitchAngleDiffusion in mimetic divergence form (exact discrete
  particle conservation + entropy sign, ladder A4), FarFieldConditions
  matching BCs (never bare Neumann, 01 §3), weighted_moment!, flat-index
  helpers; IslandGrid now records y_c for the A8 monitor.
- verify/: solve-level MMS + zero-drive configurations (A5/A1-solve) and the
  yc_block_sigma_min conditioning monitor (A8, the L23 §4.2 silent-noise
  regression tripwire).

All new kernels pass a --check-bounds=yes run (M1 lesson).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…/A8 + solve-MMS)

test/runtests_islands_solve.jl (67 tests, wired into runtests.jl):
- A5 zero-drive null: residual exactly machine zero at g ≡ 0; Newton falls back
  to the zero state from a perturbation.
- A1-solve: assembled Newton-Krylov solve recovers the manufactured state at
  design order (observed 3.98 on the nx = 17→33 pair).
- A4: exact discrete particle conservation (≲1e-11) + entropy sign of the
  mimetic pitch-angle operator; allocation-free apply!.
- A3: Δ_cos even / Δ_sin odd under ξ-reflection, spectrally exact projections.
- A7: ⟨∂²h/∂x²⟩_Ω = 0 to 1e-10 across Ω and prefactors (coefficient-free).
- A8: y_c-block σ_min monitor is finite/positive and detects an artificially
  singularized pencil.
- Preconditioner gate: YBlockJacobi cuts GMRES iterations >2× at identical
  solutions; far-field BC rows; pseudo-arclength fold detection; species +
  gated-frames plumbing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ctural regression case

- benchmarks/islands/ (+ figures/): the docs/05 B-ladder scripts B2 (large-w
  limits), B4 (polarization ω_E structure), B5a/b/c (York threshold triangle) —
  all SKIPPED, each naming the QUESTIONS.md entries (Q2-Q4) whose human
  clearance un-gates it. Un-skipping by filling in a coefficient is the
  forbidden action; the scripts say so.
- regression-harness: new computed case islands_l0_structural tracking the
  structural numbers that silently move if the discretization/solver/quadratures
  drift — solve-MMS error + Newton/GMRES iteration counts (nx=17), the A7
  closure identity, and the A8 y_c-block sigma_min. Verified locally:
  err=5.254e-2, 6 Newton / 1210 GMRES, A7=8.0e-17, sigma_min=0.1139.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
- docs/src/islands/papers/paper-1/OUTLINE.md: the Level-0 figure contract
  (docs/07 §3), claims → figures → ladder IDs. C1-C3 (discretization order,
  solver conditioning, conservation structure) are green as CI artifacts;
  C4-C8 (neoclassics, large-w limits, the York triangle, the Δ_pol(ω_E)
  reversal, the L23 electron-Δ_pol question) are gated on QUESTIONS Q2-Q4.
- docs/src/islands.md: M2 status (all seven submodules, gating summary).
- LOG.md: M2 session entry, including the solve-well-posedness lesson (generic
  y-diffusion without BCs is unstable; the mimetic degenerate form + far-field
  x-BCs are the correct structure).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…docs missing_docs)

Documenter's checkdocs=:exports requires every exported docstring in the
package (including submodules) to appear in a page; the islands.md @autodocs
block only listed the top-level Islands module, so the PhaseSpace/Operators/
Verify exports failed the docs build. Add per-submodule @autodocs sections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
logan-nc and others added 30 commits July 13, 2026 23:57
… + parallel-flow weight W

Clearing Q3's parallel-flow weight W surfaced (escalated as Q6) that the code's
velocity_moment!/weighted_moment! used a flat measure missing the physical ∫d³v
Jacobians (√E/2 speed, 1/√(1−yb) pitch) — and that the already-cleared QN
density δn̄_i used that flat moment. The user chose the physical ∫d³v with the
flux-surface b. Derived and cleared (human sign-off, velocity-moment-measure.md):

- physical_velocity_weights: the √E/2 speed Jacobian (folded into
  Gauss-Laguerre) and the 1/√(1−y·b_min) pitch Jacobian (b_min=(1−ε)/(1+ε), an
  exact singular-weight quadrature = the IinvB edge; forbidden region zeroed,
  Σwy_phys = 2/b_min exactly).
- parallel_flow_weight: W = v̂_∥ = σ√E√(1−y·b_min) (clears Q3's W); its √(1−yb)
  cancels the pitch Jacobian so J̄_∥ is regular.
- velocity_moment!/weighted_moment! gained wy/wE kwargs (default flat — M1/M2
  manufactured tests untouched); Operators.Quasineutrality carries the physical
  weights, so δn̄_i is now the physical moment (max|Φ| shifted 5.7→4.5, the
  approved QN revision; closure algebra α/S unchanged).

This resolves Q6, clears Q3's W (un-gating Moments.parallel_current! → the Δ
outputs), and UNBLOCKS term F (Q5) — Ū is now a bounded physical moment.

physics-verifier PASS; 1596 islands assertions green (Σwy=2/b_min exact,
forbidden zeroed, W σ-odd, QN wired); build_docs_local.jl green. Doc-first:
docs/01 §3/§4, QUESTIONS Q6/Q3/Q5, Moments docstrings, derivations index/nav.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
… Level-0 collision operator is complete (6/6)

Implement the sixth and final collision term — the momentum-restoring
field-particle integral (F), the one nonlocal Level-0 term (human sign-off;
orbit-averaged-collision.md §6, unblocked by the Q6 physical ∫d³v measure).

- Operators.MomentumRestoring + apply!: forms the parallel-flow moment
  Ū(x,ξ) = (1/√π⟨ν̂_ii⟩_u){ν̂_ii v̂_∥ g}_v (physical measure; moment weight
  W = ν̂_ii·v̂_∥, σ-odd) into a new cache.Ubar scratch, then adds the σ-even
  redistribution +2ν̂_ii(1+ε)Ū/(m ρ̂_θi) (positive — ÷−m ρ̂_θi of the RHS; the
  F̂_M=e^{−E} cancels in the g=shape convention).
- Configure.momentum_restoring_term builds W, the redistribution, the physical
  weights, and inv_norm = 1/(√π⟨ν̂_ii⟩_u) from the cleared momentum_restoring_average.
- Wired into configure_level0 (9-term kinetic stack); IslandCache gained Ubar.

Linear in g (Ū is a moment), allocation-free (cache.Ubar), AD-transparent; uses
only cleared inputs. All six collision terms are now complete — no gated kinetic
physics remains.

physics-verifier PASS (traced Ū vs L23 Eq. 8.3.17 line-by-line, positive sign,
linearity, no guessed number); 1690 islands assertions green (W σ-odd,
redistribute positive, F(2g)=2F(g), nu_star=0 guard); build_docs_local.jl green.
Doc-first: docs/01 §2.3, QUESTIONS Q5, numerics.md §2/§8,
orbit-averaged-collision.md (6/6), anchor-sync marker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…rrent Δ outputs

Wire the physical Level-0 solve into the Δ growth/torque moments — the first
physics deliverable off the converged state (docs/01 §4). No new [VERIFY]
coefficient: assembly + diagnostics only, physics-verifier PASS.

- Moments.parallel_current! gains wy/wE kwargs (forwarded to weighted_moment!)
  so J̄_∥ carries the physical ∫d³v measure; W = v̂_∥'s √(1−y b_min) cancels the
  pitch Jacobian and J̄_∥ is regular. Defaults to the flat quadrature.
- Configure.delta_outputs(grid, phys, species, Usol, cfg): builds cleared W +
  physical measure, forms J̄_∥ from the solved bulk-ion g, projects to
  Δ_neo ≡ Δ_cos and Δ_sin with the cleared ∓μ₀R/2ψ̃ prefactors.
- Moments.channel_decomposition + grid_interpolant: the docs/01 §4 flux-surface
  split — ⟨J̄_∥⟩_Ω bootstrap+curvature channel and the Δ_pol polarization
  residual, plus the ⟨J̄_∥⟩_Ω profile (approximate diagnostic, L23 Eq. 2.5.3).

Doc-first: numerics.md §7/§8. Tests: 138 solve + 1540 configure + 5 anchor-sync
green (nodal-exact interpolant, flux-function Δ_pol→0, profile recovers f(Ω),
additive split, single-bulk contract); build_docs_local.jl green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ton for the physical Level-0 solve

The Level-0 physics solve had never converged at physical parameters: matrix-free
newton_krylov stalls because cond(J) ~ 1e9 (grows as 1/ρ̂_θi from the 1/ρ̂_θi
streaming + collision coefficients), and restarted GMRES cannot solve the linear
system. Diagnosis (dense Jacobian on a tiny grid) showed the nonlinear problem is
well-posed — Newton converges in 6-9 exact steps regardless of conditioning.

newton_direct forms the dense Jacobian (reusing dense_jacobian) and solves each
step exactly with an Armijo line search — the robust solve for benchmark-scale
grids (N ≲ 1e4). Pure numerics, no physics content. The scalable matrix-free path
is an (x,ξ) advection-plane preconditioner (diagnosis: the plane block drops
cond 1.24e9→4.5e5; YBlockJacobi/y-block is the wrong tool — it worsens it).

Tests: 143 islands-solve assertions green (new: matches newton_krylov on a
well-conditioned case, converges on a stiff advective stack). Full diagnosis
(solver conditioning + island under-resolution + channel_decomposition fragility)
recorded in docs/src/islands/LOG.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…nding (attempt reverted)

Record the solver-milestone progress: adaptive w-continuation works (reaches large
w via newton_direct + step-halving), and the correct approach for the (x,ξ)-plane
preconditioner. Two dead ends found and reverted (not committed): colored-JVP with
all planes seeded is contaminated by the dense momentum-restoring coupling; a
pure-advection sub-stack block is singular (needs the collision diagonal to
regularize). Correct build: stack minus momentum-restoring, y-colored JVP (pitch/
cross are y-banded). newton_direct + delta_outputs remain the committed wins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…e preconditioner (y-colored JVP)

The scalable matrix-free fix for the physical-ρ̂_θi conditioning (cond ~1e9 →
~1e5). The ill-conditioning is cross-pencil advection, not the y_c collision
block, so YBlockJacobi is the wrong tool; inverting the exact (x,ξ)-plane block
per (y,E,σ) drops the preconditioned condition number by ~4 orders, which lets
matrix-free newton_krylov converge at physical ρ̂_θi (matching newton_direct)
where unpreconditioned GMRES stalls.

Plane blocks are built matrix-free by a y-colored JVP: drop the one nonlocal
term (momentum-restoring, the dense all-plane coupler) so the reduced Jacobian
couples planes only through the y-banded pitch/cross collision operators
(K=GᵀDG half-bandwidth ≤ order, within fixed (E,σ)); planes spaced beyond the
band are seeded together by color, nx·nξ·(2·order+1) JVPs independent of
ny·nE·nσ. Pitch/cross are kept for their within-plane collision diagonal, which
regularizes the otherwise-singular pure-advection block.

Mirrors YBlockJacobi: struct + block-callback constructor + one-shot
(stack,grid,u;bc,…) convenience + ldiv! (SVD/TSVD-regularized blocks,
phi_scale=−α on Φ rows). Adds Solvers.plane_blocks (stack-agnostic JVP
extractor) and Solvers.without_momentum_restoring. Pure numerics — no physics.

Unit test (mirrors the newton_direct test): colored extraction is bit-exact vs
the reduced-stack dense diagonal blocks; cond(J)>1e8 → cond(M⁻¹J)<1e6 (≥3
orders); preconditioned newton_krylov converges at ρ̂_θi=0.05 and matches
newton_direct where unpreconditioned stalls; wrong block size throws. Doc-first:
numerics.md §5. 154 solve assertions green; grids/operators/configure green;
build_docs_local.jl green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ntinuation (globalization enabler)

Natural-parameter continuation over an increasing w-schedule — the globalization
that reaches large island widths the cold Newton solve cannot. Each requested
target is reached by marching the parameter up from the previous converged
state, warm-starting every solve from the last one, with adaptive step control
(halve on a failed/singular solve, grow on success, capped by the distance to
the next target). Rebuilds the stack only once per accepted step, never per
residual eval; a solve_at that throws (singular linearization from too big a
step) is treated as non-convergence → triggers a halving.

Stack-agnostic (pure numerics): takes ws, a solve_at(w, u_warm) closure, and u0;
returns per-requested-w converged states. Simpler than pseudo_arclength (no
tangent, no fold handling) — for the monotone B2 w-sweep where no folds are
expected; pseudo_arclength stays for the Level-3 penetration fold.

Unit test (manufactured stiff residual with a drifting, ~1/w-narrowing basin):
cold-from-zero and a single warm jump both fail at large w, but stepped
continuation converges to the exact drifting root at every requested w; adaptive
halving alone bridges a coarse 2-point schedule; an unreachable target returns
converged=false with progress banked (never throws/hangs); unsorted schedule
throws. Doc-first: numerics.md §6. 169 solve assertions green;
build_docs_local.jl green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…he radial grid so Δx(0) ≤ w/K

The Δ output moments are dominated by the current response at the separatrix
(x ~ w), not the x=0 node, so a grid that under-resolves the island half-width w
gives Lx-/clustering-sensitive garbage (the diagnosed sign-flips came from the
whole moment landing on one under-resolved node). This adds the adequacy
protocol (04 §2):

- island_clustering_x(w, Lx, nx; K): inverts the exact sinh-map central spacing
  Δx(0)=Lx·sinh(βΔs)/sinh(β) by bisection for the clustering β meeting
  Δx(0) ≤ w/K (K nodes across the half-width, K≈5–10). Returns 0 (uniform) when
  already fine; refuses to over-cluster and starve the far field (β>beta_cap).
- resolved_island_grid(; w, nx, K, Lx_over_w, …): builds an IslandGrid with
  Lx = Lx_over_w·w (far field Lx/w ≳ 5) and the computed clustering_x.
- central_x_spacing / is_island_resolved: diagnostics reporting the two adequacy
  numbers (Δx(0) ≤ w/K and Lx/w ≥ 5) for the ≥2-resolution convergence protocol
  — no Δ-output benchmark passes on one grid (docs/05).

Pure numerics — no physics. Unit test: β hits the w/K target exactly across
(w,Lx,nx,K); uniform when already fine; over-clustering refused; resolved grid
passes is_island_resolved; a coarse grid is flagged. Doc-first: numerics.md §1.
42 grids assertions green; build_docs_local.jl green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ck-check finds dense under-resolved (checkpoint gate)

Records the milestone reassessment: the resolved Δ_neo(w) checkpoint is not
reachable with dense newton_direct (Δ_neo swings 24-41% and flips sign up to the
dense N≈11k ceiling, so the ∝w read is a resolution artifact, not a physics bug).
Next: the matrix-free PlaneJacobi + newton_krylov + continuation resolved sweep,
with K- and nx-convergence, before items 4/5. Stop-and-reassess gate honored.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ll; Δ_neo is outer-region-dominated (moment/far-field issue)

Probe (step 2) result: PlaneJacobi + newton_krylov converges cleanly on resolved
grids beyond the dense N≲1e4 cap (N up to 20.5k, all conv), so reaching resolution
is solved. BUT Δ_neo grows ~power-law with island resolution K (1.40→1.74→2.20),
not converging — because the per-x integrand ∮J̄cosξ is NOT localized to the island
(only 7-14% of Δ from |x|<w, shrinking with resolution; largest |m1| near the
domain edge). Δ_neo divergence is a far-field/outer-region effect, not a solver
bug and not a rational-surface singularity. Stopped before items 4/5; root cause
(box-too-small vs far-field/drive vs matched-asymptotic extraction) not yet pinned
— surfaced to the user, no QUESTIONS.md entry yet (would presume the cause).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…t (outer-tail artifact) — escalate; solver stack done

Option-(a) test result: neither a bigger box (Lx/w 6→20) nor island-restriction
converges Δ_neo. Restricted to |x|<{1.5..4}w it shrinks toward ~0 across K=8/12/16
while the full-domain value grows 1.40→1.74→2.20 — so the reported Δ_neo is
essentially the spurious outer-tail quadrature artifact (center-clustered grid,
huge Simpson weights on the small decaying tail), and the genuine island cos-moment
is small/noisy. The volume-moment extraction itself is the blocker, not the solver.

Escalated as QUESTIONS Q7 (intended Δ_neo extraction + quadrature: resolved-outer
volume moment vs matched-asymptotic Δ' jump vs small-island-value-is-physical) — a
docs/01 §4 physics/normalization decision, physics-verifier before any impl. Solver
enablers (PlaneJacobi / natural_continuation / resolution protocol) are landed and
green; Δ_neo(w) checkpoint + B2 + item-4 decomposition are blocked on Q7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ure (removes the layer-clustering artifact); far-field BC escalated (Q7)

The Δ moment's radial integration is swapped from composite-Simpson (grid.x.wq)
to a cubic-spline quadrature (FastInterpolations, the repo idiom) of the per-node
ξ-projections m_{cos,sin}(x). On the layer-clustered grid the island physics
requires (nodes packed at x=0), Simpson puts huge weights on the sparse far-field
nodes and over-weights the small radial tail, making the raw moment grid-sensitive
(Simpson vs spline differ 3×, sign-flip on clustered grids); integrating the
interpolated profile removes that clustering artifact. Definition, prefactors, and
the spectral ξ-projection are unchanged. physics-verifier PASS (pure quadrature
swap, physics-neutral: no coefficient/sign/normalization/definition change; parity
and the channel_decomposition additive split preserved). Doc-first: numerics.md §7
+ docstring, scoped explicitly as "quadrature only."

This corrects one of the two causes of the non-convergent Δ_neo diagnosed this
session; the residual blocker is the far-field boundary condition (our Dirichlet
g_far ∝ x over-constrains the edge → a resolution-sharpening boundary layer that
contaminates the solve), now escalated as the sharpened QUESTIONS Q7 with concrete
options (analytic far-field / York-style localized ∂ĝ/∂p=0 / domain mitigation) —
a signed-off-physics decision, not implemented. York cross-check (papers; codes
not public) confirms the volume-moment extraction FORM is correct (Diss19 Eq.
4.12), so only the far-field is in question. 169 solve + 1540 configure + 5
anchor-sync green; build_docs_local.jl green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…nn York-localized) for the Q7 comparison

Adds a far-field boundary-condition mode toggle on Operators.FarFieldConditions:
:dirichlet (default, unchanged — pin the value g → g_far ∝ x, the I19-Formulation-A
drive-in-the-BC form) vs :neumann (pin the slope ∂g/∂x → s_far, the York/kokuchou
localized form ∂ĝ/∂p=0 for ĝ = g − g_far, so g floats by a constant and reaches its
own asymptote instead of forming the diagnosed edge boundary layer).

apply_farfield! branches: :neumann builds the boundary residual from the x-grid D1
row (∂g/∂x − slope). Configure.gradient_far_field(...; mode) emits the value or the
slope; s_far = L̂_n0⁻¹[1+(E−3/2)η_i] is exactly ∂/∂x of the same cleared far field,
so no new coefficient is introduced. configure_level0(...; farfield_mode) threads it.

physics-verifier PASS: physics-neutral — :dirichlet is a no-op, :neumann slope is
the exact derivative of the cleared value, no coefficient/sign/normalization added,
no [VERIFY]/[CHECKED] tag cleared. Doc-first: numerics.md §4 + docstrings. New
:neumann unit test (D1-row slope residual, constant-annihilation, :dirichlet
back-compat). 178 solve (was 169) + 1540 configure + 5 anchor-sync green.

This is the paper-comparison toggle for the open Q7 far-field decision; the
:neumann-vs-:dirichlet convergence/localization experiment and the corrected
analytic far-field (A) follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
… failure; A (analytic far-field) is the principled fix

Bare symmetric :neumann does not converge (nx=41/61 conv=0, values swing) — the
additive-constant null mode (σ-even c(E,σ) with zero density moment) makes the
Jacobian singular. Dirichlet over-constrains, bare Neumann under-constrains; neither
works. The "if B works, proceed to A" precondition is false → reassessed. Principled
fix = A (pin the corrected asymptote: linear + drift-island-shift), well-posed and
accurate, = L23 §7.1's unimplemented "analytic far-field" future work. Surfaced to
the user for the path decision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…bit shift ⟨x_D⟩ — the principled Q7 fix

Adds the :analytic far-field mode — the derived, well-posed improvement over both
:dirichlet (over-constrains ∝x → boundary layer, Δ_neo diverges) and :neumann
(under-constrains → winged-branch null mode, doesn't converge).

The exact far field is the neoclassical response at the canonical momentum
p̂ = x − x_D (I19 Eq. 2, p_φ=(ψ−ψs)−Iv_∥/ω_c). The code's :dirichlet uses the
leading p̂ ≈ x, dropping the O(ρ̂_θi) orbit-width term that gradient-drive.md §2
explicitly discarded ("small shift at |x|=Lx") — the boundary-layer evidence shows
it is not negligible. :analytic restores it:
  g_far = (x − ⟨x_D⟩_θ)·slope,  ⟨x_D⟩_θ = ρ̂_θi(σ√E/(1+ε))·A(y)
with A(y)=⟨√(1−yb)/b⟩_θ the CLEARED drift bracket (the boxed x_D of the signed-off
omega-D-drift-frequency.md §2). No new coefficient — every factor is already
cleared. Well-posed (Dirichlet → pins the level, no null mode) AND accurate (true
asymptote → no boundary layer); applied as a :dirichlet value condition.
Forbidden-y / near-y_c bracket miss ⇒ zero shift (guarded, not guessed).

Doc-first: derivations/analytic-far-field.md [DERIVED: 2026-07-17] (awaiting human
sign-off of the orbit-averaged ⟨x_D⟩ choice). physics-verifier PASS (every link
confirmed vs primary sources; no new/guessed coefficient/sign/normalization).
New :analytic unit test (exact cleared formula + σ-oddness + forbidden-y-no-shift +
:dirichlet back-compat); 1563 configure green (was 1540). Early numerics: :analytic
converges (nx=41 conv, m1 peak @ island) where :dirichlet diverges and :neumann
stalls; resolution-convergence sweep in progress.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…t fix the boundary layer (offset too small); domain-size next

The :analytic drift-orbit-shifted far field converges + localizes at nx=41 but
diverges like :dirichlet at nx=61 (Δ_neo -2.94 vs -2.84; m1 peak → edge). ⟨x_D⟩ is
~1% of the far-field value, too small to change the boundary layer — so the dropped
orbit-shift offset is NOT the cause. A stays a correct, physics-verified, well-posed
improvement (committed 186893e), but not the convergence fix. Leading next
candidate: domain size (Lx/w=6 too small → linear value-BC incompatible → resolution-
sharpening layer); test larger Lx/w. Surfaced to the user.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…n-fraction artifact (scale-invariant), not plasma-scale; stepping back

At physical w=0.1 (≪1) / Lx=0.6 the dirichlet solve fails to converge and the m1
peak sits at x/w≈−5.3…−5.6 = ≈0.9·(Lx/w), the SAME domain fraction as the w=1 case
(peak @ 0.96·Lx). So the edge feature scales with the domain, not absolute x — an
outer-boundary artifact at ~0.9·Lx independent of w, not a plasma-scale (x~1) effect;
physical w makes the solve harder, not easier. None of the far-field fixes crack the
Δ_neo convergence. Two undistinguished hypotheses: (i) solve-accuracy artifact in the
stiff outer streaming region (points at preconditioner/tolerance, not BC); (ii) the
response isn't localized (long passing tail) so a finite-domain volume moment is
edge-dominated → York's small 2-3w domain essential. Stepping back for human steer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…rix-free artifact; physical solve is near-singular (y_c layer), not a BC problem

newton_direct (exact dense, no precond) at physical w=0.03: the m1 peak is at the
ISLAND (x/w=0), not the edge — so the edge feature in every matrix-free sweep was a
PlaneJacobi/Krylov artifact in the stiff outer streaming region. BUT the exact solve
also fails to converge — the line search stalls at resmax≈7e-3, i.e. a near-singular
Jacobian, almost certainly the documented y_c trapped-passing matching layer
(rcond~1e-16, needs TSVD; newton_direct uses plain LU). So the Δ_neo non-convergence
is a SOLVE problem (y_c near-singularity + matrix-free edge artifact), NOT a far-field
BC problem — B/A were the wrong lever (A stays a correct verified toggle regardless).
Stepping back for human steer; next: A8 yc_block_sigma_min monitor to confirm the
near-singular block, or replicate York's small-domain setup as a reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…y_c layer; the stall is globalization + a matrix-free edge artifact (hopeful reframe)

A8 yc_block_sigma_min: the y_c block is NOT the near-singularity (its σmin is
43-1230x LARGER than the whole-J σmin). No genuine null mode — σmin bounded
(~1e-5, doesn't shrink with resolution), cond only ~4e5 (mild) to ~6e6 (resolved,
heavy clustering) — well within exact-LU capability. So newton_direct stalling at
resmax≈7e-3 is a globalization/cold-start problem (Newton from zeros at small w),
not a singularity — exactly what natural_continuation addresses. And the exact solve
LOCALIZES correctly (m1 peak @ island), so the outer-edge feature was a matrix-free
PlaneJacobi accuracy artifact, not the BC. Two addressable issues with existing
tools: continuation + exact solve; improve PlaneJacobi outer accuracy if scale
needs matrix-free. NOT a far-field problem (B/A were the wrong lever; A stays a
correct verified toggle). Next: confirm globalization via continuation to w=0.03.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ls to resmax~1e-3 from any init; handing back for a strategic decision

newton_direct at physical w=0.03 from far-field init reaches resmax=2.5e-3 (10x
better than zeros' 2e-2) but still doesn't converge; Δ differs wildly (-79 vs -29).
So a good initial guess is not the fix. After extensive investigation the physical
Level-0 solve doesn't robustly converge below ~1e-3 under any path. Ruled out:
far-field BC (B/A), y_c block (A8), null mode/near-singularity (cond~1e6-1e7),
simple globalization. Confirmed OK: localization, quadrature/moment. Remaining
suspicion: strong ExB nonlinearity (Armijo crawls) or a consistency question.
Handing back for a strategy call (solver-robustness effort / York-numerics
ground-truth comparison / human judgment). Solid + committed this session:
quadrature fix, PlaneJacobi, continuation, resolution protocol, 3-mode far-field
toggle (A [DERIVED]+verified) — correct infrastructure, convergent Δ_neo not yet
achieved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…A derived+verified but not the fix); the real blocker is physical-solve non-convergence

Records that the Q7 far-field investigation is complete and was the wrong lever, so
a fresh session is not misled into re-chasing it. The actual blocker for a
resolution-convergent Δ_neo is the physical Level-0 solve not converging (resmax
~1e-3); ruled out the far-field, y_c block (A8), null mode, and globalization. Two
standing items now: (1) physical-solve robustness (recommended: York-numerics
ground-truth reference first), (2) A's [DERIVED] sign-off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…the OUTPUT Δ is York's gate — our resmax~1e-3 stall is not a bug

Read L23 §3.1.5/3.1.6/6.1.1/6.2 and Diss19 Ch. III/IV first-hand (the recommended
M1 first task: establish whether the York codes converge Δ_neo, and how). Result:
kokuchou (direct 4D {p,ξ}, our closest analogue) uses Picard at a 10% tolerance,
never met in any run; Φ̂ residual >100%/iter across the whole physical E×B regime —
yet the OUTPUT Δ_loc converges stably (§6.2 Fig.6.3). RDK-NTM converges Δ only via
the S-streamline coordinate (analytic layers) + reporting at the "0th iteration in
Φ" (E×B off). So our resmax~1e-3 field-residual floor is ~100× below what kokuchou
achieved and ~1000× below York's own criterion — we have been gating on the wrong
quantity (field residual, not the output Δ) at an unphysically tight tolerance.

Docs-only: new synthesis note (notes/york-convergence-ground-truth.md) with page
cites; QUESTIONS Q7 update escalating the methodology decision (adopt York's
output-convergence posture as definition of done — a threshold change needing
sign-off); LOG entry. No src/ change, no coefficient cleared.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…not the solve) is the blocker; redirects the 2026-07-18 pivot

Measured (user: "measure Δ stability now"). Two clean signals at physical
ρ̂_θi=0.05, w=0.05: (1) at fixed resolution Δ_neo is insensitive to the field
residual (−434 at resmax=1e-5 vs −441 at resmax=0.15) — confirms empirically that
gating on field resmax is the wrong lever, as the ground-truth predicted; (2) across
x-resolution Δ_neo does NOT converge (−435 → −38 → −9.3, exact solve; m1 peak
migrates off the island). The exact solve CONVERGES the field (resmax=1e-5) — so the
2026-07-18 "physical-solve non-convergence" blocker was largely a matrix-free
(PlaneJacobi) artifact, not the real problem. The real blocker is the OUTPUT
EXTRACTION / non-localisation (Q7-original) + the grid: the response layer sits at
the drift island (shifted ρ̂_θi ω̂_D, velocity-spread), not the magnetic island our
rectilinear x-mesh packs (design 04 §1; L23 §3.1.6). Next lever (needs a steer):
the drift-island-separatrix grid map. Docs-only (LOG + QUESTIONS Q7); no src/ change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…spread shift envelope, not the magnetic island (04 §1)

The perturbed response localises on the drift islands, which sit at x shifted from
the magnetic island (x=0) by x_D^island = ρ̂_θi ω̂_D L̂_q (docs/01 §2.2, CLEARED) —
σ-signed and spread across velocity space. Measured at physical ρ̂_θi=w=0.05, the
envelope reaches X=3.94w: the drift islands lie entirely outside the old fine region
[-w,+w], in the coarse tail — the cause of the resolution-divergent Δ_neo and
migrating m1 peak (LOG 2026-07-19).

Implemented (reuses the CLEARED ω̂_D — no new coefficient):
- Configure.drift_island_shift_envelope: R = max_passing |ρ̂_θi ω̂_D L̂_q| over passing
  y<y_c (trapped have no shifted island, 01 §2.2), from the cleared drift table.
- Configure.drift_island_resolved_grid: builds the band grid from phys.
- PhaseSpace.banded_x_nodes / drift_island_grid: uniform central band at Δx≤w/K over
  [-(R+w),R+w] + geometric tails to ±Lx (Lx beyond the envelope), matching kokuchou's
  uniform high-res central region (L23 Ch. 3).
- PhaseSpace.MappedFDGrid(nodes; order): constructor from explicit nodes (Fornberg
  D1/D2; trapezoidal wq — x-quadrature is unused downstream, the Δ x-integral uses
  spline quadrature).

Doc-first: numerics.md §1 band-grid subsection + implementing symbols; corrected the
analytic-far-field.md §4 L̂_q⁻¹ typo to the CLEARED docs/01 §2.2 L̂_q form (flagged in
LOG). Tests: grids 63/63, configure 1563/1563, anchor-sync 12/12, operators 30/30,
solve 178/178. LOG entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…ECKED] not [CLEARED] (Q8)

The physics-verifier confirmed the band-grid physics is faithful (L̂_q direction
correct, no guessed coefficient, passing-only correct) but caught a provenance
mislabel: the drift-island shift structure x_D = ρ̂_θi ω̂_D L̂_q is docs/01 §2.2
[CHECKED: I19 Eq. 33; D21 Eq. 21; Diss19 Eq. 2.37] — the ω̂_D coefficient is
[CLEARED] (§2.1) but the shift FORM is not human-signed-off (erratum-prone I19
lineage, CLAUDE.md rule 6). Corrected the tag in Configure.drift_island_shift_envelope
docstring, numerics.md, analytic-far-field.md; escalated to QUESTIONS Q8. Mitigation
recorded: the [CHECKED] shift enters only to size the grid (margin-protected by +w
band + far tails), never as a physics output value — the grid map's correctness gate
is the empirical Δ_neo convergence test, not the shift value. Docs/docstring only; no
logic change (tests unaffected).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…t not sufficient — blocker now precisely at the matrix-free preconditioner edge artifact

Payoff test on the drift-island band grid. Matrix-free (PlaneJacobi) Δ_neo still
unstable with the m1 peak at the domain edge (x/w=-7.36) — the documented outer-region
artifact. But the EXACT newton_direct solve on the band grid LOCALIZES the moment at
the island (m1 peak x/w=-0.33,+1.25) — confirming the edge feature was the matrix-free
artifact and the band grid does its job. Exact is poorly conditioned/too slow at the
band's N (resmax 0.1-0.4), so Δ_neo still isn't resolution-stable. Net: band grid is
necessary + validated but not sufficient; the remaining blocker is the matrix-free
preconditioner's outer-region accuracy on the band grid (flagged 2026-07-18), exactly
the milestone premise that matrix-free is mandatory at island resolution. LOG only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…p made PlaneJacobi anti-precondition

Root-caused the band-grid matrix-free failure (dense cond experiments): the band
grid had a 35× adjacent-spacing JUMP — a sliver last interval from the old
banded_x_nodes clamp (tail[end]=Lx after the geometric loop overshot) — which wrecks
the FD conditioning so the (x,ξ) plane blocks' TSVD inverse injects noise, and
PlaneJacobi made cond WORSE instead of better. (Refreshing the preconditioner at the
iterate did NOT help — 1.7× — it was never the frozen-ExB; it was the grid.)

Fix (pure numerics): banded_x_nodes now builds a graded geometric tail with a single
ratio r ≤ max_ratio (default 1.3), solved by bisection so it lands exactly on Lx —
every adjacent ratio is r, no sliver; uniform-tail fallback for short tails. Renamed
growth→max_ratio. Confirmed: max Δx-ratio 35.5→1.20, and PlaneJacobi now DROPS
cond(M⁻¹J) 7× (2.3e7→3.2e6) instead of anti-preconditioning. New smoothness test
asserts max Δx-ratio ≤ max_ratio.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
… matrix-free solve (10x lower residual, Δneo more stable, peak off the edge) but Δneo not yet resolution-converged

The smoothed band grid + working PlaneJacobi: matrix-free field residual ~10x lower
(2-3e-3 → 1.7-4.6e-4), Δneo more stable (125% sign-flipping → 66% no-flip, decreasing
magnitude), and the m1 peak migrated from the domain edge (x/w=-7.4) back to the band
edge (x/w=-2.2 ≈ ±(R+w)) — the outer-edge artifact is largely gone. Not yet
resolution-converged; the residual floors ~1e-4 (cond(M⁻¹J)≈3e6 after the 7x drop)
and the peak sits at the band→tail transition. Candidate next levers: strengthen the
preconditioner below ~1e5, a K=8 convergence point, or widen the envelope past 2w.
Full islands suite green; all code + tests committed + pushed. LOG only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…gence lever — Lx=20w gives the first cleanly-converged physical solve

10-config Slurm array (K × domain × band-width, matrix-free on the smoothed band
grid). Findings: (#2) island resolution K does NOT converge Δ_neo — it oscillates
(-24,-14,-22,-12 for K=4,6,8,10) — so the band already resolves the drift islands;
(#3) the DOMAIN Lx is the lever — Lx/w=6,8,12,20 → resmax 4.6e-4,5.6e-4,1.6e-6,9.3e-11,
and Lx=20w CONVERGES cleanly (9 Newton iters, Δneo=-1.88, O(1) channels) — the first
cleanly-converged physical Level-0 solve. The far field at Lx=8w was too close (the
drift-island envelope reaches ~2w, so the domain needs ~20w). Widening the band margin
alone does not stabilize Δneo. Remaining: the volume-moment extraction (Q7) on the now-
converged base. LOG only; scan is scratch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
…); Δ_neo is ~99% far-field-dominated (Q7 extraction, now proven)

2nd Slurm array on the adequate domain (Lx≥16w) with an island-fraction diagnostic.
Findings: Δ_neo is roughly K-convergent once the domain is adequate (Lx=20w:
-1.65/-1.88/-1.80 for K=4/6/8, all converged resmax≤1.7e-8) — BUT island-fraction
(share of ∫m1 dx from |x|<3w) reads 0.01-0.03 for EVERY config: 97-99% of Δ_neo is the
outer region, m1 peaks near the domain edge, and Δ_neo shrinks -2.78→-1.06 as Lx=16→28
(not domain-convergent). So the whole convergence saga resolves — band grid + smoothed
tail + adequate domain give the first cleanly-converged physical solves — and the sole
remaining blocker is the original Q7 extraction (the raw volume moment is far-field-
dominated, not the localized island quantity), now proven on converged solves with a
hard number. Q7 updated; the fix is a signed-off-physics decision (subtract g_far /
decaying BC / matched-asymptotic), human sign-off required. LOG + QUESTIONS only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pUwoFRo9a5AjF8HuwcZMr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request WIP Work in progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant