Stage: SIMPLE / field-line diagnostics (milestone M1)
Source language: Fortran 2008
Manuals to read first: itpplasma/SPOIC spoic.f90:106-141 (trace — the working symplectic field-line scheme against SPEC data: Newton on the implicit radial update, A_theta as canonical momentum, zeta as time); SPECTRE fortran_src/poincare_mod.F90 and spectre/field_tracer.py (the reference tracers to match); DOC/coordinates-and-fields.md.
Depends on: itpplasma/libneo#371
Goal
SIMPLE ships a standalone app spectre_poincare.x producing Poincare sections and rotational-transform profiles for a SPECTRE equilibrium by symplectic field-line integration, per volume. Field lines never cross MRxMHD interfaces (B.n = 0 on both sides), so no crossing logic is involved; this milestone validates the whole libneo evaluation stack against SPECTRE's own tracer before any guiding-center work.
Files to edit
app/spectre_poincare.f90: NEW. Namelist input: SPECTRE file, volume list, seeds per volume, turns, section plane zeta0; output one poincare_volN.dat per volume (columns: turn index, s, theta, R, Z).
test/tests/test_spectre_poincare.py: NEW. Runs the app on the libneo fixture and compares against committed SPECTRE-tracer reference sections.
DOC/coordinates-and-fields.md: document the SPECTRE field input and its coordinate conventions (mandatory per repo policy).
src/CMakeLists.txt / CMakeLists.txt: link LIBNEO::spectre, add app target.
Behavior to implement
Field-line flow as canonical system with zeta as time, conjugate pair (A_theta, theta), radial coordinate solved implicitly (semi-implicit symplectic Euler as in SPOIC, second-order midpoint optional):
! Newton solve for r at fixed theta: A_theta(r_new) - A_theta_old = h * dH/dtheta
fun = f%dAth(1)*(f%Ath - Athold) + h*(f%dAzt(2)*f%dAth(1) - f%dAzt(1)*f%dAth(2))
r = r - fun/dfun
theta = theta + h*f%dAzt(1)/f%dAth(1); zeta = zeta + h
Seeds placed on zeta = zeta0, radially spread inside each volume, off-axis offset in volume 1.
Acceptance scenarios (BDD)
- Given the fixture equilibrium, when tracing 16 seeds per volume for 500 toroidal turns, then no field line leaves its volume (
|s| <= 1 throughout) — direct numerical witness of B.n = 0.
- Given the same seeds traced by SPECTRE's Poincare tracer (reference data committed), then section point clouds agree: for regular surfaces, radial spread of matched surfaces within 1e-6; island chains reproduced with matching O-point positions and widths within 5%.
- Given a seed on a regular surface, then the fitted rotational transform matches SPECTRE's
write_transform output for that surface to 1e-6.
- Given step-halving, then section points converge at the order of the chosen scheme (no first-order pollution from the Newton tolerance).
Success criteria
make && make test TEST=spectre_poincare
Non-goals
- No guiding-center orbits, no interface crossing, no losses.
- No chaos classification beyond visual/reference comparison (SIMPLE classifiers arrive with guiding-center milestones).
Verification
make test TEST=spectre_poincare
Stage: SIMPLE / field-line diagnostics (milestone M1)
Source language: Fortran 2008
Manuals to read first: itpplasma/SPOIC
spoic.f90:106-141(trace— the working symplectic field-line scheme against SPEC data: Newton on the implicit radial update,A_thetaas canonical momentum,zetaas time); SPECTREfortran_src/poincare_mod.F90andspectre/field_tracer.py(the reference tracers to match);DOC/coordinates-and-fields.md.Depends on: itpplasma/libneo#371
Goal
SIMPLE ships a standalone app
spectre_poincare.xproducing Poincare sections and rotational-transform profiles for a SPECTRE equilibrium by symplectic field-line integration, per volume. Field lines never cross MRxMHD interfaces (B.n = 0on both sides), so no crossing logic is involved; this milestone validates the whole libneo evaluation stack against SPECTRE's own tracer before any guiding-center work.Files to edit
app/spectre_poincare.f90: NEW. Namelist input: SPECTRE file, volume list, seeds per volume, turns, section planezeta0; output onepoincare_volN.datper volume (columns: turn index, s, theta, R, Z).test/tests/test_spectre_poincare.py: NEW. Runs the app on the libneo fixture and compares against committed SPECTRE-tracer reference sections.DOC/coordinates-and-fields.md: document the SPECTRE field input and its coordinate conventions (mandatory per repo policy).src/CMakeLists.txt/CMakeLists.txt: linkLIBNEO::spectre, add app target.Behavior to implement
Field-line flow as canonical system with
zetaas time, conjugate pair(A_theta, theta), radial coordinate solved implicitly (semi-implicit symplectic Euler as in SPOIC, second-order midpoint optional):Seeds placed on
zeta = zeta0, radially spread inside each volume, off-axis offset in volume 1.Acceptance scenarios (BDD)
|s| <= 1throughout) — direct numerical witness ofB.n = 0.write_transformoutput for that surface to 1e-6.Success criteria
Non-goals
Verification
make test TEST=spectre_poincare