Longitudinal slicing (Slicer)

The Slicer command assigns every live macro-particle in each bunch to a longitudinal slice. It stores the result in a named SliceSet owned by the bunch. Slicing is a local classification operation: it does not reorder any particle array and it does not change bunch membership.

See Longitudinal coordinate and reference time for coordinate and time conventions. Choose a coordinate and named slice set, then execute Slicer before each collective-effect command that needs its updated data.

Configuration

An input entry uses the command name Slicer and a user-defined slice set key:

{
    "sc_slicer": {
        "S (m)": 12.5,
        "Command": "Slicer",
        "Slice set": "space_charge",
        "Coordinate": "z_periodic",
        "Slice model": "equal_particle",
        "Number of slices": 128,
        "Z range mode": "auto",
        "Save turns": [[0], [100, 1000, 100]]
    }
}

The range configuration is mode-specific. No flat Z min, Z max or Number of sigma fields are accepted.

auto

Uses the actual minimum and maximum of the current live distribution. It is the widest data-driven range and never excludes an observed outlier. If every live particle has the same selected coordinate, the range retains its true zero span; no artificial width is added.

explicit

Uses the fixed local interval supplied by Explicit:

"Z range mode": "explicit",
"Explicit": {"Z min": -0.30, "Z max": 0.30}

All ranges are resolved at command execution. With z_rel or z_periodic, values outside an explicit interval are clipped to the first or last slice and a warning is logged; they are never silently dropped.

Slice IDs are ordered from high to low selected slice coordinate: slice 0 is the largest-z interval and slice N-1 is the smallest-z interval. Uniform-bin indexing uses FP64 arithmetic and checks the neighboring saved edge after division, so a stored FP32 value just below a boundary keeps its correct owner. Classification and the output table use the same generated edge array on CPU, CUDA and the CUDA batch path. In increasing coordinate order, equal_length bins are left-closed and right-open, except that the final bin includes the maximum. This does not change the precision of the particle arrays or local projections.

Interface Parameters

The following table lists the parameters accepted by a Slicer sequence entry. JSON keys are shown in the spelling used by generated input files; PASS normalizes key case internally.

Common command parameters

Parameter

Key

Type

Default / required

Description

command

"Command"

str

Required

Must be "Slicer". This selects the Slicer command implementation.

s

"S (m)"

float

Required

Longitudinal machine position at which the slice data are updated.

name

sequence object key

str

Required as sequence key

Name of this command instance. The sequence loader also passes it to the command for diagnostics.

slice_set

"Slice set"

str

Required

Name of the bunch-owned SliceSet to update, for example "space_charge" or "beambeam_ip1".

slice_model

"Slice model"

str

"equal_length"

Particle-to-slice mapping model. The only accepted values are "equal_length" and "equal_particle".

coordinate

"Coordinate"

str

"z_rel"

z_rel for continuous time slicing; z_periodic for circumference-folded SC slicing; arrival_phase for the wake observation clock; collision_z inside an explicit CrossingAngle interval. SC requires an explicit z_periodic selection.

purpose / configuration

"Purpose" / "Configuration"

str / str or null

"general" / null

beam_beam requires a matching IP configuration and z_rel or collision_z. Its explicit range must cover all live particles; see Beam-Beam Interaction (BeamBeam) for frame and ordering rules.

num_slices

"Number of slices"

int

10

Configured number of longitudinal bins. Must be at least 1; the value is retained even when the live population is smaller.

z_range_mode

"Z range mode"

str

"auto"

Selects "auto" or "explicit".

save_turns

"Save turns"

list of int lists

[]

Optional snapshot selections: [turn] or [start, end, step].

periodic

"Periodic"

bool

false

Whole-ring arrival-phase projection for coasting WakeField; requires equal_length and an explicit interval of length C.

max_phase_slip

"Max phase slip"

float

0.05

Maximum observed phase change per reference turn accepted by WakeField, in revolutions; (0, 0.1]. Diagnostic slicing records but does not enforce it.

Range-mode parameters

Only the block corresponding to Z range mode is used. auto has no mode-specific block. explicit requires the Explicit block.

Mode / parameter

Key

Type

Default / required

Description

auto

"Z range mode"

str

Optional

Uses the actual minimum and maximum of the current live distribution; observed outliers are included.

explicit

"Z range mode"

str

Optional

Uses a fixed interval. Explicit is required with this mode.

explicit block

"Explicit"

object

Required for explicit mode

Mode-specific object containing Z min and Z max.

z_min

"Z min"

float

Required for explicit mode

Lower bound in the selected slice coordinate; must be smaller than Z max.

z_max

"Z max"

float

Required for explicit mode

Upper bound in the selected slice coordinate; must be larger than Z min.

Configuration validation

At beam initialization, repeated Slicer entries referring to the same Slice set must have identical Slice model, Number of slices, range mode and (for explicit mode) the explicit block. A conflicting definition raises ValueError and identifies both sequence entries. At execution, an explicit range that does not cover all live particles produces a warning; out-of-range particles are clipped to the first or last slice.

Within one beam, a named SliceSet may be shared by enabled consumers of the same physical module, for example several WakeField commands. Different modules must use different names: a wake and a beam-beam interaction cannot consume the same set. Input validation reports the conflicting set, modules and commands. Identical names on different beams are independent. Repeated, compatible Slicer commands may still update the same set; this rule does not change explicit update frequency or perform automatic reslicing. The same input check reserves sets with Purpose=beam_beam for BeamBeam, even when no BeamBeam command currently reads them. Commands that do not read slices, such as a zero-interaction-length IBS, do not claim a set.

output_format (JSON "Output format") defaults to "hdf5-gzip1" and accepts "hdf5" (uncompressed) and "tfs". The default uses gzip-1 with shuffle. The choice affects particle details only; slice summaries remain TFS and CSV. See Table output formats for the HDF5 layout and reader.

Slice models

Use equal_particle in place of the former equal_charge or Equal particle names; those names are no longer accepted.

equal_length divides the resolved interval into N equal-width bins:

\[i = N-1-\operatorname{clip}\left(\left\lfloor \frac{z-z_{min}}{\Delta z}\right\rfloor,0,N-1\right), \qquad \Delta z = \frac{z_{max}-z_{min}}{N}.\]

For a nonzero range, equal_length requires finite, strictly increasing FP64 edges. If rounding makes adjacent edges coincide, Slicer raises an error instead of changing the interval or number of slices. This requirement applies to both auto and explicit ranges; choose a representable interval or fewer slices when necessary.

equal_particle sorts only temporary z values and indices, assigns IDs by rank, and scatters those IDs back to the original particle order. The particle pool itself is unchanged. Rank assignment keeps populations nearly equal, including when several particles have identical coordinates. The saved boundaries enclose these rank-assigned members; they also determine the widths and centers consumed by SpaceCharge, WakeField and ECloud.

For \(n>0\) live particles sorted in increasing coordinate order as \(s_0,\ldots,s_{n-1}\), an interior boundary \(i=1,\ldots,N-1\) separates the ranks at \(k_i=\lceil in/N\rceil\). Starting from the linear quantile candidate \(q_i\) at fraction \(i/N\), Slicer saves

\[\begin{split}e_i=\operatorname{clip}(q_i,L_i,U_i),\qquad [L_i,U_i]= \begin{cases} [s_{k_i-1},s_{k_i}],&0<k_i<n,\\ [s_{n-1},z_{max}],&k_i=n. \end{cases}\end{split}\]

The outer edges remain \(e_0=z_{min}\) and \(e_N=z_{max}\). A candidate already in its allowed gap is unchanged. Rank IDs and counts are unchanged, including empty slices when \(N>n\). These intervals are closed envelopes: slice_id determines ownership at shared endpoints and repeated coordinates. Do not reclassify rank slices using the half-open coordinate-bin rule above. Repeated coordinates can still produce zero-width slices; their density and consumer requirements are described below.

With an explicit range, this enclosure applies to the clipped coordinates used for slicing. Stored particle coordinates and actual member extrema are unchanged. ECloud still rejects actual members outside its slice bounds; clipping does not make such particles physically contained.

When an auto range has zero span at coordinate \(z_0\), every saved z_min and z_max equals \(z_0\), and every delta_z is zero. equal_length assigns all live particles to slice 0 and leaves the other slices empty. equal_particle retains rank assignment. A bunch with no live particles keeps its empty result.

Slots with no allocated particle records cache only zero-charge slice geometry and refresh the observation time; they require no particle slicing and produce no slot snapshots. This geometry lets stateful effects such as ElectronCloud advance through zero-charge intervals. Bunches containing lost records or reserved records for later injection still update and save their slices normally. For an unallocated slot with an auto range, ElectronCloud uses the bunch reference time as a zero-charge observation point instead of treating the tiny fallback slice width as a physical pulse. Explicit empty intervals remain intact.

If the number of live particles is smaller than N, only that many slices can be populated. The remaining slices are retained with zero count and a warning is emitted. effective_num_slices records \(\min(N_{live},N)\); the configured mesh size is not changed.

SliceSet data

Each bunch has a mapping such as bunch.slice_sets["space_charge"]. After execution, slice_id is an integer array aligned with the bunch’s current particle range; lost particles have ID -1. slice_table contains one array per slice:

z_min, z_max, z_center

Boundaries and center in the selected slice coordinate, listed from high-z to low-z (slice 0 is the high-z interval).

z_particle_min, z_particle_max

Actual minimum and maximum of the slice’s live macroparticle members in the selected coordinate at this Slicer execution. These values precede explicit range clipping and can therefore extend beyond the saved slice boundaries. Empty slices have NaN extrema; zero-width live slices have equal extrema. Beam-beam PIC uses these member bounds for head/tail sampling. Equal-particle rank membership, rather than quantile geometry, determines these extrema.

delta_z

z_max - z_min for each slice.

macro_count

Number of live macro-particles.

real_charge

Equivalent number of real particles, macro_count * bunch.ratio. It is not Coulombs; multiply by the signed particle charge and elementary charge when physical charge is required.

lind_density

Linear real-particle density, real_charge / delta_z. An occupied slice with zero width has undefined density, recorded as NaN; an empty slice has zero density.

effective_num_slices

Number of bins that can be populated by the current live population.

Zero-width slices remain usable for diagnostics and wake models that treat slices as point sources. Consumers that require finite density, such as SpaceCharge, reject occupied zero-width slices. For those consumers, use an explicit interval with a physically justified finite width and a model such as equal_length that gives the occupied slices finite widths. An explicit range alone does not remove coincident interior edges in rank-based slicing. SpaceCharge retains its existing requirement that every saved slice have positive width, including empty slices.

Results also record valid_turn and valid_s. A subsequent global regrouping clears all particle-dependent fields and consumers must wait for a new Slicer execution.

Snapshots

Save turns is optional and belongs to the command instance, not the shared SliceSet configuration. Each item is either [turn] or [start, end, step] with inclusive endpoints. Slicing still runs on every turn; only selected turns write files. Each selected execution writes a same-instant particle HDF5 file (TFS when selected) (tag, z, slice_id, loss data) and a per-slice TFS summary, also exported to CSV, to output/.../slice/. Particle and TFS summary files carry metadata that identify the turn, position, beam, bunch, slice set, model and coordinate convention.

An overlong end turn is clipped to the final simulated turn with a warning. A range whose start lies outside the simulated turn range is ignored with a warning. Negative starts are similarly clipped while preserving the configured step sequence; malformed ranges (an end before its start), non-integer values and non-positive steps remain errors.

Responsibilities

SortBunch and ReorganizeBunch perform global bucket assignment and may reorder all particle arrays. They invalidate every existing SliceSet because particle ranges can change. Slicer then recomputes the selected set at its position in the sequence. Space-charge and beam-beam modules can refer to different named sets and therefore use different slice meshes.

Important

After every executed SortBunch or ReorganizeBunch, run Slicer again before using slice information. Sorting/regrouping clears the previous slice_id and slice_table. Recompute each named SliceSet required by subsequent commands, even if Slicer already ran earlier in the same turn.

Examples of actual execution order (each Slicer updates the set used by the following consumer):

Correct:   SortBunch       -> Slicer -> SpaceCharge
Correct:   ReorganizeBunch -> Slicer -> WakeField
Incorrect: Slicer -> SortBunch -> SpaceCharge

The last sequence requires another Slicer between SortBunch and SpaceCharge. Consumers do not automatically rebuild invalidated slices. This rule applies on both CPU and CUDA. Slicer itself does not require a preceding SortBunch when the existing particle order and bunch grouping are unchanged.

The mapping uses current array positions: global particle index i belongs to slice_id[i - bunch.start_idx]. tag moves with its particle during sorting, but is not an index into slice_id. Keeping the same tags therefore does not make an old slice mapping reusable after sorting. See Bunch Regrouping (ReorganizeBunch) for the grouping operation.

The stored particle coordinate is the continuous bunch-relative coordinate \(z_{rel}\). z_rel slicing uses it directly; z_periodic and arrival_phase use temporary projections. None replaces the stored coordinate.

Slice coordinate and reuse

Coordinate=z_rel is the default: bin the continuous time-scaled coordinate \(z=\beta_b c(T_b-t_i)\) directly for continuous wake timing. SpaceCharge requires the separate z_periodic option described below. The separate arrival_phase option forms a temporary periodic arrival projection for coasting wakes. Periodic=true is an alias for that option. ring_position is not supported: z plus a nominal slot offset cannot supply an exact physical ring position under this coordinate definition.

The latest explicit Slicer result is authoritative. Its saved z intervals, widths and memberships are reused until the user executes Slicer again. RF never rescales, recenters or recomputes these arrays. A local interval of width \(\Delta z\) in z_rel corresponds, at the current reference event, to \(\Delta t=\Delta z/(\beta_b c)\) and center \(T_b-z_{slice}/(\beta_b c)\). Thus saved intervals remain intervals in the current z coordinate, not frozen physical time intervals. Reuse accuracy is the user’s responsibility. Structural regrouping invalidates old local indices and requires an explicit new Slicer execution.

Wake sources store their sampled physical times and widths when emitted. Subsequent reference changes cannot move historical sources. Periodic arrival-phase slices have a separately recorded common observation window; see WakeField for that approximation. Quasi-static SpaceCharge uses circumference-folded z intervals; time-scaled z is not an exact simultaneous three-dimensional spatial distribution for arbitrary velocity spread.

Z range mode remains auto or explicit. Particle storage stays in the configured float32 or float64 precision; local bin arithmetic uses float64. Saved slice boundaries, centers, widths and density tables use float64 on both CPU and CUDA. CUDA promotes a local working coordinate when particle storage is float32, so rounding the slice geometry cannot turn a uniform wake grid into a nonuniform one. The tracked particle coordinates remain unchanged. Snapshots preserve continuous z and record the reference time, beta and coordinate definition. Periodic snapshots also include slice_coordinate. The density is real-particle count per metre, not coulombs per metre.

Outside a collision frame, output metadata ZCoordinate="z_rel" describes the original particle z column; it is output metadata, not an input option or a default assignment. Coordinate identifies the selected slicing projection, while CoordinateDefinition="z=beta*c*(T-t)", ReferenceArrivalTime (seconds) and ReferenceBeta define the original particle coordinate. Arrival-phase snapshots additionally save ObservationTime (seconds), ObservationVelocity (metres per second), and SliceCoordinateDefinition. Together with Circumference, these specify the saved observation window; its time parameters can differ from the bunch reference parameters.

SliceSet runtime interface

The command configuration is converted to one SliceSet per bunch. The following fields are available to SpaceCharge, BeamBeam and diagnostic code; they are outputs of Slicer rather than additional JSON input parameters.

Field

Type

Valid before slicing

Description

name

str

Yes

User-defined lookup key from Slice set.

model

str

Yes

Normalized slice model name.

num_slices

int

Yes

Configured mesh size.

z_range_mode

str

Yes

Normalized range mode.

explicit

ExplicitRange or None

Yes

Canonical explicit bounds when explicit mode is selected.

slice_id

int array

No

One ID per particle in the bunch’s current particle range; lost particles have -1.

slice_table

dict of arrays

No

Per-slice geometry and population arrays listed in the SliceSet data section above.

valid_turn

int or None

No

Simulation turn at which the result was generated.

valid_s

float or None

No

Sequence position at which the result was generated.

Circumference-folded slicing for SpaceCharge

Coordinate=z_periodic forms the temporary coordinate

\[z_{slice,i}=[(z_i+C/2)\bmod C]-C/2.\]

It uses the finite positive ring circumference, independently of the prescribed clock. Both CPU and GPU support equal_length and equal_particle, with auto or explicit ranges. auto uses the live folded-coordinate minimum and maximum. explicit must lie within \([-C/2,C/2]\); use that full interval for a whole-ring mesh, retaining empty bins. A narrower interval clips out-of-range folded coordinates to boundary slices. A bunch straddling the seam can give an auto range spanning nearly the whole ring.

SpaceCharge accepts only this coordinate. SC configuration requires "Coordinate": "z_periodic" in the corresponding Slicer. Missing coordinate metadata, z_rel and arrival_phase are rejected by SC. This is the per-bunch common-reference-velocity approximation; folding does not reconstruct an exact simultaneous distribution for arbitrary velocity spread or combine overlapping populations belonging to different bunches.

WakeField rejects z_periodic because its centers do not retain continuous arrival times. Use separate named slice sets for SC and wakes. The Periodic flag selects arrival_phase; Coordinate identifies the mode, including in saved output.

Periodic arrival slicing for coasting wakes

Coordinate=arrival_phase requires equal_length, explicit and an interval \([z_{min},z_{max}]\) of length C, for example Explicit={"z min": -C, "z max": 0} or a centered [-C/2,C/2] interval. At each explicit Slicer update, let \(a=n+s/C\) and let \(\Psi(t)\) be the integrated prescribed revolution frequency. The physical window endpoints and its linear coordinate mapping are

\[ \begin{align}\begin{aligned}T_L=\Psi^{-1}(a-z_{max}/C),\qquad T_R=\Psi^{-1}(a-z_{min}/C),\\v_{obs}=\frac{C}{T_R-T_L},\qquad T_{obs}=T_L+\frac{z_{max}}{v_{obs}}.\end{aligned}\end{align} \]

These windows meet exactly at their clock-cycle boundaries during acceleration; using the instantaneous frequency for their duration would create overlaps or gaps. For the centered interval, \(T_{obs}=(T_L+T_R)/2\). CPU and GPU form

\[u_i=\frac{v_{obs}}{C}(T_{obs}-t_i),\qquad z_{phase,i}=z_{max}-C[(z_{max}/C-u_i)\bmod1].\]

The bins represent the window \([T_L,T_R)\), and retain that observation event until the next user update. Different bunch references are allowed; all populations contributing to one periodic wake must use the same saved observation window and circumference. Source bin 0 is the earliest arrival. Lost particles have ID -1; stored z is never folded. An exact seam phase maps to \(z_{phase}=z_{max}\), the start of the window and slice 0. The right-endpoint phase is periodically identified with the window start, rather than the last slice; no extra source passage is emitted. Slip diagnostics continue to use the continuous, unreduced phase \(u_i\).

Use a Slicer at the wake location with causal history. Reusing a periodic snapshot does not advance its observation window; the user must update it for each new physical source passage. This differs from reusing local z intervals. SpaceCharge requires its own z_periodic SliceSet. The one-passage-per-reference- turn approximation and convergence requirements are explained in WakeField.

Max phase slip defaults to 0.05 revolutions, with allowed values (0, 0.1]. Slicer records the continuous phase change at consecutive observations without rejecting diagnostic output; WakeField checks the bound. Same-turn updates use the same previous-turn baseline. Invalidation resets this diagnostic. It cannot reconstruct unsampled crossings or prove convergence of short-wavelength modes.