# -*- coding: utf-8 -*-
"""
Zero-frequency (DC Robinson) instability: the per-mode mu = 1..4 stability
bound without mode coupling, and the coupled criterion built from the
Robinson terms [1].
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 math import factorial
from typing import TYPE_CHECKING
import numpy as np
from albums.physics.robinson import A_tilde, B_tilde, d_tilde
if TYPE_CHECKING: # pragma: no cover - hints only
from mbtrack2 import CavityResonator, Synchrotron
[docs]def zero_frequency_no_coupling(
ring: Synchrotron,
cavity_list: list[CavityResonator],
I0: float,
F: np.ndarray,
mu: int,
bunch_length: float,
) -> float:
"""Per-mode zero-frequency stability bound (no coupling). Eq. (14) in [1]."""
coef1 = ring.ac * ring.omega1 * I0 / (ring.E0 * ring.T0)
coef2 = (ring.omega1 * bunch_length) ** (2 * mu - 2) / (
2 ** (mu - 1) * factorial(mu)
)
sum_val = 0
for i, cavity in enumerate(cavity_list):
sum_val += (
cavity.m ** (2 * mu - 1) * cavity.RL * F[i] ** 2 * np.sin(-2 * cavity.psi)
)
return coef1 * coef2 * sum_val
[docs]def zero_frequency_instability(
ring: Synchrotron,
cavity_list: list[CavityResonator],
I0: float,
F: np.ndarray,
omega_r: float,
bunch_length: float,
mode_coupling: bool,
) -> bool:
"""Zero-frequency (DC Robinson) instability test.
Parameters
----------
ring : Synchrotron
Ring parameters.
cavity_list : list of CavityResonator
Solved cavities.
I0 : float
Beam current in A.
F : numpy.ndarray
Amplitude form factor per cavity.
omega_r : float
Synchrotron angular frequency from
robinson_frequency.
bunch_length : float
RMS bunch length in [s].
mode_coupling : bool
If True use the coupled criterion (Eq. B.12); otherwise the per-mode
mu = 1..4 criterion (Eq. 14).
Returns
-------
bool
True if the equilibrium is zero-frequency unstable.
References
----------
Eq. (14) / (B.12) in [1].
"""
if mode_coupling is False:
if omega_r**2 < zero_frequency_no_coupling(
ring, cavity_list, I0, F, 1, bunch_length
):
return True
elif omega_r**2 < zero_frequency_no_coupling(
ring, cavity_list, I0, F, 2, bunch_length
):
return True
elif omega_r**2 < zero_frequency_no_coupling(
ring, cavity_list, I0, F, 3, bunch_length
):
return True
elif omega_r**2 < zero_frequency_no_coupling(
ring, cavity_list, I0, F, 4, bunch_length
):
return True
else:
return False
else:
if omega_r**2 - A_tilde(ring, cavity_list, I0, F, 0) < 0:
return True
elif 4 * omega_r**2 - B_tilde(ring, cavity_list, I0, F, 0, bunch_length) < 0:
return True
elif (omega_r**2 - A_tilde(ring, cavity_list, I0, F, 0)) * (
4 * omega_r**2 - B_tilde(ring, cavity_list, I0, F, 0, bunch_length)
) + d_tilde(ring, cavity_list, I0, F, 0, bunch_length) < 0:
return True
else:
return False