Skip to content

KF/PE - BUGFIX! - Self-consistent xi_s for the NTV kernel input; static scheduling for the kinetic kernel loop - #425

Draft
logan-nc wants to merge 2 commits into
feature/kinetic-resonance-knotsfrom
bugfix/kinetic-clebsch-xi-s
Draft

KF/PE - BUGFIX! - Self-consistent xi_s for the NTV kernel input; static scheduling for the kinetic kernel loop#425
logan-nc wants to merge 2 commits into
feature/kinetic-resonance-knotsfrom
bugfix/kinetic-clebsch-xi-s

Conversation

@logan-nc

Copy link
Copy Markdown
Collaborator

Stacked on #422 (feature/kinetic-resonance-knots). The overnight resolution of the PE-vs-NTV torque discrepancy (issue #423's measured motivation; RESULTS.md §34–§35).

The bug

In kinetic runs, the Clebsch ξ^α fed to the NTV kernel (via dbob_m/divx_m) was re-solved from the ideal A, B, C matrices — inconsistent with the self-consistent kinetic tangential response exactly where resonant layers live. Fortran (gpeq.f, kin_flag) instead scales the stored self-consistent ξ_s by the singfac regularization factor and inverts nothing. This is the same physics flaw #407 fixes on the MatrixSplines branch (there: a silently broken Cholesky of the non-Hermitian kinetic A; here: a valid Cholesky of the wrong — ideal — A).

The consequence (measured, DIII-D kinetic-calculated full chain)

The perturbative NTV evaluation was driven by a tangential displacement that ignores the kinetic layer response, producing a phantom 4× torque concentrated in a ~2e-3-wide resonant core at the pedestal ω_E crossing (fgar: 0.7241 N·m, of which +0.622 in ψ∈[0.90, 0.95]; the self-consistent EL solution collects 0.046 there — and the EL side was verified faithful at every level: boundary ≡ volume torque to 7 digits, FKG assembly and kinetic RHS sign-by-sign Fortran-conformant per fortran-physics-reviewer, matrix-spline resolution and integrator step size both exonerated by direct null experiments).

With the fix, the phantom collapses (+0.622 → +0.033) and the two independent torque calculations agree band-by-band (resonant layer: 0.0461 vs 0.0455). Domain-matched totals (ΔIm over [ψ_c, psilim] — fgar's exact domain; the sub-ψ_c Im(u1†u2) offset is non-dissipative initial-condition content, ±0.05 with opposite signs across cases):

case (deterministic, post-:static) PE (domain-matched) fgar agreement
rot factor 0.2, reg_spot 0.05 0.1456 0.1460 0.3%
rot factor 1.0, reg_spot 0.05 0.1322 0.1655 20%
rot factor 1.0, reg_spot 0.01 0.1322 0.1397 5.4%

Where the comparison is regularization-unambiguous (rot=0.2: resonances away from rationals), the two independent torque calculations now agree to 0.3%. The rot=1.0 residual sits inside fgar's own reg_spot sensitivity band (its answer moves 18% between reg 0.05 and 0.01 — the acknowledged near-rational input ambiguity, present in Fortran too); PE is reg-independent by construction.

Second fix in this PR: determinism

CalculatedKineticMatrices.jl's per-surface kernel loop was the only threaded loop in the codebase using Threads.@threads without :static while indexing per-thread scratch by threadid() — dynamic-scheduling task migration corrupts kinetic matrix rows at rare-migration frequency. Observed live: three runs of one identical deck gave et[1] = 1.0053 / 1.1355 / 0.9895. With :static, identical decks reproduce bit-identically (verified), and et returns exactly to the pre-fix value — every historical calculated-kinetic result carries this latent race.

Effects on outputs: kinetic-run regularized quantities (xi_clebsch_alpha, *_reg fields) and every NTV torque driven by them change; ideal runs and reg_spot = 0 are bit-unaffected. Kinetic harness cases will move — new baselines with this physics justification.

Review items

⚠️ REQUIRES THIRD-PARTY HUMAN REVIEW BEFORE MERGING — NON-NEGOTIABLE. DO NOT MERGE WITHOUT AN APPROVING HUMAN REVIEW.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LzbLFQKyuRE5DYZmLokKmk

logan-nc and others added 2 commits August 21, 2026 23:38
…eq.f kin_flag analog)

The Clebsch xi_alpha fed to the NTV kernel was re-solved from the IDEAL A,B,C
even in kinetic runs, inconsistent with the self-consistent kinetic tangential
response exactly where resonant layers live. Mirror Fortran: scale the stored
xi_s by the singfac regularization factor and invert nothing (analog of the
#407 fix, adapted to the FourFitVars API; kinetic-ness detected via populated
kwmats pending proper flag threading).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzbLFQKyuRE5DYZmLokKmk
The per-surface kernel loop indexed per-thread scratch (thread_intrs and the
four matrix buffers) by threadid() under DEFAULT dynamic scheduling -- the only
threaded loop in the codebase missing :static. Task migration at yield points
lets two tasks share a buffer and corrupt matrix rows, making every
calculated-kinetic run nondeterministic at rare-migration frequency (observed:
three runs of an identical DIII-D deck gave et[1] = 1.0053, 1.1355, 0.9895).
All other threadid-indexed loops already use :static per the GPEC convention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzbLFQKyuRE5DYZmLokKmk
logan-nc added a commit that referenced this pull request Aug 22, 2026
…iguous case); PR #425

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzbLFQKyuRE5DYZmLokKmk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant