def test_simple_input_othermethods(self): # Test other methods to pass the simplest input length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() section = RingSection(length, alpha_0, momentum) ring_reference = Ring(particle, [section]) with self.subTest('Simple input - Single section'): ring = Ring(particle, section) np.testing.assert_equal(ring_reference.circumference, ring.circumference) np.testing.assert_equal(ring_reference.alpha_0, ring.alpha_0) np.testing.assert_equal(ring_reference.momentum, ring.momentum) with self.subTest('Simple input - Single section tuple'): ring = Ring(particle, (section, )) np.testing.assert_equal(ring_reference.circumference, ring.circumference) np.testing.assert_equal(ring_reference.alpha_0, ring.alpha_0) np.testing.assert_equal(ring_reference.momentum, ring.momentum) with self.subTest('Simple input - Direct classmethod'): ring = Ring.direct_input(particle, length, alpha_0, momentum) np.testing.assert_equal(ring_reference.circumference, ring.circumference) np.testing.assert_equal(ring_reference.alpha_0, ring.alpha_0) np.testing.assert_equal(ring_reference.momentum, ring.momentum)
def test_non_linear_momentum_compaction_multisection(self): # Test passing non linear momentum compaction factor in multisection length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() alpha_1 = 1e-6 alpha_2 = 1e-9 alpha_5 = 1e-12 section_1 = RingSection(length, alpha_0, momentum) section_2 = RingSection(length, alpha_0, momentum, alpha_1=alpha_1, alpha_2=alpha_2, alpha_5=alpha_5) ring = Ring(particle, [section_1, section_2]) with self.subTest('Non linear alpha - Multisection - alpha_1'): np.testing.assert_equal(0, ring.alpha_1[0, :]) np.testing.assert_equal(alpha_1, ring.alpha_1[1, :]) with self.subTest('Non linear alpha - Multisection - alpha_2'): np.testing.assert_equal(0, ring.alpha_2[0, :]) np.testing.assert_equal(alpha_2, ring.alpha_2[1, :]) with self.subTest('Non linear alpha - Multisection - alpha_5'): np.testing.assert_equal(0, ring.alpha_5[0, :]) np.testing.assert_equal(alpha_5, ring.alpha_5[1, :])
def test_other_synchronous_data_other_input(self): # Test passing other sync data length = 300 # m alpha_0 = 1e-3 particle = Proton() momentum = 26e9 # eV/c tot_energy = 26e9 # eV kin_energy = 26e9 # eV bending_radius = 70 # m b_field = momentum / c / particle.charge / bending_radius # T with self.subTest('Other sync data - Direct - tot_energy'): ring = Ring.direct_input(particle, length, alpha_0, energy=tot_energy) np.testing.assert_allclose(tot_energy, ring.energy) with self.subTest('Other sync data - Direct - kin_energy'): # NB: allclose due to double conversion ring = Ring.direct_input(particle, length, alpha_0, kin_energy=kin_energy) np.testing.assert_allclose(kin_energy, ring.kin_energy) with self.subTest('Other sync data - Direct - b_field'): # NB: allclose due to double conversion ring = Ring.direct_input(particle, length, alpha_0, bending_field=b_field, bending_radius=bending_radius) np.testing.assert_allclose(momentum, ring.momentum)
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 test_parameters_at_sample(self): # Test passing non linear momentum compaction factor length = 300 # m alpha_0 = 1e-3 particle = Proton() momentum = [26e9, 27e9, 28e9] # eV/c section = RingSection(length, alpha_0, momentum) ring = Ring(particle, [section]) params = ring.parameters_at_sample(1) with self.subTest('Time based program - momentum'): np.testing.assert_equal(momentum[1], params['momentum'])
def test_warning_eta_order(self): # Test the warning when identical time programs are given # for each section length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c eta_orders = 4 particle = Proton() warn_message = 'The eta_orders can only be computed up to eta_2!' with self.assertWarnsRegex(Warning, warn_message): section = RingSection(length, alpha_0, momentum) Ring(particle, [section], eta_orders=eta_orders)
def test_unused_kwarg(self): # Test the warning that kwargs were not used # (e.g. miss-typed or bad option) length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() kwargs = {'bad_kwarg': 0} warn_message = ("Unused kwargs have been detected, " + f"they are \['{list(kwargs.keys())[0]}'\]") with self.assertWarnsRegex(Warning, warn_message): section = RingSection(length, alpha_0, momentum) Ring(particle, [section], **kwargs)
def test_parameters_at_time(self): # Test passing non linear momentum compaction factor length = 300 # m alpha_0 = [[0, 100e-6], [1e-3, 1.5e-3]] particle = Proton() momentum = [[0, 100e-6], [26e9, 26e9]] # eV/c section = RingSection(length, alpha_0, momentum) ring = Ring(particle, [section]) params = ring.parameters_at_time(50e-6) with self.subTest('Time based program - momentum'): np.testing.assert_equal(np.mean(momentum[1]), params['momentum']) np.testing.assert_equal(50e-6, params['cycle_time'])
def test_simple_input_multisection_othermethods(self): # Test other methods to pass the simplest input with multisection length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() section = RingSection(length / 2, alpha_0, momentum) ring_reference = Ring(particle, [section, section]) with self.subTest('Simple input - Multisection tuple'): ring = Ring(particle, (section, section)) np.testing.assert_equal(ring_reference.circumference, ring.circumference) np.testing.assert_equal(ring_reference.alpha_0, ring.alpha_0) np.testing.assert_equal(ring_reference.momentum, ring.momentum)
def test_exception_mix_time_turn(self): # Test the exception when time/turn programs are mixed for various # sections length = 300 # m alpha_0 = 1e-3 momentum_1 = [26e9, 27e9, 28e9] # eV/c momentum_2 = [[0, 100e-6], [26e9, 26e9]] # eV/c particle = Proton() error_message = ('The synchronous data for' + 'the different sections is mixing time and turn ' + 'based programs which is not supported.') with self.assertRaisesRegex(excpt.InputError, error_message): section_1 = RingSection(length / 2, alpha_0, momentum_1) section_2 = RingSection(length / 2, alpha_0, momentum_2) Ring(particle, [section_1, section_2])
def test_simple_input(self): # Test the simplest input length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() section = RingSection(length, alpha_0, momentum) ring = Ring(particle, [section]) with self.subTest('Simple input - circumference'): np.testing.assert_equal(length, ring.circumference) with self.subTest('Simple input - alpha_0'): np.testing.assert_equal(alpha_0, ring.alpha_0) with self.subTest('Simple input - momentum'): np.testing.assert_equal(momentum, ring.momentum)
def test_error_time_prog_multisection(self): # Test the error when different time programs are given # for each section length = 300 # m alpha_0 = 1e-3 momentum_1 = [[0, 100e-6], [26e9, 26e9]] # eV/c momentum_2 = [[0, 100e-6], [27e9, 27e9]] # eV/c particle = Proton() error_message = ('The synchronous data for all sections ' + 'are defined time based and ' + 'are not identical. This case is not yet ' + 'implemented.') with self.assertRaisesRegex(NotImplementedError, error_message): section_1 = RingSection(length / 2, alpha_0, momentum_1) section_2 = RingSection(length / 2, alpha_0, momentum_2) Ring(particle, [section_1, section_2])
def test_time_based_sync_program(self): # Test passing non linear momentum compaction factor length = 300 # m alpha_0 = 1e-3 particle = Proton() momentum = [[0, 100e-6], [26e9, 26e9]] # eV/c tot_energy = [[0, 100e-6], [26e9, 26e9]] # eV kin_energy = [[0, 100e-6], [26e9, 26e9]] # eV bending_radius = 70 # m b_field = np.array(momentum) b_field[1, :] *= 1 / c / \ particle.charge / bending_radius # T with self.subTest('Time based program - momentum'): section = RingSection(length, alpha_0, momentum) ring = Ring(particle, [section]) np.testing.assert_equal(np.mean(momentum[1]), np.mean(ring.momentum)) with self.subTest('Time based program - tot_energy'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, energy=tot_energy) ring = Ring(particle, [section]) np.testing.assert_allclose(np.mean(tot_energy[1]), np.mean(ring.energy)) with self.subTest('Time based program - kin_energy'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, kin_energy=kin_energy) ring = Ring(particle, [section]) np.testing.assert_allclose(np.mean(kin_energy[1]), np.mean(ring.kin_energy)) with self.subTest('Time based program - b_field'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, bending_field=b_field, bending_radius=bending_radius) ring = Ring(particle, [section]) np.testing.assert_allclose(np.mean(momentum[1]), np.mean(ring.momentum))
def test_assert_wrong_section_list(self): # Test the exception that other than RingSection is passed length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() section = RingSection(length, alpha_0, momentum) error_message = ( "The RingSection_list should be exclusively composed " + "of RingSection object instances.") with self.subTest('Wrong RingSection_list - other type'): with self.assertRaisesRegex(excpt.InputError, error_message): Ring(particle, ['test']) with self.subTest('Wrong RingSection_list - multisection other type'): with self.assertRaisesRegex(excpt.InputError, error_message): Ring(particle, [section, 'test'])
def test_warning_time_prog_multisection(self): # Test the warning when identical time programs are given # for each section length = 300 # m alpha_0 = 1e-3 momentum = [[0, 100e-6], [26e9, 26e9]] # eV/c particle = Proton() warn_message = 'The synchronous data for all sections ' + \ 'are defined time based and ' + \ 'are identical. Presently, ' + \ 'the momentum is assumed constant for one turn over ' + \ 'all sections, no increment in delta_E from ' + \ 'one section to the next. Please use custom ' + \ 'turn based program if needed.' with self.assertWarnsRegex(Warning, warn_message): section_1 = RingSection(length / 2, alpha_0, momentum) section_2 = RingSection(length / 2, alpha_0, momentum) Ring(particle, [section_1, section_2])
def test_turn_based_sync_program(self): # Test passing turn based momentum program length = 300 # m alpha_0 = 1e-3 particle = Proton() momentum = [26e9, 27e9, 28e9] # eV/c tot_energy = [26e9, 27e9, 28e9] # eV kin_energy = [26e9, 27e9, 28e9] # eV bending_radius = 70 # m b_field = np.array(momentum) / c / \ particle.charge / bending_radius # T with self.subTest('Turn based program - momentum'): section = RingSection(length, alpha_0, momentum) ring = Ring(particle, [section]) np.testing.assert_equal(momentum, ring.momentum[0, :]) with self.subTest('Turn based program - tot_energy'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, energy=tot_energy) ring = Ring(particle, [section]) np.testing.assert_allclose(tot_energy, ring.energy[0, :]) with self.subTest('Turn based program - kin_energy'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, kin_energy=kin_energy) ring = Ring(particle, [section]) np.testing.assert_allclose(kin_energy, ring.kin_energy[0, :]) with self.subTest('Turn based program - bending_field'): # NB: allclose due to double conversion section = RingSection(length, alpha_0, bending_field=b_field, bending_radius=bending_radius) ring = Ring(particle, [section]) np.testing.assert_allclose(momentum, ring.momentum[0, :])
def test_non_linear_momentum_compaction_other_input(self): # Test passing non linear momentum compaction factor length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() alpha_1 = 1e-6 alpha_2 = 1e-9 alpha_5 = 1e-12 ring = Ring.direct_input(particle, length, alpha_0, momentum, alpha_1=alpha_1, alpha_2=alpha_2, alpha_5=alpha_5) with self.subTest('Simple input - Direct input'): np.testing.assert_equal(alpha_1, ring.alpha_1) np.testing.assert_equal(alpha_2, ring.alpha_2) np.testing.assert_equal(alpha_5, ring.alpha_5)
def test_other_synchronous_data_multisection(self): # Test passing other sync data in multisection length = 300 # m alpha_0 = 1e-3 particle = Proton() momentum = 26e9 # eV/c tot_energy = 26e9 # eV kin_energy = 26e9 # eV bending_radius = 70 # m b_field = momentum / c / particle.charge / bending_radius # T with self.subTest('Other sync data - Multisection - tot_energy'): section_1 = RingSection(length / 2, alpha_0, momentum) section_2 = RingSection(length / 2, alpha_0, energy=tot_energy) ring = Ring(particle, [section_1, section_2]) np.testing.assert_allclose(momentum, ring.momentum[0, :]) np.testing.assert_allclose(tot_energy, ring.energy[1, :]) with self.subTest('Other sync data - Multisection - kin_energy'): # NB: allclose due to double conversion section_1 = RingSection(length / 2, alpha_0, momentum) section_2 = RingSection(length / 2, alpha_0, kin_energy=kin_energy) ring = Ring(particle, [section_1, section_2]) np.testing.assert_allclose(momentum, ring.momentum[0, :]) np.testing.assert_allclose(kin_energy, ring.kin_energy[1, :]) with self.subTest('Other sync data - Multisection - b_field'): # NB: allclose due to double conversion section_1 = RingSection(length / 2, alpha_0, momentum) section_2 = RingSection(length / 2, alpha_0, bending_field=b_field, bending_radius=bending_radius) ring = Ring(particle, [section_1, section_2]) np.testing.assert_allclose(momentum, ring.momentum[0, :]) np.testing.assert_allclose(momentum, ring.momentum[1, :])
def test_particle_types(self): # Test various particle input length = 300 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c section = RingSection(length, alpha_0, momentum) with self.subTest('Particle type - Proton()'): particle = Proton() ring = Ring(particle, [section]) np.testing.assert_equal(Proton().mass, ring.Particle.mass) np.testing.assert_equal(Proton().charge, ring.Particle.charge) with self.subTest('Particle type - "proton"'): particle = "proton" ring = Ring(particle, [section]) np.testing.assert_equal(Proton().mass, ring.Particle.mass) np.testing.assert_equal(Proton().charge, ring.Particle.charge) with self.subTest('Particle type - Electron()'): particle = Electron() ring = Ring(particle, [section]) np.testing.assert_equal(Electron().mass, ring.Particle.mass) np.testing.assert_equal(Electron().charge, ring.Particle.charge) with self.subTest('Particle type - "electron"'): particle = "electron" ring = Ring(particle, [section]) np.testing.assert_equal(Electron().mass, ring.Particle.mass) np.testing.assert_equal(Electron().charge, ring.Particle.charge) with self.subTest('Particle type - Particle()'): user_mass = 208 * Proton().mass user_charge = 82 particle = Particle(user_mass, user_charge) ring = Ring(particle, [section]) np.testing.assert_equal(user_mass, ring.Particle.mass) np.testing.assert_equal(user_charge, ring.Particle.charge)
''' **Examples of usage of the Ring object.** :Authors: **Simon Albright**, **Alexandre Lasheen** ''' # BLonD Common import from blond_common.interfaces.machine_parameters.ring import \ Ring, RingSection, machine_program from blond_common.interfaces.beam.beam import Proton, Electron, Particle # To declare a Ring with simple input length = 628 # m alpha_0 = 1e-3 momentum = 26e9 # eV/c particle = Proton() ring = Ring(particle, [RingSection(length, alpha_0, momentum)]) # ring = Ring.direct_input(particle, length, alpha_0, momentum) print('-- Simple input') print(f'Ring circumference {ring.circumference_design} [m]') print(f'Sync. data - Momentum {ring.momentum} [eV/c]') print(f'Sync. data - Beta {ring.beta}') print(f'Sync. data - Gamma {ring.gamma}') print(f'Linear momentum compaction {ring.alpha_0}') print() # To declare a Ring with other synchronous data (all possible definitions # from the RingSection object, example with total energy)
# ## 1. Defining the Ring object, where the base synchrotron parameters are defined # ## 1.1 Single parameters # In[2]: # Simplest case: define a synchrotron with constant momentum from blond_common.interfaces.input_parameters.ring import Ring from blond_common.interfaces.beam.beam import Proton ring_length = 6911.5 # m gamma_transition = 17.95 alpha_0 = 1 / gamma_transition**2. momentum = 25.92e9 # eV/c particle = Proton() ring = Ring(ring_length, alpha_0, momentum, particle) # Note that size of programs is (n_sections, n_turns+1) print('Momentum : %.5e eV/c' % (ring.momentum[0, 0])) print('Kinetic energy : %.5e eV' % (ring.kin_energy[0, 0])) print('Total energy : %.5e eV' % (ring.energy[0, 0])) print('beta : %.5f' % (ring.beta[0, 0])) print('gamma : %.5f' % (ring.gamma[0, 0])) print('Revolution period : %.5e s' % (ring.t_rev[0])) # In[3]: # Now we define a synchrotron by giving the kinetic energy from blond_common.interfaces.input_parameters.ring import Ring