Skip to content

Spin push for thin kick elements - #1606

Merged
ax3l merged 19 commits into
BLAST-ImpactX:developmentfrom
cemitch99:spin_push_thin_kicks
Aug 12, 2026
Merged

ax3l merged 19 commits into
BLAST-ImpactX:developmentfrom
cemitch99:spin_push_thin_kicks

Conversation

@cemitch99

@cemitch99 cemitch99 commented Aug 10, 2026 •

Copy link
Copy Markdown
Member

This PR adds the spin push through those Thin elements not associated with fringe fields. The logic for all of these elements uses the same pattern, and only the evaluation of the magnetic or electric fields should differ.

The implementation here is $s$-symmetric. A reversibility test will be included.

This closes Issue #1322

@cemitch99 cemitch99 changed the title Add Kicker spin push. Spin push for thin kick elements Aug 10, 2026
@cemitch99
cemitch99 requested review from ax3l and qianglbl August 10, 2026 22:34
@codspeed

codspeed Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 58 untouched benchmarks
🆕 10 new benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
🆕 test_Buncher[nospin] N/A 268.7 µs N/A
🆕 test_Buncher[spin] N/A 1.3 ms N/A
🆕 test_Kicker[nospin] N/A 110.5 µs N/A
🆕 test_Kicker[spin] N/A 1.3 ms N/A
🆕 test_NonlinearLens[nospin] N/A 1.4 ms N/A
🆕 test_NonlinearLens[spin] N/A 2.6 ms N/A
🆕 test_ShortRF[nospin] N/A 246.4 µs N/A
🆕 test_ShortRF[spin] N/A 861.6 µs N/A
🆕 test_ThinDipole[nospin] N/A 199.2 µs N/A
🆕 test_ThinDipole[spin] N/A 552.7 µs N/A

Comparing cemitch99:spin_push_thin_kicks (0c24f29) with development (a488422)

Open in CodSpeed

@cemitch99

Copy link
Copy Markdown
Member Author

The error is due to a warning associated with a possible loss of precision (double > float conversion) when running w/ SIMD.

@cemitch99 cemitch99 added the component: spin tracking Spin tracking label Aug 11, 2026
@cemitch99 cemitch99 added the component: elements Elements/maps/external fields label Aug 11, 2026
Comment thread src/elements/Buncher.H Outdated
Comment thread src/elements/Buncher.H Outdated
Comment thread src/elements/Kicker.H Outdated
Comment thread src/elements/Kicker.H Outdated
Comment thread src/elements/NonlinearLens.H Outdated
Comment thread src/elements/NonlinearLens.H Outdated
Comment thread src/elements/ShortRF.H Outdated
Comment thread src/elements/ShortRF.H Outdated
Comment thread src/elements/ThinDipole.H Outdated
Comment thread src/elements/ThinDipole.H Outdated
CI is correct, this was a bug.

Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja>
@ax3l ax3l self-assigned this Aug 11, 2026
@ax3l

ax3l commented Aug 11, 2026 •

Copy link
Copy Markdown
Member

Thanks for the PR! 🎉

I fixed the bug that CI caught.
Will do a detailed review a bit later :)

Comment thread src/elements/ThinDipole.H Outdated
ax3l added 3 commits August 12, 2026 09:53
Used by compilers and our SIMD implementation to optimize
write-backs into memory.
Comment thread src/elements/Buncher.H Outdated
The spin push duplicated the complex sqrt/log/division block from
operator() and then called operator(), which recomputed it. That
evaluated the most expensive part of the element twice per particle.

Hoist it into dF_dzeta() and single-source the momentum kick in
apply_kick(), so the phase space push and the spin push share one
evaluation. F'(zeta) does not change over the thin kick, so the spin
push reuses the same value for the magnetic field and for the kick.

Numerically identical: both evaluations had identical inputs, and
py - m_kick*dF.m_imag is the same IEEE operation as the previous
py + dpy with dpy = -m_kick*dF.m_imag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread src/elements/NonlinearLens.H Outdated
Comment thread src/elements/ShortRF.H Outdated
@ax3l

ax3l commented Aug 12, 2026 •

Copy link
Copy Markdown
Member

@cemitch99 a general question on the implementation of half-kicks here:
Excluding ShortRF, for the elements here (Kicker, Buncher, NonlinearLens, ThinDipole) the fields depend only on coordinates the kick leaves unchanged (x, y, plus t for Buncher). Like TaperedPL, we could also achieve an exactly reversible kick via midpoint push, that is second order and exactly reversible, too.

midpoint is 1 tbmt_precession_vector + 1 rotate_spin instead of 2 of each. rotate_spin carries a sincos and a sqrt, so it's the expensive half.
In #1609 I also saw a 2x smaller error constant (midpoint vs. trapezoidal rule behavior) for the midpoint scheme.

Is there a reason to prefer the half-kick structure that I'm missing?

ax3l and others added 3 commits August 12, 2026 11:52
The geometric factor -(1 + h*x)/beta_gamma_z in the Thomas-BMT precession
vector is a Frenet-Serret Jacobian and needs the design-orbit curvature.

Passing h and B_y at half strength and scaling the generator by the full
arc length gives the correct half-step contribution for every term that
enters linearly, but evaluates (1 + h*x) with half the curvature, an error
of order 0.5*x/rc on the field part of the rotation. Reversibility does
not catch it: the construction is self-inverting for any value of h.

Move the factor of one half from h and B_y onto the arc length, which is
equivalent for the linear terms and matches the convention already used by
ExactCFbend (h = 1/rc, unscaled fields, generator scaled by the step).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Evaluate the Thomas-BMT generator once, at the momentum halfway through
the kick, instead of applying two half rotations around the phase space
kick. This is the structure already used by TaperedPL.

Both forms are exactly reversible and second order: the reversed element
maps p_out back to p_in, so it sees the same midpoint, and the negated
strength gives the inverse rotation. They differ at third order, where
the midpoint rule has half the error constant of the trapezoidal rule
that two half kicks amount to.

Per particle this costs 1 tbmt_precession_vector + 1 rotate_spin instead
of 2 of each. Measured on the thin Multipole, which has the same
structure, that was ~28% off the spin push (~39% of the spin-specific
part) and 2x smaller error against a converged reference.

Applies to Kicker, Buncher, NonlinearLens and ThinDipole, whose fields
depend only on coordinates the kick leaves unchanged. Buncher also
changes the energy deviation, so pt is averaged along with the transverse
momenta. ShortRF keeps the half kick form: it changes the reference
energy, so px/py/pt are renormalized across the kick and a plain average
would mix two normalizations.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ax3l

ax3l commented Aug 12, 2026 •

Copy link
Copy Markdown
Member

In case midpush sounds good to you, I prepared a PR for this branch that you can apply directly:
cemitch99#4

If you merge the linked PR to your fork then the PR here will automatically update.

Performance: Midpoint Spin Push for Thin Kicks
@cemitch99 cemitch99 mentioned this pull request Aug 12, 2026
34 of 36 tasks
@cemitch99

Copy link
Copy Markdown
Member Author

@ax3l Ok, ready for re-review.

@ax3l ax3l left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thank you! 🎉

@ax3l
ax3l merged commit 33a7180 into BLAST-ImpactX:development Aug 12, 2026
18 checks passed
@ax3l ax3l mentioned this pull request Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: elements Elements/maps/external fields component: spin tracking Spin tracking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants