You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Subsystem: NEO-2-QL non-axisymmetric (isw_qflux_NA=1) solve Branch to fix:feat/ql-qflux-mode-input (PR #121, the PR that adds none mode); also present in the stacked feat/ql-misalignment-drive (PR #119). Related:#118, #121, #119
Summary
A source-only non-axisymmetric run (in_file_pert='none', isw_m_phi_input=1) with no source actually configured (no perturbation field, helical drive off) assembles an identically zero source vector. That vector is the Arnoldi seed, so its normalization divides by zero (0/0 = NaN). The NaN propagates into the Hessenberg matrix and zhseqr fails to converge at every Arnoldi step, printing try_eigvecvals: zhseqr failed to compute all eigenvalues in a loop for ~8 minutes, never producing qflux output and never aborting cleanly.
Reproduction
Minimal source-only NA &ntv_input (single electron species, HELCORE-type Boozer geometry), drive off:
Run neo_2_ql.x on a single surface. Actual: endless try_eigvecvals: zhseqr failed to compute all eigenvalues; no qflux_ntv.dat / neo2_multispecies_out.h5.
Expected: either a single clear diagnostic (source-only NA run has no source) or the exact zero NA response, in O(1) time.
Root cause (file:line, branch feat/ql-qflux-mode-input)
NEO-2-QL/neo_magfie_perturbation.f90:100-108 (added by QL: allow prescribed perturbation mode without field file #121): in_file_pert='none' short-circuits with mnmax_pert = 0; RETURN, so the perturbation field contribution bnoverb0 == 0. The only guard added is that none requires isw_m_phi_input=1; nothing requires a non-zero source.
With the drive off, no other NA source is assembled, so source_vector == 0, and NEO-2-QL/ripple_solver_ArnoldiOrder2_test.f90:3587 sets f_init_arnoldi = source_vector_all(:,1,ispec) = 0.
NEO-2-QL/arnoldi_mod.f90:307-309: q_spec = SUM(CONJG(fnew)*fnew) = 0, then qvecs_prev(:,1) = fnew / SQRT(SUM(q_spec)) = 0/0 = NaN. No zero-norm guard.
NaN contaminates hmat; zhseqr returns info>0 (arnoldi_mod.f90:451,455) at every m up to mmax = n_arnoldi = 500, for each of the 3 source columns. arnoldi never tests ierr inside its DO m=2,mmax loop (arnoldi_mod.f90:339), so it re-fails instead of aborting. That is the spin.
Not reachable on main
On main, neo_read_pert opens in_file_pert with status='old' unconditionally (NEO-2-QL/neo_magfie_perturbation.f90:97), so 'none' is a file-not-found error; has_perturbation_file, isw_m_phi_input, m_phi_input, and the mnmax_pert=0 short-circuit do not exist there. The zero-source NA path is introduced by none mode, and PR #121 alone reproduces the failure using its own feature. This is therefore a #121 gap, not a pre-existing arnoldi_mod bug.
Proposed fix (scoped to #121, arnoldi_mod.f90 untouched)
Guard the degenerate zero-source NA run in the code #121 owns. Where the source-only NA source is assembled/known (the none-mode path in neo_magfie_perturbation.f90 plus the source-only entry in NEO-2-QL/neo2.f90), detect an identically zero assembled source and either:
preferred: STOP with one clear message, e.g. "source-only NA run (in_file_pert='none') has no source: set a drive (isw_hel_drive/=0 with non-zero hel_*) or provide a perturbation file"; or
short-circuit to the exact zero NA response without invoking arnoldi.
Test the assembled source, not the mode flag: on the stacked feat/ql-misalignment-drive (PR #119) a valid none + drive-on run has a non-zero source and must pass unchanged.
Files to edit
NEO-2-QL/neo_magfie_perturbation.f90 and/or NEO-2-QL/neo2.f90: the guard.
TEST/: new behavioral test (below).
Test (behavioral, red-then-green)
Add a TEST/ case in the style of TEST/test_ntv_perturbation_input.f90 (#121): a source-only none config with no drive yields the guard outcome (clean error or exact zero) with no NaN and no repeated zhseqr failure; a none + drive-on config still assembles a non-zero source. The test fails before the guard and passes after. Assert the user-visible outcome (no NaN / clean result), not the guard helper itself.
Success criteria
The new NTV test is green in the repo test suite (make test), the rest unchanged.
The reproduction namelist returns in O(1) with a clear result or diagnostic, not a spin.
Golden records unchanged.
Non-goals
Do not edit arnoldi_mod.f90 / ripple_solver_* core numerics here.
Do not attempt the near-resonant driven case (lambda = m*iota + n = -0.01); convergence of a driven (non-zero-source) near-resonant run is a separate question.
Defensive hardening in arnoldi_mod.f90: guard the zero-norm seed at :309 (zero source => exact f=0, skip Arnoldi), the Gram-Schmidt breakdown at :335, and abort the m-loop on ierr/=0 at :339 instead of re-failing 500x. Belt-and-suspenders; not required to clear this issue.
Subsystem: NEO-2-QL non-axisymmetric (
isw_qflux_NA=1) solveBranch to fix:
feat/ql-qflux-mode-input(PR #121, the PR that addsnonemode); also present in the stackedfeat/ql-misalignment-drive(PR #119).Related: #118, #121, #119
Summary
A source-only non-axisymmetric run (
in_file_pert='none',isw_m_phi_input=1) with no source actually configured (no perturbation field, helical drive off) assembles an identically zero source vector. That vector is the Arnoldi seed, so its normalization divides by zero (0/0 = NaN). The NaN propagates into the Hessenberg matrix andzhseqrfails to converge at every Arnoldi step, printingtry_eigvecvals: zhseqr failed to compute all eigenvaluesin a loop for ~8 minutes, never producing qflux output and never aborting cleanly.Reproduction
Minimal source-only NA
&ntv_input(single electron species, HELCORE-type Boozer geometry), drive off:Run
neo_2_ql.xon a single surface. Actual: endlesstry_eigvecvals: zhseqr failed to compute all eigenvalues; noqflux_ntv.dat/neo2_multispecies_out.h5.Expected: either a single clear diagnostic (source-only NA run has no source) or the exact zero NA response, in O(1) time.
Root cause (file:line, branch
feat/ql-qflux-mode-input)NEO-2-QL/neo_magfie_perturbation.f90:100-108(added by QL: allow prescribed perturbation mode without field file #121):in_file_pert='none'short-circuits withmnmax_pert = 0; RETURN, so the perturbation field contributionbnoverb0 == 0. The only guard added is thatnonerequiresisw_m_phi_input=1; nothing requires a non-zero source.source_vector == 0, andNEO-2-QL/ripple_solver_ArnoldiOrder2_test.f90:3587setsf_init_arnoldi = source_vector_all(:,1,ispec) = 0.NEO-2-QL/arnoldi_mod.f90:307-309:q_spec = SUM(CONJG(fnew)*fnew) = 0, thenqvecs_prev(:,1) = fnew / SQRT(SUM(q_spec))=0/0 = NaN. No zero-norm guard.hmat;zhseqrreturnsinfo>0(arnoldi_mod.f90:451,455) at everymup tommax = n_arnoldi = 500, for each of the 3 source columns.arnoldinever testsierrinside itsDO m=2,mmaxloop (arnoldi_mod.f90:339), so it re-fails instead of aborting. That is the spin.Not reachable on
mainOn
main,neo_read_pertopensin_file_pertwithstatus='old'unconditionally (NEO-2-QL/neo_magfie_perturbation.f90:97), so'none'is a file-not-found error;has_perturbation_file,isw_m_phi_input,m_phi_input, and themnmax_pert=0short-circuit do not exist there. The zero-source NA path is introduced bynonemode, and PR #121 alone reproduces the failure using its own feature. This is therefore a #121 gap, not a pre-existingarnoldi_modbug.Proposed fix (scoped to #121,
arnoldi_mod.f90untouched)Guard the degenerate zero-source NA run in the code #121 owns. Where the source-only NA source is assembled/known (the
none-mode path inneo_magfie_perturbation.f90plus the source-only entry inNEO-2-QL/neo2.f90), detect an identically zero assembled source and either:STOPwith one clear message, e.g."source-only NA run (in_file_pert='none') has no source: set a drive (isw_hel_drive/=0 with non-zero hel_*) or provide a perturbation file"; orarnoldi.Test the assembled source, not the mode flag: on the stacked
feat/ql-misalignment-drive(PR #119) a validnone+ drive-on run has a non-zero source and must pass unchanged.Files to edit
NEO-2-QL/neo_magfie_perturbation.f90and/orNEO-2-QL/neo2.f90: the guard.TEST/: new behavioral test (below).Test (behavioral, red-then-green)
Add a
TEST/case in the style ofTEST/test_ntv_perturbation_input.f90(#121): a source-onlynoneconfig with no drive yields the guard outcome (clean error or exact zero) with no NaN and no repeatedzhseqrfailure; anone+ drive-on config still assembles a non-zero source. The test fails before the guard and passes after. Assert the user-visible outcome (no NaN / clean result), not the guard helper itself.Success criteria
make test), the rest unchanged.Non-goals
arnoldi_mod.f90/ripple_solver_*core numerics here.lambda = m*iota + n = -0.01); convergence of a driven (non-zero-source) near-resonant run is a separate question.Optional follow-up (separate, low priority, solver owner)
Defensive hardening in
arnoldi_mod.f90: guard the zero-norm seed at:309(zero source => exactf=0, skip Arnoldi), the Gram-Schmidt breakdown at:335, and abort them-loop onierr/=0at:339instead of re-failing 500x. Belt-and-suspenders; not required to clear this issue.