From cb8b05d866a81403b03b438c82cb388be130f3bb Mon Sep 17 00:00:00 2001 From: Gamelin Alexis <gamelin@synchrotron-soleil.fr> Date: Wed, 10 Jun 2020 13:28:49 +0200 Subject: [PATCH] Rework import Remove tools.py to avoid circular import problem with wakefield.py -> merged into wakefield.py Remove machines folder to save machine data in a seperate git instance Rework import so the code can be used as independant module mbtrack2 --- README.md | 2 - SOLEIL_U_74BA_HOA_SYM02_V0313_cleaned.mat | Bin 54128 -> 0 bytes collective_effects/__init__.py | 7 + collective_effects/resistive_wall.py | 2 +- collective_effects/tapers.py | 2 +- collective_effects/tools.py | 412 ---------------------- collective_effects/wakefield.py | 393 ++++++++++++++++++++- machines/__init__.py | 7 - machines/soleil.py | 63 ---- plotting.py | 74 ---- tracking/__init__.py | 11 + tracking/aperture.py | 2 +- tracking/element.py | 2 +- tracking/monitors/__init__.py | 6 + tracking/monitors/monitors.py | 4 +- tracking/particles.py | 2 +- tracking/rf.py | 2 +- 17 files changed, 421 insertions(+), 570 deletions(-) delete mode 100644 README.md delete mode 100644 SOLEIL_U_74BA_HOA_SYM02_V0313_cleaned.mat delete mode 100644 collective_effects/tools.py delete mode 100644 machines/__init__.py delete mode 100644 machines/soleil.py delete mode 100644 plotting.py diff --git a/README.md b/README.md deleted file mode 100644 index a33e1c2..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# mbtrack2 - diff --git a/SOLEIL_U_74BA_HOA_SYM02_V0313_cleaned.mat b/SOLEIL_U_74BA_HOA_SYM02_V0313_cleaned.mat deleted file mode 100644 index f021674c7c458deeff2a876be27f7853ba1a1b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54128 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 Hg7*IduwOKw diff --git a/collective_effects/__init__.py b/collective_effects/__init__.py index 27c993f..867d0d1 100644 --- a/collective_effects/__init__.py +++ b/collective_effects/__init__.py @@ -5,3 +5,10 @@ Created on Tue Jan 14 12:25:30 2020 @author: gamelina """ +from mbtrack2.collective_effects.instabilities import MBI_threshold +from mbtrack2.collective_effects.resistive_wall import skin_depth, CircularResistiveWall +from mbtrack2.collective_effects.tapers import StupakovRectangularTaper, StupakovCircularTaper +from mbtrack2.collective_effects.wakefield import ComplexData, Impedance, WakeFunction, ImpedanceModel, Wakefield +from mbtrack2.collective_effects.wakefield import read_CST, read_IW2D, spectral_density +from mbtrack2.collective_effects.wakefield import gaussian_bunch_spectrum, beam_spectrum, effective_impedance +from mbtrack2.collective_effects.wakefield import yokoya_elliptic, beam_loss_factor \ No newline at end of file diff --git a/collective_effects/resistive_wall.py b/collective_effects/resistive_wall.py index 95ae59f..240e30e 100644 --- a/collective_effects/resistive_wall.py +++ b/collective_effects/resistive_wall.py @@ -8,7 +8,7 @@ Define resistive wall elements based on the Wakefield class. import numpy as np from scipy.constants import mu_0, epsilon_0, c -from collective_effects.wakefield import Wakefield, Impedance +from mbtrack2.collective_effects.wakefield import Wakefield, Impedance def skin_depth(omega, rho, mu_r = 1, epsilon_r = 1): """ General formula for the skin depth diff --git a/collective_effects/tapers.py b/collective_effects/tapers.py index 0e09b36..34dde18 100644 --- a/collective_effects/tapers.py +++ b/collective_effects/tapers.py @@ -8,7 +8,7 @@ Created on Tue Mar 31 13:15:36 2020 from scipy.constants import mu_0, epsilon_0, c, pi import numpy as np from scipy.integrate import trapz -from collective_effects.wakefield import Wakefield, Impedance +from mbtrack2.collective_effects.wakefield import Wakefield, Impedance class StupakovRectangularTaper(Wakefield): """ diff --git a/collective_effects/tools.py b/collective_effects/tools.py deleted file mode 100644 index 44c0efc..0000000 --- a/collective_effects/tools.py +++ /dev/null @@ -1,412 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Tools and utilities functions for the Wakefield and Impedances classes. - -@author: Alexis Gamelin -@date: 24/04/2020 -""" - -import pandas as pd -import numpy as np -from scipy.integrate import trapz -from scipy.interpolate import interp1d -from collective_effects.wakefield import Wakefield, Impedance, WakeFunction - -def read_CST(file, impedance_type='long', divide_by=None): - """ - Read CST file format into an Impedance object. - - Parameters - ---------- - file : str - Path to the file to read. - impedance_type : str, optional - Type of the Impedance object. - divide_by : float, optional - Divide the impedance by a value. Mainly used to normalize transverse - impedance by displacement. - - Returns - ------- - result : Impedance object - Data from file. - """ - df = pd.read_csv(file, comment="#", header = None, sep = "\t", - names = ["Frequency","Real","Imaginary"]) - df["Frequency"] = df["Frequency"]*1e9 - if divide_by is not None: - df["Real"] = df["Real"]/divide_by - df["Imaginary"] = df["Imaginary"]/divide_by - if impedance_type == "long": - df["Real"] = np.abs(df["Real"]) - df.set_index("Frequency", inplace = True) - result = Impedance(variable = df.index, - function = df["Real"] + 1j*df["Imaginary"], - impedance_type=impedance_type) - return result - -def read_IW2D(file, impedance_type='long'): - """ - Read IW2D file format into an Impedance object. - - Parameters - ---------- - file : str - Path to the file to read. - impedance_type : str, optional - Type of the Impedance object. - - Returns - ------- - result : Impedance object - Data from file. - """ - df = pd.read_csv(file, sep = ' ', header = None, - names = ["Frequency","Real","Imaginary"], skiprows=1) - df.set_index("Frequency", inplace = True) - result = Impedance(variable = df.index, - function = df["Real"] + 1j*df["Imaginary"], - impedance_type=impedance_type) - return result - -def loss_factor(wake, sigma): - """ - Compute the loss factor or the kick factor of a Wakefield, Impedance or - WakeFunction for a Gaussian bunch. Formulas from Eq. (2) p239 and - Eq.(7) p240 of [1]. - - Parameters - ---------- - wake : Wakefield, Impedance or WakeFunction object. - sigma : float - RMS bunch length in [s] - - Returns - ------- - kloss: float - Loss factor in [V/C] or kick factor in [V/C/m] depanding on the - impedance type. - - References - ---------- - [1] : Handbook of accelerator physics and engineering, 3rd printing. - """ - - if isinstance(wake, Impedance): - - positive_index = wake.data.index > 0 - frequency = wake.data.index[positive_index] - sd = spectral_density(frequency, sigma, m=0) - - if(wake.impedance_type == "long"): - kloss = trapz(x = frequency, - y = 2*wake.data["real"][positive_index]*sd) - elif(wake.impedance_type == "xdip" or wake.impedance_type == "ydip"): - kloss = trapz(x = frequency, - y = 2*wake.data["imag"][positive_index]*sd) - elif(wake.impedance_type == "xquad" or wake.impedance_type == "yquad"): - kloss = trapz(x = frequency, - y = 2*wake.data["imag"][positive_index]*sd) - else: - raise TypeError("Impedance type not recognized.") - - if isinstance(wake, WakeFunction): - # To be implemented. - pass - - if isinstance(wake, Wakefield): - # To be implemented. Create field in wakefield with values ? - pass - - return kloss - -def spectral_density(frequency, sigma, m = 1, mode="Hermite"): - """ - Compute the spectral density of different modes for various values of the - head-tail mode number, based on Table 1 p238 of [1]. - - Parameters - ---------- - frequency : list or numpy array - sample points of the spectral density in [Hz] - sigma : float - RMS bunch length in [s] - m : int, optional - head-tail (or azimutal/synchrotron) mode number - mode: str, optional - type of the mode taken into account for the computation: - -"Hermite" modes for Gaussian bunches - - Returns - ------- - numpy array - - References - ---------- - [1] : Handbook of accelerator physics and engineering, 3rd printing. - """ - - if mode == "Hermite": - return (2*np.pi*frequency*sigma)**(2*m)*np.exp( - -1*(2*np.pi*frequency*sigma)**2) - else: - raise NotImplementedError("Not implemanted yet.") - -def Gaussian_bunch_spectrum(frequency, sigma): - """ - Compute a Gaussian bunch spectrum [1]. - - Parameters - ---------- - frequency : array - sample points of the beam spectrum in [Hz]. - sigma : float - RMS bunch length in [s]. - - Returns - ------- - bunch_spectrum : array - Bunch spectrum sampled at points given in frequency. - - References - ---------- - [1] : Gamelin, A. (2018). Collective effects in a transient microbunching - regime and ion cloud mitigation in ThomX. p86, Eq. 4.19 - """ - return np.exp(-1/2*(2*np.pi*frequency)**2*sigma**2) - - -def beam_spectrum(frequency, M, bunch_spacing, sigma=None, - bunch_spectrum=None): - """ - Compute the beam spectrum assuming constant spacing between bunches [1]. - - Parameters - ---------- - frequency : list or numpy array - sample points of the beam spectrum in [Hz]. - M : int - Number of bunches. - bunch_spacing : float - Time between two bunches in [s]. - sigma : float, optional - If bunch_spectrum is None then a Gaussian bunch with sigma RMS bunch - length in [s] is assumed. - bunch_spectrum : array, optional - Bunch spectrum sampled at points given in frequency. - - Returns - ------- - beam_spectrum : array - - References - ---------- - [1] Rumolo, G - Beam Instabilities - CAS - CERN Accelerator School: - Advanced Accelerator Physics Course - 2014, Eq. 9 - """ - - if bunch_spectrum is None: - bunch_spectrum = Gaussian_bunch_spectrum(frequency, sigma) - - beam_spectrum = (bunch_spectrum * np.exp(1j*np.pi*frequency * - bunch_spacing*(M-1)) * - np.sin(M*np.pi*frequency*bunch_spacing) / - np.sin(np.pi*frequency*bunch_spacing)) - - return beam_spectrum - - -def effective_impedance(ring, imp, m, mu, sigma, xi=None, mode="Hermite"): - """ - Compute the effective (longitudinal or transverse) impedance. - Formulas from Eq. (1) and (2) p238 of [1]. - - Parameters - ---------- - ring : Synchrotron object - imp : Impedance object - mu : int - coupled bunch mode number, goes from 0 to (M-1) where M is the - number of bunches - m : int - head-tail (or azimutal/synchrotron) mode number - sigma : float - RMS bunch length in [s] - xi : float, optional - (non-normalized) chromaticity - mode: str, optional - type of the mode taken into account for the computation: - -"Hermite" modes for Gaussian bunches - - Returns - ------- - Zeff : float - effective impedance in [ohm] or in [ohm/m] depanding on the impedance - type. - - [1] Handbook of accelerator physics and engineering, 3rd printing. - """ - - if not isinstance(imp, Impedance): - raise TypeError("{} should be an Impedance object.".format(imp)) - - fmin = imp.data.index.min() - fmax = imp.data.index.max() - if fmin > 0: - raise ValueError("A double sided impedance spectrum, with positive and" - " negative frequencies, is needed to compute the " - "effective impedance.") - - if mode == "Hermite": - def h(f): - return spectral_density(frequency=f, sigma=sigma, m=m, - mode="Hermite") - else: - raise NotImplementedError("Not implemanted yet.") - - M = 416 - - pmax = fmax/(ring.f0 * M) - 50 - pmin = fmin/(ring.f0 * M) + 50 - - p = np.arange(pmin,pmax+1) - - if imp.impedance_type == "long": - fp = ring.f0*(p*M + mu + m*ring.tune[2]) - fp = fp[np.nonzero(fp)] # Avoid division by 0 - num = np.sum( imp(fp) * h(fp) / (fp*2*np.pi) ) - den = np.sum( h(fp) ) - Zeff = num/den - - elif imp.impedance_type == "xdip" or imp.impedance_type == "ydip": - if imp.impedance_type == "xdip": - tuneXY = ring.tune[0] - xi = ring.chro[0] - elif imp.impedance_type == "ydip": - tuneXY = ring.tune[1] - xi = ring.chro[1] - fp = ring.f0*(p*M + mu + tuneXY + m*ring.tuneS) - f_xi = xi/ring.eta*ring.f0 - num = np.sum( imp(fp) * h(fp - f_xi) ) - den = np.sum( h(fp - f_xi) ) - Zeff = num/den - else: - raise TypeError("Effective impedance is only defined for long, xdip" - " and ydip impedance type.") - - return Zeff - - -def Yokoya_elliptic(x_radius , y_radius): - """ - Compute Yokoya factors for an elliptic beam pipe. - Function adapted from N. Mounet IW2D. - - Parameters - ---------- - x_radius : float - Horizontal semi-axis of the ellipse in [m]. - y_radius : float - Vertical semi-axis of the ellipse in [m]. - - Returns - ------- - yoklong : float - Yokoya factor for the longitudinal impedance. - yokxdip : float - Yokoya factor for the dipolar horizontal impedance. - yokydip : float - Yokoya factor for the dipolar vertical impedance. - yokxquad : float - Yokoya factor for the quadrupolar horizontal impedance. - yokyquad : float - Yokoya factor for the quadrupolar vertical impedance. - """ - if y_radius < x_radius: - small_semiaxis = y_radius - large_semiaxis = x_radius - else: - small_semiaxis = x_radius - large_semiaxis = y_radius - - # read Yokoya factors interpolation file - # BEWARE: columns are ratio, dipy, dipx, quady, quadx - yokoya_file = pd.read_csv("collective_effects/data/" + - "Yokoya_elliptic_from_Elias_USPAS.csv") - ratio_col = yokoya_file["x"] - # compute semi-axes ratio (first column of this file) - ratio = (large_semiaxis - small_semiaxis)/(large_semiaxis + small_semiaxis) - - # interpolate Yokoya file at the correct ratio - yoklong = 1 - - if y_radius < x_radius: - yokydip = np.interp(ratio, ratio_col, yokoya_file["dipy"]) - yokxdip = np.interp(ratio, ratio_col, yokoya_file["dipx"]) - yokyquad = np.interp(ratio, ratio_col, yokoya_file["quady"]) - yokxquad = np.interp(ratio, ratio_col, yokoya_file["quadx"]) - else: - yokxdip = np.interp(ratio, ratio_col, yokoya_file["dipy"]) - yokydip = np.interp(ratio, ratio_col, yokoya_file["dipx"]) - yokxquad = np.interp(ratio, ratio_col, yokoya_file["quady"]) - yokyquad = np.interp(ratio, ratio_col, yokoya_file["quadx"]) - - return (yoklong, yokxdip, yokydip, yokxquad, yokyquad) - -def beam_loss_factor(impedance, frequency, spectrum, ring): - """ - Compute "beam" loss factor using the beam spectrum, uses a sum instead of - integral compared to loss_factor [1]. - - Parameters - ---------- - impedance : Impedance of type "long" - frequency : array - Sample points of spectrum. - spectrum : array - Beam spectrum to consider. - ring : Synchrotron object - - Returns - ------- - kloss_beam : float - Beam loss factor in [V/C]. - - References - ---------- - [1] : Handbook of accelerator physics and engineering, 3rd printing. - Eq (3) p239. - """ - pmax = np.floor(impedance.data.index.max()/ring.f0) - pmin = np.floor(impedance.data.index.min()/ring.f0) - - if pmin >= 0: - # Add negative part - negative_index = impedance.data.index*-1 - negative_data = impedance.data.set_index(negative_index) - negative_data["imag"] = -1*negative_data["imag"] - try: - negative_data = negative_data.drop(0) - except KeyError: - pass - - all_data = impedance.data.append(negative_data) - all_data = all_data.sort_index() - impedance.data = all_data - - pmin = -1*pmax - - p = np.arange(pmin+1,pmax) - pf0 = p*ring.f0 - ReZ = np.real(impedance(pf0)) - spectral_density = np.abs(spectrum)**2 - # interpolation of the spectrum is needed to avoid problems liked to - # division by 0 - # computing the spectrum directly to the frequency points gives - # wrong results - spect = interp1d(frequency, spectral_density) - kloss_beam = ring.f0 * np.sum(ReZ*spect(pf0)) - - return kloss_beam - - diff --git a/collective_effects/wakefield.py b/collective_effects/wakefield.py index 4994c4a..095090b 100644 --- a/collective_effects/wakefield.py +++ b/collective_effects/wakefield.py @@ -12,11 +12,11 @@ import re import pandas as pd import numpy as np import matplotlib.pyplot as plt -import collective_effects.tools as tools from scipy.interpolate import interp1d -from tracking.element import Element +from mbtrack2.tracking.element import Element from copy import deepcopy from scipy.integrate import trapz +from scipy.interpolate import interp1d class ComplexData: """ @@ -327,6 +327,45 @@ class Impedance(ComplexData): power_y += 1./2. return power_y + def loss_factor(self, sigma): + """ + Compute the loss factor or the kick factor for a Gaussian bunch. + Formulas from Eq. (2) p239 and Eq.(7) p240 of [1]. + + Parameters + ---------- + sigma : float + RMS bunch length in [s] + + Returns + ------- + kloss: float + Loss factor in [V/C] or kick factor in [V/C/m] depanding on the + impedance type. + + References + ---------- + [1] : Handbook of accelerator physics and engineering, 3rd printing. + """ + + positive_index = self.data.index > 0 + frequency = self.data.index[positive_index] + sd = spectral_density(frequency, sigma, m=0) + + if(self.impedance_type == "long"): + kloss = trapz(x = frequency, + y = 2*self.data["real"][positive_index]*sd) + elif(self.impedance_type == "xdip" or self.impedance_type == "ydip"): + kloss = trapz(x = frequency, + y = 2*self.data["imag"][positive_index]*sd) + elif(self.impedance_type == "xquad" or self.impedance_type == "yquad"): + kloss = trapz(x = frequency, + y = 2*self.data["imag"][positive_index]*sd) + else: + raise TypeError("Impedance type not recognized.") + + return kloss + class Wakefield: """ Defines a Wakefield which corresponds to a single physical element which @@ -703,7 +742,7 @@ class ImpedanceModel(Element): legend.append(attr) if sigma is not None: - spect = tools.spectral_density(zero_impedance.data.index, sigma) + spect = spectral_density(zero_impedance.data.index, sigma) spect = spect/spect.max()*total_imp.max() ax.plot(sum_imp.data.index*1e-9, spect, 'r', linewidth=2.5) @@ -731,7 +770,7 @@ class ImpedanceModel(Element): for j, component_name in enumerate(list_components): try: impedance = getattr(getattr(self, attr), component_name) - loss_array[j,i] = tools.loss_factor(impedance, sigma) + loss_array[j,i] = impedance.loss_factor(sigma) except AttributeError: pass @@ -800,5 +839,351 @@ class ImpedanceModel(Element): return summary + +def read_CST(file, impedance_type='long', divide_by=None): + """ + Read CST file format into an Impedance object. + + Parameters + ---------- + file : str + Path to the file to read. + impedance_type : str, optional + Type of the Impedance object. + divide_by : float, optional + Divide the impedance by a value. Mainly used to normalize transverse + impedance by displacement. + + Returns + ------- + result : Impedance object + Data from file. + """ + df = pd.read_csv(file, comment="#", header = None, sep = "\t", + names = ["Frequency","Real","Imaginary"]) + df["Frequency"] = df["Frequency"]*1e9 + if divide_by is not None: + df["Real"] = df["Real"]/divide_by + df["Imaginary"] = df["Imaginary"]/divide_by + if impedance_type == "long": + df["Real"] = np.abs(df["Real"]) + df.set_index("Frequency", inplace = True) + result = Impedance(variable = df.index, + function = df["Real"] + 1j*df["Imaginary"], + impedance_type=impedance_type) + return result + +def read_IW2D(file, impedance_type='long'): + """ + Read IW2D file format into an Impedance object. + + Parameters + ---------- + file : str + Path to the file to read. + impedance_type : str, optional + Type of the Impedance object. + + Returns + ------- + result : Impedance object + Data from file. + """ + df = pd.read_csv(file, sep = ' ', header = None, + names = ["Frequency","Real","Imaginary"], skiprows=1) + df.set_index("Frequency", inplace = True) + result = Impedance(variable = df.index, + function = df["Real"] + 1j*df["Imaginary"], + impedance_type=impedance_type) + return result + +def spectral_density(frequency, sigma, m = 1, mode="Hermite"): + """ + Compute the spectral density of different modes for various values of the + head-tail mode number, based on Table 1 p238 of [1]. + + Parameters + ---------- + frequency : list or numpy array + sample points of the spectral density in [Hz] + sigma : float + RMS bunch length in [s] + m : int, optional + head-tail (or azimutal/synchrotron) mode number + mode: str, optional + type of the mode taken into account for the computation: + -"Hermite" modes for Gaussian bunches + + Returns + ------- + numpy array + + References + ---------- + [1] : Handbook of accelerator physics and engineering, 3rd printing. + """ + + if mode == "Hermite": + return (2*np.pi*frequency*sigma)**(2*m)*np.exp( + -1*(2*np.pi*frequency*sigma)**2) + else: + raise NotImplementedError("Not implemanted yet.") + +def gaussian_bunch_spectrum(frequency, sigma): + """ + Compute a Gaussian bunch spectrum [1]. + + Parameters + ---------- + frequency : array + sample points of the beam spectrum in [Hz]. + sigma : float + RMS bunch length in [s]. + + Returns + ------- + bunch_spectrum : array + Bunch spectrum sampled at points given in frequency. + + References + ---------- + [1] : Gamelin, A. (2018). Collective effects in a transient microbunching + regime and ion cloud mitigation in ThomX. p86, Eq. 4.19 + """ + return np.exp(-1/2*(2*np.pi*frequency)**2*sigma**2) + + +def beam_spectrum(frequency, M, bunch_spacing, sigma=None, + bunch_spectrum=None): + """ + Compute the beam spectrum assuming constant spacing between bunches [1]. + + Parameters + ---------- + frequency : list or numpy array + sample points of the beam spectrum in [Hz]. + M : int + Number of bunches. + bunch_spacing : float + Time between two bunches in [s]. + sigma : float, optional + If bunch_spectrum is None then a Gaussian bunch with sigma RMS bunch + length in [s] is assumed. + bunch_spectrum : array, optional + Bunch spectrum sampled at points given in frequency. + + Returns + ------- + beam_spectrum : array + + References + ---------- + [1] Rumolo, G - Beam Instabilities - CAS - CERN Accelerator School: + Advanced Accelerator Physics Course - 2014, Eq. 9 + """ + + if bunch_spectrum is None: + bunch_spectrum = Gaussian_bunch_spectrum(frequency, sigma) + + beam_spectrum = (bunch_spectrum * np.exp(1j*np.pi*frequency * + bunch_spacing*(M-1)) * + np.sin(M*np.pi*frequency*bunch_spacing) / + np.sin(np.pi*frequency*bunch_spacing)) + + return beam_spectrum + + +def effective_impedance(ring, imp, m, mu, sigma, xi=None, mode="Hermite"): + """ + Compute the effective (longitudinal or transverse) impedance. + Formulas from Eq. (1) and (2) p238 of [1]. + + Parameters + ---------- + ring : Synchrotron object + imp : Impedance object + mu : int + coupled bunch mode number, goes from 0 to (M-1) where M is the + number of bunches + m : int + head-tail (or azimutal/synchrotron) mode number + sigma : float + RMS bunch length in [s] + xi : float, optional + (non-normalized) chromaticity + mode: str, optional + type of the mode taken into account for the computation: + -"Hermite" modes for Gaussian bunches + + Returns + ------- + Zeff : float + effective impedance in [ohm] or in [ohm/m] depanding on the impedance + type. + + [1] Handbook of accelerator physics and engineering, 3rd printing. + """ + + if not isinstance(imp, Impedance): + raise TypeError("{} should be an Impedance object.".format(imp)) + + fmin = imp.data.index.min() + fmax = imp.data.index.max() + if fmin > 0: + raise ValueError("A double sided impedance spectrum, with positive and" + " negative frequencies, is needed to compute the " + "effective impedance.") + + if mode == "Hermite": + def h(f): + return spectral_density(frequency=f, sigma=sigma, m=m, + mode="Hermite") + else: + raise NotImplementedError("Not implemanted yet.") + + M = 416 + + pmax = fmax/(ring.f0 * M) - 50 + pmin = fmin/(ring.f0 * M) + 50 + + p = np.arange(pmin,pmax+1) + + if imp.impedance_type == "long": + fp = ring.f0*(p*M + mu + m*ring.tune[2]) + fp = fp[np.nonzero(fp)] # Avoid division by 0 + num = np.sum( imp(fp) * h(fp) / (fp*2*np.pi) ) + den = np.sum( h(fp) ) + Zeff = num/den + + elif imp.impedance_type == "xdip" or imp.impedance_type == "ydip": + if imp.impedance_type == "xdip": + tuneXY = ring.tune[0] + xi = ring.chro[0] + elif imp.impedance_type == "ydip": + tuneXY = ring.tune[1] + xi = ring.chro[1] + fp = ring.f0*(p*M + mu + tuneXY + m*ring.tuneS) + f_xi = xi/ring.eta*ring.f0 + num = np.sum( imp(fp) * h(fp - f_xi) ) + den = np.sum( h(fp - f_xi) ) + Zeff = num/den + else: + raise TypeError("Effective impedance is only defined for long, xdip" + " and ydip impedance type.") + + return Zeff + + +def yokoya_elliptic(x_radius , y_radius): + """ + Compute Yokoya factors for an elliptic beam pipe. + Function adapted from N. Mounet IW2D. + + Parameters + ---------- + x_radius : float + Horizontal semi-axis of the ellipse in [m]. + y_radius : float + Vertical semi-axis of the ellipse in [m]. + + Returns + ------- + yoklong : float + Yokoya factor for the longitudinal impedance. + yokxdip : float + Yokoya factor for the dipolar horizontal impedance. + yokydip : float + Yokoya factor for the dipolar vertical impedance. + yokxquad : float + Yokoya factor for the quadrupolar horizontal impedance. + yokyquad : float + Yokoya factor for the quadrupolar vertical impedance. + """ + if y_radius < x_radius: + small_semiaxis = y_radius + large_semiaxis = x_radius + else: + small_semiaxis = x_radius + large_semiaxis = y_radius + + # read Yokoya factors interpolation file + # BEWARE: columns are ratio, dipy, dipx, quady, quadx + yokoya_file = pd.read_csv("collective_effects/data/" + + "Yokoya_elliptic_from_Elias_USPAS.csv") + ratio_col = yokoya_file["x"] + # compute semi-axes ratio (first column of this file) + ratio = (large_semiaxis - small_semiaxis)/(large_semiaxis + small_semiaxis) + + # interpolate Yokoya file at the correct ratio + yoklong = 1 + + if y_radius < x_radius: + yokydip = np.interp(ratio, ratio_col, yokoya_file["dipy"]) + yokxdip = np.interp(ratio, ratio_col, yokoya_file["dipx"]) + yokyquad = np.interp(ratio, ratio_col, yokoya_file["quady"]) + yokxquad = np.interp(ratio, ratio_col, yokoya_file["quadx"]) + else: + yokxdip = np.interp(ratio, ratio_col, yokoya_file["dipy"]) + yokydip = np.interp(ratio, ratio_col, yokoya_file["dipx"]) + yokxquad = np.interp(ratio, ratio_col, yokoya_file["quady"]) + yokyquad = np.interp(ratio, ratio_col, yokoya_file["quadx"]) + + return (yoklong, yokxdip, yokydip, yokxquad, yokyquad) + +def beam_loss_factor(impedance, frequency, spectrum, ring): + """ + Compute "beam" loss factor using the beam spectrum, uses a sum instead of + integral compared to loss_factor [1]. + + Parameters + ---------- + impedance : Impedance of type "long" + frequency : array + Sample points of spectrum. + spectrum : array + Beam spectrum to consider. + ring : Synchrotron object + + Returns + ------- + kloss_beam : float + Beam loss factor in [V/C]. + + References + ---------- + [1] : Handbook of accelerator physics and engineering, 3rd printing. + Eq (3) p239. + """ + pmax = np.floor(impedance.data.index.max()/ring.f0) + pmin = np.floor(impedance.data.index.min()/ring.f0) + + if pmin >= 0: + # Add negative part + negative_index = impedance.data.index*-1 + negative_data = impedance.data.set_index(negative_index) + negative_data["imag"] = -1*negative_data["imag"] + try: + negative_data = negative_data.drop(0) + except KeyError: + pass + + all_data = impedance.data.append(negative_data) + all_data = all_data.sort_index() + impedance.data = all_data + + pmin = -1*pmax + + p = np.arange(pmin+1,pmax) + pf0 = p*ring.f0 + ReZ = np.real(impedance(pf0)) + spectral_density = np.abs(spectrum)**2 + # interpolation of the spectrum is needed to avoid problems liked to + # division by 0 + # computing the spectrum directly to the frequency points gives + # wrong results + spect = interp1d(frequency, spectral_density) + kloss_beam = ring.f0 * np.sum(ReZ*spect(pf0)) + + return kloss_beam \ No newline at end of file diff --git a/machines/__init__.py b/machines/__init__.py deleted file mode 100644 index c67145e..0000000 --- a/machines/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Tue Jan 14 18:11:33 2020 - -@author: gamelina -""" - diff --git a/machines/soleil.py b/machines/soleil.py deleted file mode 100644 index c8ac723..0000000 --- a/machines/soleil.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -""" -SOLEIL synchrotron parameters script. - -@author: Alexis Gamelin -@date: 14/01/2020 -""" - -import numpy as np -from tracking.synchrotron import Synchrotron -from tracking.optics import Optics -from tracking.particles import Electron, Beam - -def soleil(mode = 'Uniform'): - """ - - """ - - h = 416 - L = 3.540969742590899e+02 - E0 = 2.75e9 - particle = Electron() - ac = 1.47e-4 - U0 = 0.310e6 - tau = np.array([6.56e-3, 6.56e-3, 3.27e-3]) - tune = np.array([18.15687, 10.22824, 0.00502]) - emit = np.array([4.5e-9, 4.5e-9*0.01]) - sigma_0 = 8e-12 - sigma_delta = 8.6e-4 - chro = [2,3] - - # mean values - beta = np.array([3, 1.3]) - alpha = np.array([0, 0]) - dispersion = np.array([0, 0, 0, 0]) - optics = Optics(local_beta=beta, local_alpha=alpha, - local_dispersion=dispersion) - - ring = Synchrotron(h, optics, particle, L=L, E0=E0, ac=ac, U0=U0, tau=tau, - emit=emit, tune=tune, sigma_delta=sigma_delta, - sigma_0=sigma_0, chro=chro) - - return ring - -def v0313(): - """ - - """ - - h = 416 - particle = Electron() - tau = np.array([7.3e-3, 13.1e-3, 11.7e-3]) - emit = np.array([53.47e-12, 53.47e-12]) - sigma_0 = 9.2e-12 - sigma_delta = 9e-4 - - lattice_file = "SOLEIL_U_74BA_HOA_SYM02_V0313_cleaned.mat" - optics = Optics(lattice_file=lattice_file) - - ring = Synchrotron(h, optics, particle, tau=tau, emit=emit, - sigma_0=sigma_0, sigma_delta=sigma_delta) - - return ring \ No newline at end of file diff --git a/plotting.py b/plotting.py deleted file mode 100644 index f03c40e..0000000 --- a/plotting.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Running script to test getplot method in Bunch class, particles module - -@author: Watanyu Foosang -@date: 27/03/2020 -""" - -import numpy as np -import matplotlib.pyplot as plt -import seaborn as sns -import pandas as pd -from tracking.particles import Bunch, Beam -from machines.soleil import soleil -from tracking.rf import * -from scipy.constants import e - -ring = soleil() # Define the properties of the storage ring -mybunch = Bunch(ring,mp_number=1000,current=1e-3) # Define bunch parameters - -mybunch.init_gaussian() # Initialize 6D bunch parameters - - -v_rf = 1.1e6 # RF peak voltage [v] -sync_phase = np.arccos(ring.U0/v_rf) # Determine the synchronous phase - -rf = RFCavity(ring, m=1, Vc=v_rf, theta=sync_phase) - -rev = [] -mean_tau = [] -mean_delta = [] -def track_long(bunch,ring,rf,turn): - """ - Track longitudinal beam parameters for one turn - """ - - rf.track(bunch) # update "delta" for one turn - bunch.particles["tau"] = bunch.particles["tau"] - bunch.particles["delta"]\ - *ring.T0*ring.ac - turn += 1 - rev.append(turn) - mean_tau.append(bunch.particles["tau"].mean()) - mean_delta.append(bunch.particles["delta"].mean()) - return turn - -def get_meanplot(ini,fin,step,val): - """ - Plot the evolution of a mean value over turns. - (For now, this function only works subject to plotting module.) - - Parameters - ---------- - ini: int, starting revolution - fin: int, final revolution - step: int, step size on the revolution axis - val: str, "tau" for maen values of tau or "del" for mean values of delta - - """ - - x = rev[ini-1:fin:step] - - if val == "tau": - val = mean_tau[ini-1:fin:step] - else: val = mean_delta[ini-1:fin:step] - - plt.plot(x,val) - - - - - - - - diff --git a/tracking/__init__.py b/tracking/__init__.py index c67145e..45db001 100644 --- a/tracking/__init__.py +++ b/tracking/__init__.py @@ -5,3 +5,14 @@ Created on Tue Jan 14 18:11:33 2020 @author: gamelina """ +from mbtrack2.tracking.particles import (Electron, Proton, Bunch, Beam, + Particle) +from mbtrack2.tracking.synchrotron import Synchrotron +from mbtrack2.tracking.rf import RFCavity +from mbtrack2.tracking.parallel import Mpi +from mbtrack2.tracking.optics import Optics, PhyisicalModel +from mbtrack2.tracking.element import (Element, LongitudinalMap, + TransverseMap, SynchrotronRadiation) +from mbtrack2.tracking.aperture import (CircularAperture, ElipticalAperture, + RectangularAperture) + diff --git a/tracking/aperture.py b/tracking/aperture.py index 4cba4b3..1771845 100644 --- a/tracking/aperture.py +++ b/tracking/aperture.py @@ -7,7 +7,7 @@ This module defines aperture elements for tracking. """ import numpy as np -from tracking.element import Element +from mbtrack2.tracking.element import Element class CircularAperture(Element): """ diff --git a/tracking/element.py b/tracking/element.py index bee031c..8692856 100644 --- a/tracking/element.py +++ b/tracking/element.py @@ -11,7 +11,7 @@ included in the tracking. import numpy as np from abc import ABCMeta, abstractmethod from functools import wraps -from tracking.particles import Beam +from mbtrack2.tracking.particles import Beam class Element(metaclass=ABCMeta): """ diff --git a/tracking/monitors/__init__.py b/tracking/monitors/__init__.py index c67145e..028472c 100644 --- a/tracking/monitors/__init__.py +++ b/tracking/monitors/__init__.py @@ -5,3 +5,9 @@ Created on Tue Jan 14 18:11:33 2020 @author: gamelina """ +from mbtrack2.tracking.monitors.monitors import (Monitor, BunchMonitor, + PhaseSpaceMonitor, + BeamMonitor, + ProfileMonitor) +from mbtrack2.tracking.monitors.plotting import (plot_bunchdata, + plot_phasespacedata) \ No newline at end of file diff --git a/tracking/monitors/monitors.py b/tracking/monitors/monitors.py index e623465..c7c6ac8 100644 --- a/tracking/monitors/monitors.py +++ b/tracking/monitors/monitors.py @@ -10,8 +10,8 @@ during tracking. import numpy as np import h5py as hp -from tracking.element import Element -from tracking.particles import Bunch, Beam +from mbtrack2.tracking.element import Element +from mbtrack2.tracking.particles import Bunch, Beam from abc import ABCMeta from mpi4py import MPI diff --git a/tracking/particles.py b/tracking/particles.py index cb4c046..d3e7f17 100644 --- a/tracking/particles.py +++ b/tracking/particles.py @@ -10,7 +10,7 @@ Module where particles, bunches and beams are described as objects. import numpy as np import pandas as pd import matplotlib.pyplot as plt -from tracking.parallel import Mpi +from mbtrack2.tracking.parallel import Mpi import seaborn as sns from scipy.constants import c, m_e, m_p, e diff --git a/tracking/rf.py b/tracking/rf.py index 24928d3..451d220 100644 --- a/tracking/rf.py +++ b/tracking/rf.py @@ -7,7 +7,7 @@ This module handles radio-frequency (RF) cavitiy elements. """ import numpy as np -from tracking.element import Element +from mbtrack2.tracking.element import Element class RFCavity(Element): """ -- GitLab