Skip to content
Snippets Groups Projects
Commit a1c59572 authored by Alexis GAMELIN's avatar Alexis GAMELIN
Browse files

Merge branch 'feature-sc_tuneshift' into 'develop'

Add transverse_space_charge_tune_shift utility function

See merge request !30
parents 7a6b01e4 17a288ec
No related branches found
No related tags found
2 merge requests!480.9.0,!30Add transverse_space_charge_tune_shift utility function
......@@ -7,6 +7,7 @@ from mbtrack2.instability.instabilities import (
mbi_threshold,
rwmbi_growth_rate,
rwmbi_threshold,
transverse_gaussian_space_charge_tune_shift,
)
from mbtrack2.instability.ions import (
fast_beam_ion,
......
......@@ -454,3 +454,82 @@ def rwmbi_threshold(ring, beff, rho_material, plane='x'):
(1-frac_tune) * omega0) / (2*c*Z0*rho_material))**0.5
return Ith
def transverse_gaussian_space_charge_tune_shift(ring, bunch_current, **kwargs):
"""
Return the (maximum) transverse space charge tune shift for a Gaussian
bunch in the linear approximation, see Eq.(1) of [1].
Parameters
----------
ring : Synchrotron object
Ring parameters.
bunch_current : float
Bunch current in [A].
sigma_s : float, optional
RMS bunch length in [s].
Default is ring.sigma_0.
emit_x : float, optional
Horizontal emittance in [m.rad].
Default is ring.emit[0].
emit_y : float, optional
Vertical emittance in [m.rad].
Default is ring.emit[1].
use_lattice : bool, optional
If True, use beta fonctions along the lattice.
If False, local values of beta fonctions are used.
Default is ring.optics.use_local_values.
n_points : int, optional
Number of points in the lattice to be considered if use_lattice ==
True. Default is 1000.
sigma_delta : float, optional
Relative energy spread.
Default is ring.sigma_delta.
gamma : float, optional
Relativistic Lorentz gamma.
Default is ring.gamma.
Returns
-------
tune_shift : array of shape (2,)
Horizontal and vertical space charge tune shift.
Reference
---------
[1] : Antipov, S. A., Gubaidulin, V., Agapov, I., Garcia, E. C., &
Gamelin, A. (2024). Space Charge and Future Light Sources.
arXiv preprint arXiv:2409.08637.
"""
sigma_s = kwargs.get('sigma_s', ring.sigma_0)
emit_x = kwargs.get('emit_x', ring.emit[0])
emit_y = kwargs.get('emit_y', ring.emit[1])
use_lattice = kwargs.get('use_lattice', not ring.optics.use_local_values)
sigma_delta = kwargs.get('sigma_delta', ring.sigma_delta)
gamma = kwargs.get('gamma', ring.gamma)
n_points = kwargs.get('n_points', 1000)
q = ring.particle.charge
m = ring.particle.mass
r_0 = 1 / (4*pi*epsilon_0) * q**2 / (m * c**2)
N = np.abs(bunch_current / ring.f0 / q)
sigma_z = sigma_s * c
if use_lattice:
s = np.linspace(0, ring.L, n_points)
beta = ring.optics.beta(s)
sig_x = (emit_x * beta[0] +
ring.optics.dispersion(s)[0]**2 * sigma_delta**2)**0.5
sig_y = (emit_y * beta[1] +
ring.optics.dispersion(s)[2]**2 * sigma_delta**2)**0.5
sig_xy = np.array([sig_x, sig_y])
return -r_0 * N / ((2 * pi)**1.5 * gamma**3 * sigma_z) * np.trapz(
beta / (sig_xy * (sig_y+sig_x)), s)
else:
beta = ring.optics.local_beta
sig_x = np.sqrt(beta[0] * emit_x)
sig_y = np.sqrt(beta[1] * emit_y)
sig_xy = np.array([sig_x, sig_y])
return -r_0 * N * ring.L / (
(2 * pi)**1.5 * gamma**3 * sigma_z) * beta / (sig_xy *
(sig_y+sig_x))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment