Something went wrong on our end
-
Gamelin Alexis authoredGamelin Alexis authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
instabilities.py 7.70 KiB
# -*- coding: utf-8 -*-
"""
General calculations about instabilities
@author: Alexis Gamelin
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy.constants import c, m_e, e, pi, epsilon_0
def mbi_threshold(ring, sigma, R, b):
"""
Compute the microbunching instability (MBI) threshold for a bunched beam
considering the steady-state parallel plate model [1][2].
Parameters
----------
ring : Synchrotron object
sigma : float
RMS bunch length in [s]
R : float
dipole bending radius in [m]
b : float
vertical distance between the conducting parallel plates in [m]
Returns
-------
I : float
MBI current threshold in [A]
[1] : Y. Cai, "Theory of microwave instability and coherent synchrotron
radiation in electron storage rings", SLAC-PUB-14561
[2] : D. Zhou, "Coherent synchrotron radiation and microwave instability in
electron storage rings", PhD thesis, p112
"""
sigma = sigma * c
Ia = 4*pi*epsilon_0*m_e*c**3/e # Alfven current
chi = sigma*(R/b**3)**(1/2) # Shielding paramter
xi = 0.5 + 0.34*chi
N = (ring.L * Ia * ring.ac * ring.gamma * ring.sigma_delta**2 * xi *
sigma**(1/3) / ( c * e * R**(1/3) ))
I = N*e/ring.T0
return I
def cbi_threshold(ring, I, Vrf, f, beta, Ncav=1):
"""
Compute the longitudinal and transverse coupled bunch instability
thresolds driven by HOMs [1].
Parameters
----------
ring : Synchrotron object
I : float
Total beam current in [A].
Vrf : float
Total RF voltage in [V].
f : float
Frequency of the HOM in [Hz].
beta : array-like of shape (2,)
Horizontal and vertical beta function at the HOM position in [m].
Ncav : int, optional
Number of RF cavity.
Returns
-------
Zlong : float
Maximum longitudinal impedance of the HOM in [ohm].
Zxdip : float
Maximum horizontal dipolar impedance of the HOM in [ohm/m].
Zydip : float
Maximum vertical dipolar impedance of the HOM in [ohm/m].
References
----------
[1] : Ruprecht, Martin, et al. "Calculation of Transverse Coupled Bunch
Instabilities in Electron Storage Rings Driven By Quadrupole Higher Order
Modes." 7th Int. Particle Accelerator Conf.(IPAC'16), Busan, Korea.
"""
fs = ring.synchrotron_tune(Vrf)*ring.f0
Zlong = fs/(f*ring.ac*ring.tau[2]) * (2*ring.E0) / (ring.f0 * I * Ncav)
Zxdip = 1/(ring.tau[0]*beta[0]) * (2*ring.E0) / (ring.f0 * I * Ncav)
Zydip = 1/(ring.tau[1]*beta[1]) * (2*ring.E0) / (ring.f0 * I * Ncav)
return (Zlong, Zxdip, Zydip)
def lcbi_growth_rate_mode(ring, I, Vrf, M, mu, fr=None, Rs=None, QL=None, Z=None):
"""
Compute the longitudinal coupled bunch instability growth rate driven by
HOMs for a given coupled bunch mode mu [1].
Use either the resonator model (fr,Rs,QL) or an Impedance object (Z).
Parameters
----------
ring : Synchrotron object
I : float
Total beam current in [A].
Vrf : float
Total RF voltage in [V].
M : int
Nomber of bunches in the beam.
mu : int
Coupled bunch mode number (= 0, ..., M-1).
fr : float, optional
Frequency of the HOM in [Hz].
Rs : float, optional
Shunt impedance of the HOM in [Ohm].
QL : float, optional
Loaded quality factor of the HOM.
Z : Impedance, optional
Longitunial impedance to consider.
Returns
-------
float
Coupled bunch instability growth rate for the mode mu.
References
----------
[1] : Eq. 51 p139 of Akai, Kazunori. "RF System for Electron Storage
Rings." Physics And Engineering Of High Performance Electron Storage Rings
And Application Of Superconducting Technology. 2002. 118-149.
"""
nu_s = ring.synchrotron_tune(Vrf)
factor = ring.eta * I / (4 * np.pi * ring.E0 * nu_s)
if Z is None:
omega_r = 2 * np.pi * fr
n_max = int(10 * omega_r / (ring.omega0 * M))
def Zr(omega):
return np.real(Rs / (1 + 1j * QL * (omega_r/omega - omega/omega_r)))
else:
fmax = Z.data.index.max()
n_max = int(2 * np.pi * fmax / (ring.omega0 * M))
def Zr(omega):
return np.real( Z( omega / (2*np.pi) ) )
n0 = np.arange(n_max)
n1 = np.arange(1, n_max)
omega_p = ring.omega0 * (n0 * M + mu + nu_s)
omega_m = ring.omega0 * (n1 * M - mu - nu_s)
sum_val = np.sum(omega_p*Zr(omega_p)) - np.sum(omega_m*Zr(omega_m))
return factor * sum_val
def lcbi_growth_rate(ring, I, Vrf, M, fr=None, Rs=None, QL=None, Z=None):
"""
Compute the maximum growth rate for longitudinal coupled bunch instability
driven by HOMs [1].
Use either the resonator model (fr,Rs,QL) or an Impedance object (Z).
Parameters
----------
ring : Synchrotron object
I : float
Total beam current in [A].
Vrf : float
Total RF voltage in [V].
M : int
Nomber of bunches in the beam.
fr : float, optional
Frequency of the HOM in [Hz].
Rs : float, optional
Shunt impedance of the HOM in [Ohm].
QL : float, optional
Loaded quality factor of the HOM.
Z : Impedance, optional
Longitunial impedance to consider.
Returns
-------
growth_rate : float
Maximum coupled bunch instability growth rate.
mu : int
Coupled bunch mode number corresponding to the maximum coupled bunch
instability growth rate.
growth_rates : array
Coupled bunch instability growth rates for the different mode numbers.
References
----------
[1] : Eq. 51 p139 of Akai, Kazunori. "RF System for Electron Storage
Rings." Physics And Engineering Of High Performance Electron Storage Rings
And Application Of Superconducting Technology. 2002. 118-149.
"""
growth_rates = np.zeros(M)
for i in range(M):
growth_rates[i] = lcbi_growth_rate_mode(ring, I, Vrf, M, i, fr=fr, Rs=Rs, QL=QL, Z=Z)
growth_rate = np.max(growth_rates)
mu = np.argmax(growth_rates)
return growth_rate, mu, growth_rates
def plot_critical_mass(ring, bunch_charge, bunch_spacing, n_points=1e4):
"""
Plot ion critical mass, using Eq. (7.70) p147 of [1]
Parameters
----------
ring : Synchrotron object
bunch_charge : float
Bunch charge in [C].
bunch_spacing : float
Time in between two adjacent bunches in [s].
n_points : float or int, optional
Number of point used in the plot. The default is 1e4.
Returns
-------
fig : figure
References
----------
[1] : Gamelin, A. (2018). Collective effects in a transient microbunching
regime and ion cloud mitigation in ThomX (Doctoral dissertation,
Université Paris-Saclay).
"""
n_points = int(n_points)
s = np.linspace(0, ring.L, n_points)
sigma = ring.sigma(s)
rp = 1.534698250004804e-18 # Proton classical radius, m
N = np.abs(bunch_charge/e)
Ay = N*rp*bunch_spacing*c/(2*sigma[2,:]*(sigma[2,:] + sigma[0,:]))
Ax = N*rp*bunch_spacing*c/(2*sigma[0,:]*(sigma[2,:] + sigma[0,:]))
fig = plt.figure()
ax = plt.gca()
ax.plot(s, Ax, label=r"$A_x^c$")
ax.plot(s, Ay, label=r"$A_y^c$")
ax.set_yscale("log")
ax.plot(s, np.ones_like(s)*2, label=r"$H_2^+$")
ax.plot(s, np.ones_like(s)*16, label=r"$H_2O^+$")
ax.plot(s, np.ones_like(s)*18, label=r"$CH_4^+$")
ax.plot(s, np.ones_like(s)*28, label=r"$CO^+$")
ax.plot(s, np.ones_like(s)*44, label=r"$CO_2^+$")
ax.legend()
ax.set_ylabel("Critical mass")
ax.set_xlabel("Longitudinal position [m]")
return fig