# -*- coding: utf-8 -*-
"""
HOM-driven longitudinal dipole coupled-bunch instability:
- Growth-rate estimate using Bosch [1] resonant approximation,
compared against approxmiate the Landau-damping threshold from
rf potential decomposition.
References
----------
[1] Bosch, R. A., K. J. Kleman, and J. J. Bisognano. "Robinson instabilities
with a higher-harmonic cavity." Physical Review Special Topics-Accelerators
and Beams 4.7 (2001): 074401.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
from albums.physics.potential import form_factors
if TYPE_CHECKING: # pragma: no cover - hints only
from mbtrack2 import Synchrotron
[docs]def dipole_coupled_bunch_growth_rate(
ring: Synchrotron,
I0: float,
f_HOM: float,
Z_HOM: float,
bunch_length: float,
omega_r: float,
) -> float:
"""Resonant dipole coupled-bunch growth rate. Eq. (22) in [1]."""
from_factor = form_factors(f_HOM, 1, bunch_length)
return (I0 * ring.eta() * 2 * np.pi * f_HOM * Z_HOM * from_factor**2) / (
2 * ring.E0 * ring.T0 * omega_r
)
[docs]def dipole_coupled_bunch(
ring: Synchrotron,
I0: float,
f_HOM: float | np.ndarray,
Z_HOM: float | np.ndarray,
bunch_length: float,
omega_r: float,
landau: np.ndarray,
) -> bool:
"""HOM-driven dipole coupled-bunch instability test.
Uses the resonant dipole_coupled_bunch_growth_rate for each HOM in
the supplied list. The instability is flagged only if the HOM
growth rate exceeds both radiation damping and the dipole Landau
threshold.
Parameters
----------
ring : Synchrotron
Ring parameters.
I0 : float
Beam current in A.
f_HOM, Z_HOM : float or array-like
HOM resonant frequency in [Hz] and shunt impedance in [Ohm].
bunch_length : float
RMS bunch length in [s].
omega_r : float
Synchrotron angular frequency.
landau : numpy.ndarray
Landau thresholds from landau_threshold;
only the dipole entry landau[0] is used.
Returns
-------
bool
True if HOM-driven coupled-bunch unstable.
Raises
------
ValueError
If f_HOM and Z_HOM have mismatched lengths.
References
----------
Eq. (22) in [1].
"""
HOM = False
if isinstance(f_HOM, (int, float)):
f_HOM = [f_HOM]
if isinstance(Z_HOM, (int, float)):
Z_HOM = [Z_HOM]
if len(f_HOM) != len(Z_HOM):
raise ValueError("f_HOM and Z_HOM must have the same length.")
else:
N = len(f_HOM)
for i in range(N):
gr_HOM = dipole_coupled_bunch_growth_rate(
ring, I0, f_HOM[i], Z_HOM[i], bunch_length, omega_r
)
gr = gr_HOM - 1 / ring.tau[2]
if gr > 0:
if gr_HOM > landau[0]:
HOM = True
break
return HOM