def setUp(self): # Bunch parameters # ----------------- N_turn = 200 N_b = 1e9 # Intensity N_p = int(2e6) # Macro-particles # Machine parameters # -------------------- C = 6911.5038 # Machine circumference [m] p = 450e9 # Synchronous momentum [eV/c] gamma_t = 17.95142852 # Transition gamma alpha = 1./gamma_t**2 # First order mom. comp. factor # Define general parameters # -------------------------- self.general_params = Ring(C, alpha, p, Proton(), N_turn) # Define beam # ------------ self.beam = Beam(self.general_params, N_p, N_b) # Define RF section # ----------------- self.rf_params = RFStation(self.general_params, [4620], [7e6], [0.])
def setUp(self): self.general_params = Ring(np.ones(self.n_sections) * self.C/self.n_sections, np.tile(self.momentum_compaction, (1, self.n_sections)).T, np.tile(self.sync_momentum, (self.n_sections, self.n_turns+1)), self.particle_type, self.n_turns, n_sections=self.n_sections) self.RF_sct_par = [] self.RF_sct_par_cpp = [] for i in np.arange(self.n_sections)+1: self.RF_sct_par.append(RFStation(self.general_params, [self.harmonic_numbers], [ self.voltage_program/self.n_sections], [self.phi_offset], self.n_rf_systems, section_index=i)) self.RF_sct_par_cpp.append(RFStation(self.general_params, [self.harmonic_numbers], [ self.voltage_program/self.n_sections], [self.phi_offset], self.n_rf_systems, section_index=i)) # DEFINE BEAM------------------------------------------------------------------ self.beam = Beam(self.general_params, self.n_macroparticles, self.n_particles) self.beam_cpp = Beam(self.general_params, self.n_macroparticles, self.n_particles) # DEFINE SLICES---------------------------------------------------------------- number_slices = 500 cut_options = CutOptions( cut_left=0., cut_right=self.bucket_length, n_slices=number_slices) self.slice_beam = Profile(self.beam, CutOptions=cut_options) self.slice_beam_cpp = Profile(self.beam_cpp, CutOptions=cut_options) # DEFINE TRACKER--------------------------------------------------------------- self.longitudinal_tracker = [] self.longitudinal_tracker_cpp = [] for i in range(self.n_sections): self.longitudinal_tracker.append(RingAndRFTracker( self.RF_sct_par[i], self.beam, Profile=self.slice_beam)) self.longitudinal_tracker_cpp.append(RingAndRFTracker( self.RF_sct_par_cpp[i], self.beam_cpp, Profile=self.slice_beam_cpp)) full_tracker = FullRingAndRF(self.longitudinal_tracker) full_tracker_cpp = FullRingAndRF(self.longitudinal_tracker_cpp) # BEAM GENERATION-------------------------------------------------------------- matched_from_distribution_function(self.beam, full_tracker, emittance=self.emittance, distribution_type=self.distribution_type, distribution_variable=self.distribution_variable, seed=1000) matched_from_distribution_function(self.beam_cpp, full_tracker_cpp, emittance=self.emittance, distribution_type=self.distribution_type, distribution_variable=self.distribution_variable, seed=1000) self.slice_beam.track() self.slice_beam_cpp.track()
def test_addition(self): np = numpy testdEs = np.linspace(-1E6, 1E6, 2000000) testdts = np.linspace(0, 10E-9, 2000000) self.beam.dE = testdEs self.beam.dt = testdts testdEs = np.linspace(-2E6, 2E6, 100000) testdts = np.linspace(-1E-9, 12E-9, 100000) self.beam.add_particles([testdts, testdEs]) self.assertEqual(self.beam.n_macroparticles, 2100000, msg="n_macroparticles not incremented correctly") testBeam = Beam(self.general_params, 200, 0) testBeam.id[:100] = 0 self.beam.add_beam(testBeam) self.assertEqual(self.beam.id[2100000:2100100].tolist(), [0]*100, msg="particle ids not applied correctly") self.assertEqual(self.beam.n_macroparticles, 2100200, msg="Added macroparticles not incremented n_macro correctly") self.beam += testBeam self.assertEqual(self.beam.n_macroparticles, 2100400, msg="Added macroparticles not incremented n_macro correctly") self.beam += (testdts, testdEs) self.assertEqual(self.beam.n_macroparticles, 2200400, msg="Added macroparticles not incremented n_macro correctly") self.assertEqual(-2E6, np.min(self.beam.dE), msg="coordinates of added beam not used correctly") self.assertEqual(2E6, np.max(self.beam.dE), msg="coordinates of added beam not used correctly") self.assertEqual(-1E-9, np.min(self.beam.dt), msg="coordinates of added beam not used correctly") self.assertEqual(12E-9, np.max(self.beam.dt), msg="coordinates of added beam not used correctly") with self.assertRaises(blExcept.ParticleAdditionError, msg="""Unequal length time and energy should raise exception"""): self.beam += ([1, 2, 3], [4, 5]) with self.assertRaises(blExcept.ParticleAdditionError, msg="""Mising time/energy should raise exception"""): self.beam += ([1, 2, 3]) with self.assertRaises(TypeError, msg='Wrong type should raise exception'): self.beam.add_beam(([1], [2]))
def run_simple(self): self.ring = Ring(self.C, self.alpha_0, self.Ek, Proton(), self.N_t, synchronous_data_type='kinetic energy', alpha_1=None, alpha_2=None) self.beam = Beam(self.ring, self.N_p, self.N_b) self.rf = RFStation(self.ring, 1, 0, np.pi) original_distribution_dt = np.zeros(self.beam.n_macroparticles) original_distribution_dE = np.linspace( -0.1*self.beam.energy, 0.1*self.beam.energy, self.beam.n_macroparticles) self.beam.dt[:] = np.array(original_distribution_dt) self.beam.dE[:] = np.array(original_distribution_dE) self.long_tracker = RingAndRFTracker( self.rf, self.beam, solver='simple') for i in range(self.ring.n_turns): self.long_tracker.track() original_distribution_dt += self.ring.n_turns * linear_drift( original_distribution_dE, self.ring.eta_0[0, 0], self.ring.beta[0, 0], self.ring.energy[0, 0], self.ring.t_rev[0]) return self.beam.dt, original_distribution_dt, original_distribution_dE
def setUp(self): circumference = 110.4 # [m] energy = 2.5e9 # [eV] alpha = 0.0082 self.R_bend = 5.559 # bending radius [m] # C_gamma = e**2 / (3*epsilon_0 * (m_e*c**2)**4) # [m J^3] # C_gamma *= e**3 # [m eV^3] harmonic_number = 184 voltage = 800e3 # eV phi_offsets = 0 self.seed = 1234 self.intensity = 2.299e9 self.n_macroparticles = int(1e2) self.sigma_dt = 10e-12 # RMS, [s] self.ring = Ring(circumference, alpha, energy, Positron(), synchronous_data_type='total energy', n_turns=1) self.rf_station = RFStation(self.ring, harmonic_number, voltage, phi_offsets, n_rf=1) self.beam = Beam(self.ring, self.n_macroparticles, self.intensity) bigaussian(self.ring, self.rf_station, self.beam, self.sigma_dt, seed=self.seed)
def setUp(self): initial_time = 0 final_time = 1E-3 # Machine and RF parameters radius = 25 gamma_transition = 4.4 # [1] C = 2 * np.pi * radius # [m] momentum_compaction = 1 / gamma_transition**2 # [1] particle_type = 'proton' self.ring = Ring(C, momentum_compaction, \ ([0, 1E-3], [3.13E8, 3.13E8]), Proton()) self.rf_params = RFStation(self.ring, [1], [1E3], [np.pi], 1) self.beam = Beam(self.ring, 1, 0) self.profile = Profile(self.beam) self.long_tracker = RingAndRFTracker(self.rf_params, self.beam) self.full_ring = FullRingAndRF([self.long_tracker]) self.n_turns = self.ring.n_turns self.map_ = [self.full_ring.track, self.profile.track] self.trackIt = TrackIteration(self.map_)
def test_synchrotron_radiation_python_vs_C_double_kick(self): atol = 0 rtol = 1e-7 iSR = SynchrotronRadiation(self.ring, self.rf_station, self.beam, self.R_bend, n_kicks=2, shift_beam=False, python=True, quantum_excitation=False, seed=self.seed) iSR.track() # Python implementation beam_C = Beam(self.ring, self.n_macroparticles, self.intensity) bigaussian(self.ring, self.rf_station, beam_C, self.sigma_dt, seed=self.seed) iSR = SynchrotronRadiation(self.ring, self.rf_station, beam_C, self.R_bend, n_kicks=2, shift_beam=False, python=False, quantum_excitation=False, seed=self.seed) iSR.track() # C implementation np.testing.assert_allclose([np.mean(self.beam.dE)], [np.mean(beam_C.dE)], atol=atol, rtol=rtol, err_msg='Python anc C yield different avg beam.dE for two kicks') np.testing.assert_allclose([np.std(self.beam.dE)], [np.std(beam_C.dE)], atol=atol, rtol=rtol, err_msg='Python anc C yield different std beam.dE for two kicks')
def test_4(self): # Create a batch of 100 equal, short bunches bunches = 100 T_s = 5 * self.rf.t_rev[0] / self.rf.harmonic[0, 0] N_m = int(1e5) N_b = 2.3e11 bigaussian(self.ring, self.rf, self.beam, 0.1e-9, seed=1234, reinsertion=True) beam2 = Beam(self.ring, bunches * N_m, bunches * N_b) bunch_spacing = 5 * self.rf.t_rf[0, 0] buckets = 5 * bunches for i in range(bunches): beam2.dt[i * N_m:(i + 1) * N_m] = self.beam.dt + i * bunch_spacing beam2.dE[i * N_m:(i + 1) * N_m] = self.beam.dE profile2 = Profile(beam2, CutOptions=CutOptions(cut_left=0, cut_right=bunches * bunch_spacing, n_slices=1000 * buckets)) profile2.track() tot_charges = np.sum(profile2.n_macroparticles)/\ beam2.n_macroparticles*beam2.intensity self.assertAlmostEqual(tot_charges, 2.3000000000e+13, 9) # Calculate fine- and coarse-grid RF current rf_current_fine, rf_current_coarse = rf_beam_current( profile2, self.rf.omega_rf[0, 0], self.ring.t_rev[0], lpf=False, downsample={ 'Ts': T_s, 'points': self.rf.harmonic[0, 0] / 5 }) rf_current_coarse /= T_s # Peak RF current on coarse grid peak_rf_current = np.max(np.absolute(rf_current_coarse)) self.assertAlmostEqual(peak_rf_current, 2.9285808008, 7)
def test_exact_order1and2_vs_expectation(self): self.ring = Ring(self.C, self.alpha_0, self.Ek, Proton(), self.N_t, synchronous_data_type='kinetic energy', alpha_1=self.alpha_1, alpha_2=self.alpha_2) self.beam = Beam(self.ring, self.N_p, self.N_b) self.rf = RFStation(self.ring, 1, 0, np.pi) original_distribution_dt = np.zeros(self.beam.n_macroparticles) original_distribution_dE = np.linspace(-0.1 * self.beam.energy, 0.1 * self.beam.energy, self.beam.n_macroparticles) self.beam.dt[:] = np.array(original_distribution_dt) self.beam.dE[:] = np.array(original_distribution_dE) self.long_tracker = RingAndRFTracker(self.rf, self.beam, solver='exact') # Forcing usage of legacy self.long_tracker.solver = 'exact' self.long_tracker.solver = self.long_tracker.solver.encode( encoding='utf_8') for i in range(self.ring.n_turns): self.long_tracker.track() original_distribution_dt += self.ring.n_turns * expected_drift( original_distribution_dE, self.ring.alpha_0[0, 0], self.ring.alpha_1[0, 0], self.ring.alpha_2[0, 0], self.ring.energy[0, 0], self.ring.t_rev[0], self.ring.ring_circumference, self.ring.Particle.mass) np.testing.assert_allclose(self.beam.dt, original_distribution_dt, rtol=relative_tolerance, atol=absolute_tolerance)
def setUp(self): self.ring = Ring(self.C, self.alpha, np.linspace(self.p_i, self.p_f, self.N_t + 1), Proton(), self.N_t) self.beam = Beam(self.ring, self.N_p, self.N_b) self.rf = RFStation(self.ring, [self.h], self.V * np.linspace(1, 1.1, self.N_t + 1), [self.dphi]) bigaussian(self.ring, self.rf, self.beam, self.tau_0 / 4, reinsertion=True, seed=1) self.profile = Profile( self.beam, CutOptions(n_slices=100, cut_left=0, cut_right=self.rf.t_rf[0, 0]), FitOptions(fit_option='gaussian')) self.long_tracker = RingAndRFTracker(self.rf, self.beam, Profile=self.profile)
def setUp(self): # Bunch parameters (dummy) N_b = 1e9 # Intensity N_p = 50000 # Macro-particles # Machine and RF parameters C = 26658.883 # Machine circumference [m] p_s = 450e9 # Synchronous momentum [eV/c] h = 35640 # Harmonic number V = 4e6 # RF voltage [V] dphi = 0 # Phase modulation/offset gamma_t = 53.8 # Transition gamma alpha = 1 / gamma_t**2 # First order mom. comp. factor # Initialise necessary classes ring = Ring(C, alpha, p_s, Particle=Proton(), n_turns=1) self.rf = RFStation(ring, [h], [V], [dphi]) beam = Beam(ring, N_p, N_b) self.profile = Profile(beam) # Test in open loop, on tune self.RFFB = LHCRFFeedback(open_drive=True) self.f_c = self.rf.omega_rf[0, 0] / (2 * np.pi)
def setUp(self): C = 2 * np.pi * 1100.009 # Ring circumference [m] gamma_t = 18.0 # Gamma at transition alpha = 1 / gamma_t**2 # Momentum compaction factor p_s = 25.92e9 # Synchronous momentum at injection [eV] N_m = 1e5 # Number of macro-particles for tracking N_b = 1.0e11 # Bunch intensity [ppb] # Set up machine parameters self.ring = Ring(C, alpha, p_s, Proton(), n_turns=1) # RF-frequency at which to compute beam current self.omega = 2 * np.pi * 200.222e6 # Create Gaussian beam self.beam = Beam(self.ring, N_m, N_b) self.profile = Profile(self.beam, CutOptions=CutOptions(cut_left=-1.e-9, n_slices=100, cut_right=6.e-9))
def setUp(self): n_turns = 200 intensity_pb = 1.2e6 # protons per bunch n_macroparticles = int(1e6) # macropartilces per bunch sigma = 0.05e-9 # sigma for gaussian bunch [s] self.time_offset = 0.1e-9 # time by which to offset the bunch # Ring parameters SPS C = 6911.5038 # Machine circumference [m] sync_momentum = 25.92e9 # SPS momentum at injection [eV/c] gamma_transition = 17.95142852 # Q20 Transition gamma momentum_compaction = 1./gamma_transition**2 # Momentum compaction array self.ring = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns=n_turns) # RF parameters SPS harmonic = 4620 # Harmonic numbers voltage = 4.5e6 # [V] phi_offsets = 0 self.rf_station = RFStation(self.ring, harmonic, voltage, phi_offsets) t_rf = self.rf_station.t_rf[0, 0] # Beam setup self.beam = Beam(self.ring, n_macroparticles, intensity_pb) bigaussian(self.ring, self.rf_station, self.beam, sigma, seed=1234, reinsertion=True) # displace beam to see effect of phase error and phase loop self.beam.dt += self.time_offset # Profile setup self.profile = Profile(self.beam, CutOptions=CutOptions(cut_left=0, cut_right=t_rf, n_slices=1024))
def run_expected_drift(self): self.ring = Ring(self.C, self.alpha_0, self.Ek, Proton(), self.N_t, synchronous_data_type='kinetic energy', alpha_1=self.alpha_1, alpha_2=self.alpha_2) self.beam = Beam(self.ring, self.N_p, self.N_b) self.rf = RFStation(self.ring, 1, 0, np.pi) original_distribution_dt = np.zeros(self.beam.n_macroparticles) original_distribution_dE = np.linspace( -0.1*self.beam.energy, 0.1*self.beam.energy, self.beam.n_macroparticles) original_distribution_dt += self.ring.n_turns * expected_drift( original_distribution_dE, self.ring.alpha_0[0, 0], self.ring.alpha_1[0, 0], self.ring.alpha_2[0, 0], self.ring.energy[0, 0], self.ring.t_rev[0], self.ring.ring_circumference, self.ring.Particle.mass) return original_distribution_dt, original_distribution_dE
def run_exact_order1and2(self): self.ring = Ring(self.C, self.alpha_0, self.Ek, Proton(), self.N_t, synchronous_data_type='kinetic energy', alpha_1=self.alpha_1, alpha_2=self.alpha_2) self.beam = Beam(self.ring, self.N_p, self.N_b) self.rf = RFStation(self.ring, 1, 0, np.pi) original_distribution_dt = np.zeros(self.beam.n_macroparticles) original_distribution_dE = np.linspace( -0.1*self.beam.energy, 0.1*self.beam.energy, self.beam.n_macroparticles) self.beam.dt[:] = np.array(original_distribution_dt) self.beam.dE[:] = np.array(original_distribution_dE) self.long_tracker = RingAndRFTracker( self.rf, self.beam, solver='exact') # Forcing usage of legacy self.long_tracker.solver = 'exact' self.long_tracker.solver = self.long_tracker.solver.encode( encoding='utf_8') for i in range(self.ring.n_turns): self.long_tracker.track() original_distribution_dt += self.ring.n_turns * exact_drift( original_distribution_dE, self.ring.alpha_0[0, 0], self.ring.alpha_1[0, 0], self.ring.alpha_2[0, 0], self.ring.beta[0, 0], self.ring.energy[0, 0], self.ring.t_rev[0]) return self.beam.dt, original_distribution_dt, original_distribution_dE
gamma_t = 55.759505 # Transition gamma alpha = 1. / gamma_t / gamma_t # First order mom. comp. factor # Tracking details N_t = 2000 # Number of turns to track dt_plt = int(sys.argv[2]) # Time steps between plots # Simulation setup ------------------------------------------------------------ print("Setting up the simulation...") print("") # Define general parameters ring = Ring(C, alpha, np.linspace(p_i, p_f, N_t + 1), Proton(), N_t) # Define beam and distribution beam = Beam(ring, N_p, N_b) # Define RF station parameters and corresponding tracker rf = RFStation(ring, [h], [V], [dphi]) long_tracker = RingAndRFTracker(rf, beam) bigaussian(ring, rf, beam, tau_0 / 4, reinsertion=True, seed=1) # Need slices for the Gaussian fit # profile = Profile(beam, CutOptions(n_slices=N_p//1000), # FitOptions(fit_option='gaussian')) # Define what to save in file # bunchmonitor = BunchMonitor(ring, rf, beam, # this_directory + '../output_files/EX_01_output_data', Profile=profile)
class testBeamClass(unittest.TestCase): # Run before every test def setUp(self): # Bunch parameters # ----------------- N_turn = 200 N_b = 1e9 # Intensity N_p = int(2e6) # Macro-particles # Machine parameters # -------------------- C = 6911.5038 # Machine circumference [m] p = 450e9 # Synchronous momentum [eV/c] gamma_t = 17.95142852 # Transition gamma alpha = 1./gamma_t**2 # First order mom. comp. factor # Define general parameters # -------------------------- self.general_params = Ring(C, alpha, p, Proton(), N_turn) # Define beam # ------------ self.beam = Beam(self.general_params, N_p, N_b) # Define RF section # ----------------- self.rf_params = RFStation(self.general_params, [4620], [7e6], [0.]) # Run after every test def tearDown(self): del self.general_params del self.beam del self.rf_params def test_variables_types(self): self.assertIsInstance(self.beam.beta, float, msg='Beam: beta is not a float') self.assertIsInstance(self.beam.gamma, float, msg='Beam: gamma is not a float') self.assertIsInstance(self.beam.energy, float, msg='Beam: energy is not a float') self.assertIsInstance(self.beam.momentum, float, msg='Beam: momentum is not a float') self.assertIsInstance(self.beam.mean_dt, float, msg='Beam: mean_dt is not a float') self.assertIsInstance(self.beam.mean_dE, float, msg='Beam: mean_dE is not a float') self.assertIsInstance(self.beam.sigma_dt, float, msg='Beam: sigma_dt is not a float') self.assertIsInstance(self.beam.sigma_dE, float, msg='Beam: sigma_dE is not a float') self.assertIsInstance(self.beam.intensity, float, msg='Beam: intensity is not a float') self.assertIsInstance(self.beam.n_macroparticles, int, msg='Beam: n_macroparticles is not an int') self.assertIsInstance(self.beam.ratio, float, msg='Beam: ratio is not a float') self.assertIsInstance(self.beam.id, numpy.ndarray, msg='Beam: id is not a numpy.array') self.assertIn('int', type(self.beam.id[0]).__name__, msg='Beam: id array does not contain int') self.assertIsInstance(self.beam.n_macroparticles_lost, int, msg='Beam: n_macroparticles_lost is not an int') self.assertIsInstance(self.beam.n_macroparticles_alive, int, msg='Beam: n_macroparticles_alive is not an int') self.assertIsInstance(self.beam.dt, numpy.ndarray, msg='Beam: dt is not a numpy.array') self.assertIsInstance(self.beam.dE, numpy.ndarray, msg='Beam: dE is not a numpy.array') self.assertIn('float', type(self.beam.dt[0]).__name__, msg='Beam: dt does not contain float') self.assertIn('float', type(self.beam.dE[0]).__name__, msg='Beam: dE does not contain float') def test_beam_statistic(self): sigma_dt = 1. sigma_dE = 1. self.beam.dt = sigma_dt*numpy.random.randn(self.beam.n_macroparticles) self.beam.dE = sigma_dE*numpy.random.randn(self.beam.n_macroparticles) self.beam.statistics() self.assertAlmostEqual(self.beam.sigma_dt, sigma_dt, delta=1e-2, msg='Beam: Failed statistic sigma_dt') self.assertAlmostEqual(self.beam.sigma_dE, sigma_dE, delta=1e-2, msg='Beam: Failed statistic sigma_dE') self.assertAlmostEqual(self.beam.mean_dt, 0., delta=1e-2, msg='Beam: Failed statistic mean_dt') self.assertAlmostEqual(self.beam.mean_dE, 0., delta=1e-2, msg='Beam: Failed statistic mean_dE') def test_losses_separatrix(self): longitudinal_tracker = RingAndRFTracker(self.rf_params, self.beam) full_tracker = FullRingAndRF([longitudinal_tracker]) try: matched_from_distribution_function(self.beam, full_tracker, distribution_exponent=1.5, distribution_type='binomial', bunch_length=1.65e-9, bunch_length_fit='fwhm', distribution_variable='Hamiltonian') except TypeError as te: self.skipTest("Skipped because of known bug in deepcopy. Exception message %s" % str(te)) self.beam.losses_separatrix(self.general_params, self.rf_params) self.assertEqual(len(self.beam.id[self.beam.id == 0]), 0, msg='Beam: Failed losses_sepatrix, first') self.beam.dE += 10e8 self.beam.losses_separatrix(self.general_params, self.rf_params) self.assertEqual(len(self.beam.id[self.beam.id == 0]), self.beam.n_macroparticles, msg='Beam: Failed losses_sepatrix, second') def test_losses_longitudinal_cut(self): longitudinal_tracker = RingAndRFTracker(self.rf_params, self.beam) full_tracker = FullRingAndRF([longitudinal_tracker]) try: matched_from_distribution_function(self.beam, full_tracker, distribution_exponent=1.5, distribution_type='binomial', bunch_length=1.65e-9, bunch_length_fit='fwhm', distribution_variable='Hamiltonian') except TypeError as te: self.skipTest("Skipped because of known bug in deepcopy. Exception message %s" % str(te)) self.beam.losses_longitudinal_cut(0., 5e-9) self.assertEqual(len(self.beam.id[self.beam.id == 0]), 0, msg='Beam: Failed losses_longitudinal_cut, first') self.beam.dt += 10e-9 self.beam.losses_longitudinal_cut(0., 5e-9) self.assertEqual(len(self.beam.id[self.beam.id == 0]), self.beam.n_macroparticles, msg='Beam: Failed losses_longitudinal_cut, second') def test_losses_energy_cut(self): longitudinal_tracker = RingAndRFTracker(self.rf_params, self.beam) full_tracker = FullRingAndRF([longitudinal_tracker]) try: matched_from_distribution_function(self.beam, full_tracker, distribution_exponent=1.5, distribution_type='binomial', bunch_length=1.65e-9, bunch_length_fit='fwhm', distribution_variable='Hamiltonian') except TypeError as te: self.skipTest("Skipped because of known bug in deepcopy. Exception message %s" % str(te)) self.beam.losses_energy_cut(-3e8, 3e8) self.assertEqual(len(self.beam.id[self.beam.id == 0]), 0, msg='Beam: Failed losses_energy_cut, first') self.beam.dE += 10e8 self.beam.losses_energy_cut(-3e8, 3e8) self.assertEqual(len(self.beam.id[self.beam.id == 0]), self.beam.n_macroparticles, msg='Beam: Failed losses_energy_cut, second') def test_addition(self): np = numpy testdEs = np.linspace(-1E6, 1E6, 2000000) testdts = np.linspace(0, 10E-9, 2000000) self.beam.dE = testdEs self.beam.dt = testdts testdEs = np.linspace(-2E6, 2E6, 100000) testdts = np.linspace(-1E-9, 12E-9, 100000) self.beam.add_particles([testdts, testdEs]) self.assertEqual(self.beam.n_macroparticles, 2100000, msg="n_macroparticles not incremented correctly") testBeam = Beam(self.general_params, 200, 0) testBeam.id[:100] = 0 self.beam.add_beam(testBeam) self.assertEqual(self.beam.id[2100000:2100100].tolist(), [0]*100, msg="particle ids not applied correctly") self.assertEqual(self.beam.n_macroparticles, 2100200, msg="Added macroparticles not incremented n_macro correctly") self.beam += testBeam self.assertEqual(self.beam.n_macroparticles, 2100400, msg="Added macroparticles not incremented n_macro correctly") self.beam += (testdts, testdEs) self.assertEqual(self.beam.n_macroparticles, 2200400, msg="Added macroparticles not incremented n_macro correctly") self.assertEqual(-2E6, np.min(self.beam.dE), msg="coordinates of added beam not used correctly") self.assertEqual(2E6, np.max(self.beam.dE), msg="coordinates of added beam not used correctly") self.assertEqual(-1E-9, np.min(self.beam.dt), msg="coordinates of added beam not used correctly") self.assertEqual(12E-9, np.max(self.beam.dt), msg="coordinates of added beam not used correctly") with self.assertRaises(blExcept.ParticleAdditionError, msg="""Unequal length time and energy should raise exception"""): self.beam += ([1, 2, 3], [4, 5]) with self.assertRaises(blExcept.ParticleAdditionError, msg="""Mising time/energy should raise exception"""): self.beam += ([1, 2, 3]) with self.assertRaises(TypeError, msg='Wrong type should raise exception'): self.beam.add_beam(([1], [2]))
# DEFINE RING------------------------------------------------------------------ general_params = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns) general_params_freq = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns) general_params_res = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns) RF_sct_par = RFStation(general_params, [harmonic_number], [voltage_program], [phi_offset], n_rf_systems) RF_sct_par_freq = RFStation(general_params_freq, [harmonic_number], [voltage_program], [phi_offset], n_rf_systems) RF_sct_par_res = RFStation(general_params_res, [harmonic_number], [voltage_program], [phi_offset], n_rf_systems) my_beam = Beam(general_params, n_macroparticles, n_particles) my_beam_freq = Beam(general_params_freq, n_macroparticles, n_particles) my_beam_res = Beam(general_params_res, n_macroparticles, n_particles) ring_RF_section = RingAndRFTracker(RF_sct_par, my_beam) ring_RF_section_freq = RingAndRFTracker(RF_sct_par_freq, my_beam_freq) ring_RF_section_res = RingAndRFTracker(RF_sct_par_res, my_beam_res) # DEFINE BEAM------------------------------------------------------------------ bigaussian(general_params, RF_sct_par, my_beam, tau_0 / 4, seed=1) bigaussian(general_params_freq, RF_sct_par_freq, my_beam_freq, tau_0 / 4, seed=1)
dt_plt = 5000 # Time steps between plots # Simulation setup ------------------------------------------------------------- print("Setting up the simulation...") print("") # Define general parameters general_params = Ring(C, alpha, np.linspace(p_i, p_f, N_t + 1), Particle(m_p, Z), n_turns=N_t) # Define beam and distribution beam = Beam(general_params, N_p, N_b) print("Particle mass is %.3e eV" % general_params.Particle.mass) print("Particle charge is %d e" % general_params.Particle.charge) linspace_test = np.linspace(p_i, p_f, N_t + 1) momentum_test = general_params.momentum beta_test = general_params.beta gamma_test = general_params.gamma energy_test = general_params.energy mass_test = general_params.Particle.mass # [eV] charge_test = general_params.Particle.charge # e*Z # Define RF station parameters and corresponding tracker rf_params = RFStation(general_params, [h], [V], [dphi]) print("Initial bucket length is %.3e s" % (2. * np.pi / rf_params.omega_rf[0, 0]))
E0 = ring.energy[0, 0] omegaS0 = np.sqrt(-h * omega0**2 * eta * np.cos(phiS) * V0 / (2 * np.pi * beta0**2 * E0)) nh = rf_station.harmonic[1, 0] / rf_station.harmonic[0, 0] V2 = rf_station.voltage[1, 0] phi2 = rf_station.phi_offset[1, 0] omegaS = omegaS0 * \ np.sqrt(1 + nh*V2*np.cos(nh*phiS+phi2) / (V0*np.cos(phiS))) fs = omegaS / (2 * np.pi) elif n_rf_systems == 1: fs = rf_station.omega_s0[0] / (2 * np.pi) # --- PS beam -------------------------------------------------------- n_macroparticles = n_bunches * n_particles beam = Beam(ring, n_macroparticles, intensity) # PS_n_bunches = 1 n_shift = 0 # how many rf-buckets to shift beam # PS_folder = this_directory +'/../input_files/' # SPS --- Profile ------------------------------------------- mpiprint('Setting up profile') profile_margin = 20 * t_rf t_batch_begin = n_shift * t_rf t_batch_end = t_rf * (bunch_spacing * (n_bunches - 1) + 1 + n_shift)
voltage_program = [10e9] phi_offset = [np.pi] bucket_length = C / c / harmonic_numbers[0] # DEFINE RING------------------------------------------------------------------ general_params = Ring(C, momentum_compaction, sync_momentum, Electron(), n_turns) RF_sct_par = RFStation(general_params, harmonic_numbers, voltage_program, phi_offset, n_rf_systems) # DEFINE BEAM------------------------------------------------------------------ beam = Beam(general_params, n_macroparticles, n_particles) # DEFINE TRACKER--------------------------------------------------------------- longitudinal_tracker = RingAndRFTracker(RF_sct_par, beam) full_tracker = FullRingAndRF([longitudinal_tracker]) # DEFINE SLICES---------------------------------------------------------------- n_slices = 500 n_bunches = 80 bunch_spacing = 1600 # buckets filling_pattern = np.zeros(bunch_spacing * n_bunches) filling_pattern[::bunch_spacing] = 1
worker.print_version() worker.initLog(bool(args['log']), args['logdir']) worker.initTrace(bool(args['trace']), args['tracefile']) worker.taskparallelism = withtp mpiprint(args) # Simulation setup ------------------------------------------------------------ mpiprint("Setting up the simulation...") # Define general parameters ring = Ring(C, alpha, np.linspace(p_i, p_f, n_turns + 1), Proton(), n_turns) # Define beam and distribution beam = Beam(ring, n_particles, N_b) # Define RF station parameters and corresponding tracker rf = RFStation(ring, [h], [V], [dphi]) bigaussian(ring, rf, beam, tau_0 / 4, reinsertion=True, seed=seed) # Need slices for the Gaussian fit # TODO add the gaussian fit profile = Profile(beam, CutOptions(n_slices=n_slices)) # FitOptions(fit_option='gaussian')) long_tracker = RingAndRFTracker(rf, beam) # beam.split_random() beam.split()
delta_f=1.12455000e-02, fmin_s0=0, fmax_s0=1.1, seed1=1234, seed2=7564, initial_amplitude=1.11100000e-07, folder_plots=this_directory + '../output_files/EX_03_fig') RFnoise.generate() rf_params.phi_noise = np.array(RFnoise.dphi, ndmin=2) print(" Sigma of RF noise is %.4e" % np.std(RFnoise.dphi)) print(" Time step of RF noise is %.4e" % RFnoise.t[1]) print("") beam = Beam(general_params, N_p, N_b) long_tracker = RingAndRFTracker(rf_params, beam) print("General and RF parameters set...") # Define beam and distribution # Generate new distribution bigaussian(general_params, rf_params, beam, tau_0 / 4, reinsertion=True, seed=1) print("Beam set and distribution generated...")
momentum_compaction = 1 / gamma_transition**2 # Cavities parameters n_rf_systems = 1 harmonic_numbers = 1 voltage_program = 8e3 #[V] phi_offset = -np.pi # DEFINE RING------------------------------------------------------------------ general_params = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns) RF_sct_par = RFStation(general_params, [harmonic_numbers], [voltage_program], [phi_offset], n_rf_systems) beam = Beam(general_params, n_macroparticles, n_particles) ring_RF_section = RingAndRFTracker(RF_sct_par, beam) full_tracker = FullRingAndRF([ring_RF_section]) fs = RF_sct_par.omega_s0[0] / 2 / np.pi bucket_length = 2.0 * np.pi / RF_sct_par.omega_rf[0, 0] # DEFINE SLICES --------------------------------------------------------------- number_slices = 100 slice_beam = Profile( beam, CutOptions(cut_left=0, cut_right=bucket_length, n_slices=number_slices))
# Pre-processing: RF phase noise ----------------------------------------------- RFnoise = FlatSpectrum(general_params, rf_params, delta_f = 1.12455000e-02, fmin_s0 = 0, fmax_s0 = 1.1, seed1=1234, seed2=7564, initial_amplitude = 1.11100000e-07, folder_plots = this_directory + '../output_files/EX_03_fig') RFnoise.generate() rf_params.phi_noise = np.array(RFnoise.dphi, ndmin =2) print(" Sigma of RF noise is %.4e" %np.std(RFnoise.dphi)) print(" Time step of RF noise is %.4e" %RFnoise.t[1]) print("") beam = Beam(general_params, N_p, N_b) long_tracker = RingAndRFTracker(rf_params, beam) print("General and RF parameters set...") # Define beam and distribution # Generate new distribution bigaussian(general_params, rf_params, beam, tau_0/4, reinsertion = True, seed=1) print("Beam set and distribution generated...") # Need slices for the Gaussian fit; slice for the first plot
# Define RF parameters (noise to be added for CC case) rf = RFStation(ring, [h], [V[0:n_turns+1]], [0.]) mpiprint("RF parameters set...") # Generate RF phase noise LHCnoise = FlatSpectrum(ring, rf, fmin_s0=0.8571, fmax_s0=1.001, initial_amplitude=1.e-5, predistortion='weightfunction') LHCnoise.dphi = np.load( os.path.join(inputDir, 'LHCNoise_fmin0.8571_fmax1.001_ampl1e-5_weightfct_6.5TeV.npz'))['arr_0'] LHCnoise.dphi = np.ascontiguousarray(LHCnoise.dphi[0:n_turns+1]) mpiprint("RF phase noise loaded...") # FULL BEAM bunch = Beam(ring, n_particles, N_b) beam = Beam(ring, n_particles*n_bunches, N_b) bigaussian(ring, rf, bunch, 0.3e-9, reinsertion=True, seed=seed) bunch_spacing_buckets = 10 for i in np.arange(n_bunches): beam.dt[i*n_particles:(i+1) * n_particles] = bunch.dt[0:n_particles] + i*rf.t_rf[0, 0]*10 beam.dE[i*n_particles:(i+1)*n_particles] = bunch.dE[0:n_particles] # Profile required for PL cutRange = (n_bunches-1)*25.e-9+3.5e-9 n_slices = np.int(cutRange/0.025e-9 + 1) n_slices = next_regular(n_slices) profile = Profile(beam, CutOptions(n_slices=n_slices, cut_left=-0.5e-9,
def setUp(self): C = 2*np.pi*1100.009 # Ring circumference [m] gamma_t = 18.0 # Gamma at transition alpha = 1/gamma_t**2 # Momentum compaction factor p_s = 25.92e9 # Synchronous momentum at injection [eV] h = 4620 # 200 MHz system harmonic phi = 0. # 200 MHz RF phase # With this setting, amplitude in the two four-section, five-section # cavities must converge, respectively, to # 2.0 MV = 4.5 MV * 4/18 * 2 # 2.5 MV = 4.5 MV * 5/18 * 2 V = 4.5e6 # 200 MHz RF voltage N_t = 1 # Number of turns to track self.ring = Ring(C, alpha, p_s, Particle=Proton(), n_turns=N_t) self.rf = RFStation(self.ring, h, V, phi) N_m = 1e6 # Number of macro-particles for tracking N_b = 72*1.0e11 # Bunch intensity [ppb] # Gaussian beam profile self.beam = Beam(self.ring, N_m, N_b) sigma = 1.0e-9 bigaussian(self.ring, self.rf, self.beam, sigma, seed=1234, reinsertion=False) n_shift = 1550 # how many rf-buckets to shift beam self.beam.dt += n_shift * self.rf.t_rf[0, 0] self.profile = Profile( self.beam, CutOptions=CutOptions( cut_left=(n_shift-1.5)*self.rf.t_rf[0, 0], cut_right=(n_shift+2.5)*self.rf.t_rf[0, 0], n_slices=4*64)) self.profile.track() # Cavities l_cav = 43*0.374 v_g = 0.0946 tau = l_cav/(v_g*c)*(1 + v_g) f_cav = 200.222e6 n_cav = 2 # factor 2 because of two four/five-sections cavities short_cavity = TravelingWaveCavity(l_cav**2 * n_cav * 27.1e3 / 8, f_cav, 2*np.pi*tau) shortInducedVoltage = InducedVoltageTime(self.beam, self.profile, [short_cavity]) l_cav = 54*0.374 tau = l_cav/(v_g*c)*(1 + v_g) long_cavity = TravelingWaveCavity(l_cav**2 * n_cav * 27.1e3 / 8, f_cav, 2*np.pi*tau) longInducedVoltage = InducedVoltageTime(self.beam, self.profile, [long_cavity]) self.induced_voltage = TotalInducedVoltage( self.beam, self.profile, [shortInducedVoltage, longInducedVoltage]) self.induced_voltage.induced_voltage_sum() self.cavity_tracker = RingAndRFTracker( self.rf, self.beam, Profile=self.profile, interpolation=True, TotalInducedVoltage=self.induced_voltage) self.OTFB = SPSCavityFeedback( self.rf, self.beam, self.profile, G_llrf=5, G_tx=0.5, a_comb=15/16, turns=50, Commissioning=CavityFeedbackCommissioning()) self.OTFB_tracker = RingAndRFTracker(self.rf, self.beam, Profile=self.profile, TotalInducedVoltage=None, CavityFeedback=self.OTFB, interpolation=True)
# Simulation setup ------------------------------------------------------------ print("Setting up the simulation...") print("") # Define general parameters containing data for both RF stations general_params = Ring([0.3*C, 0.7*C], [[alpha], [alpha]], [p_s*np.ones(N_t+1), p_s*np.ones(N_t+1)], Proton(), N_t, n_sections = 2) # Define RF station parameters and corresponding tracker beam = Beam(general_params, N_p, N_b) rf_params_1 = RFStation(general_params, [h], [V1], [dphi], section_index=1) long_tracker_1 = RingAndRFTracker(rf_params_1, beam) rf_params_2 = RFStation(general_params, [h], [V2], [dphi], section_index=2) long_tracker_2 = RingAndRFTracker(rf_params_2, beam) # Define full voltage over one turn and a corresponding "overall" set of #parameters, which is used for the separatrix (in plotting and losses) Vtot = total_voltage([rf_params_1, rf_params_2]) rf_params_tot = RFStation(general_params, [h], [Vtot], [dphi]) beam_dummy = Beam(general_params, 1, N_b) long_tracker_tot = RingAndRFTracker(rf_params_tot, beam_dummy)
PLOT_NO_BEAM = True # Plot settings plt.rc('axes', labelsize=12, labelweight='normal') plt.rc('lines', linewidth=1.5, markersize=6) plt.rc('font', family='sans-serif') plt.rc('legend', fontsize=12) # Logger for messages on console & in file Logger(debug=True) ring = Ring(C, alpha, p_s, Particle=Proton(), n_turns=1) rf = RFStation(ring, [h], [3.1e6], [dphi]) # SPS-equivalent for 0.57 eVs, 1.65 ns bunch = Beam(ring, N_m, N_p) bigaussian(ring, rf, bunch, sigma_dt=1.65e-9 / 4) #tau_0) # Real RF voltage rf = RFStation(ring, [h], [V], [dphi]) beam = Beam(ring, N_m * NB, N_p * NB) buckets = rf.t_rf[0, 0] * 10 for i in range(12): beam.dt[i * N_m:(i + 1) * N_m] = bunch.dt[0:N_m] + i * buckets beam.dE[i * N_m:(i + 1) * N_m] = bunch.dE[0:N_m] for i in range(12, 60): beam.dt[i * N_m:(i + 1) * N_m] = bunch.dt[0:N_m] + i * buckets + 32 * buckets beam.dE[i * N_m:(i + 1) * N_m] = bunch.dE[0:N_m] for i in range(60, 108): beam.dt[i * N_m:(i + 1) *
alpha = 1 / gamma_transition**2 C = 2 * np.pi * radius # [m] n_turns = 2000 general_params = Ring(C, alpha, 310891054.809, Proton(), n_turns) # Cavities parameters n_rf_systems = 1 harmonic_numbers_1 = 1 voltage_1 = 8000 # [V] phi_offset_1 = np.pi # [rad] rf_params = RFStation(general_params, [harmonic_numbers_1], [voltage_1], [phi_offset_1], n_rf_systems) my_beam = Beam(general_params, n_macroparticles, n_particles) cut_options = CutOptions(cut_left=0, cut_right=2.0 * 0.9e-6, n_slices=200) slices_ring = Profile(my_beam, cut_options) #Phase loop #configuration = {'machine': 'PSB', 'PL_gain': 0., 'RL_gain': [34.8,16391], # 'PL_period': 10.e-6, 'RL_period': 7} configuration = { 'machine': 'PSB', 'PL_gain': 0, 'RL_gain': [1.e7, 1.e11], 'period': 10.e-6 } phase_loop = BeamFeedback(general_params, rf_params, slices_ring, configuration)
momentum_compaction = 1 / gamma_transition**2 # [1] # Cavities parameters n_rf_systems = 1 harmonic_numbers = 1 voltage_program = 8e3 #[V] phi_offset = np.pi # DEFINE RING------------------------------------------------------------------ general_params = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns) RF_sct_par = RFStation(general_params, [harmonic_numbers], [voltage_program], [phi_offset], n_rf_systems) my_beam = Beam(general_params, n_macroparticles, n_particles) ring_RF_section = RingAndRFTracker(RF_sct_par, my_beam) # DEFINE BEAM------------------------------------------------------------------ bigaussian(general_params, RF_sct_par, my_beam, sigma_dt, seed=1) # DEFINE SLICES---------------------------------------------------------------- slice_beam = Profile( my_beam, CutOptions(cut_left=-5.72984173562e-7, cut_right=5.72984173562e-7, n_slices=100)) # LOAD IMPEDANCE TABLES--------------------------------------------------------
# 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 ring = Ring(C, alpha, np.linspace(p_i, p_f, 2001), Proton(), N_t) # Define beam and distribution beam = Beam(ring, N_p, N_b) # Define RF station parameters and corresponding tracker rf = RFStation(ring, [h], [V], [dphi]) long_tracker = RingAndRFTracker(rf, beam) bigaussian(ring, rf, beam, tau_0/4, reinsertion = True, seed=1) # Need slices for the Gaussian fit profile = Profile(beam, CutOptions(n_slices=100), FitOptions(fit_option='gaussian')) # Define what to save in file