def __init__(self, GeneralParameters, n_macroparticles, theta_coordinate_range, FullRingAndRF, TotalInducedVoltage = None): #: *Number of macroparticles used in the synchrotron_frequency_tracker method* self.n_macroparticles = int(n_macroparticles) #: *Copy of the input FullRingAndRF object to retrieve the accelerator programs* self.FullRingAndRF = copy.deepcopy(FullRingAndRF) #: *Copy of the input TotalInducedVoltage object to retrieve the intensity effects #: (the synchrotron_frequency_tracker particles are not contributing to the #: induced voltage).* self.TotalInducedVoltage = None if TotalInducedVoltage is not None: self.TotalInducedVoltage = TotalInducedVoltage intensity = TotalInducedVoltage.slices.Beam.intensity else: intensity = 0. from beams.beams import Beam #: *Beam object containing the same physical information as the real beam, #: but containing only the coordinates of the particles for which the #: synchrotron frequency are computed.* self.Beam = Beam(GeneralParameters, n_macroparticles, intensity) # Generating the distribution from the user input if len(theta_coordinate_range) == 2: self.Beam.dt = np.linspace(theta_coordinate_range[0], theta_coordinate_range[1], n_macroparticles) * (self.Beam.ring_radius/(self.Beam.beta*c)) else: if len(theta_coordinate_range) != n_macroparticles: raise RuntimeError('The input n_macroparticles does not match with the length of the theta_coordinates') else: self.Beam.dt = np.array(theta_coordinate_range) * (self.Beam.ring_radius/(self.Beam.beta*c)) self.Beam.dE = np.zeros(int(n_macroparticles)) for RFsection in self.FullRingAndRF.RingAndRFSection_list: RFsection.beam = self.Beam #: *Revolution period in [s]* self.timeStep = GeneralParameters.t_rev[0] #: *Number of turns of the simulation (+1 to include the input parameters)* self.nTurns = GeneralParameters.n_turns+1 #: *Saving the theta coordinates of the particles while tracking* self.theta_save = np.zeros((self.nTurns, int(n_macroparticles))) #: *Saving the dE coordinates of the particles while tracking* self.dE_save = np.zeros((self.nTurns, int(n_macroparticles))) #: *Tracking counter* self.counter = 0 # The first save coordinates are the input coordinates self.theta_save[self.counter] = self.Beam.dt / (self.Beam.ring_radius/(self.Beam.beta*c)) self.dE_save[self.counter] = self.Beam.dE
# DEFINE RING------------------------------------------------------------------ n_turns = 1 general_params = GeneralParameters(n_turns, C, momentum_compaction, sync_momentum, particle_type, number_of_sections=1) RF_sct_par = RFSectionParameters(general_params, n_rf_systems, harmonic_numbers, voltage_program, phi_offset) # DEFINE BEAM------------------------------------------------------------------ beam = Beam(general_params, n_macroparticles, n_particles) # DEFINE TRACKER--------------------------------------------------------------- longitudinal_tracker = RingAndRFSection(RF_sct_par, beam) full_tracker = FullRingAndRF([longitudinal_tracker]) # DEFINE SLICES---------------------------------------------------------------- number_slices = 500 slice_beam = Slices(RF_sct_par, beam, number_slices, cut_left=0., cut_right=bucket_length) # Single RF -------------------------------------------------------------------
alpha = 1. / gamma_t / gamma_t # First order mom. comp. factor # Tracking details N_t = 2000 # Number of turns to track dt_plt = 200 # Time steps between plots # Simulation setup ------------------------------------------------------------ print("Setting up the simulation...") print("") # Define general parameters general_params = GeneralParameters(N_t, C, alpha, np.linspace(p_i, p_f, 2001), 'proton') # Define beam and distribution beam = Beam(general_params, N_p, N_b) # Define RF station parameters and corresponding tracker rf_params = RFSectionParameters(general_params, 1, h, V, dphi) long_tracker = RingAndRFSection(rf_params, beam) longitudinal_bigaussian(general_params, rf_params, beam, tau_0 / 4, reinsertion='on', seed=1) # Need slices for the Gaussian fit slice_beam = Slices(rf_params, beam, 100, fit_option='gaussian')