Source code for albums.physics.potential

# -*- coding: utf-8 -*-
"""
Equilibrium-derived closed-form quantities: RF potential well, bunch length,
form factors, incoherent (Robinson) frequency and the Landau-damping threshold.

These are the low-level quantities shared by the Stage-1 solvers
(albums.equilibrium) and by nearly every Stage-2 theory.

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 scipy.integrate import quad

if TYPE_CHECKING:  # pragma: no cover - hints only
    from mbtrack2 import CavityResonator, Synchrotron


[docs]def potential_decomposition( ring: Synchrotron, cavity_list: list[CavityResonator] ) -> tuple[float, float, float]: """Taylor coefficients of the RF potential well about the synchronous point. Parameters ---------- ring : Synchrotron Ring parameters. cavity_list : list of CavityResonator Solved cavities. Returns ------- a, b, c : float Quadratic, cubic and quartic potential-well coefficients. References ---------- Eq. (4)-(6) in [1]. """ a_sum = b_sum = c_sum = 0 for cavity in cavity_list: a_sum += cavity.m * cavity.Vc * np.sin(cavity.theta) b_sum += cavity.m**2 * cavity.Vc * np.cos(cavity.theta) c_sum += cavity.m**3 * cavity.Vc * np.sin(cavity.theta) a = ring.ac * ring.omega1 / (2 * ring.E0 * ring.T0) * a_sum b = ring.ac * ring.omega1**2 / (6 * ring.E0 * ring.T0) * b_sum c = -ring.ac * ring.omega1**3 / (24 * ring.E0 * ring.T0) * c_sum return (a, b, c)
[docs]def bunch_length( ring: Synchrotron, a: float, b: float, c: float, tau_boundary: float ) -> float: """RMS bunch length from the potential-well distribution. Integrates the Boltzmann distribution of the quartic potential well over [-tau_boundary, tau_boundary] and returns its standard deviation. Parameters ---------- ring : Synchrotron Ring parameters. a, b, c : float Potential-well coefficients from potential_decomposition. tau_boundary : float Integration half-width in [s]. Returns ------- float RMS bunch length in [s]. References ---------- Eq. (8) in [1]. """ U0 = ring.ac**2 * ring.sigma_delta**2 / 2 def U(tau): return a * tau**2 + b * tau**3 + c * tau**4 def numerator(tau): return tau**2 * np.exp(-U(tau) / (2 * U0)) def denominator(tau): return np.exp(-U(tau) / (2.0 * U0)) num = quad(numerator, -tau_boundary, tau_boundary)[0] den = quad(denominator, -tau_boundary, tau_boundary)[0] return np.sqrt(num / den)
[docs]def form_factors(f: float, m: int, bunch_length: float) -> float: """Gaussian-bunch amplitude form factor at harmonic m of frequency f. Parameters ---------- f : float Fundamental frequency in [Hz]. m : int Harmonic number of the cavity. bunch_length : float RMS bunch length in [s]. Returns ------- float Form factor exp(-(m omega sigma)^2 / 2) in [0, 1]. """ omega = 2 * np.pi * f return np.exp(-(m**2) * omega**2 * bunch_length**2 / 2)
[docs]def robinson_frequency( ring: Synchrotron, cavity_list: list[CavityResonator], F: np.ndarray ) -> float: """Incoherent synchrotron (Robinson) angular frequency omega_r. Parameters ---------- ring : Synchrotron Ring parameters. cavity_list : list of CavityResonator Solved cavities. F : numpy.ndarray Amplitude form factor per cavity. Returns ------- float Synchrotron angular frequency in [rad/s]. References ---------- Eq. (10) in [1]. """ sum_val = 0 for i, cavity in enumerate(cavity_list): sum_val += cavity.m * F[i] * cavity.Vc * np.sin(cavity.theta) omega2 = ring.ac * ring.omega1 / (ring.E0 * ring.T0) * sum_val return np.sqrt(omega2)
[docs]def landau_threshold( ring: Synchrotron, omega_r: float, c: float, b: float ) -> np.ndarray: """Landau-damping frequency-spread threshold for modes mu = 1..4. Parameters ---------- ring : Synchrotron Ring parameters. omega_r : float Synchrotron angular frequency from robinson_frequency. c, b : float Quartic and cubic potential-well coefficients from potential_decomposition. Returns ------- numpy.ndarray Shape (4, 1) thresholds for the dipole, quadrupole, sextupole and octupole modes. References ---------- Eq. (19) in [1]. """ dipole_landau = ( 0.78 * ring.ac**2 * ring.sigma_delta**2 / omega_r * np.abs(3 * c / omega_r**2 - (3 * b / omega_r**2) ** 2) ) out = np.zeros((4, 1)) out[0] = dipole_landau out[1] = 2.24 / 0.78 * dipole_landau out[2] = 4.12 / 0.78 * dipole_landau out[3] = 6.36 / 0.78 * dipole_landau return out