Trace periodic join compatibility and nullspace - #161
Conversation
There was a problem hiding this comment.
Review verdict: Comment
Summary: PR #161 adds a join-end compatibility trace facility to NEO-2-QL, controlled by the NEO2_JOIN_END_TRACE_FILE environment variable. New routines join_end_trace_enabled, record_join_end_compatibility, and initialize_join_end_output are added to join_diagnostics_mod.f90; join_ends.f90 computes null-space/compatibility quantities and records them. A test extension validates shape/non-finite rejection and trace content. The real(kind(1.0d0)) declarations are modernized to real(real64 in the diagnostics module.
Findings:
-
[minor] NEO-2-QL/join_ends.f90:115-140 —
source_afterandmeasure_sumare only updated inside theisw_lorentz==1block (lines ~162-186). For non-Lorentz cases they remain 0.0 (initialized at ~140). The trace will then recordsource_after=0, measure_sum=0, source_factor=0 for non-Lorentz runs, which is misleading since no Lorentz correction was applied. Consider documenting this in a comment or only recording these fields whenisw_lorentz==1`. -
[minor] TEST/test_join_failure_diagnostic.f90:132 — The hardcoded
line_count /= 44assertion is fragile: if the set of values written byrecord_join_end_compatibilitychanges (e.g., adding or removing a diagnostic field), this test breaks with no guidance. Consider deriving the expected count or adding a comment explaining how 44 is computed (17 scalar + 10 per laguerre × 1 laguerre + index-dependent null records). -
[minor] NEO-7-QL/join_ends.f90:386 —
CALL gbsv(ndim,ndim,trace_matrix,...)useskl=ku=ndimon an n×n matrix.mat2bandallocates a band of(4*ndim+1) × ndim, which for large ndim (e.g. ndim=1000) consumes ~32 MB. Acceptable for an opt-in diagnostic, but worth a comment noting this is intentionally dense. -
[minor] NEO-2-QL/join_ends.f90:407 — When
trace_info .ne. 0,ierr=9is set and the subroutine returns before the maingbsvsolve. The test does not exercise this path (it only testsierr=7from shape/finite checks). Consider adding a test case forierr=9to verify the early-return behavior is handled correctly by callers.
Verdict: Comment — The implementation is well-structured and the test coverage is
join_endsreplaces one periodic equation per retained Laguerre block with the Lorentz current-closure constraint. The remaining periodic seam could therefore have come from an incompatible source, an incorrect nullspace, or reconstruction of a different source.Add an opt-in
NEO2_JOIN_END_TRACE_FILEdiagnostic. For each join it records the Lorentz source correction, transfer-matrix identity error, original periodic-system left and right null vectors, compatibility residual, both replaced-row residuals, and algebraic scales. The CSV writer rejects wrong shapes, nonfinite values, nonpositive scales, and I/O failures.The diagnostic is observation-only. When disabled it allocates no diagnostic arrays and performs no diagnostic solve. It does not change the Lorentz projection, Pfirsch-Schlueter current constraint, particle-conservation treatment, collision operator, discretization, convergence criteria, Fourier convention, CGS units, boundary conditions, ABI, or array layout.
The accepted 480-step, 30-pitch batch replay resolves the open hypothesis:
2.81e-17relative;1.18e-14and1.17e-14relative;1.39e-16relative;1.39e-16and5.27e-15relative;2.71e-16relative;7.85e-4of the unsigned source scale;7.28e-4;8.48e-4.The periodic solve is compatible and satisfies both original rows. The seam instead follows from applying the Lorentz correction only to the joined propagator source. Stage-1 reconstruction replays the saved local sources, which do not contain a spatially localized form of that correction. This PR does not invent such a localization and does not accept a physical pointwise current.
With the diagnostic enabled, all 398 saved propagators and 199 reconstructed boundaries are bit-for-bit identical to the parent result. Every numerical dataset in the 199 local-response HDF5 files and the global response file is also identical. All 12 focused tests and the trace-analysis test pass under bounds checks and floating-point traps. A follow-up commit separates finiteness and positivity checks because Fortran logical operators are not required to short-circuit; this prevents a nonfinite diagnostic scale from reaching an ordered comparison under invalid-operation traps.
Verification
Test fails on parent
At
130ea2c:The existing test passes, but no requested join-end trace is produced.
Test passes after fix
The format warning is already present for the legacy
join_ends.f90file at the parent commit. This PR keeps its existing layout instead of reformatting unrelated lines.