Synchrotron Radiation Contribution

This section in short

The emittance_evolution method of analytical classes can include the contribution of Synchrotron Radiation and quantum excitation. It done automatically if specific keyword arguments are provided. They are described in the API reference and below, as well as how to obtain them.

When computing analytical emittance evolutions, in some scenarios the contribution of Synchrotron Radiation (SR) and quantum excitation might be significant. It is possible to include these contributions on top of the IBS ones when calling the emittance_evolution method, by providing the following keyword arguments:

  • sr_equilibrium_epsx: the horizontal equilibrium emittance due to SR, in [m] (or, if not [m], the same unit as epsx and epsy).

  • sr_equilibrium_epsy: the vertical equilibrium emittance due to SR, in [m] (or, if not [m], the same unit as epsx and epsy).

  • sr_equilibrium_sigma_delta: the equilibrium energy spread due to SR.

  • sr_tau_x: the horizontal damping time due to SR, in [s].

  • sr_tau_y: the vertical damping time due to SR, in [s].

  • sr_tau_z: the longitudinal damping time due to SR, in [s].

Note

It is possible to choose to provide normalized or geometric equilibrium emittances, as described in this section. What matters is that the same type as epsx and epsy is given, as indicated by the normalized_emittances boolean argument. In short: either provide all in geometric or all in normalized units, don’t mix it up.

It is possible to obtain these parameters from either Xsuite or MAD-X, as will be shown below.

Getting SR Parameters from Xsuite

All necessary parameters can be obtained in the result of a Twiss call on your xtrack.Line. It is important however to have first configured the radiation model, and to make the Twiss call asking for these results (see the Xsuite user guide pages on synchrotron radiation and Twiss beams sizes). See below a function that does just so:

def get_sr_inputs_from_line(line: xt.Line, normalized: bool = True) -> tuple[float, ...]:
    """Assumes line has a reference particle and is compatible with SR modes."""
    # Set the radiation mode to 'mean' and call twiss with
    # 'eneloss_and_damping' (see Xsuite user guide)
    line.configure_radiation(model="mean")
    twiss = line.twiss(eneloss_and_damping=True)

    # The damping times (in [s]) are provided as:
    sr_tau_x, sr_tau_y, sr_tau_z = twiss["damping_constants_s"]

    # The transverse equilibrium emittances (in [m]) are provided as:
    emit = "nemitt" if normalized is True else "gemitt"
    sr_equilibrium_epsx = twiss[f"eq_{emit}_x"]
    sr_equilibrium_epsy = twiss[f"eq_{emit}_y"]

    # We will need to store the equilibrium longitudinal emittance too for later
    sr_eq_zeta = twiss[f"eq_{emit}_zeta"]  # or 'eq_gemitt_zeta' for geometric

    # The equilibrium momentum spread is not directly provided but can be obtained via
    # a method of the twiss result, using the equilibrium emittances obtained above.
    if normalized is True:
        beam_sizes = twiss.get_beam_covariance(
            nemitt_x=sr_equilibrium_epsx,
            nemitt_y=sr_equilibrium_epsy,
            nemitt_zeta=sr_eq_zeta,
        )
    else:
        beam_sizes = twiss.get_beam_covariance(
            gemitt_x=sr_equilibrium_epsx,
            gemitt_y=sr_equilibrium_epsy,
            gemitt_zeta=sr_eq_zeta,
        )

    # The value we want corresponds to the 'sigma_pzeta' key in this result, since in
    # Xsuite it is equivalent to 'sigma_delta' (see Xsuite physics guide, Eq 1.14 and 1.23).
    # Take it at the location of the particle kicks (start / end of line):
    sr_equilibrium_sigma_delta = beam_sizes["sigma_pzeta"][0]  # 0 for end / start of line

    # Return results
    return (
        sr_equilibrium_epsx,
        sr_equilibrium_epsy,
        sr_equilibrium_sigma_delta,
        sr_tau_x,
        sr_tau_y,
        sr_tau_z,
    )

Getting SR Parameters from MAD-X

While a bit more cumbersome, it is possible to get these parameters from MAD-X as well. Let’s assume your sequence and beam are defined, one might get the necessary parameters as follows:

def get_sr_inputs_from_madx(
    madx: cpymad.madx.Madx, sequence: str, normalized: bool = True
) -> tuple[float, ...]:
    """Assumes beam, sequence etc are already defined. RF system should be ON."""
    # Make sure to include radiation effects for the sequence's beam
    madx.sequence[sequence].beam.radiate = True

    # Let's then call the 'emit' command with DELTAP=0, which will
    # update the beam with equilibrium values directly
    madx.command.emit(deltap=0)

    # The transverse equilibrium emittances (in [m]) are provided as:
    suffix = "n" if normalized is True else ""
    sr_equilibrium_epsx = madx.sequence[sequence].beam[f"ex{suffix}"]
    sr_equilibrium_epsy = madx.sequence[sequence].beam[f"ey{suffix}"]

    # The equilibrium momentum spread is not directly provided but can be obtained
    # from the relative energy spread using the relativistic beta as:
    beta_rel = madx.sequence[sequence].beam.beta
    sigma_e = madx.sequence[sequence].beam.sige
    sr_equilibrium_sigma_delta = sigma_e / beta_rel / beta_rel

    # We will need to get from the active beam: particle energy, energy loss per
    # turn (in [GeV]) and the revolution frequency (in [MHz])
    E0 = madx.sequence[sequence].beam.energy * 1e9  # it is in GeV in MAD-X
    U0 = madx.sequence[sequence].beam.U0 * 1e9  # it is in GeV in MAD-X
    frev = madx.sequence[sequence].beam.freq0 * 1e6  # it is in MHz in MAD-X

    # We will need the synchrotron radiation integrals to determine the
    # damping partition numbers (see https://arxiv.org/pdf/1507.02213.pdf)
    madx.command.twiss(chrom=True)  # chrom to trigger their calculation
    I2 = madx.table.summ.synch_2[0]
    I4 = madx.table.summ.synch_4[0]
    jx = 1 - I4 / I2  # horizontal damping partition number
    jz = 2 + I4 / I2  # longitudinal damping partition number

    # This is enough to compute the damping times
    # (see https://arxiv.org/pdf/1507.02213.pdf)
    sr_tau_x = 2 * E0 * frev / (jx * U0)
    sr_tau_y = 2 * E0 * frev / U0
    sr_tau_z = 2 * E0 * frev / (jz * U0)

    # Return results
    return (
        sr_equilibrium_epsx,
        sr_equilibrium_epsy,
        sr_equilibrium_sigma_delta,
        sr_tau_x,
        sr_tau_y,
        sr_tau_z,
    )