Stage: orbit tracing / 6D CPP
Source language: Fortran
Manuals to read first: DOC/derivations/cp_cpp_derivation.wl, src/orbit_cpp_canonical.f90, src/simple.f90, src/orbit_full.f90, Xiao and Qin 2021 CPC 265 107981 (10.1016/j.cpc.2021.107981)
Goal
Make orbit_model = 5 use the CPP slow-manifold integrator at GC-sized timesteps for Boozer/VMEC fields. After the PR lands, CPP loss results should not change from prompt losses to full confinement merely by increasing npoiper2, provided the requested step remains inside the documented CPP slow-manifold regime.
Files to edit
src/orbit_cpp_canonical.f90: fix the full-metric CPP symmetric-midpoint Newton Jacobian and convergence test.
test/tests/test_cpp_canonical.f90: add a finite-difference Jacobian check for the full-metric CPP residual path.
test/tests/test_cpp6d_vs_gc.f90: add a behavioral guard that CPP does not accept a step with a large post-update residual in the W7-X Boozer path.
Syntax or behavior to implement
Production CPP is selected by:
orbit_model = 5
orbit_coord = 1
This route goes through orbit_cpp_canonical with MODEL_CPP_SYM. CPP is a canonical Pauli particle on the slow manifold. It should use the implicit midpoint solve for slow guiding-center motion, not the CP gyro-resolved step-size rule.
The full-metric Jacobian currently omits the midpoint-coordinate derivative terms for the CPP force gradient:
d/dqmid_k [ 0.5 m dg_ab,j v_a v_b + qc dA_a,j v_a - mu dB_j ]
Those terms include second derivatives of g, A, and B. Implement them analytically if the field API exposes them consistently, or compute the full-metric Jacobian by finite differencing the same residual block used by Newton. Keep the source of truth in one residual routine.
Newton convergence must check the residual at the accepted state. A small correction alone is not enough when the Jacobian is approximate or numerically degraded.
Scaffold
call sym_residual_blk(st, z_trial, fvec)
call sym_jacobian_blk(st, z_trial, fjac)
call solve_linear(fjac, fvec, dz, ierr)
z_new = z_trial - dz
call sym_residual_blk(st, z_new, fnew)
if (maxval(abs(fnew)) < newton_tol) then
st%z = z_new
exit
end if
z_trial = z_new
For the full-metric residual, validate sym_jacobian_blk with central differences:
call sym_residual_blk(st, z + eps*ej, fp)
call sym_residual_blk(st, z - eps*ej, fm)
jfd(:, j) = (fp - fm)/(2*eps)
Positive fixtures to add
test/tests/test_cpp_canonical.f90: full-metric CPP Jacobian agrees with finite differences for a representative Boozer/VMEC state to a tolerance set by the field interpolation accuracy.
test/tests/test_cpp6d_vs_gc.f90: one CPP Boozer step at a GC-sized timestep exits with ierr == 0 and a small post-update residual.
Negative fixtures to add
test/tests/test_cpp6d_vs_gc.f90: force or expose a degraded Jacobian path and assert that the step reports non-convergence instead of accepting a large residual.
Observed failure
A W7-X alpha-loss benchmark at SIMPLE v1.5.0-116-g4cbca07 showed strong CPP sensitivity to npoiper2:
10 us, GC npoiper2=512: confined 1.000
10 us, CPP npoiper2=512: confined 0.946
10 us, CPP npoiper2=2048: confined 0.946
10 us, CPP npoiper2=8192: confined 1.000
10 us, CPP npoiper2=16384: confined 1.000
10 us, CP npoiper2=16384: confined 1.000
10 ms, GC npoiper2=1024: confined 0.829
10 ms, CPP npoiper2=1024: confined 0.318, first loss at 6.8e-9 s
The trend points to the CPP nonlinear solve. Smaller steps hide the defect. CPP itself is meant to run on the slow manifold; the large-step path should not behave like full CP gyro-resolution.
Success criteria
math -script DOC/derivations/cp_cpp_derivation.wl
fo test test_cpp_canonical
fo test test_cpp6d_vs_gc
fo
A focused W7-X benchmark should also show no prompt CPP loss caused solely by the production timestep choice.
Non-goals
- Do not change CP6D gyro-resolved stepping.
- Do not change CPP initialization or normalization unless a failing test proves a mismatch with
DOC/derivations/cp_cpp_derivation.wl.
- Do not replace Newton with fixed-point Picard iteration for
MODEL_CPP_SYM.
- Do not weaken current conservation or energy checks.
Verification
math -script DOC/derivations/cp_cpp_derivation.wl && fo test test_cpp_canonical && fo test test_cpp6d_vs_gc && fo
Stage: orbit tracing / 6D CPP
Source language: Fortran
Manuals to read first:
DOC/derivations/cp_cpp_derivation.wl,src/orbit_cpp_canonical.f90,src/simple.f90,src/orbit_full.f90, Xiao and Qin 2021 CPC 265 107981 (10.1016/j.cpc.2021.107981)Goal
Make
orbit_model = 5use the CPP slow-manifold integrator at GC-sized timesteps for Boozer/VMEC fields. After the PR lands, CPP loss results should not change from prompt losses to full confinement merely by increasingnpoiper2, provided the requested step remains inside the documented CPP slow-manifold regime.Files to edit
src/orbit_cpp_canonical.f90: fix the full-metric CPP symmetric-midpoint Newton Jacobian and convergence test.test/tests/test_cpp_canonical.f90: add a finite-difference Jacobian check for the full-metric CPP residual path.test/tests/test_cpp6d_vs_gc.f90: add a behavioral guard that CPP does not accept a step with a large post-update residual in the W7-X Boozer path.Syntax or behavior to implement
Production CPP is selected by:
This route goes through
orbit_cpp_canonicalwithMODEL_CPP_SYM. CPP is a canonical Pauli particle on the slow manifold. It should use the implicit midpoint solve for slow guiding-center motion, not the CP gyro-resolved step-size rule.The full-metric Jacobian currently omits the midpoint-coordinate derivative terms for the CPP force gradient:
Those terms include second derivatives of
g,A, andB. Implement them analytically if the field API exposes them consistently, or compute the full-metric Jacobian by finite differencing the same residual block used by Newton. Keep the source of truth in one residual routine.Newton convergence must check the residual at the accepted state. A small correction alone is not enough when the Jacobian is approximate or numerically degraded.
Scaffold
For the full-metric residual, validate
sym_jacobian_blkwith central differences:Positive fixtures to add
test/tests/test_cpp_canonical.f90: full-metric CPP Jacobian agrees with finite differences for a representative Boozer/VMEC state to a tolerance set by the field interpolation accuracy.test/tests/test_cpp6d_vs_gc.f90: one CPP Boozer step at a GC-sized timestep exits withierr == 0and a small post-update residual.Negative fixtures to add
test/tests/test_cpp6d_vs_gc.f90: force or expose a degraded Jacobian path and assert that the step reports non-convergence instead of accepting a large residual.Observed failure
A W7-X alpha-loss benchmark at SIMPLE
v1.5.0-116-g4cbca07showed strong CPP sensitivity tonpoiper2:The trend points to the CPP nonlinear solve. Smaller steps hide the defect. CPP itself is meant to run on the slow manifold; the large-step path should not behave like full CP gyro-resolution.
Success criteria
A focused W7-X benchmark should also show no prompt CPP loss caused solely by the production timestep choice.
Non-goals
DOC/derivations/cp_cpp_derivation.wl.MODEL_CPP_SYM.Verification