From 235dbca86a30924bd06e414e767c117161ccadd7 Mon Sep 17 00:00:00 2001 From: Gamelin Alexis <gamelin@synchrotron-soleil.fr> Date: Fri, 14 Feb 2020 16:59:28 +0100 Subject: [PATCH] Change how empty bunches are dealed with Empty bunches are now not None any more but represented by Bunch class with 1 mp set to dead Change init_beam to reflect the change --- Tracking/beam.py | 95 ++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/Tracking/beam.py b/Tracking/beam.py index a28bfd4..9fde0f4 100644 --- a/Tracking/beam.py +++ b/Tracking/beam.py @@ -21,7 +21,8 @@ class Bunch: Macro-particle number current : float, optional Bunch current in [A] - + alive : bool, optional + If False, the bunch is defined as empty Attributes ---------- mp_number : int @@ -44,19 +45,26 @@ class Bunch: Initialize bunch particles with 6D gaussian phase space. """ - def __init__(self, ring, mp_number=1e3, current=1e-3): - particles = {"x":np.zeros((int(mp_number),)), - "xp":np.zeros((int(mp_number),)), - "y":np.zeros((int(mp_number),)), - "yp":np.zeros((int(mp_number),)), - "tau":np.zeros((int(mp_number),)), - "delta":np.zeros((int(mp_number),)), - } - self.particles = pd.DataFrame(particles) - self.alive = pd.Series(np.ones((int(mp_number),),dtype=bool)) + def __init__(self, ring, mp_number=1e3, current=1e-3, alive=True): + self.ring = ring + if not alive: + mp_number = 1 + current = 0 self._mp_number = int(mp_number) + + particles = {"x":np.zeros((self.mp_number,)), + "xp":np.zeros((self.mp_number,)), + "y":np.zeros((self.mp_number,)), + "yp":np.zeros((self.mp_number,)), + "tau":np.zeros((self.mp_number,)), + "delta":np.zeros((self.mp_number,)), + } + self.particles = pd.DataFrame(particles) + self.alive = pd.Series(np.ones((self.mp_number,),dtype=bool)) self.current = current + if not alive: + self.alive = pd.Series(np.zeros((self.mp_number,),dtype=bool)) def __len__(self): """Return the number of alive particles""" @@ -256,10 +264,10 @@ class Beam: self.bunch_list = bunch_list def __len__(self): - """Return the number of bunches""" + """Return the number of (not empty) bunches""" length = 0 for bunch in self: - if bunch is not None: + if bunch.current != 0: length += 1 return length @@ -278,15 +286,22 @@ class Beam: def init_beam(self, filling_pattern, current_per_bunch=1e-3, mp_per_bunch=1e3): """ - Initialize beam with a given filling pattern but with uniform current - per bunch and marco-particle number per bunch. + Initialize beam with a given filling pattern and marco-particle number + per bunch. Then initialize the different bunches with a 6D gaussian + phase space. + + If the filling pattern is an array of bool then the current per bunch + is uniform, else the filling pattern can be an array with the current + in each bunch. Parameters ---------- filling_pattern : numpy array or list of length ring.h - Filling pattern of the beam, - charge_per_bunch : float, optional - Charge per bunch in [C] + Filling pattern of the beam, can be a list or an array of bool, + then current_per_bunch is used. Or can be an array with the current + in each bunch. + current_per_bunch : float, optional + Current per bunch in [A] mp_per_bunch : float, optional Macro-particle number per bunch """ @@ -295,24 +310,34 @@ class Beam: raise ValueError(("The length of filling pattern is {} ".format(len(filling_pattern)) + "but should be {}".format(self.ring.h))) + filling_pattern = np.array(filling_pattern) bunch_list = [] - for value in filling_pattern: - if value == True: - bunch_list.append(Bunch(self.ring, mp_per_bunch, current_per_bunch)) - elif value == False: - bunch_list.append(None) - else: - raise ValueError("{} should be True or False".format(value)) + if filling_pattern.dtype == np.dtype("bool"): + for value in filling_pattern: + if value == True: + bunch_list.append(Bunch(self.ring, mp_per_bunch, current_per_bunch)) + elif value == False: + bunch_list.append(Bunch(self.ring, alive=False)) + elif filling_pattern.dtype == np.dtype("float64"): + for current in filling_pattern: + if current != 0: + bunch_list.append(Bunch(self.ring, mp_per_bunch, current)) + elif current == 0: + bunch_list.append(Bunch(self.ring, alive=False)) + else: + raise TypeError("{} should be bool or float64".format(filling_pattern.dtype)) + self.bunch_list = bunch_list - # init bunches => gauss + + for bunch in self: + bunch.init_gaussian() @property def current(self): """Total beam current in [A]""" current = 0 for bunch in self: - if bunch is not None: - current += bunch.current + current += bunch.current return current @property @@ -320,8 +345,7 @@ class Beam: """Total beam charge in [C]""" charge = 0 for bunch in self: - if bunch is not None: - charge += bunch.charge + charge += bunch.charge return charge @property @@ -329,18 +353,17 @@ class Beam: """Total number of particle in the beam""" particle_number = 0 for bunch in self: - if bunch is not None: - particle_number += bunch.particle_number + particle_number += bunch.particle_number return particle_number @property def filling_pattern(self): - """Filling pattern of the beam""" + """Return an array with the filling pattern of the beam as bool""" filling_pattern = [] for bunch in self: - if isinstance(bunch, Bunch): + if filling_pattern != 0: filling_pattern.append(True) else: filling_pattern.append(False) - return filling_pattern - \ No newline at end of file + return np.array(filling_pattern) + -- GitLab