Dipole (SBend)

This module describes the PASS dipole element SBend, used to simulate the motion of charged particles in a sector bending magnet. The dipole is the most fundamental bending element in accelerators, deflecting the particle orbit through a uniform magnetic field.

The PASS dipole is a thick element (length > 0), supporting full nonlinear tracking including edge angle effects, fringe field effects, and multiple symplectic integration schemes.

Fint specifies the entrance fringe integral. A positive Fintx specifies the exit integral; Fintx <= 0 inherits Fint. In particular, setting Fintx = 0 does not disable the exit finite-gap terms when Fint > 0.

  • Registration name: sbend

  • Key features:

    • Supports rot-kick-rot (RKR) and drift-kick-drift-exact (DKD-exact) body models, default rot-kick-rot

    • Supports uniform (2nd-order) and yoshida4 (4th-order) symplectic integrators

    • Supports nonlinear edge angle (wedge) effects

    • Supports nonlinear fringe field effects

    • Supports aperture check

The fields below configure PASS.para.schema.elements.SBendItem. The key in Sequence.add(name, item) supplies the element name; it is not a configuration-model field.

Parameter List

General Parameters

Python configuration field

JSON key

Type

Unit

Default

Description

s

S (m)

float

m

Required

Longitudinal position of the element exit or zero-length action point.

length

Length (m)

float

m

0.0

Element length (\(L\))

k0l

K0L

float

0.0

Normalized dipole field integral (\(K_{0L}\))

e1

E1 (rad)

float

rad

0.0

Entrance edge angle (\(e_1\)), default 0

e2

E2 (rad)

float

rad

0.0

Exit edge angle (\(e_2\)), default 0

hgap

Hgap (m)

float

m

0.0

Magnet half gap (\(g_{\text{half}}\)), default 0

fint

Fint

float

0.0

Entrance fringe field integral (\(F\)), default 0

fintx

Fintx

float

0.0

Exit fringe field integral, default 0 (auto-set to fint when \(\leq 0\))

num_slices

Num slices

int

1

1

Number of slices, default 1

model

Model

str

'adaptive'

Physical model, options: adaptive (default, auto-selects rot-kick-rot), rot-kick-rot, drift-kick-drift-exact

integrator

Integrator

str

'adaptive'

Integrator, options: adaptive (default uniform), uniform, yoshida4

aperture_type

Aperture type

str

—

'off'

Aperture type, default off

aperture_value

Aperture value

list

m / rad

[]

Aperture parameter values, default []

Absolute normal/skew field errors and static DX/DY/DPSI alignment use the common Element errors interface. Alignment moves only the magnetic field; apertures and SC boundaries remain in the design frame.

Extended Parameters (Reserved)

Python configuration field

JSON key

Type

Unit

Default

Description

is_ramping

Is ramping

bool

False

Reserved configuration field; tracking does not evaluate a magnetic-field time table.

k0l_ramping_file

K0L ramping file

str

''

Reserved configuration field; tracking does not evaluate a magnetic-field time table.

Usage Examples

Sector Bend

{
    "BEND1": {
        "S (m)": 10.0,
        "Command": "SBend",
        "Length (m)": 1.5,
        "K0L": 0.05,
        "Num slices": 5,
        "Integrator": "yoshida4",
        "Aperture type": "off"
    }
}

Sector bend with end faces perpendicular to the reference trajectory, no edge effects.

Rectangular Bend

{
    "BEND2": {
        "S (m)": 20.0,
        "Command": "SBend",
        "Length (m)": 2.0,
        "K0L": 0.1,
        "E1 (rad)": 0.05,
        "E2 (rad)": 0.05,
        "Hgap (m)": 0.02,
        "Fint": 0.5,
        "Num slices": 10,
        "Integrator": "yoshida4",
        "Aperture type": "off"
    }
}

Rectangular bend with edge angle and fringe field effects. Bending angle \(\alpha = K_{0L} = 0.1\) rad, edge angles \(e_1 = e_2 = \alpha/2 = 0.05\) rad.

Thin Lens Bend

{
    "BEND3": {
        "S (m)": 30.0,
        "Command": "SBend",
        "Length (m)": 0.0,
        "K0L": 0.02,
        "Aperture type": "off"
    }
}

Zero-length dipole, applying only the \(K_{0L}\) thin lens kick, no body tracking, no edge effects.

Small-angle numerical stability

The polar drift contains the horizontal curvature term \(\rho(1-\cos\theta)\). Both CPU and GPU evaluate it with the same half-angle identity \(1-\cos\theta=2\sin^2(\theta/2)\), without branching on the angle. The fused GPU kernel precomputes the half-angle sine alongside the existing full-angle sine and cosine and reuses them across slices, while the internal slicing path uses the same half-angle evaluation. This avoids small-angle cancellation without dividing by \(1+\cos\theta\). Particle storage precision, integration settings, and the physical map are unchanged. Other FP32 rounding errors remain; tracking accuracy still requires a precision and slice-convergence check.

For a static rot-kick-rot map without internal space-charge nodes, FP32 particle arrays use FP64 working coordinates on CPU and FP64 registers and scalar parameters in the fused GPU kernel. The internal rotations and dipole kicks cancel reference-scale momenta; rounding each substep to FP32 can obscure a small betatron displacement. The completed element map is written back to the original particle storage precision. The integration scheme and physical map are unchanged.

For a static bend without internal space-charge nodes, CPU and GPU accumulate the longitudinal increments separately from the entry coordinate, then apply \(z_{\mathrm{out}}=z_{\mathrm{in}}+\sum_j\Delta z_j\) once at the exit. This prevents repeated rounding of small slice increments against a large FP32 \(z_{\mathrm{in}}\). It is an accumulation strategy, not a coordinate fold; the stored coordinate remains continuous. The increment accumulator uses the working precision of the selected map, including FP64 for static RKR. Internal space-charge paths keep the live longitudinal coordinate available at each node. Rounding at element boundaries and other finite-precision errors remain.

The polar drift also keeps the small velocity correction separate from the geometric path difference. For \(g=\gamma_0^{-2}\) and \(r=-g\delta(2+\delta)/(1+\delta)^2\), evaluate \(\beta_0/\beta-1=r/(\sqrt{1+r}+1)\). If \(\ell\) is the particle path length, the longitudinal increment is \(\Delta z=(L-\ell)-\ell r/(\sqrt{1+r}+1)\) on both CPU and GPU. This avoids first rounding the near-unity velocity ratio to one in FP32.

Coordinate Convention

Use the continuous longitudinal coordinate in Longitudinal coordinate and reference time. \(T_b\) is the ideal reference particle passage time at this position, not a measured bunch-centroid time. The local-map symbols \(\beta_0\) and \(P_0\) refer to the current bunch reference. \(p_x=P_x/P_0\) is normalized momentum, not a trajectory slope.

PASS uses normalized curvilinear coordinates. The six-dimensional phase-space variables are \((x, p_x, y, p_y, z, \delta)\):

Variable

Symbol

Definition

x

\(x\)

Horizontal offset (relative to the reference orbit)

px

\(p_x\)

Normalized horizontal momentum, \(p_x = P_x / P_0\)

y

\(y\)

Vertical offset

py

\(p_y\)

Normalized vertical momentum, \(p_y = P_y / P_0\)

z

\(\zeta\)

Longitudinal coordinate, \(z=\zeta=\beta_b c(T_b-t_i)\)

dp

\(\delta\)

Relative momentum deviation, \(\delta = P / P_0 - 1\)

where \(P_0\) is the reference particle momentum, \(\beta_0 = v_0 / c\) is the reference particle normalized velocity, \(s\) is the arc length along the reference orbit, and \(t\) is time.

The longitudinal momentum component is defined as:

\[p_z = \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\]

Other commonly used physical quantities:

\[h = \frac{1}{\rho} = \frac{K_0 L}{L} = \frac{K_{0L}}{L}\]
\[K_0 = \frac{q_0 B_0}{P_0} = \frac{K_{0L}}{L}\]
\[\chi = \frac{q}{q_0} \cdot \frac{m_0}{m}\]

where \(h\) is the reference orbit curvature, \(\rho\) is the bending radius, \(K_0\) is the normalized dipole field strength, and \(\chi\) is the charge-to-mass ratio factor (for a beam of identical particle species, \(\chi = 1\)). For a sector bend, \(h = K_0\).

Overall Tracking Flow

A complete dipole consists of the entrance edge, body, and exit edge. The tracking order is:

====== Entrance edge (B=0 → B=B0) ======

YRotation(-e1)  →  Fringe Field  →  Wedge(-e1, K0)
[Pure geometric rotation]  [Nonlinear fringe field]  [Rotation + focusing kick]
[B=0]                      [B: 0→B0]                 [B=B0]

       ↓

====== Body (B=B0) ======

Slice 1 → Slice 2 → ... → Slice N
(Reference trajectory coordinate system, symplectic integrator)

       ↓

====== Exit edge (B=B0 → B=0) ======

Wedge(-e2, K0)   →  Fringe Field  →  YRotation(-e2)
[Rotation + focusing kick]  [Nonlinear fringe field]  [Pure geometric rotation]
[B=B0]                      [B: B0→0]                 [B=0]

Entrance net rotation: (-e1) + (+e1) = 0
Exit net rotation: (+e2) + (-e2) = 0
→ Body operates in the reference trajectory coordinate system

The complete map is:

\[\mathcal{M}_{\text{bend}} = \mathcal{M}_{\text{exit}} \circ \mathcal{M}_{\text{body}} \circ \mathcal{M}_{\text{entry}}\]

With \(N\) internal body slices, this is:

\[\mathcal{M}_{\text{bend}} = \mathcal{M}_{\text{exit}} \circ \mathcal{B}_N \circ \cdots \circ \mathcal{B}_1 \circ \mathcal{M}_{\text{entry}}\]

There is one real entrance, N body slices, and one real exit. CPU and GPU tracking apply the edge maps outside the body loop. Internal space-charge kicks subdivide only body transport and do not create additional edge maps. Increasing Num slices therefore requires no extra exit-integral parameter. Representing a magnet as several independent SBend elements is a different operation: each element then executes its own entrance and exit maps.

Entrance edge:

\[\mathcal{M}_{\text{entry}} = \text{Wedge}(-e_1, K_0) \circ \text{Fringe}(e_1) \circ \text{YRotation}(-e_1)\]

Exit edge (mirror-symmetric to the entrance):

\[\mathcal{M}_{\text{exit}} = \text{YRotation}(-e_2) \circ \text{Fringe}(e_2) \circ \text{Wedge}(-e_2, K_0)\]

Note

  • When \(e_1 = 0\), both YRotation and Wedge are skipped (no edge angle effect)

  • When fint = 0 or hgap = 0, the finite-gap terms vanish; the geometric nonlinear fringe map remains when \(K_0 \ne 0\).

  • When \(K_0 = 0\), both Fringe and Wedge are skipped

  • The execution order of entrance and exit are mirror images of each other

  • At the exit, the fringe map uses \(-K_0\) because the field transition reverses from rising to falling. The wedge retains \(K_0\) because it rotates through the same uniform field.

Why This Order

Role of YRotation: Pure geometric coordinate rotation, transforming particle coordinates from the reference trajectory coordinate system to the magnet end-face coordinate system. It applies no force and only changes the observational reference frame.

Role of Fringe Field: Computes nonlinear fringe field effects in the end-face reference frame. The particle slope \(x' = p_x / p_z\) in the Fringe formula must be the slope relative to the magnet end face, so YRotation must be performed first.

Role of Wedge: Rotates the observation plane in the uniform magnetic field \(B_0\), while applying the edge angle focusing kick. Wedge includes both geometric rotation (rotating the coordinate system back to the reference trajectory system) and magnetic field kick.

The geometric rotations of YRotation and Wedge are in opposite directions, with zero net rotation:

\[\text{Rotation of YRotation}(-e_1) + \text{Geometric rotation of Wedge}(-e_1) = (-e_1) + (+e_1) = 0\]

Therefore the body operates in the reference trajectory coordinate system, requiring no additional rotation.

Body: DKD-exact Model

Hamiltonian

In curvilinear coordinates, the complete dipole Hamiltonian is:

\[H_{\text{bend}} = \frac{p_\tau}{\beta_0} - (1+hx)\sqrt{(1+\delta)^2 - p_x^2 - p_y^2} + \chi K_0\!\left(x + \frac{h x^2}{2}\right)\]

Splitting it into the propagation part (exact straight drift \(H_D\)) and the kick parts (\(H_h\), \(H_{K_0}\), \(H_{K_0 h}\)):

\[H_D = \frac{p_\tau}{\beta_0} - \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\]
\[H_h = -h x (1+\delta)\]
\[H_{K_0} = \chi K_0 x\]
\[H_{K_0 h} = \frac{\chi K_0 h x^2}{2}\]

where \(H_D\) is the exact straight drift Hamiltonian (preserving the \(p_z\) square root without small-momentum expansion), and the remaining three terms are thin lens kicks.

Exact Drift Map D

The Hamilton’s equations of the propagation part give the exact straight drift:

\[p_z = \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\]
\[x \leftarrow x + \frac{p_x}{p_z} \cdot L_D\]
\[y \leftarrow y + \frac{p_y}{p_z} \cdot L_D\]
\[\zeta \leftarrow \zeta + L_D \cdot \left(1 - \frac{\beta_0}{\beta} \cdot \frac{1+\delta}{p_z}\right)\]

where \(L_D\) is the drift length, and \(\beta\) is the particle’s actual normalized velocity:

\[\beta = \frac{(1+\delta) \beta_0 \gamma_0}{\sqrt{1 + \left[(1+\delta) \beta_0 \gamma_0\right]^2}}\]

Note

The meaning of “exact”: the drift part preserves the exact square root \(p_z = \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\) without small-momentum expansion \(p_x \ll 1\). The approximation lies only in separating the propagation part from the kick part (split-operator method).

Dipole Kick Map K

The kick parts are combined into a single thin lens kick (position unchanged, momentum jump only):

\[p_x \leftarrow p_x + L_K \cdot \left[h(1+\delta) - \chi K_0 - \chi K_0 h x\right]\]
\[\zeta \leftarrow \zeta - \frac{\beta_0}{\beta} \cdot h x L_K\]

Physical meaning of each term:

Term

Source

Physical Meaning

\(h(1+\delta) L_K\)

\(H_h\)

Curvature kick (reference orbit bending)

\(-\chi K_0 L_K\)

\(H_{K_0}\)

Main dipole bending

\(-\chi K_0 h x L_K\)

\(H_{K_0 h}\)

Weak focusing (curvature-dipole field coupling)

\(-(\beta_0/\beta) \cdot h x L_K\)

\(H_h\)

Path-length effect (longitudinal)

Note

For a sector bend \(h = K_0\), the net kick of the reference particle (\(x=0, \delta=0, \chi=1\)) is \(h L_K - K_0 L_K = 0\). This is correct: in curvilinear coordinates, the reference particle moves along the reference orbit, and \(p_x\) is always 0. The bending effect is already encoded in the curvilinear coordinate system itself.

Uniform Integrator (2nd-order symplectic)

Each slice uses the drift-kick-drift (DKD) structure, i.e., 2nd-order leapfrog:

\[S_2(\Delta s) = D\!\left(\frac{\Delta s}{2}\right) \circ K(\Delta s) \circ D\!\left(\frac{\Delta s}{2}\right)\]

The per-slice error is \(O(\Delta s^3)\), and the global error is \(O(\Delta s^2)\). A 2nd-order symplectic integrator where every step is a canonical transformation.

yoshida4 Integrator (4th-order symplectic)

A 4th-order symplectic map is constructed by composing three 2nd-order DKD steps [Yoshida 1990]:

\[S_4(\Delta s) = S_2(z_1 \Delta s) \circ S_2(z_0 \Delta s) \circ S_2(z_1 \Delta s)\]

where the Yoshida coefficients are:

\[z_1 = \frac{1}{2 - 2^{1/3}} \approx 1.3512\]
\[z_0 = 1 - 2 z_1 \approx -1.7024\]

Note

\(z_0 < 0\) means the middle step is a backward tracking (the drift and kick “lengths” are negative). This is a mathematical requirement of the Yoshida composition method and is fully self-consistent in the symplectic map group. The per-slice error is \(O(\Delta s^5)\), and the global error is \(O(\Delta s^4)\).

Integrator Selection Recommendations:

Scenario

Recommended Integrator

Reason

Fast simulation

uniform

2 drifts + 1 kick per slice, low computational cost

High-precision simulation

yoshida4

4th-order accuracy, but 6 drifts + 3 kicks per slice

With space charge

uniform + more slices

Space charge uses its independently configured Num kicks; external Yoshida substeps do not multiply PIC calls

Body model selection

model accepts rot-kick-rot, drift-kick-drift-exact or adaptive; adaptive currently selects rot-kick-rot.

  • RKR combines polar transport, including reference curvature, with dipole momentum updates.

  • DKD-exact splits straight exact drifts from curvature and magnetic momentum updates.

The submaps and splitting differ. Increase the slice count and check convergence of trajectories, tunes and longitudinal transport for the bend angle, amplitudes and momentum range of interest. An analytic submap does not guarantee that one slice is sufficient for every configuration. integrator="adaptive" currently selects uniform; it is not automatic error control. Fourth-order integration in smooth fields does not remove roundoff or discrete aperture-sampling errors. Internal space charge uses the independently configured Space charge.Num kicks.

Entrance Edge: YRotation

Physical Purpose

YRotation is a pure geometric coordinate rotation that does not involve any magnetic field. Its purpose is to transform particle coordinates from the reference trajectory coordinate system to the magnet end-face coordinate system, so that subsequent fringe field calculations can be performed in the correct reference frame.

When the magnet end face has an angle \(e_1\) with respect to the reference trajectory normal, the particle’s incident slope relative to the end face is not equal to \(p_x / p_z\). YRotation rotates the coordinate system by \(-e_1\), so that the rotated \(p_x / p_z\) becomes the slope relative to the end face.

Complete Derivation

YRotation(-e1)                    Wedge(-e1, K0)
─────────────────                 ──────────────────
Coordinate system: trajectory → end-face    Coordinate system: end-face → trajectory
Magnetic field: B = 0 (field-free region)   Magnetic field: B = B0 (field region)
Rotation: -e1                                Rotation: +e1 (opposite to YRotation)
Kick: none                                   Kick: Δpx = K0·x·sin(e1) (focusing)
─────────────────                 ──────────────────

Net rotation: (-e1) + (+e1) = 0
Net effect: fringe field effect + focusing kick

Step 1: Momentum rotation

The reference frame is rotated about the \(y\) axis by angle \(\theta\). This rotation occurs in the \((x, z)\) plane of 3D space, with the \(y\) direction unaffected. Therefore, the \(x\) component of momentum \(p_x\) and the \(z\) component \(p_z\) are mixed, while \(p_y\) is unchanged. The standard rotation transformation of momentum is:

\[\begin{split}\begin{pmatrix} p_x' \\ p_z' \end{pmatrix} = \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} p_x \\ p_z \end{pmatrix}\end{split}\]

Therefore:

\[p_x' = \cos\theta \cdot p_x - \sin\theta \cdot p_z\]
\[p_z' = \sin\theta \cdot p_x + \cos\theta \cdot p_z\]

This is a pure momentum rotation with no force involved.

Step 2: Position projection

The key is the definition of \(x\) in curvilinear coordinates: x is the transverse offset measured on the transverse plane at the reference position \(s. When the reference frame is rotated by :math:\)theta`, the direction of the “transverse plane” changes, and the same physical position has a different \(x'\) value in the new coordinate system.

The particle’s trajectory in the old frame is \(\vec{r}(\lambda) = (x + \lambda p_x/p_z,\; 0,\; \lambda)\). The \(z'\) axis direction of the new frame is \(\hat{z}' = (\sin\theta, 0, \cos\theta)\), and the transverse direction is \(\hat{x}' = (\cos\theta, 0, -\sin\theta)\).

In the new frame, zero longitudinal position means:

\[\vec{r} \cdot \hat{z}' = (x + \lambda p_x/p_z)\sin\theta + \lambda\cos\theta = 0\]

Solving for \(\lambda\):

\[\lambda = -\frac{x \sin\theta \cdot p_z}{p_x \sin\theta + p_z \cos\theta} = -\frac{x \sin\theta \cdot p_z}{p_z'}\]

The new transverse position is:

\[x' = \vec{r} \cdot \hat{x}' = (x + \lambda p_x/p_z)\cos\theta - \lambda\sin\theta\]

Substituting \(\lambda\) and simplifying, using the orthogonality of rotation \(p_z'\cos\theta - p_x'\sin\theta = p_z\), we finally obtain:

\[x' = \frac{x \cdot p_z}{p_z'} = \frac{x \cdot p_z}{p_x \sin\theta + p_z \cos\theta}\]

Equivalent implementation form:

The implementation uses x_hat = x / (cos_angle * ptt), where ptt = 1 + tan_angle * px / pz:

\[\cos\theta \cdot p_{tt} = \cos\theta + \sin\theta \cdot \frac{p_x}{p_z} = \frac{p_z'}{p_z}\]

Therefore \(x' = x / (\cos\theta \cdot p_{tt}) = x \cdot p_z / p_z'\), consistent with the derivation.

Step 3: y direction

The \(y\) direction does not directly participate in the rotation, but due to the tilting of the transverse plane, the particle acquires an additional offset in the \(y\) direction due to trajectory slope while traveling to the new transverse plane:

\[y' = y - \sin\theta \cdot \frac{x \cdot p_y}{p_z'} = y - \tan\theta \cdot \frac{x \cdot p_y}{p_z \cdot p_{tt}}\]

Step 4: \(\zeta\) direction

The longitudinal coordinate \(z=\zeta=\beta_b c(T_b-t_i)\). After rotating the reference frame, \(\sin\theta \cdot x\) is the projection of the transverse position onto the new longitudinal direction (additional path length due to reference frame rotation), which needs to be converted to a time increment:

\[\Delta\zeta = \beta_0 \cdot \tan\theta \cdot \frac{x \cdot \text{time\_fac}}{p_z \cdot p_{tt}}\]

where \(\text{time\_fac} = 1/\beta_0 + p_\tau\) is the time-path conversion factor (see variable conversion section).

Final Formulas

Definitions:

\[p_z = \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\]
\[p_{tt} = 1 + \tan(\theta) \cdot \frac{p_x}{p_z}\]

where \(\theta\) is the rotation angle (entrance \(\theta = -e_1\), exit \(\theta = -e_2\)).

Time factor:

\[\text{time\_fac} = \frac{1}{\beta_0} + p_\tau = \sqrt{(1+\delta)^2 + \frac{1}{\beta_0^2 \gamma_0^2}}\]

Six-dimensional map:

\[x \leftarrow \frac{x}{\cos\theta \cdot p_{tt}}\]
\[p_x \leftarrow \cos\theta \cdot p_x - \sin\theta \cdot p_z\]
\[y \leftarrow y - \tan\theta \cdot \frac{x \cdot p_y}{p_z \cdot p_{tt}}\]
\[\zeta \leftarrow \zeta + \beta_0 \cdot \tan\theta \cdot \frac{x \cdot \text{time\_fac}}{p_z \cdot p_{tt}}\]
\[p_y, \delta \text{ unchanged}\]

Variable Conversion Notes

The normalized energy deviation \(p_\tau\) and the stored momentum deviation \(\delta\) satisfy:

\[(1+\delta)^2 = \left(\frac{1}{\beta_0} + p_\tau\right)^2 - \frac{1}{\beta_0^2 \gamma_0^2}\]

Therefore:

\[\frac{1}{\beta_0} + p_\tau = \sqrt{(1+\delta)^2 + \frac{1}{\beta_0^2 \gamma_0^2}}\]

Derivation: The total particle energy \(E = E_0(1 + p_\tau)\). From \(E^2 - E_0^2 = (Pc)^2 - (P_0 c)^2\):

\[(1+\delta)^2 = (P/P_0)^2 = \frac{(1+p_\tau)^2 - 1/\gamma_0^2}{\beta_0^2}\]

Expanding and using \(1 - 1/\gamma_0^2 = \beta_0^2\):

\[(1+\delta)^2 = 1 + \frac{2 p_\tau}{\beta_0^2} + \frac{p_\tau^2}{\beta_0^2}\]

Writing \(p_z\) in terms of the energy deviation gives sqrt(1 + 2*pt/beta0 + pt*pt - px*px - py*py), which after substituting the above relation equals exactly \(\sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\).

Entrance Edge: Fringe Field

Physical Purpose

The magnetic field of a real magnet is not a step function at the end face, but has a gradual transition region. This gradual region produces additional nonlinear effects, mainly vertical focusing.

Physical Derivation

B_y                                          B_y = B0
↑                              ┌──────────────
│                             /
│         Fringe             /  end face
│         Field             /
│       (B: 0→B0)          /
│                        /
│  B = 0               /
└────────────┬────────┘──────────────────────── → s
             ↑        ↑
             YRotation Fringe    Wedge / Body
             (B=0)    (0→B0)     (B=B0)

hgap = half gap
Δp_y = vertical focusing kick

Fringe field distribution

The magnetic field at the end face of a real magnet transitions as:

\[B_y(s) = B_0 \cdot b(s), \quad b(s): 0 \to 1\]

where \(b(s)\) is the normalized fringe field distribution function. This gradual field produces nonlinear effects on particles, mainly vertical focusing.

Fringe field integral

Forest defines the fringe field integral:

\[F = \int \frac{b(s)\bigl(K_0 - b(s)K_0\bigr)}{g_{\text{full}} \cdot K_0^2} \, ds\]

where \(g_{\text{full}}\) is the magnet full gap (\(g_{\text{full}} = 2 \times \text{hgap}\)). \(F\) describes the “strength” of the fringe field: \(F=0\) corresponds to a hard edge, and larger \(F\) means stronger fringe field effects.

Warning

Naming relationship between hgap and g

The hgap parameter is the magnet half gap, i.e., half the distance between the upper and lower pole faces.

  • hgap = half gap = \(g_{\text{half}}\)

  • Magnet full gap \(g_{\text{full}} = 2 \times \text{hgap}\)

In the fringe field code, the auxiliary quantity \(f_h\) directly uses hgap (half gap):

\[f_h = \text{hgap} \times \text{fint}\]

Thus \(f_h\) is the half gap multiplied by the fringe field integral.

A formula written in terms of the full gap requires the corresponding coefficient conversion. PASS uses the half-gap convention in the generating function below.

Fringe angle and characteristic coefficient

The fringe map uses the angle \(\Phi_0\) below and the characteristic coefficient \(\psi=b_0\tan\Phi_0\), where \(b_0=K_0\chi\):

\[\Phi_0 = \arctan\!\left(\frac{x'}{1+y'^2}\right) - c_2 \left(1 + x'^2(2+y'^2)\right) p_z\]

where \(x' = p_x/p_z\), \(y' = p_y/p_z\) are the particle slopes, and \(c_2 = 2 K_0 \chi \cdot f_h\) is the linear fringe field strength parameter.

In the implementation, yp2 = 1 + y'^2, so 1 + yp2 = 2 + y'^2. Thus the finite-gap factor is \(1+x'^2(2+y'^2)\). The arctangent denominator remains \(1+y'^2\); it is a different occurrence of yp2.

Note

The finite-gap term uses \(p_z\), not its reciprocal; the derivatives follow the same generating function. Setting fint*hgap to zero removes this term and therefore does not test its finite-gap effect.

Formula references: fringe implementation and physics manual. These references use different finite-gap conventions; the equation above defines the convention used by PASS.

  • First term \(\arctan(x'/(1+y'^2))\): Incident angle correction of the particle at the end face. \(x'\) is the horizontal slope, and \(1+y'^2\) reflects the geometric correction of vertical motion on the horizontal incident angle (3D direction cosines).

  • Second term \(-c_2(1 + x'^2(2+y'^2))p_z\): Fringe field integral effect. \(c_2\) is the fringe field strength, and \((1 + x'^2(2+y'^2))\) is the higher-order slope correction.

Partial derivatives and forces

Differentiate \(\psi=b_0\tan\Phi_0\) with respect to the independent variables \((x', y', p_z)\), then apply the chain rule to obtain the force components. Differentiating the tangent supplies the factor \(b_0/\cos^2\Phi_0\); the quantities below are derivatives of \(\psi\).

Introducing intermediate variables \(c_{o2} = b_0 / \cos^2\Phi_0\), \(c_{o1}\), \(c_{o3}\) (see formula section for details), the partial derivatives are:

\[\phi_1 = \frac{\partial \psi}{\partial x'}, \quad \phi_2 = \frac{\partial \psi}{\partial y'}, \quad \phi_3 = \frac{\partial \psi}{\partial p_z}\]

Force components (chain rule \(k_i = \phi_1 \partial x'/\partial p_i + \phi_2 \partial y'/\partial p_i + \phi_3 \partial p_z/\partial p_i\)):

\[k_x = \phi_1 \frac{1+x'^2}{p_z} + \phi_2 \frac{x'y'}{p_z} - \phi_3 x'\]
\[k_y = \phi_1 \frac{x'y'}{p_z} + \phi_2 \frac{1+y'^2}{p_z} - \phi_3 y'\]
\[k_z = \phi_1 \frac{\text{tfac} \cdot x'}{p_z^2} + \phi_2 \frac{\text{tfac} \cdot y'}{p_z^2} - \phi_3 \frac{\text{tfac}}{p_z}\]

where \(\text{tfac} = -(1/\beta_0 + p_\tau)\) comes from the dependence of \(t\) on \(p_z\) in \(z=\zeta=\beta_b c(T_b-t_i)\).

Implicit equation

The fringe field map is not a simple kick (position unchanged, momentum jump), but an implicit map. The reason is that the fringe field effect is nonlinearly coupled with the particle’s \(y\) coordinate: as the particle passes through the fringe field, the \(y\) coordinate itself is changing, so the force (depending on \(y\)) and the displacement (depending on the force) are mutually coupled.

The implicit solution comes from the generating function expanded to second order:

\[y_f = \frac{2y}{1 + \sqrt{1 - 2 k_y y}}\]

This form guarantees canonicity (symplecticity): when \(k_y y\) is small, \(y_f \approx y + k_y y^2/2\), i.e., the second-order expansion.

Parameters

Parameter

Symbol

Description

fint

\(F\)

Fringe field integral, \(F=0\) for hard edge

hgap

\(g_{\text{half}}\)

Magnet half gap, full gap \(g_{\text{full}} = 2 \cdot \text{hgap}\)

k0

\(K_0\)

Normalized dipole field strength

Complete Formulas

Define auxiliary quantities:

\[f_h = \text{hgap} \cdot F\]
\[f_{\text{sad}} = \frac{1}{72 \cdot f_h} \quad (f_h > 0 \text{, otherwise } 0)\]
\[b_0 = K_0 \cdot \chi\]
\[\text{relp} = \frac{1}{\sqrt{(1+\delta)^2}}\]
\[\text{tfac} = -\left(\frac{1}{\beta_0} + p_\tau\right) = -\sqrt{(1+\delta)^2 + \frac{1}{\beta_0^2 \gamma_0^2}}\]
\[c_2 = b_0 \cdot f_h \cdot 2\]
\[c_3 = b_0^2 \cdot f_{\text{sad}} \cdot \text{relp}\]

where \(c_2\) is the linear fringe field strength, and \(c_3\) is the 6th-order nonlinear correction (from \(f_{\text{sad}} = 1/(72 f_h)\), called the “sixth-order achromatic detuning” term).

Particle slopes:

\[x' = \frac{p_x}{p_z}, \quad y' = \frac{p_y}{p_z}\]

Characteristic functions and partial derivatives:

Here \(\phi_0=\Phi_0\), and \(\phi_1,\phi_2,\phi_3\) are the partial derivatives of \(\psi=b_0\tan\phi_0\) with respect to \(x',y',p_z\).

\[\phi_0 = \arctan\!\left(\frac{x'}{1 + y'^2}\right) - c_2 \left(1 + x'^2(2+y'^2)\right) p_z\]
\[c_{o2} = \frac{b_0}{\cos^2\phi_0}\]
\[c_{o1} = \frac{c_{o2}}{1 + \left(\frac{x'}{1+y'^2}\right)^2} \cdot \frac{1}{1+y'^2}\]
\[c_{o3} = c_{o2} \cdot c_2\]
\[\phi_1 = c_{o1} - c_{o3} \cdot 2 x'(2+y'^2) p_z\]
\[\phi_2 = -2 c_{o1} \cdot x' y' \cdot \frac{1}{1+y'^2} - c_{o3} \cdot 2 x'^2 y' \cdot p_z\]
\[\phi_3 = -c_{o3} \left(1 + x'^2(2+y'^2)\right)\]

Force components:

\[k_x = \phi_1 \frac{1+x'^2}{p_z} + \phi_2 \frac{x' y'}{p_z} - \phi_3 x'\]
\[k_y = \phi_1 \frac{x' y'}{p_z} + \phi_2 \frac{1+y'^2}{p_z} - \phi_3 y'\]
\[k_z = \phi_1 \frac{\text{tfac} \cdot x'}{p_z^2} + \phi_2 \frac{\text{tfac} \cdot y'}{p_z^2} - \phi_3 \frac{\text{tfac}}{p_z}\]

Six-dimensional map:

\[y_f = \frac{2y}{1 + \sqrt{1 - 2 k_y y}}\]
\[x \leftarrow x + \frac{1}{2} k_x y_f^2\]
\[p_y \leftarrow p_y - 4 c_3 y_f^3 - b_0 \tan(\phi_0) \cdot y_f\]
\[\zeta \leftarrow \zeta + \beta_0 \left(\frac{1}{2} k_z y_f^2 + c_3 y_f^4 \cdot \text{relp}^2 \cdot \text{tfac}\right)\]
\[p_x, \delta \text{ unchanged}\]

Note

  • \(p_x\) and \(\delta\) are unchanged: the fringe field is a static magnetic field and does no work

  • The \(-b_0 \tan(\phi_0) y_f\) term in the \(p_y\) change is the main vertical focusing

  • \(-4 c_3 y_f^3\) is the 6th-order nonlinear correction

  • \(y_f\) is solved through the implicit equation, ensuring precise treatment and symplecticity of nonlinear effects

  • The \(x\) change is an \(O(y^2)\) order horizontal-vertical coupling

Entrance Edge: Wedge (Edge Angle)

Physical Purpose

Wedge describes the coordinate transformation of a particle passing through a tilted end face in a uniform magnetic field \(B_0\). It accomplishes two things simultaneously:

  1. Geometric rotation: Rotates the coordinate system from the end-face reference frame back to the reference trajectory reference frame (opposite rotation direction to YRotation, canceling each other)

  2. Magnetic field kick: Applies the edge angle focusing effect \(\Delta p_x \propto -x\)

When \(K_0 = 0\) (no magnetic field), Wedge degenerates to pure YRotation (proof below).

Computation Formulas

Parameters: \(\theta\) (wedge angle, entrance \(\theta = -e_1\)), \(K_0\), \(\chi\)

Definitions:

\[b_1 = K_0 \cdot \chi\]
\[p_z = \sqrt{(1+\delta)^2 - p_x^2 - p_y^2}\]
\[A = \frac{1}{\sqrt{(1+\delta)^2 - p_y^2}}\]
\[\text{rvv} = \frac{\beta}{\beta_0}\]

where \(\beta\) is the particle’s actual normalized velocity (see the formula in the drift map).

Six-dimensional map:

\[p_x' = p_x \cos\theta + (p_z - b_1 x) \sin\theta\]
\[p_z' = \sqrt{(1+\delta)^2 - p_x'^2 - p_y^2}\]
\[x' = x \cos\theta + \frac{x p_x \sin(2\theta) + \sin^2\theta \cdot (2 x p_z - b_1 x^2)}{p_z' + p_z \cos\theta - p_x \sin\theta}\]
\[D = \arcsin(A \cdot p_x) - \arcsin(A \cdot p_x')\]
\[\Delta y = \frac{p_y (\theta + D)}{b_1}\]
\[\Delta \ell = \frac{(1+\delta) (\theta + D)}{b_1}\]

Final updates:

\[x \leftarrow x'\]
\[p_x \leftarrow p_x'\]
\[y \leftarrow y + \Delta y\]
\[\zeta \leftarrow \zeta - \frac{\Delta \ell}{\text{rvv}}\]
\[p_y, \delta \text{ unchanged}\]

Physical Meaning of the Kick Term

Expanding the \(p_x'\) formula:

\[p_x' = \underbrace{p_x \cos\theta + p_z \sin\theta}_{\text{geometric rotation}} \;\underbrace{-\; b_1 x \sin\theta}_{\text{magnetic field kick}}\]
  • Geometric rotation part: \(p_x \cos\theta + p_z \sin\theta\), opposite in direction to YRotation’s \(\cos\theta \cdot p_x - \sin\theta \cdot p_z\), canceling each other

  • Magnetic field kick part: \(-b_1 x \sin\theta = -K_0 \chi x \sin\theta\), proportional to \(-x\), i.e., edge angle focusing

For the entrance (\(\theta = -e_1\)), the kick is:

\[\Delta p_x = -K_0 \chi x \sin(-e_1) = K_0 \chi x \sin(e_1) > 0 \quad (\text{when } x > 0)\]

This gives particles on the outside of the orbit (\(x > 0\)) an inward momentum, i.e., a focusing effect. The equivalent focal length is \(f = \rho / \sin(e_1)\).

Relationship Between Delta-ell and zeta

Equation Eq. 1.201 gives the path length \(\Delta\ell\), while the code updates the longitudinal coordinate \(\zeta\). The two are different:

\[\Delta\ell = \frac{(1+\delta)(\theta + D)}{b_1} \quad \text{(path length)}\]
\[\Delta\zeta = -\frac{\Delta\ell}{\text{rvv}} \quad (\zeta \text{ coordinate update})\]

Physical reason:

  1. \(\Delta\ell\) is the path length the particle travels in the wedge

  2. \(z=\zeta=\beta_b c(T_b-t_i)\), updating \(\zeta\) requires time: \(\Delta t = \Delta\ell / v = \Delta\ell / (\text{rvv} \cdot \beta_0 c)\)

  3. \(\Delta s\) is already handled in the geometric transformations of \(x'\) and \(\Delta y\), so \(\zeta\) only needs the time correction part:

\[\Delta\zeta = -\beta_0 c \cdot \Delta t = -\beta_0 c \cdot \frac{\Delta\ell}{\text{rvv} \cdot \beta_0 c} = -\frac{\Delta\ell}{\text{rvv}}\]
  • Negative sign: \(z=\zeta=\beta_b c(T_b-t_i)\), time increase causes \(\zeta\) to decrease

  • Division by rvv: \(\text{rvv} = v/v_0 = \beta/\beta_0\), converting path length to time requires dividing by the particle’s actual velocity

\[\zeta \leftarrow \zeta - \frac{\Delta \ell}{\text{rvv}}\]

Warning

Do not add \(\Delta\ell\) directly to \(\zeta\). \(\Delta\ell\) is path length, \(\zeta\) is a time-related coordinate, and the two are related through \(-\Delta\ell/\text{rvv}\).

arcsin Clipping

The computation of \(D\) in Wedge uses \(\arcsin\):

\[D = \arcsin(A \cdot p_x) - \arcsin(A \cdot p_x')\]

where \(A = 1/\sqrt{(1+\delta)^2 - p_y^2}\). Theoretically \(|A \cdot p_x| \leq 1\) (because \(|p_x| \leq \sqrt{(1+\delta)^2 - p_y^2}\)), but floating-point errors may cause \(A \cdot p_x = 1.0000000001\), in which case Python’s np.arcsin returns NaN and triggers a RuntimeWarning.

The code uses np.clip to limit the argument to the \([-1, 1]\) range:

arg_px = np.clip(arg_px, -1.0, 1.0)
arg_new_px = np.clip(arg_new_px, -1.0, 1.0)

Clipping protects the inverse sine against roundoff near its domain boundary.

Proof That Wedge Degenerates to YRotation When K0=0

Wedge’s \(p_x'\) formula:

\[p_x' = p_x \cos\theta + (p_z - b_1 x) \sin\theta\]

Setting \(b_1 = K_0 \chi \to 0\):

\[p_x' = p_x \cos\theta + p_z \sin\theta\]

YRotation’s \(p_x'\) formula is \(p_x' = \cos\alpha \cdot p_x - \sin\alpha \cdot p_z\). Setting \(\alpha = -\theta\):

\[p_x' = \cos\theta \cdot p_x + \sin\theta \cdot p_z\]

The momentum formulas are consistent.

Position \(x'\):

Setting \(b_1 = 0\), Wedge’s \(x'\) simplifies to:

\[x' = x \cos\theta + \frac{2 x \sin\theta \cdot p_x'}{p_z' + p_z \cos\theta - p_x \sin\theta}\]

Using the rotation orthogonality \(p_z' = p_x \sin\theta + p_z \cos\theta\), the denominator becomes \(2 p_z \cos\theta\), and we finally obtain:

\[x' = \frac{x \cdot p_z}{p_z'} = \frac{x \cdot p_z}{p_x \sin\theta + p_z \cos\theta}\]

Consistent with YRotation’s position formula.

y and \(\zeta\):

When \(b_1 \to 0\), \(D \to 0\), \(\theta + D \to \theta\), so \(\Delta y = p_y \theta / b_1 \to \infty\).

This means the formulas for \(y\) and \(\zeta\) diverge as \(b_1 \to 0\). Therefore, the \(b_1 = 0\) limit of Wedge is not continuous—when \(|b_1| < \epsilon\), the code directly branches to YRotation:

if abs(b1) < const.eps:
    # Directly call YRotation, skipping computation containing 1/b1
    self._y_rotation_cpu(x, px, y, py, z, dp, tag, mask, theta, beta0)
    return

Note

Wedge degenerates to YRotation at \(b_1 = 0\) through a code branch structure. The momentum and position formulas are consistent in the \(b_1 \to 0\) limit, but \(y\) and \(\zeta\) contain a \(1/b_1\) factor, making the limit discontinuous, so a branch is necessary.

Edge Angle Sign Convention

e1 > 0 (focusing):

                  End face normal
                    ↗  e1
Trajectory normal  ↑        ↗
          |      ╱  End face
          |    ╱
──────────┼──╱──────────→ s (reference trajectory)
          |  ╱
          |╱

End face normal tilts toward the bending outside relative to trajectory normal


e1 < 0 (defocusing):

          |╲
          |  ╲
──────────┼──╲──────────→ s (reference trajectory)
          |    ╲  End face
          |      ╲
Trajectory normal  ↓        ╲  e1
                   ╲ End face normal

End face normal tilts toward the bending inside relative to trajectory normal

The sign convention for edge angles \(e_1\), \(e_2\) follows the MAD-X convention:

  • \(e_1 > 0\): The entrance end face normal tilts toward the bending outside relative to the reference trajectory normal

  • \(e_2 > 0\): The exit end face normal tilts toward the bending outside relative to the reference trajectory normal

Common magnet types:

Magnet Type

\(e_1\)

\(e_2\)

Description

Sector bend

0

0

End face perpendicular to the reference trajectory

Rectangular bend

\(\alpha/2\)

\(\alpha/2\)

\(\alpha\) is the bending angle

General

Arbitrary

Arbitrary

User-specified

References

  • Xsuite Physics Guide, Sec 1.10.3 (exact bend), Sec 1.10.9 (fringe field), Sec 1.10.10 (wedge), Sec 1.10.12 (quadrupole wedge correction)

  • Forest, E. et al., “Edge Focusing Effects in Sector Bending Magnets”

  • Yoshida, H., “Construction of higher order symplectic integrators”, Phys. Lett. A 150 (1990)

  • MAD-NG fringe field implementation: https://github.com/MethodicalAcceleratorDesign/MAD

Internal Space Charge

A positive-length element may set space_charge (JSON Space charge) to an ElementSpaceCharge object. Num slices controls external transport, while Space charge.Num kicks controls SC integration. See Element Slicing and Internal Space Charge for scheduling, shared resources, supported backends and examples.