Skip to content

Commit ed7d651

Browse files
logan-ncclaude
andcommitted
PE - EXPERIMENT - Kinetic runs regularize the stored xi_s (Fortran gpeq.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
1 parent d2abb6f commit ed7d651

1 file changed

Lines changed: 26 additions & 5 deletions

File tree

src/PerturbedEquilibrium/FieldReconstruction.jl

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,25 @@ function compute_clebsch_displacements(
364364
return clebsch_psi, clebsch_psi1, clebsch_alpha
365365
end
366366

367+
# Kinetic runs: mirror Fortran gpeq.f kin_flag — regularize the STORED self-consistent ξ_s
368+
# by the same singfac factor and never re-solve from matrices. The ideal-matrix resolve is
369+
# inconsistent with the kinetic solution's tangential response (the resonant layers live in
370+
# exactly that dynamics), and the kinetic A is non-Hermitian and must not be re-inverted
371+
# here. Kinetic-ness detected by populated kwmats splines (sentinel has 5 knots).
372+
if length(ffit.kwmats[1].cache.x) > 8
373+
for ipsi in 1:npsi
374+
q = equil.profiles.q_spline(psi_grid[ipsi])
375+
for ipert in 1:mpert
376+
m = mlow + ipert - 1
377+
singfac = m - nn * q
378+
reg_factor = singfac^2 / (singfac^2 + reg_spot^2)
379+
clebsch_psi1[ipsi, ipert] = xi_psi1_modes[ipsi, ipert] * reg_factor
380+
clebsch_alpha[ipsi, ipert] = xi_s_modes[ipsi, ipert] * reg_factor / chi1
381+
end
382+
end
383+
return clebsch_psi, clebsch_psi1, clebsch_alpha
384+
end
385+
367386
# Per-thread workspaces: matrix ops and spline hints are not safe to share across threads.
368387
# Size by maxthreadid() and index by threadid() under :static scheduling (GPEC convention).
369388
nt = Threads.maxthreadid()
@@ -404,7 +423,7 @@ function compute_clebsch_displacements(
404423
# xms = -(A\B)*xmp1 - (A\C)*xsp
405424
xsp_vec = view(xi_psi_modes, ipsi, :)
406425
mul!(xms_vec, bmat, xmp1_vec) # xms = B*xmp1
407-
mul!(xms_vec, cmat_buf, xsp_vec, 1.0+0.0im, 1.0+0.0im) # xms += C*xsp
426+
mul!(xms_vec, cmat_buf, xsp_vec, 1.0 + 0.0im, 1.0 + 0.0im) # xms += C*xsp
408427
# amat is positive-definite by construction (Newcomb kinetic-energy form), so cholesky is
409428
# safe. cholesky! factorizes in place (amat is a per-thread scratch buffer, refilled by
410429
# ffit.amats each surface), avoiding a fresh factorization allocation per surface.
@@ -980,10 +999,12 @@ function _apply_rzphi_transform(
980999
# Per-thread scratch (the immutable `ft` functor and `geom` are shared read-only): θ-space
9811000
# transform inputs/outputs (length mtheta) and mode-space forward-DFT outputs (length mpert),
9821001
# so the DFTs run in place with no per-surface allocation.
983-
bufs = [(R=zeros(ComplexF64, mtheta), Z=zeros(ComplexF64, mtheta), P=zeros(ComplexF64, mtheta),
984-
psi=zeros(ComplexF64, mtheta), th=zeros(ComplexF64, mtheta), ze=zeros(ComplexF64, mtheta),
985-
Ro=zeros(ComplexF64, mpert), Zo=zeros(ComplexF64, mpert), Po=zeros(ComplexF64, mpert))
986-
for _ in 1:Threads.maxthreadid()]
1002+
bufs = [
1003+
(R=zeros(ComplexF64, mtheta), Z=zeros(ComplexF64, mtheta), P=zeros(ComplexF64, mtheta),
1004+
psi=zeros(ComplexF64, mtheta), th=zeros(ComplexF64, mtheta), ze=zeros(ComplexF64, mtheta),
1005+
Ro=zeros(ComplexF64, mpert), Zo=zeros(ComplexF64, mpert), Po=zeros(ComplexF64, mpert))
1006+
for _ in 1:Threads.maxthreadid()
1007+
]
9871008

9881009
Threads.@threads :static for ipsi in 1:npsi
9891010
buf = bufs[Threads.threadid()]

0 commit comments

Comments
 (0)