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

Rework ImpedanceModel

Simplify and optimize adding element into ImpedanceModel.
parent 58370b5b
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ import pandas as pd ...@@ -6,6 +6,7 @@ import pandas as pd
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pickle import pickle
from copy import deepcopy
from scipy.integrate import trapz from scipy.integrate import trapz
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
from mpl_toolkits.axes_grid1.inset_locator import inset_axes from mpl_toolkits.axes_grid1.inset_locator import inset_axes
...@@ -14,52 +15,43 @@ from mbtrack2.utilities.misc import (beam_loss_factor, effective_impedance, ...@@ -14,52 +15,43 @@ from mbtrack2.utilities.misc import (beam_loss_factor, effective_impedance,
from mbtrack2.utilities.spectrum import (beam_spectrum, from mbtrack2.utilities.spectrum import (beam_spectrum,
gaussian_bunch_spectrum, gaussian_bunch_spectrum,
spectral_density) spectral_density)
from mbtrack2.impedance.wakefield import WakeField
from mbtrack2.tracking.element import Element
class ImpedanceModel(Element): class ImpedanceModel():
""" """
Define the impedance model of the machine. Define the impedance model of the machine.
The model must be completed with successive add(...) calls, then
compute_sum() must be run.
Parameters Parameters
---------- ----------
ring : Synchrotron object ring : Synchrotron object
wakefield_list : list of WakeField objects
WakeFields to add to the model.
wakefiled_positions : list
Longitudinal positions corresponding to the added Wakfields.
Attributes Attributes
---------- ----------
wakefields : list of WakeField objects wakefields : list of WakeField objects
WakeFields in the model. WakeFields in the model.
positions : array positions : list of arrays
WakeFields positions. Positions corresponding the different WakeFields.
names : array names : list of str
Names of (unique) WakeField objects. Names of the WakeField objects.
sum : WakeField sum : WakeField
Sum of every WakeField in the model. Sum of every WakeField in the model weigthed by beta functions.
sum_"name" : WakeField sum_"name" : WakeField
Sum of every Wakefield with the same "name". Sum of the "name" Wakefield weigthed by beta functions.
sum_names : array sum_names : array
Names of attributes where the WakeFields are summed by name. Names of attributes where the WakeFields are summed by name.
Methods Methods
------- -------
add(wakefield_list, wakefiled_positions) add(wakefield, positions, name)
Add elements to the model. Add the same WakeField object at different locations to the model.
add_multiple_elements(wakefield, wakefiled_positions) sum_beta(wake, beta)
Add the same element at different locations to the model. Weight a WakeField object by an array of beta functions.
sum_elements() compute_sum_names()
Sum all WakeFields into self.sum. Compute the weighted WakeField for each WakeField object type.
update_name_list() compute_sum()
Update self.names with uniques names of self.wakefields. Compute the sum of all weighted WakeField into self.sum.
find_wakefield(name)
Return indexes of WakeFields with the same name in self.wakefields.
sum_by_name(name)
Sum the elements with the same name in the model into sum_name.
sum_by_name_all(name)
Sum all the elements with the same name in the model into sum_name.
plot_area(Z_type="Zlong", component="real", sigma=None, attr_list=None) plot_area(Z_type="Zlong", component="real", sigma=None, attr_list=None)
Plot the contributions of different kind of WakeFields. Plot the contributions of different kind of WakeFields.
save(file) save(file)
...@@ -68,132 +60,101 @@ class ImpedanceModel(Element): ...@@ -68,132 +60,101 @@ class ImpedanceModel(Element):
Load impedance model from file. Load impedance model from file.
""" """
def __init__(self, ring, wakefield_list=None, wakefiled_positions=None): def __init__(self, ring):
self.ring = ring self.ring = ring
self.optics = self.ring.optics self.optics = self.ring.optics
self.wakefields = [] self.wakefields = []
self.positions = np.array([]) self.positions = []
self.names = np.array([]) self.names = []
self.sum_names = np.array([]) self.sum_names = []
self.add(wakefield_list, wakefiled_positions)
def add(self, wakefield, positions, name=None):
def track(self, beam):
""" """
Track a beam object through this Element. Add the same WakeField object at different locations to the model.
Parameters Parameters
---------- ----------
beam : Beam object wakefield : WakeField
WakeField object to add to the model.
positions : array, float or int
Array of longitudinal positions where the elements are loacted.
name : str, optional
Name of the element type. If None, the name of the WakeField object
is used. The default is None.
Returns
-------
None.
""" """
raise NotImplementedError self.wakefields.append(wakefield)
self.positions.append(positions)
def sum_elements(self): if name is None:
"""Sum all WakeFields into self.sum""" name = wakefield.name
beta = self.optics.beta(self.positions) if name is None:
self.sum = WakeField.add_several_wakefields(self.wakefields, beta) raise ValueError("Please give a valid name.")
if "sum" not in self.sum_names: if name not in self.names:
self.sum_names = np.append(self.sum_names, "sum") self.names.append(name)
else:
def update_name_list(self): raise ValueError("This name is already taken.")
"""Update self.names with uniques names of self.wakefields."""
for wakefield in self.wakefields: @staticmethod
if wakefield.name is None: def sum_beta(wake, beta):
continue
if wakefield.name not in self.names:
self.names = np.append(self.names, wakefield.name)
def count_elements(self):
"""Count number of each type of WakeField in the model."""
self.count = np.zeros(len(self.names))
for wakefield in self.wakefields:
if wakefield.name is not None:
self.count += (wakefield.name == self.names).astype(int)
def find_wakefield(self, name):
""" """
Return indexes of WakeFields with the same name in self.wakefields. Weight a WakeField object by an array of beta functions.
Parameters Parameters
---------- ----------
name : str wake : WakeField
WakeField name. WakeField element object.
beta : array of shape (2, N)
Beta function at the locations of the elements.
Returns Returns
------- -------
index : list wake_sum : WakeField
Index of positions in self.wakefields. WakeField object weighted by beta functions.
""" """
index = [] wake_sum = deepcopy(wake)
for i, wakefield in enumerate(self.wakefields): for component_name in wake.components:
if wakefield.name == name: comp = getattr(wake_sum, component_name)
index.append(i) weight = ((beta[0,:] ** comp.power_x) *
return index (beta[1,:] ** comp.power_y))
setattr(wake_sum, component_name, weight.sum()*comp)
def sum_by_name(self, name): return wake_sum
"""
Sum the elements with the same name in the model into sum_name. def compute_sum_names(self):
Parameters
----------
name : str
Name of the WakeField to sum.
"""
attribute_name = "sum_" + name
index = self.find_wakefield(name)
beta = self.optics.beta(self.positions[index])
wakes = []
for i in index:
wakes.append(self.wakefields[i])
wake_sum = WakeField.add_several_wakefields(wakes, beta)
setattr(self, attribute_name, wake_sum)
if attribute_name not in self.sum_names:
self.sum_names = np.append(self.sum_names, attribute_name)
def sum_by_name_all(self):
"""
Sum all the elements with the same name in the model into sum_name.
""" """
for name in self.names: Compute the weighted WakeField for each WakeField object type.
self.sum_by_name(name) The new summed WakeField object are set to into self.sum_name.
def add(self, wakefield_list, wakefiled_positions):
""" """
Add elements to the model. for idx, wake in enumerate(self.wakefields):
attribute_name = "sum_" + self.names[idx]
Parameters beta = self.optics.beta(self.positions[idx])
---------- wake_sum = self.sum_beta(wake, beta)
wakefield_list : list of WakeField objects setattr(self, attribute_name, wake_sum)
WakeFields to add to the model. self.sum_names.append(attribute_name)
wakefiled_positions : list
Longitudinal positions corresponding to the added Wakfields. def compute_sum(self):
""" """
if (wakefield_list is not None) and (wakefiled_positions is not None): Compute the sum of all weighted WakeField into self.sum.
for wakefield in wakefield_list: self.compute_sum_names must be called before this.
self.wakefields.append(wakefield)
for position in wakefiled_positions:
self.positions = np.append(self.positions, position)
self.update_name_list()
def add_multiple_elements(self, wakefield, wakefiled_positions):
""" """
Add the same element at different locations to the model. self.compute_sum_names()
for i, name in enumerate(self.sum_names):
if i==0:
self.sum = deepcopy(getattr(self, name))
else:
wake2 = getattr(self, name)
for component_name2 in wake2.components:
comp2 = getattr(wake2, component_name2)
try:
comp1 = getattr(self.sum, component_name2)
setattr(self.sum, component_name2, comp1 + comp2)
except AttributeError:
setattr(self.sum, component_name2, comp2)
Parameters
----------
WakeField : WakeField object
WakeField to add to the model.
wakefiled_positions : list
Longitudinal positions corresponding to the added Wakfield.
"""
for position in wakefiled_positions:
self.positions = np.append(self.positions, position)
self.wakefields.append(wakefield)
self.update_name_list()
def plot_area(self, Z_type="Zlong", component="real", sigma=None, def plot_area(self, Z_type="Zlong", component="real", sigma=None,
attr_list=None, zoom=False): attr_list=None, zoom=False):
""" """
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment