transfer_matrices module

Define every element longitudinal transfer matrix.

Units are taken exactly as in TraceWin, i.e. first line is z (m) and second line is dp/p.

Todo

Send beta as argument to avoid recomputing it each time

Todo

electric field interpolated twice: a first time for acceleration, and a second time to iterate itg_field. Maybe this could be done only once.

Todo

Integrate my doc with demonstration of transfer matrix for field map form.

z_dummy(gamma_in, *args, **kwargs)[source]

Return an eye transfer matrix.

Parameters:

gamma_in (float)

Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], None]

_drift_matrix(gamma, half_dz)[source]
Parameters:
Return type:

ndarray[tuple[Any, ...], dtype[double]]

z_drift(gamma_in, delta_s, omega_0_bunch, n_steps=1)[source]

Calculate the transfer matrix of a drift.

Parameters:
Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], None]

z_field_map_rk4(gamma_in, d_z, n_steps, omega0_rf, delta_phi_norm, delta_gamma_norm, complex_e_func, real_e_func)[source]

Calculate the transfer matrix of FieldMap using Runge-Kutta.

We slice the field map in a serie of drift-thin acceleration gap-drift. We pre-compute some constants to speed up the calculation:

Parameters:
  • gamma_in (float) – Lorentz factor at entry of field map.

  • d_z (float) – Size of the integration step in \(\mathrm{m}\).

  • n_steps (int) – Number of integration steps.

  • omega0_rf (float) – RF pulsation in \(\mathrm{rad/s}\).

  • delta_phi_norm (float) –

    Constant to speed up calculation.

    \[\Delta\phi_\mathrm{norm} = \frac{\omega_0 \Delta z}{c}\]

  • delta_gamma_norm (float) –

    Constant to speed up calculation.

    \[\Delta\gamma_\mathrm{norm} = \frac{q_\mathrm{adim} \Delta z} {E_\mathrm{rest}}\]

  • complex_e_func (Callable[[float | tuple[float, float] | tuple[float, float, float], float], complex]) – Takes in the z-position of the particle and the phase, return the complex field component at this phase and position.

  • real_e_func (Callable[[float | tuple[float, float] | tuple[float, float, float], float], float]) – Takes in the z-position of the particle and the phase, return the real field component at this phase and position.

Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], complex]

Returns:

  • NDArray[np.float64]\(2\times 2 \times n\) matrix, holding the \(2\times2\) longitudinal transfer matrix of every field map slice along the field map.

  • NDArray[np.float64]\(2\times n\) array, holding Lorentz factor and phase of the synchronous particle along the linac.

  • complex – Complex integral of the field experienced by the synchronous particle when crossing the cavity.

z_thin_lense(scaled_e_middle, gamma_in, gamma_out, gamma_middle, half_dz, omega0_rf)[source]

Compute propagation in a slice of field map using thin lense approximation.

Thin lense approximation: drift-acceleration-drift. The transfer matrix of the thin accelerating gap is:

\[\begin{split}\begin{bmatrix} k_3 & 1 \\ k_1 & k_2 \\ \end{bmatrix}\end{split}\]

Where:

\[\begin{split}\left\{ \begin{aligned} k_1 &= \Im(\widetilde{E}_\mathrm{scaled}^\mathrm{norm}) \frac{\omega_0}{\beta_m c} \\ k_2 &= 1 - (2 - \beta_m^2)\Re(\widetilde{E}_\mathrm{scaled}^\mathrm{norm}) \\ k_3 &= \frac{1 - \Re(\widetilde{E}_\mathrm{scaled}^\mathrm{norm})}{k_2} \end{aligned} \right.\end{split}\]

\(\widetilde{E}_\mathrm{scaled}^\mathrm{norm}\) is proportional to the complex electric field at the middle of the accelerating gap:

\[\widetilde{E}_\mathrm{scaled}^\mathrm{norm} = \frac{\Delta\gamma_\mathrm{norm}}{\gamma_m\beta_m^2} \widetilde{E}(z + \frac{\Delta z}{2}, \phi_m)\]

Quantities with a \(m\) subscript are taken at the middle of the accelerating gap. \(i\) are in the first drift, \(i+1\) in the second.

Note

In TraceWin documentation:

  • \(k_1\) and \(k_2\) are called \(K_1\) and \(K_2\). They miss a \(\Delta z\) term.

  • Our complex electric field \(\widetilde{E}\) would be written:

    \[\widetilde{E} = E_0 \sin{ \left( \frac{Kz}{\beta_c} \right) } \left[ \cos{(\omega t_s + \varphi_0)} + j\sin{(\omega t_s + \varphi_0)} \right]\]
Parameters:
  • scaled_e_middle (complex) –

    Complex electric field in the accelerating gap multiplied by \(\Delta\gamma_\mathrm{norm}\):

    \[\widetilde{E}_\mathrm{scaled} = \Delta\gamma_\mathrm{norm} \widetilde{E}_z\left( z + \Delta z, \phi_m \right)\]

    where

    \[\Delta\gamma_\mathrm{norm} = \frac{q_\mathrm{adim} \Delta z} {E_\mathrm{rest}}\]

    In the routine, we define:

    \[\widetilde{E}_\mathrm{scaled}^\mathrm{norm} = \frac{ \widetilde{E}_\mathrm{scaled} }{ \gamma_m \beta_m^2 }\]

  • gamma_in (float) – gamma at entrance of first drift.

  • gamma_out (float) – gamma at exit of first drift.

  • gamma_middle (float) – gamma at the thin acceleration drift.

  • half_dz (float) – Half a spatial step in \(\mathrm{m}\).

  • omega0_rf (float) – Pulsation of the cavity.

  • omega_0_bunch – Pulsation of the beam.

Return type:

ndarray[tuple[Any, ...], dtype[double]]

Returns:

Transfer matrix of the thin lense.

z_bend(gamma_in, delta_s, factor_1, factor_2, factor_3, omega_0_bunch)[source]

Compute the longitudinal transfer matrix of a bend.

factor_1 is:

\[\frac{-h^2\Delta s}{k_x^2}\]

factor_2 is:

\[\frac{h^2 \sin{(k_x\Delta s)}}{k_x^3}\]

factor_3 is:

\[\Delta s \left(1 - \frac{h^2}{k_x^2}\right)\]
Parameters:
Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], None]

z_superposed_field_maps_rk4(gamma_in, d_z, n_steps, omega0_rf, delta_phi_norm, delta_gamma_norm, complex_e_func, real_e_func)[source]

Calculate the transfer matrix of superposed FIELD_MAP using RK.

Parameters:
Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], complex]

z_field_map_leapfrog(d_z, gamma_in, n_steps, omega0_rf, k_e, phi_0_rel, e_spat, q_adim, inv_e_rest_mev, gamma_init, omega_0_bunch, **kwargs)[source]

Calculate the transfer matrix of a FIELD_MAP using leapfrog.

Todo

clean, fix, separate leapfrog integration in dedicated module

This method is less precise than RK4. However, it is much faster.

Classic leapfrog method: speed(i+0.5) = speed(i-0.5) + accel(i) * dt pos(i+1) = pos(i) + speed(i+0.5) * dt

Here, dt is not fixed but dz. z(i+1) += dz t(i+1) = t(i) + dz / (c beta(i+1/2)) (time and space variables are on whole steps) beta calculated from W(i+1/2) = W(i-1/2) + qE(i)dz (speed/energy is on half steps)

Parameters:
Return type:

tuple[ndarray[tuple[Any, ...], dtype[double]], ndarray[tuple[Any, ...], dtype[double]], float]