def track(self, beam): '''Add the transverse space charge contribution to the beam's transverse kicks. ''' slices = beam.get_slices( self.slicer, statistics=["mean_x", "mean_y", "sigma_x", "sigma_y"]) prefactor = (beam.charge * self.length / (beam.p0 * beam.betagamma * beam.gamma * c)) # Nlambda_i is the line density [Coul/m] for the current slice for s_i, (Nlambda_i, mean_x, mean_y, sig_x, sig_y) in enumerate( zip( slices.lambda_bins(smoothen=False) / slices.slice_widths, slices.mean_x, slices.mean_y, slices.sigma_x, slices.sigma_y)): p_id = slices.particle_indices_of_slice(s_i) if len(p_id) == 0: continue en_x, en_y = self.get_efieldn(pm.take(beam.x, p_id), pm.take(beam.y, p_id), mean_x, mean_y, sig_x, sig_y) kicks_x = (en_x * Nlambda_i) * prefactor kicks_y = (en_y * Nlambda_i) * prefactor kicked_xp = pm.take(beam.xp, p_id) + kicks_x kicked_yp = pm.take(beam.yp, p_id) + kicks_y pm.put(beam.xp, p_id, kicked_xp) pm.put(beam.yp, p_id, kicked_yp)
def apply(self, bunch, slice_set_list, slice_set_age_list): """Calculate and apply a quadrupolar (cross term y-x) wake kick to bunch.yp using the given slice_set. Only particles within the slicing region, i.e particles_within_cuts (defined by the slice_set) experience the kick. """ times_list = [s.convert_to_time(s.z_centers) for s in slice_set_list] betas_list = [s.beta for s in slice_set_list] moments_list = [s.n_macroparticles_per_slice for s in slice_set_list] quadrupole_kick_yx = self._accumulate_source_signal( bunch, times_list, slice_set_age_list, moments_list, betas_list) p_idx = slice_set_list[0].particles_within_cuts_slice s_idx = pm.take(slice_set_list[0].slice_index_of_particle, p_idx) bunch.yp[p_idx] += pm.take(quadrupole_kick_yx, s_idx) * bunch.x[p_idx]