Skip to content

Implement Strang splitting with space charge#920

Open
cemitch99 wants to merge 8 commits into
BLAST-ImpactX:developmentfrom
cemitch99:strang_splitting_test
Open

Implement Strang splitting with space charge#920
cemitch99 wants to merge 8 commits into
BLAST-ImpactX:developmentfrom
cemitch99:strang_splitting_test

Conversation

@cemitch99

@cemitch99 cemitch99 commented Mar 26, 2025

Copy link
Copy Markdown
Member

This PR modifies the main tracking loop with collective effects to use a second-order Strang splitting.

  • increases the accuracy of the space charge calculation by moving from first-order to second-order with respect to the slice step size, currently set by nslice
  • ensures that integration in s is time-symmetric, which is needed for reversible back-tracking

Close #846

  • simple implementation for the case that nslice is an even integer
  • implement and test in the envelope tracking loop
  • implement and test in the particle tracking loop
  • modify implementation for the case of general nslice
  • add benchmark test(s)

A follow-up PR will address Issue #794

9.029112e-04,
9.029112e-04,
1.841402e-06,
8.94427191e-04,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Here the targets were tuned to analytically-determined values, instead of being set to coincide with a low-resolution run.

atol = 0.0 # ignored
rtol = 2.0e-3 # from random sampling of a smooth distribution
rtol = 3.5e-3 # from random sampling of a smooth distribution
print(f" rtol={rtol} (ignored: atol~={atol})")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The original tolerance was too tight.

Comment thread src/tracking/envelope.cpp Outdated
@cemitch99

cemitch99 commented Mar 28, 2025

Copy link
Copy Markdown
Member Author

The attached result illustrates the improvement in numerical convergence obtained when running the expanding beam test with envelope tracking (input_expanding_envelope.in).

ImpactX_StrangSplitting.pdf

Add linear return maps for additional elements (BLAST-ImpactX#923)
Comment thread src/tracking/envelope.cpp
Comment thread src/tracking/envelope.cpp
<< " slice_step=" << slice_step << "\n";
}

std::visit([&ref, &cm](auto&& element)

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.

Is the reference particle pushed twice now? o.0

Happens again in line 176 below

@cemitch99 cemitch99 Jun 27, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Clarified in person:

  • also includes envelope push
  • note the difference in weights (half step for push, full step for SC & CSR, another half step for push)

@cemitch99 cemitch99 Jun 27, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We have to make sure that thin elements, which only go through this loop body once, are still only kicked once though.

@ax3l

ax3l commented Jun 25, 2026

Copy link
Copy Markdown
Member

A small comment: this PR attempted a map/2 + collective kick + map/2 strang split, because intuitively this keeps the more costly collective kick centered and avoids doing +1 kick per element on its slices.

But, this only holds for Thick-derived, constant-field, non-s-dependent elements as a performance optimization. For thick elements that have s-dependent fields (RFCavity, SoftQuad, SoftSol), for potentially-thick but not easily splittable elements (LinearMap/SpinMap/Programmable) and for all Thin elements, a Kick/2 + map + kick/2 is the self-consistent fallback to use.

Under that viewpoint, I personally would recommend to do optimizations for number of collective kicks done later on: it complicates the code for a subset of the elements, and alternatives to optimize, like merging the half-kick at the last nslice with the next half-kick of the next element could be explored too (both optimizations are a bit messy in book-keeping).

Even with kick/2 + map + kick/2: in practice, because of the lower nslice needed now it might not even always pay off to carve out that one extra collective kick per element... (to be measured). Of course, for low numbers of nslice the cost is big, a regime we can now enter more with strang splitting...

@ax3l ax3l mentioned this pull request Jun 25, 2026
6 tasks
@cemitch99

Copy link
Copy Markdown
Member Author

Hm; I don't understand your last comment. The idea, as it is implemented in IMPACT-Z, is to use map/2 + collective kick + map/2 for all thick elements. If there is an s-dependence in the field, then the calculation of map is applied by numerical integration via splitting into substeps, whose number is set by the mapsteps parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Element Slicing: Strang Splitting

2 participants